5
$\begingroup$

I am looking at a file generated by another CAS. I'd like to convert it to Mathematica syntax.

Only issue is how to convert exp(....) to Exp[....]. I am using StringReplace with pattern to do the replacement but it is not catching all possible cases. I am not good at regular expressions in Mathematica.

Here are 5 simple input examples to test with

ClearAll[z]
str1 = "exp(x)^2";
str2 = "exp((x+2))";
str3 = "exp( (x+2) * exp(exp(x)+2) )";
str4 = "(4*x)/exp((x-(2/5))/((3/(exp(x)+5))*4+(x-(2-x))*x))+4"
str5="(20*x^4+(-30)*x^3+12*x^2+4*x)*exp(x)^2+(200*x^4+(-300)*x^3+300*x^2+(-236)*x)*exp(x)+(500*x^4+(-750)*x^3+1500*x^2+(-1400)*x+720)"

These should become

str1 = "Exp[x]^2";
str2 = "Exp[(x+2)]";
str3 = "Exp[ (x+2) * Exp[Exp[x]+2]  ]";
str4 = "(4*x)/Exp[(x-(2/5))/((3/(Exp[x]+5))*4+(x-(2-x))*x)]+4"
str5 = "(20*x^4+(-30)*x^3+12*x^2+4*x)*Exp[x]^2+(200*x^4+(-300)*x^3+300*x^2+(-236)*x)*Exp[x]+(500*x^4+(-750)*x^3+1500*x^2+(-1400)*x+720)"

This is what I tried among many other things

StringReplace[str, "exp(" ~~ z__ ~~ ")" :> "Exp[" ~~ z ~~ "]"]

Only the first and second worked. The third one, it did not change any of the internal ones. it failed on str4 and str5 also.

Any suggestions how to do this conversion all in one command? Either using string patterns or regular expression in Mathematica.

I am using version 12.3.1

$\endgroup$
1
  • 1
    $\begingroup$ As far as I understand StringReplace is indeed a wolframized version of extended regular expressions. In the case of nested parentheses it's noteworthy that extended regular expressions are simply not expressive enough construct to handle arbitrary counting and matching of nested parentheses, which is required here (unless you work around it with the @ trick). $\endgroup$
    – kirma
    Sep 14 '21 at 12:57
7
$\begingroup$

Update: We can convert the strings to expressions without any string processing:

ClearAll[sR0]
sR0 = ToExpression[#, TraditionalForm] &;

sR0 /@ {str1, str2, str3, str4, str5} // Column

enter image description here

If you need to get strings as output wrap the expression with ToString[#, InputForm]& using the third argument of ToExpression:

ClearAll[sR01]
sR01 = ToExpression[#, TraditionalForm, ToString[#, InputForm] &] &;

sR01 /@ {str1, str2, str3, str4, str5}
{"E^(2*x)", 
 "E^(2 + x)", 
 "E^(E^(2 + E^x)*(2 + x))",
 "4 + (4*x)/E^((-2/5 + x)/(12/(5 + E^x) + x*(-2 + 2*x)))",
 "720 - 1400*x + 1500*x^2 - 750*x^3 + 500*x^4 +
    E^(2*x)*(4*x + 12*x^2 - 30*x^3 + 20*x^4) + 
    E^x*(-236*x + 300*x^2 - 300*x^3 + 200*x^4)"}

Original answer:

ClearAll[sR]
sR = StringReplace[#, "exp(" ~~ Shortest[z__] ~~ ")" /; 
   Equal @@ (StringCount[z, #] & /@ {"(", ")"}) :> 
 "Exp[" <> sR @ z <> "]"] &;

sR /@ {str1, str2, str3, str4, str5} 
{"Exp[x]^2",
 "Exp[(x+2)]",
 "Exp[ (x+2) * Exp[Exp[x]+2] ]", 
 "(4*x)/Exp[(x-(2/5))/((3/(Exp[x]+5))*4+(x-(2-x))*x)]+4", 
 "(20*x^4+(-30)*x^3+12*x^2+4*x)*Exp[x]^2+(200*x^4+(-300)*x^3+300*x^2+
   (-236)*x)*Exp[x]+(500*x^4+(-750)*x^3+1500*x^2+(-1400)*x+720)"}

You can also use FixedPoint as follows:

ClearAll[sR2]
sR2 = FixedPoint[StringReplace[
     "exp(" ~~ Shortest[z__] ~~ ")" /; 
       Equal @@ (StringCount[z, #] & /@ {"(", ")"}) :> 
      "Exp[" <> z <> "]"], #] &;

sR2 /@ {str1, str2, str3, str4, str5} == sR /@ {str1, str2, str3, str4, str5}
 True
$\endgroup$
6
  • $\begingroup$ Thanks. I tried it on the main files, there are cases where it does not work. Here is one str4="(20*x^4+(-30)*x^3+12*x^2+4*x)*exp(x)^2+(200*x^4+(-300)*x^3+300*x^2+(-236)*x)*exp(x)+(500*x^4+(-750)*x^3+1500*x^2+(-1400)*x+720)" it gives "(20*x^4+(-30)*x^3+12*x^2+4*x)*Exp[x)^2+(200*x^4+(-300)*x^3+300*x^2+(- 236)*x)*Exp[x)+(500*x^4+(-750)*x^3+1500*x^2+(-1400]*x+720]" I will add this example to my question for completion. $\endgroup$
    – Nasser
    Sep 9 '21 at 5:04
  • $\begingroup$ Also please note that str4 test also did not pass. It generated Exp[x) there as well. $\endgroup$
    – Nasser
    Sep 9 '21 at 5:12
  • $\begingroup$ @Nasser, please see the updated version. $\endgroup$
    – kglr
    Sep 9 '21 at 5:20
  • $\begingroup$ Thanks for the update. But for str5 it still gives Exp[x)^2 $\endgroup$
    – Nasser
    Sep 9 '21 at 5:26
  • $\begingroup$ @Nasser, updated version works for str1 thru str5 (will need another update for str6:) $\endgroup$
    – kglr
    Sep 9 '21 at 5:34
8
$\begingroup$

A simple trick is to notice that in Mathematica, Exp[x] can be written as Exp@(x) where the @ symbol has very high precedence. A replacement of the string "exp" by the string "Exp@" therefore does the necessary conversion without needing any bracket-matching logic:

convert[s_String] := ToExpression[StringReplace[s, "exp" -> "Exp@"]]

convert[str1]
(*    E^(2 x)    *)

convert[str2]
(*    E^(2 + x)    *)

convert[str3]
(*    E^(E^(2 + E^x) (2 + x))    *)

convert[str4]
(*    4 + 4 E^(-((-(2/5) + x)/(12/(5 + E^x) + x (-2 + 2 x)))) x    *)

convert[str5]
(*    720 - 1400 x + 1500 x^2 - 750 x^3 + 500 x^4 + E^(2 x) (4 x + 12 x^2 - 30 x^3 + 20 x^4) + E^x (-236 x + 300 x^2 - 300 x^3 + 200 x^4)    *)

If you want pretty string forms (instead of automatic evaluation with ToExpression as above), use an invisible application esc-@-esc to hide the @ symbols:

convert2[s_String] := StringReplace[s, "exp" -> "Exp\[InvisibleApplication]"]

convert2[str1]
(*    "Exp\[InvisibleApplication](x)^2"    *)
(*    actually looks like "Exp(x)^2" in the front-end but is
      correct Mathematica syntax                                *)

ToExpression[%]
(*    E^(2 x)    *)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.