4

In TraditionalForm output, I would like to have Conjugate be always displayed as an overbar, not an asterisk superscript. In particular for complicated expressions like Conjugate[Log[z]], I would like to have a long overbar.

There are various solutions proposed in other threads, including the simplest version:

Unprotect[Conjugate];
Format[Conjugate[x_], TraditionalForm] := OverBar@Pane@x;
Protect[Conjugate];

This gives the desired result, but only the first time I call // TraditionalForm on some output.

How can I ensure that this new format rule is applied throughout the rest of my notebook?

PS: As requested here a full MWE with Mathematica 13.0.1.0.

Quit[];
Unprotect[Conjugate];
Format[Conjugate[x_], TraditionalForm] := OverBar@Pane@x;
Protect[Conjugate];
Conjugate[Log[z]] // TraditionalForm
Conjugate[Log[z]] // TraditionalForm

I obtain the output

$\overline{\log z}$

$(\log z)^*$

J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574
Marco
  • 140
  • 6
  • 1
    The docs indicate that output of the form TraditionalForm[expr] gets special handling, which can be seen by examining the cell expression of the * form: There's no * in it, just a TemplateBox that I assume the FE typesets. (Menu Cell > Show Expression, to see it.) I don't know off hand how to modify it. – Michael E2 May 10 '22 at 17:33

5 Answers5

7

You are encountering two issues.

  1. Conjugate is a symbol which autoloads definitions when it is used or displayed.
  2. The autoloaded definitions use Condition, making it difficult to force your new definition to be favored.

I recommend using my Initial function to solve these issues, 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, "ExcludedContexts" -> {}]
    ],
    protect=Unprotect[sym]
    },
(* Force autoloading of sym *)
sym;
Quiet@MakeBoxes[sym[],TraditionalForm];

(* Autloading can cause a symbol to become protected *)
Unprotect[sym];

(* Insert new values in front *)
Replace[
    new,
    Rule[values_, n_] :> insertValues[n, values, sym],
    {2}
];
Protect@protect;

]

insertValues[n_, v_, sym_] := If[n =!= {}, v[sym] = DeleteDuplicatesBy[ Join[n, v[sym]], equivalenceClass ] ]

equivalenceClass[lhs_ :> rhs_] := If[FreeQ[Hold[rhs], Condition], lhs, lhs :> rhs ]

Then, you can make your new definition with:

Initial[Conjugate] /: Format[Conjugate[x_], TraditionalForm] := OverBar @ Pane @ x

and you should get your desired behavior.

Update

If you really want the argument to be parenthesized (it seems unnecessary to me), then you could do:

Initial[Conjugate] /: MakeBoxes[Conjugate[x_], TraditionalForm] := TemplateBox[
    {Parenthesize[x, TraditionalForm, Power, Left]},
    "Conjugate",
    DisplayFunction -> Function@OverscriptBox[PaneBox@#,"_"]
]
Carl Woll
  • 130,679
  • 6
  • 243
  • 355
  • Thank you, this works great! Is there a way to keep automatic parentheses being added for expressions like Conjugate[Log[z]+Log[x]]. – Marco May 11 '22 at 12:21
2

You can deal with it through stylesheets, which may or may not be convenient for you. You can set up a stylesheet for your notebooks or execute this:

SetOptions[EvaluationNotebook[], 
 StyleDefinitions -> 
  Notebook[{Cell[StyleData[StyleDefinitions -> "Default.nb"]], 
    Cell[StyleData["Conjugate"], 
     TemplateBoxOptions -> {DisplayFunction -> (OverscriptBox[
           PaneBox[#1], 
           StyleBox["_", FontFamily -> "Times", 
            SingleLetterItalics -> False]] &), 
       Tooltip -> Automatic}]}]]

Note the TemplateBoxOptions must be set for the style "Conjugate" for this to work.

Michael E2
  • 235,386
  • 17
  • 334
  • 747
1

So I tracked the difference between TraditionalForm and DisplayForm to use of TemplateBox. Answer of @Michael E2 is really good, however a more minimal override may be written:

Unprotect[TemplateBox];
TemplateBox[x_, "Conjugate", SyntaxForm -> SuperscriptBox] := 
 OverscriptBox[x[[1]], "_"]
Protect[TemplateBox];

I tested on following input:

Conjugate[c] // TraditionalForm
Conjugate[Log[z]] // TraditionalForm
Conjugate[Log[z]] // TraditionalForm

No nasty stars attached.

fqrt
  • 84
  • 2
  • I like that this solution automatically parenthesizes expresssions like Conjugate[Log[x] + Log[z]]. Is there a way to add the Pane object back in to get a more nicely looking output? – Marco May 11 '22 at 12:20
0

This thing is usually done with Format function definition. However Conjugate as a built-in is protected. The code snippet to do that is

Unprotect[Conjugate]
Format[Conjugate[a_],StandardForm]:= OverBar[a]
Protect[Conjugate]

where the last line is optional. Works quite all right.

Result of snippet

fqrt
  • 84
  • 2
  • I can't see the failing example for what you mentioned, could you provide minimal working example when it stops working? – fqrt May 10 '22 at 12:25
  • 1
    Running such a cell twice produces the erroneous $x^*$ output for me, as I stated in the question. See edit of the question to have a complete MWE you can copy-paste. Please note that I care about TraditionalForm not StandardForm. – Marco May 10 '22 at 16:27
0

The final solution I used is a slight modification of @fqrt's answer using a TemplateBox below, but introducing an additional PaneBox:

Unprotect[TemplateBox];
TemplateBox[x_, "Conjugate", SyntaxForm -> SuperscriptBox] := OverscriptBox[PaneBox[x[[1]], ImageMargins -> 1], "_"];
Protect[TemplateBox];
Marco
  • 140
  • 6
  • 2
    You're welcome to do this, of course, but I think it's a very bad idea to give DownValues to TemplateBox. – Carl Woll May 16 '22 at 16:20
  • @CarlWoll Thanks for the feedback, could you elaborate on possible unintended side effects or similar? – Marco May 17 '22 at 21:58