10

If I type e1 := 3 x + 2 (1 + y) z // TreeForm, I get an expression tree. If I then type e1 /. x -> 3, I get another prefectly correct expression tree.

Is there a way that I can get TreeForm's formatting to keep the nodes in the same location after the transformation?

Artes
  • 57,212
  • 12
  • 157
  • 245
SixWingedSeraph
  • 627
  • 3
  • 10

4 Answers4

7

The simplest way to do what you'd like to do seems to be this:

e1 /. x -> "3"

enter image description here

Head["3"]
String 

Replacing x by a string "3" prevents evaluating a part of the expression including Times[3, x].

A bit more tricky way yielding the same result would be this:

e1 /. x -> String["3"][[1]]
Artes
  • 57,212
  • 12
  • 157
  • 245
6

I liked a response that got deleted. If all you want is the cosmetic look, and do not care if the expression is actually altered, here is something I use to make expressions "inert". The idea is to replace numeric functions with their string names.

inertify[expr_Hold] := 
 Module[{xx}, 
  xx[Release[
     expr /. f_Symbol /; MemberQ[Attributes[f], NumericFunction] :> 
       ToString[f]]] /. xx -> Hold]

Here is the example.

e1 := 3 x + 2 (1 + y) z

In[227]:= e2 = inertify[Hold[Evaluate[e1]]]

Out[227]= Hold["Plus"["Times"[3, x], "Times"[2, "Plus"[1, y], z]]]

In[228]:= TreeForm[First@e2 /. x -> 3]

enter image description here

Daniel Lichtblau
  • 58,970
  • 2
  • 101
  • 199
  • 2
    I had to look up Release on the documentation. Old habits die hard? – Michael Wijaya Jun 07 '12 at 21:12
  • I liked the response too ;-) but since the question was to get exactly the same structure I deleted it. I tried first something else with Unevaluated and didn't understand why this did not work. It seems Rojo has the answer. – halirutan Jun 08 '12 at 04:08
  • @halirutan I gave Rojo's an upvote. I would have for yours as well, were it not deleted. Unevaluated is a tricky beast, because one does not have control over when those might get stripped in internal code. As for "exactly" the same structure, yours came quite close and the question left unstated whether renaming, or an extra "wrapper" level, might be acceptable. (Absent such guidance, the appropriate assumption is perhaps that neither is acceptable. But it seems sensible to offer possibilities slightly outside the scope of specification in such cases.) – Daniel Lichtblau Jun 08 '12 at 14:52
6

Seems TreeForm leaks evaluation when formatting, but wrapping an extra Unevaluated seems to solve it. So

e1 := 3 x + 2 (1 + y) z // Unevaluated // Unevaluated // TreeForm

Now it all seems to work

Rojo
  • 42,601
  • 7
  • 96
  • 188
  • Nice one... +1. – halirutan Jun 08 '12 at 04:10
  • That looks familiar. :^) – Mr.Wizard Jun 08 '12 at 08:03
  • The various solutions are helpful, but what I want is for "TreeForm's formatting to keep the nodes in the same location after the transformation". In other words, the leftmost "Times" would be replaced by "3" but all the nodes would be in the same location. (What I really want is also to delete the left two leaves which now contain "3", so that the tree undergoes a one-step evaluation after 3 is substituted to x but with the nodes that are left (i.e. all the nodes except the left two leaves) in the same place on the screen. But I did not ask for that.) – SixWingedSeraph Jun 08 '12 at 16:02
  • In the previous comment I should have said "The leftmost Times should have been changed to 9. – SixWingedSeraph Jun 09 '12 at 02:22
4

Does this work for you:

Unprotect@TreeForm
SetAttributes[TreeForm, HoldFirst]
TreeForm[e1 /. x -> 3]

Mathematica graphics

It has a superfluous TreeForm at the root ... maybe there is a way to remove that?

image_doctor
  • 10,234
  • 23
  • 40