8
$\begingroup$

How do I get Mathematica to produce TeX output that does not omit the multiplication signs?

For example, this expression:

(z03*z14*z32 + z01*z12*z43 + z14*(z01 + z03 + z12 + z32)*z43)

displays in Mathematica as:

(z14 z43 (z01+z03+z12+z32)+z01 z12 z43+z03 z14 z32)

And the output of TeXForm looks like this:

(z14 z43 (z01 + z03 + z12 + z32) + z01 z12 z43 + z03 z14 z32) // TeXForm

$ \text{z14} \text{z43} (\text{z01}+\text{z03}+\text{z12}+\text{z32})+\text{z01} \text{z12} \text{z43}+\text{z03} \text{z14} \text{z32}$

which is really hard to read because the spaces get ignored.

How do I get TeXForm to produce this instead?: $$ \text{z14}\times\text{z43}\times(\text{z01}+\text{z03}+\text{z12}+\text{z32})+\text{z01}\times\text{z12}\times\text{z43}+\text{z03}\times\text{z14}\times\text{z32} $$

Even better would be:

$$ \text{z14}.\text{z43}.(\text{z01}+\text{z03}+\text{z12}+\text{z32})+\text{z01}.\text{z12}.\text{z43}+\text{z03}.\text{z14}.\text{z32} $$

Worse come to worse, I could even settle for something like this: $$ \text{z14}\;\text{z43}\;(\text{z01}+\text{z03}+\text{z12}+\text{z32})+\text{z01}\;\text{z12}\;\text{z43}+\text{z03}\;\text{z14}\;\text{z32} $$

$\endgroup$
  • $\begingroup$ Use a string and \[Times] instead of * for multiplication? $\endgroup$ – rm -rf Dec 19 '13 at 4:10
8
$\begingroup$

Here is a very robust (!!) method

expr = (z14 z43 (z01 + z03 + z12 + z32) + z01 z12 z43 + z03 z14 z32);
StringReplace[ToString[expr, TeXForm], " " :> "\\times"]

Using Ctrl+Shift+C to copy as plain text results in

$$\text{z14}\times\text{z43}\times(\text{z01}+\text{z03}+\text{z12}+\text{z32})+\text{z01}\times\text{z12}\times\text{z43}+\text{z03}\times\text{z14}\times\text{z32}$$

Edit

The above approach might serve you well in the simple setting the OP is representing, in general, this method is very likely to break, because it relies on that a multiplication is converted into a single space in TeXForm.

As questions in our latex tag suggest, there are several problems and subtilities with TeXForm and a general and always working answer can hardly be given at this point without further information.

$\endgroup$
  • $\begingroup$ This works, thanks $\endgroup$ – blondiepassesby Dec 19 '13 at 21:14
  • $\begingroup$ well, now that I am starting to use your trick more, I find that it is not that robust. It works most of the time, but fails when there is a greek letter in the expression: for some reason, Mathematica adds a space after greek letters in the TeXForm output, and that gets caught as a mutltiply by your strignreplace technique. Darn. $\endgroup$ – blondiepassesby Jan 5 '14 at 18:25
  • $\begingroup$ @blondiepassesby I thought you were aware that the italic very robust in my answer was more a warning sign than a statement?! I was really meant ironically, because I was afraid that it might not work in certain cases. $\endgroup$ – halirutan Jan 6 '14 at 0:16
  • $\begingroup$ Hmm. Not entirely sure that irony is that helpful or even encouraged on stackexchange answers, especially the kind that may or may not be picked by readers of your answers. I certainly didn't read it as such and accepted your answer at face value. In future, I'd recommend being as explicit as possible. $\endgroup$ – blondiepassesby Jan 7 '14 at 8:06
  • 1
    $\begingroup$ @blondiepassesby First, I'm sorry that you haven't been able to pick up that it meant use it with caution. I thought it was obvious, that a string-replacement in the final texform will not work in all possible circumstances. You are free to unaccept my answer. But before you recommend something, I want you to recall that everyone answering here is very likely doing it in his free time, just for fun. If you want a general solution, free of irony, you just have to pay money and you'll get a totally serious answer/solution. $\endgroup$ – halirutan Jan 7 '14 at 11:21
5
$\begingroup$

We want cross? Let's use Cross!

expr /. Times -> Cross // TeXForm

$ \text{z14}\times (\text{z01}+\text{z03}+\text{z12}+\text{z32})\times \text{z43}+\text{z01}\times \text{z12}\times \text{z43}+\text{z03}\times \text{z14}\times \text{z32} $

$\endgroup$
  • $\begingroup$ Or, if the OP prefers, 'expr /. Times -> Dot // TeXForm' $\endgroup$ – A.G. Dec 29 '14 at 6:18
3
$\begingroup$

Row appears to work:

expr = (z03*z14*z32 + z01*z12*z43 + z14*(z01 + z03 + z12 + z32)*z43);
expr /. Times :> (Row[{##}, "\[Times]"] &) // TeXForm

Copying as plain text as halirutan did and wrapping in $ symbols:

$\text{z14}\times \text{z01}+\text{z03}+\text{z12}+\text{z32}\times \text{z43}+\text{z01}\times \text{z12}\times \text{z43}+\text{z03}\times \text{z14}\times \text{z32}$


  • Note: This code fails in recent versions due to a bug: Incompatibility of Row and TeXForm.
    kguler discovered that the bug may be circumvented by setting:

    BoxForm`$UseTemplateSlotSequenceForRow = False;
    
$\endgroup$
  • $\begingroup$ Hmm, does this really work for you? Here, I get this output. $\endgroup$ – halirutan Dec 19 '13 at 23:41
  • 1
    $\begingroup$ @halirutan In version 7, yes, it does. I already voted for your answer. (Does a space always represent multiplication in TeX?) $\endgroup$ – Mr.Wizard Dec 20 '13 at 2:21
2
$\begingroup$

TeXForm works by creating TraditionalForm boxes, and then converting those boxes into a TeX string. This means there are two methods to change the TeXForm format of an expression:

  1. Change the TraditionalForm output
  2. Change the conversion code that converts TraditionalForm boxes into TeX.

I like changing the TraditionalForm output instead of changing the conversion code, because boxes don't carry context. There may be multiple expressions that produce similar boxes, and if you try to write conversion code after the expression has been turned into boxes you may be affecting expressions that you don't want to modify. It's a little bit like trying to repair a car after an accident vs preventing the accident in the first place.

So, the first step is to figure out how to change the TraditionalForm of products. Without going into details, this is actually difficult to do, because a variety of different expressions will produce expression that look like space separated terms. So, rather than try to add formatting rules for all of these different expressions, it is much simpler to look for the signature of a product of terms, which is:

RowBox[{a, " ", b, " ", c, ..}]

and then replace all the spaces with the symbol of your choice (in fact, TraditionalForm already does something like this when it tries to reorder products into a more "TraditionalForm" like order).

Therefore, we want to add a TraditionalForm formatting rule that post-processes the TraditionalForm boxes after all other formatting has take place. The way I will implement this is to add a rule that gets fired before any other formatting has occurred. This rule will create the normal TraditionalForm boxes, and then convert any products into "$\times$" separated products. For this purpose, it will be convenient to make use of my Initial wrapper, which I repeat here for convenience:

Initial /: Verbatim[TagSetDelayed][Initial[sym_], lhs_, rhs_] := With[
    {
    new=Block[{sym},
        TagSetDelayed[sym,lhs,rhs];
        First @ Language`ExtendedDefinition[sym]
    ],
    protect=Unprotect[sym]
    },

    sym;
    Quiet@MakeBoxes[sym[],TraditionalForm];

    Unprotect[sym];
    Replace[
        new,
        Rule[values_,n:Except[{}]] :> (
            values[sym] = DeleteDuplicates @ Join[n, values[sym]]
        ),
        {2}
    ];
    Protect@protect;
]

Using the Initial wrapper, the following MakeBoxes rule will fire before all others:

Initial[TraditionalForm] /: MakeBoxes[e_, TraditionalForm] /; TrueQ@$TeX := Block[{$TeX = False},
    ReplaceAll[
        MakeBoxes[e, TraditionalForm],
        RowBox[b_?productQ] :> RuleCondition @ Replace[RowBox[b], " "->"\[Times]", {2}]
    ]
]
productQ[b_] := Length[b]>1 && MatchQ[b[[2 ;; -2 ;; 2]], {" "..}]

Let's see this in action:

$TeX = False;
x+2y //TraditionalForm

enter image description here

Versus:

$TeX = True;
x+2y //TraditionalForm

enter image description here

All that remains is to modify the TeXForm code to block $TeX to True when creating the TraditionalForm boxes. This can again be done using the Initial wrapper:

Initial[Convert`TeX`ExpressionToTeX] /: 
    Convert`TeX`ExpressionToTeX[e__] /; !TrueQ@$TeX := Block[
        {$TeX = True},
        Convert`TeX`ExpressionToTeX[e]
    ]

Let's take a look at an example:

x+2y //TeXForm

$x+2\times y$

Perfect. For your more complicated example:

(z03*z14*z32 + z01*z12*z43 + z14*(z01 + z03 + z12 + z32)*z43) //TeXForm

$\text{z14}\times \text{z43}\times (\text{z01}+\text{z03}+\text{z12}+\text{z32})+\text{z01}\times \text{z12}\times \text{z43}+\text{z03}\times \text{z14}\times \text{z32}$

Here is the above code in one block:

Initial /: Verbatim[TagSetDelayed][Initial[sym_], lhs_, rhs_] := With[
    {
    new=Block[{sym},
        TagSetDelayed[sym,lhs,rhs];
        First @ Language`ExtendedDefinition[sym]
    ],
    protect=Unprotect[sym]
    },

    sym;
    Quiet@MakeBoxes[sym[],TraditionalForm];

    Unprotect[sym];
    Replace[
        new,
        Rule[values_,n:Except[{}]] :> (
            values[sym] = DeleteDuplicates @ Join[n, values[sym]]
        ),
        {2}
    ];
    Protect@protect;
]

Initial[TraditionalForm] /: MakeBoxes[e_, TraditionalForm] /; TrueQ@$TeX := Block[{$TeX = False},
    ReplaceAll[
        MakeBoxes[e, TraditionalForm],
        RowBox[b_?productQ] :> RuleCondition @ Replace[RowBox[b], " "->"\[Times]", {2}]
    ]
]
productQ[b_] := Length[b]>1 && MatchQ[b[[2 ;; -2 ;; 2]], {" "..}]

Initial[Convert`TeX`ExpressionToTeX] /: 
    Convert`TeX`ExpressionToTeX[e__] /; !TrueQ@$TeX := Block[
        {$TeX = True},
        Convert`TeX`ExpressionToTeX[e]
    ]
$\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.