MathGroup Archive 1995

[Date Index] [Thread Index] [Author Index]

Search the Archive

Mathematica->FrameMaker

  • To: mathgroup at christensen.cybernetics.net
  • Subject: [mg866] Mathematica->FrameMaker
  • From: Dave Wagner <wagner at bullwinkle.cs.Colorado.EDU>
  • Date: Thu, 27 Apr 1995 01:38:33 -0400

By popular demand, here is a notebook that shows the general idea
of how to convert Mathematica expressions into FrameMaker equations.
As you'll see, the format of the two is remarkably similar.
Note the following:

  1.  It's only a beginning.
  2.  There are lots of mumblings and musings to myself scattered throughout.
  3.  I chose a recursive approach.  Given the structural similarity
      between the two formats, a rule-based approach might be easier.
  3.  You have to wrap the output inside a MIF file and then import
      that file into FrameMaker.  Although you could conceivably
      reverse-engineer the format of a MIF file, I highly recommend
      that instead you ftp the MIF reference manual from
      ftp.frame.com.  It's incredibly detailed (over 200 pages)
      and the price is right: free!

Regarding the C program that translates Mathematica notebooks into MIF
files:  it only runs on the Macintosh, certain font information is
hard-coded into it, it has warts, etc..  In other words, it's not fit
for human consumption in its present state.

		Dave Wagner
		Principia Consulting
		(303) 786-8371
		princon at csn.net
		http://www.csn.net/princon

============= Clip here ===========================
(*^
::[	Information =
	"This is a Mathematica Notebook file.  It contains ASCII text, and can be
	transferred by email, ftp, or other text-file transfer utility.  It should
	be read or edited using a copy of Mathematica or MathReader.  If you 
	received this as email, use your mail application or copy/paste to save 
	everything from the line containing (*^ down to the line containing ^*)
	into a plain text file.  On some systems you may have to give the file a 
	name ending with ".ma" to allow Mathematica to recognize it as a Notebook.
	The line below identifies what version of Mathematica created this file,
	but it can be opened using any other version as well.";
	FrontEndVersion = "Macintosh Mathematica Notebook Front End Version 2.2";
	MacintoshStandardFontEncoding; 
	
	fontset = title, inactive, noPageBreakBelow, nohscroll, preserveAspect, groupLikeTitle, center, M7, bold, e8,  24, "Times"; 
	fontset = subtitle, inactive, noPageBreakBelow, nohscroll, preserveAspect, groupLikeTitle, center, M7, bold, e6,  18, "Times"; 
	fontset = subsubtitle, inactive, noPageBreakBelow, nohscroll, preserveAspect, groupLikeTitle, center, M7, italic, e6,  14, "Times"; 
	fontset = section, inactive, noPageBreakBelow, nohscroll, preserveAspect, groupLikeSection, grayBox, M22, bold, a20,  18, "Times"; 
	fontset = subsection, inactive, noPageBreakBelow, nohscroll, preserveAspect, groupLikeSection, blackBox, M19, bold, a15,  14, "Times"; 
	fontset = subsubsection, inactive, noPageBreakBelow, nohscroll, preserveAspect, groupLikeSection, whiteBox, M18, bold, a12,  12, "Times"; 
	fontset = text, inactive, nohscroll, noKeepOnOnePage, preserveAspect, M7,  12, "Times"; 
	fontset = smalltext, inactive, nohscroll, noKeepOnOnePage, preserveAspect, M7,  12, "Courier"; 
	fontset = input, noPageBreakInGroup, nowordwrap, preserveAspect, groupLikeInput, M42, N23, bold, L-5,  12, "Courier"; 
	fontset = output, output, inactive, noPageBreakInGroup, nowordwrap, preserveAspect, groupLikeOutput, M42, N23, L-5,  12, "Courier"; 
	fontset = message, inactive, noPageBreakInGroup, nowordwrap, preserveAspect, groupLikeOutput, M42, N23, R65535, L-5,  12, "Courier"; 
	fontset = print, inactive, noPageBreakInGroup, nowordwrap, preserveAspect, groupLikeOutput, M42, N23, L-5,  12, "Courier"; 
	fontset = info, inactive, noPageBreakInGroup, nowordwrap, preserveAspect, groupLikeOutput, M42, N23, B65535, L-5,  12, "Courier"; 
	fontset = postscript, PostScript, formatAsPostScript, output, inactive, noPageBreakInGroup, nowordwrap, preserveAspect, groupLikeGraphics, M7, l34, w282, h287,  12, "Courier"; 
	fontset = name, inactive, nohscroll, noKeepOnOnePage, preserveAspect, M7, italic, R65535, B65535,  10, "Geneva"; 
	fontset = header, inactive, noKeepOnOnePage, preserveAspect, M7,  12, "Times"; 
	fontset = leftheader, inactive, L2,  12, "Times"; 
	fontset = footer, inactive, noKeepOnOnePage, preserveAspect, center, M7,  12, "Times"; 
	fontset = leftfooter, inactive, L2,  12, "Times"; 
	fontset = help, inactive, nohscroll, noKeepOnOnePage, preserveAspect, M7,  10, "Times"; 
	fontset = clipboard, inactive, nohscroll, noKeepOnOnePage, preserveAspect, M7,  12, "Times"; 
	fontset = completions, inactive, nohscroll, noKeepOnOnePage, preserveAspect, M7,  12, "Times"; 
	fontset = special1, inactive, nohscroll, noKeepOnOnePage, preserveAspect, M7, bold,  18, "Times"; 
	fontset = special2, inactive, nohscroll, noKeepOnOnePage, preserveAspect, M7, bold,  14, "Times"; 
	fontset = special3, inactive, nohscroll, noKeepOnOnePage, preserveAspect, M7, bold,  12, "Times"; 
	fontset = special4, inactive, nohscroll, noKeepOnOnePage, preserveAspect, blackDot, M27,  12, "Times"; 
	fontset = special5, inactive, nohscroll, noKeepOnOnePage, preserveAspect, M27,  12, "Times"; 
	paletteColors = 256; showRuler; automaticGrouping; currentKernel; 
]
:[font = title; inactive; preserveAspect; startGroup]
Mathematica->FrameMaker
Equation Translation
;[s]
2:0,1;11,0;45,-1;
2:1,25,18,Times,1,24,0,0,0;1,25,18,Times,3,24,0,0,0;
:[font = text; inactive; preserveAspect]
Here's a sample expression.
:[font = input; preserveAspect; startGroup]
foo=(-b + Sqrt[b^2-4 a c])/(2 a)
:[font = output; output; inactive; preserveAspect; endGroup]
(-b + (b^2 - 4*a*c)^(1/2))/(2*a)
;[o]
           2
-b + Sqrt[b  - 4 a c]
---------------------
         2 a
:[font = input; preserveAspect; startGroup]
FullForm[foo]
:[font = output; output; inactive; preserveAspect; endGroup]
FullForm[(-b + (b^2 - 4*a*c)^(1/2))/(2*a)]
;[o]
Times[Rational[1, 2], Power[a, -1], 
 
  Plus[Times[-1, b], Power[Plus[Power[b, 2], 
 
     Times[-4, a, c]], Rational[1, 2]]]]
:[font = text; inactive; preserveAspect]
The MIF equivalent is:
:[font = smalltext; inactive; preserveAspect]
<MathFullForm ` equal[char[x],over[plus[minus[char[b]],
pm[sqrt[plus[power[char[b],num[2,"2"]],minus[times[num[4,"4"],
char[a],char[c]]]]]]],times[num[2,"2"],char[a]]]]' >
:[font = text; inactive; preserveAspect]
Note that the negative power must be converted to an "over".  This can be recognized as follows:
:[font = input; preserveAspect; startGroup]
Numerator[foo]
:[font = output; output; inactive; preserveAspect; endGroup]
-b + (b^2 - 4*a*c)^(1/2)
;[o]
           2
-b + Sqrt[b  - 4 a c]
:[font = input; preserveAspect; startGroup]
Denominator[foo]
:[font = output; output; inactive; preserveAspect; endGroup]
2*a
;[o]
2 a
:[font = text; inactive; preserveAspect]
If the denominator is 1, it is not a fraction!
:[font = input; preserveAspect; startGroup]
Numerator[x^2+2x+1]
:[font = output; output; inactive; preserveAspect; endGroup]
1 + 2*x + x^2
;[o]
           2
1 + 2 x + x
:[font = input; preserveAspect; startGroup]
Denominator[x^2+2x+1]
:[font = output; output; inactive; preserveAspect; endGroup]
1
;[o]
1
:[font = text; inactive; preserveAspect]
This is easy!
:[font = text; inactive; preserveAspect]
What about other places where fractions can occur?
:[font = input; preserveAspect; startGroup]
Exp[a/b]
:[font = output; output; inactive; preserveAspect; endGroup]
E^(a/b)
;[o]
 a/b
E
:[font = input; preserveAspect; startGroup]
FullForm[%]
:[font = output; output; inactive; preserveAspect; endGroup]
FullForm[E^(a/b)]
;[o]
Power[E, Times[a, Power[b, -1]]]
:[font = input; preserveAspect; startGroup]
Denominator[%[[2]]]
:[font = output; output; inactive; preserveAspect; endGroup]
b
;[o]
b
:[font = text; inactive; preserveAspect]
So, the application of this test must be recursive.  Be careful not to get into an infinite recursion! It will probably be necessary to use a helper function.
:[font = input; preserveAspect; startGroup]
cfrac = Nest[1/(1+#)&, a, 4]
:[font = output; output; inactive; preserveAspect; endGroup]
(1 + (1 + (1 + (1 + a)^(-1))^(-1))^(-1))^(-1)
;[o]
        1
-----------------
          1
1 + -------------
            1
    1 + ---------
              1
        1 + -----
            1 + a
:[font = input; preserveAspect; startGroup]
FullForm[cfrac]
:[font = output; output; inactive; preserveAspect; endGroup]
FullForm[(1 + (1 + (1 + (1 + a)^(-1))^(-1))^(-1))^(-1)]
;[o]
Power[Plus[1, Power[Plus[1, 
 
     Power[Plus[1, Power[Plus[1, a], -1]], -1]], -1]], -1]
:[font = input; preserveAspect; startGroup]
Denominator[cfrac]
:[font = output; output; inactive; preserveAspect; endGroup]
1 + (1 + (1 + (1 + a)^(-1))^(-1))^(-1)
;[o]
          1
1 + -------------
            1
    1 + ---------
              1
        1 + -----
            1 + a
:[font = input; preserveAspect; startGroup]
Denominator[%]
:[font = output; output; inactive; preserveAspect; endGroup]
1
;[o]
1
:[font = text; inactive; preserveAspect]
So it looks like it's never the case that Denominator can return a non-1 value twice in a row.
:[font = text; inactive; preserveAspect]
Here's a sketch of how to proceed:
:[font = input; preserveAspect]
Clear[parse]
parse[x_] /; Denominator[x]=!=1 :=
	over[parse[Numerator[x]], parse[Denominator[x]]]
:[font = input; preserveAspect; startGroup]
parse[1/2]
:[font = output; output; inactive; preserveAspect; endGroup]
over[parse[1], parse[2]]
;[o]
over[parse[1], parse[2]]
:[font = input; preserveAspect; startGroup]
parse[cfrac]
:[font = output; output; inactive; preserveAspect; endGroup]
over[parse[1], parse[1 + 
 
    (1 + (1 + (1 + a)^(-1))^(-1))^(-1)]]
;[o]
                               1
over[parse[1], parse[1 + -------------]]
                                 1
                         1 + ---------
                                   1
                             1 + -----
                                 1 + a
:[font = input; preserveAspect; startGroup]
Clear[parse]
parse[x_] /; Denominator[x]=!=1 :=
	over[parse[Numerator[x]], parse[Denominator[x]]]
parse[x_+y_] := plus[parse[x],parse[y]]
:[font = message; inactive; preserveAspect; endGroup]
General::spell1: 
   Possible spelling error: new symbol name "plus"
     is similar to existing symbol "Plus".
:[font = input; preserveAspect; startGroup]
??parse
:[font = print; inactive; preserveAspect; endGroup]
Global`parse
parse[x_] /; Denominator[x] =!= 1 := 
  over[parse[Numerator[x]], parse[Denominator[x]]]
 
parse[(x_) + (y_)] := plus[parse[x], parse[y]]
:[font = input; preserveAspect; startGroup]
parse[(a+b)/(c+d)]
:[font = output; output; inactive; preserveAspect; endGroup]
over[plus[parse[a], parse[b]], plus[parse[c], parse[d]]]
;[o]
over[plus[parse[a], parse[b]], plus[parse[c], parse[d]]]
:[font = input; preserveAspect; startGroup]
parse[cfrac]
:[font = output; output; inactive; preserveAspect; endGroup]
over[parse[1], add[parse[1], 
 
   over[parse[1], add[parse[1], 
 
     over[parse[1], add[parse[1], 
 
       over[parse[1], add[parse[1], parse[a]]]]]]]]]
;[o]
over[parse[1], add[parse[1], 
 
   over[parse[1], add[parse[1], 
 
     over[parse[1], add[parse[1], 
 
       over[parse[1], add[parse[1], parse[a]]]]]]]]]
:[font = text; inactive; preserveAspect]
Note that this only works if the denominator-checking rule is the very first rule!  It appears that recursion won't be a problem, but have to think about this.
:[font = input; preserveAspect; startGroup]
FullForm[a-b]
:[font = output; output; inactive; preserveAspect; endGroup]
FullForm[a - b]
;[o]
Plus[a, Times[-1, b]]
:[font = input; preserveAspect; startGroup]
% /. Times[-1,x_] -> minus[x]
:[font = output; output; inactive; preserveAspect; endGroup]
a + minus[b]
;[o]
a + minus[b]
:[font = input; preserveAspect]
parse[Times[-1,x_]] := minus[parse[x]]
:[font = input; preserveAspect; startGroup]
parse[(a-b)/c]
:[font = output; output; inactive; preserveAspect; endGroup]
over[plus[parse[a], minus[parse[b]]], parse[c]]
;[o]
over[plus[parse[a], minus[parse[b]]], parse[c]]
:[font = text; inactive; preserveAspect]
Parsing symbols is tricky, because in general they are more than one character long.  It would be safest to parse them into "string"s rather than "char"s.
:[font = input; preserveAspect; startGroup]
StringByteCount["bar"]
:[font = output; output; inactive; preserveAspect; endGroup]
3
;[o]
3
:[font = input; preserveAspect; startGroup]
StringByteCount[ToString[bar]]
:[font = output; output; inactive; preserveAspect; endGroup]
3
;[o]
3
:[font = text; inactive; preserveAspect]
This fails miserably is the thing passed to it is not a symbol!
:[font = input; preserveAspect; startGroup]
StringByteCount[ToString[foo]]
:[font = output; output; inactive; preserveAspect; endGroup]
69
;[o]
69
:[font = text; inactive; preserveAspect]
Here's how to embed a double-quote inside a FrameMath string:
:[font = input; preserveAspect; startGroup]
"he\"\"llo"
:[font = output; output; inactive; preserveAspect; endGroup]
"he\"\"llo"
;[o]
he""llo
:[font = input; preserveAspect; startGroup]
parse[foo]
:[font = output; output; inactive; preserveAspect; endGroup]
over[plus[minus[parse[b]], parse[(b^2 - 4*a*c)^(1/2)]], 
 
  parse[2*a]]
;[o]
                                       2
over[plus[minus[parse[b]], parse[Sqrt[b  - 4 a c]]], 
 
  parse[2 a]]
:[font = input; preserveAspect; startGroup]
parse[Power[a_,b_]] := power[parse[a],parse[b]]
:[font = message; inactive; preserveAspect; endGroup]
General::spell1: 
   Possible spelling error: new symbol name "power"
     is similar to existing symbol "Power".
:[font = input; preserveAspect; startGroup]
parse[foo]
:[font = output; output; inactive; preserveAspect; endGroup]
over[plus[minus[parse[b]], 
 
   power[plus[power[parse[b], parse[2]], parse[-4*a*c]], 
 
    over[parse[1], parse[2]]]], parse[2*a]]
;[o]
over[plus[minus[parse[b]], 
 
   power[plus[power[parse[b], parse[2]], parse[-4 a c]], 
 
    over[parse[1], parse[2]]]], parse[2 a]]
:[font = input; preserveAspect]
Clear[parse]
parse[Plus[x_, y__]] := Map[parse, plus[x,y]]
:[font = input; preserveAspect; startGroup]
parse[a+b+c]
:[font = output; output; inactive; preserveAspect; endGroup]
plus[parse[a], parse[b], parse[c]]
;[o]
plus[parse[a], parse[b], parse[c]]
:[font = input; preserveAspect]
Clear[parse]
parse[x_] /; Denominator[x]=!=1 :=
	over[parse[Numerator[x]], parse[Denominator[x]]]
parse[Plus[x_, y__]] := Map[parse, plus[x,y]]
parse[Times[-1, x_]] := minus[parse[x]]
parse[Times[n_?Negative, x__]] := minus[parse[Times[-n,x]]]
parse[Times[x_, y__]] := Map[parse, times[x,y]]
parse[Sqrt[x_]] := sqrt[parse[x]]
parse[Power[a_, b_]] := power[parse[a], parse[b]]
parse[x_Symbol] /; StringByteCount[ToString[x]]===1 :=
	char[x]
parse[x_Symbol] := string[InputForm[ToString[x]]]
parse[n_?NumberQ] := num[FullForm[n],InputForm[ToString[n]]]
:[font = input; preserveAspect; startGroup]
parse[foo]
:[font = output; output; inactive; preserveAspect; endGroup]
over[plus[minus[char[b]], 
 
   sqrt[plus[power[char[b], num[2, InputForm["2"]]], 
 
     minus[times[num[4, InputForm["4"]], char[a], char[c]]]]
 
     ]], times[num[2, InputForm["2"]], char[a]]]
;[o]
over[plus[minus[char[b]], 
 
   sqrt[plus[power[char[b], num[2, "2"]], 
 
     minus[times[num[4, "4"], char[a], char[c]]]]]], 
 
  times[num[2, "2"], char[a]]]
:[font = text; inactive; preserveAspect]
Compare to the real thing:
:[font = smalltext; inactive; preserveAspect]
over[plus[minus[char[b]],
pm[sqrt[plus[power[char[b],num[2,"2"]],minus[times[num[4,"4"],
char[a],char[c]]]]]]],times[num[2,"2"],char[a]]]
:[font = input; preserveAspect; startGroup]
parse[-b + Sqrt[glarble^2- 4 scoomb c]/(2 scoomb)]
:[font = output; output; inactive; preserveAspect; endGroup]
plus[minus[char[b]], over[sqrt[plus[power[string[InputForm["glarbl\
 
         e"]], num[FullForm[2], InputForm["2"]]], 
 
     minus[times[num[FullForm[4], InputForm["4"]], char[c], 
 
       string[InputForm["scoomb"]]]]]], 
 
   times[num[FullForm[2], InputForm["2"]], 
 
    string[InputForm["scoomb"]]]]]
;[o]
plus[minus[char[b]], over[sqrt[plus[power[string["glarble"], 
 
      num[2, "2"]], minus[times[num[4, "4"], char[c], 
 
       string["scoomb"]]]]], times[num[2, "2"], string["scoomb"]]]]
:[font = input; preserveAspect; startGroup]
parse[Pi]
:[font = output; output; inactive; preserveAspect; endGroup]
string[InputForm["Pi"]]
;[o]
string["Pi"]
:[font = input; preserveAspect; startGroup]
parse[N[Pi]]
:[font = output; output; inactive; preserveAspect; endGroup]
num[FullForm[3.141592653589793238], InputForm["3.14159"]]
;[o]
num[3.141592653589793238, "3.14159"]
:[font = input; preserveAspect; startGroup]
FullForm[%]
:[font = output; output; inactive; preserveAspect; endGroup; endGroup]
FullForm[num[3.141592653589793238, InputForm["3.14159"]]]
;[o]
num[3.141592653589793238, InputForm["3.14159"]]
^*)


  • Prev by Date: MMA to BTM & Vice-Versa
  • Next by Date: mesh lines
  • Previous by thread: MMA to BTM & Vice-Versa
  • Next by thread: mesh lines