Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I need to write output of a Mathematica expression (a list of equations) in a file. I use

    WriteInput[fname_, var_, eqlist_] := Module[{str, leq},
    str = OpenWrite[fname];
    leq = Length[eqlist];
    WriteString[str, "{"];
    removebracketvar[x_] := 
    StringReplace[StringReplace[ToString[x],{"["-> "","]"->"",","->""}],Whitespace->""];
    (*write equations*)
    Do[ 
    WriteString[str, 
    removebracketvar[ToString[eqlist[[i]] , InputForm]] ];
    WriteString[str , ";\n"] ,
    {i, leq}];
    WriteString[str, "}"];
    Close[str]
    ]

This works fine for small coefficients, e.g.,

 SetDirectory["/home/mydir"];WriteInput["sys1.txt",{x[1,1],x[2,1],x[1,2]},  
 {3.4x[1,1]^2,x[2,1]^2,x[1,2]^2}]

i.e., it generates the following file sys1.txt

{3.4*x11^2;
x21^2;
x12^2;
}

However, the problem comes up when 1. the coefficients are integer, e.g.,

SetDirectory["/home/mydir"];
WriteInput["sys1.txt", {x[1, 1], x[2, 1], x[1, 2]}, {3.0 x[1, 1]^2, x[2, 1]^2, x[1, 2]^2}]

which writes sys1.txt as

{3.*x11^2;
x21^2;
x12^2;
}

where '3.' is not appropriate for the later operations on the file by some other external code. 3.0 or 3 is what I want.

Coefficients in scientific form are also problematic. e.g.,

  SetDirectory["/home/mydir"];
  WriteInput["sys1.txt", {x[1, 1], x[2, 1], x[1, 2]},
    {3.998723445*10^6 x[1, 1]^2, x[2, 1]^2, x[1, 2]^2}]

gives

{3.998723445*^6*x11^2;*x11^2;
x21^2;
x12^2;
}

where it has this weird *^ notation for the exponents. I want 10^(6) instead, or just in the non-scientific form, i.e., 3998723.445 is also fine.

Is there any good way of tweaking this short code to get the coefficients in the form I want?

share|improve this question
    
If you change the file extension to csv/tsv/dat from txt you will get numbers of the form 3.998723445e6. I don't know if that is good enough for you. –  mohit6up Apr 20 '12 at 21:06
    
Thanks a lot for your suggestions. When I evoke 'removebracketvar[eqlist[[i]]]', I am getting the following error: Syntax::bktx: "(removebracketvar[x_]:=Fold[StringReplace[#1,#2]&,ToString[x//FortranForm],{Re‌​gularExpression["\\.([^0-9])"]->"$1",RegularExpres sion["e([0-9]+)"]->"*10^($1)",RegularExpression["\(\\s*(([0-9]+\\,\\s)+[0-9]+" has extra ")" after it (line 128 of "/home/homeMathematica_files/removebracketvar.m"). I didn't see any additional " here. Also the output file has still round brackets from fortran form e.g., x(1), left. I think this is very close to what I want but this err –  user1086 Apr 23 '12 at 21:36
    
@Heike, Your trick is working for me for now. But what if I want to get the equations in f1= eqlist[[1]]; f2= eqlist[[2]]; ... ? i.e., I want to add 'fi= ' in front of each equation where 'i' runs from 1 to no. of equations. Thanks for your help. dbm368 –  user1087 Apr 24 '12 at 2:26
add comment

migrated from stackoverflow.com Apr 21 '12 at 0:54

This question came from our site for professional and enthusiast programmers.

2 Answers

You could define your own definitions for formatting numbers and variables. For example

WriteInput1[file_, var_, eqlist_] := 
 Module[{text, removewhite, eq2, gg, hh, format},

  format[a_?NumericQ] := Block[{Format},
    ToString@NumberForm[a, 10,
      NumberFormat -> (Module[{man},
          man = #1;
          If[StringTake[#1, -1] === ".", man = man <> "0"];
          If[#3 === "", man, Row[{man, "*10^(", #3, ")"}]]] &)]];

  gg /: Format[gg[a_], InputForm] := OutputForm[format[a]];
  hh /: Format[hh[a_], InputForm] := OutputForm[
    StringReplace[ToString[a], {"[" -> "", "]" -> "", "," -> ""}]];

  eq2 = eqlist /. Join[(# -> hh[#]) & /@ var, {a_?NumericQ :> gg[a]}];

  removewhite[x_String] := StringReplace[x, Whitespace -> ""];
  (*write equations*)

  text = Fold[# <> removewhite[ToString[#2, InputForm]] <> ";\n" &,
    "{", eq2];
  text = text <> "}";
  WriteString[OpenWrite[file],text];
  Close[file];
  text
  ]

ToString uses Format to decide how to convert expressions to strings. What I'm doing here is wrapping any occurrences of elements in var with hh and any numbers with gg and using TagSet to tell Format how to deal with expressions of the form gg[...] or hh[...].

Example

WriteInput1["sys1.txt", {x[1, 1], x[2, 1], x[1, 2]},
    {3.998723445*10^6 x[1, 1]^2, x[2, 1]^2, x[1, 2]^2}]

(* ==> {3.998723445*10^(6)*x11^2;
       x21^2;
       x12^2;
       }
*)

WriteInput["sys1.txt", {x[1, 1], x[2, 1], x[1, 2]}, 
    {3.0 x[1, 1]^2, x[2, 1]^2, x[1, 2]^2}]

(* => {3.0*x11^2;
      x21^2;
      x12^2;
      }
*)
share|improve this answer
add comment

You could also use regular expressions to do the string formatting. This would just mean you'd have to modify the function removebracketvar in your code by this:

removebracketvar[x_] := Fold[
  StringReplace[#1, #2] &,
  ToString[x // FortranForm],
  {
   RegularExpression["\\.([^0-9])"] -> "$1",
   RegularExpression["e([0-9]+)"] -> "*10^($1)",
   RegularExpression["\\(\\s*(([0-9]+\\,\\s*)+[0-9]+)\\s*\\)"] :> 
    StringReplace["$1", "," -> ""],
   "**" -> "^"
   }]

Here, I first convert the input to FortranForm because it's a nice simple notation that is amenable to regular expressions. Then I do a sequence of string replacements: In the first and second steps, I replace trailing dots and exponential notation. The third regular expression extracts the indices from the variable, and the last rule rewrites the power notation.

To call this function you should not convert the argument to string, so it would be written as

removebracketvar[eqlist[[i]]]

For more on regular expressions, see these somewhat related posts:

Edit

Since there appears to have been some difficulty trying out the code, I'll add the whole function from the original question, modified under the assumption that you have already defined the above removebracketvar:

WriteInput[fname_, var_, eqlist_] := 
 Module[{str, leq}, str = OpenWrite[fname];
  leq = Length[eqlist];
  WriteString[str, "{"];
  (*write equations*)
  Do[WriteString[str, removebracketvar[eqlist[[i]]]];
   WriteString[str, ";\n"], {i, leq}];
  WriteString[str, "}"];
  Close[str]]

I tried it for example with

WriteInput["sys1.txt", {x[1, 1], x[2, 1], x[1, 2]}, {3.0 x[1, 1]^2, 
  x[2, 1]^2, x[1, 2]^2}]

and get the expected output

{3*x11^2;
x21^2;
x12^2;
}

I might as well add some explanations for the regular expressions appearing in the repeated application of StringReplace (repeated because of the Fold statement) above:

RegularExpression["\\.([^0-9])"] -> "$1"

This looks for the decimal point (\\.) followed by anything that is not a digit: digits are [0-9], and non-digits are [^0-9]. The latter is enclosed in ( ) to group it in order to be able to refer to it later. This is done in the last part, -> "$1", where $1 stands for the group we just defined. The replacement -> therefore reproduces the non-digit that was found after a trailing decimal point, but not the decimal point itself.

With all these words of explanation, it's no wonder that regular expressions are so popular... they save so much typing. That's why I won't attempt to write another huge explanation for the other regular expressions above. Suffice it to say that I'm again grouping things I want to keep for later, and also use the + sign to indicate when a pattern that precedes it must occur at least once. Then there's the \\s and *, but you should read the links I already posted to find out what they do...

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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