4

I'm having a little trouble with substituting functions into an expression. A minimal example is as follows:

diffy := D[U[z], z];
Unevaluated[diffy]/. U[z] :> Exp[-I*k*z]
    Derivative[1][U][z]

Instead I want to do this:

Unevaluated[D[U[z], z]] /. U[z] :> Exp[-I*k*z]
    -I E^(-I k z) k

but obviously I can't do the latter because my practical "diffy" expression is a result of many steps and consists of many lines of functions and derivatives of U[z].

Is there a way Mathematica can take a function, substitute it into an expression such as "diffy" and evaluate it? I tried enclosing my expression above in "Evaluate[]" but that did not work.

Update: The solution provided works for the above prototype, but when I add another level, it all breaks down. This is a minimum example:

U0 := U[z];
diffy1 := Hold[D[U0, z]];
diffy1 /. U[z] :> Exp[-I*k*z] // ReleaseHold
    Derivative[1][U][z]

I have tried holding the first expression, releasing the hold in the definition of the second one and then holding again - and many other combinations of holding/releasing but nothing has worked so far. Is there a fundamental reason why this is not working? Maybe I'm not thinking of Mathematica correctly but I don't understand why this does not work immediately.

  • I don't know what is your goal at the end but with this setup you can Block[{U}, U[z_] := Exp[-I*k*z]; diffy] – Kuba Apr 21 '14 at 19:57
  • 1
    Try diffy := Hold[D[U[z], z]]; then use diffy /. U[z] :> Exp[-I k z] // ReleaseHold. – kale Apr 21 '14 at 20:01
  • Thanks kale! worked perfectly. I'm a little confused about the difference between a delayed set (:=) and the hold command. Are they fundamentally different? – Ismail Hameduddin Apr 21 '14 at 20:04
  • 1
    := will evaluate at the time you reference the variable. Thus it will reevaluate every time you use it. For example: rnd := Random[]; {rnd, rnd, rnd}. Hold keeps the actual pattern unevaluated until you release it. – Justin Kaeser Apr 21 '14 at 20:09

2 Answers2

2

Holding the pattern works:

diffy := Hold[D[U[z], z]]
held = diffy /. U[z] :> Exp[-I*k*z]

Edit for completeness:

held // ReleaseHold
Justin Kaeser
  • 271
  • 1
  • 4
0

Based on your extended example I think you are going to need to change your fundamental approach to this problem, as it becomes too complicated to work out which parts should be evaluated and which should be held. (That is, for a general case.)

For the simpler example I recommend that you read How do I evaluate only one step of an expression? and my self-answer. Using step defined there we may write:

diffy := D[U[z], z];

step[diffy] /. U[z] :> Exp[-I*k*z] // ReleaseHold
-I E^(-I k z) k

(If you prefer you could also write: Unevaluated @@ step[diffy] /. U[z] :> Exp[-I*k*z])

This methodology breaks down however for your referential definition because nowhere is it specified which parts should and should not evaluate:

U0 := U[z];
diffy1 := D[U0, z];
step[diffy1] // FullForm
HoldForm[D[U0, z]]

For this particular example I presume you want only D to not evaluate, so you could Block it:

Block[{D}, diffy1 /. U[z] :> Exp[-I*k*z]]
-I E^(-I k z) k

If you always know which heads (functions) you wish to prevent from evaluating this is a fine method.


Evaluation by Context

Perhaps making only those substitutions described in definitions that exist in the Global` Context will have the effect that you desire. Please consider:

SetAttributes[evaluateGlobal, HoldFirst]

evaluateGlobal[expr_, supplemental_: {}] :=
  With[{values = {UpValues, NValues, OwnValues, DownValues, SubValues}},
    With[{rules = Flatten @ Outer[Apply, values, MakeExpression @ Names["Global`*"]]},
      Hold[expr] //. rules /. supplemental // ReleaseHold
    ]
  ]

This function allows either a one parameter input form, which will require manual holding:

U0 := U[z];
diffy1 := D[U0, z];

evaluateGlobal[Hold[diffy1]] /. U[z] :> Exp[-I*k*z] // ReleaseHold
-I E^(-I k z) k

Or a two parameter form to simplify its application for this use:

evaluateGlobal[diffy1, U[z] :> Exp[-I*k*z]]
-I E^(-I k z) k
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • Thanks, this makes sense but can I just tell it to not evaluate anything at all, and then plug in my expressions and then evaluate them? I thought this was what I was already doing. The problem with the "Block" approach is that I have many diverse types of terms in my actual application (imagine all combinations of up to third-order mixed derivatives in three variables) that are not particularly amenable to specifying separately, unless blocking "D" would block all of the D's (even the "double" D's). – Ismail Hameduddin Apr 22 '14 at 19:53
  • @Ismail almost anything is possible so long as there is a clear algorithm to follow. Do I understand that you wish to evaluate (substitute) only your own definitions in the Global` context, while holding everything else as it is? – Mr.Wizard Apr 22 '14 at 20:17
  • Mr. Wizard: I'm not sure what Global precisely means to be honest but I have a multi-step derivation in which I finally end up with an expression with high order mixed derivatives of U with respect to x, y, z. I'm a Mathematica novice and was under the impression that I could just derive everything and then "plug in" U(x,y,z) and let Mathematica do all the derivatives, etc. and "plug" them into the expression. I then realized that I have to "hold" the expression from being evaluated to do this procedure. I thought I was doing exactly this above but it seems I was wrong. What am I missing? – Ismail Hameduddin Apr 22 '14 at 21:09
  • @Ismail Global` is the default context in which user Symbols (and therefore definitions) are created. By using only these definitions only your explicit transformations would be performed. I shall extend my answer to give an example of what I am proposing; please examine its behavior and tell me if it does what you need. – Mr.Wizard Apr 22 '14 at 21:18
  • @Ismail Edit complete. – Mr.Wizard Apr 22 '14 at 21:30
  • Yes it worked! This is magic! :-) Thanks so much! What did you do exactly? – Ismail Hameduddin Apr 22 '14 at 21:39
  • @Ismail I'm glad I could help. My function manually applies all user definitions that exist in the Global` context, by generating their underlying Rules using e.g. DownValues. Before you conclude that this does everything you expect please read about contexts so that you are not surprised. Also, I attempted to write this in a generalized fashion (to allow reuse) but you may want to change it once you understand more; for example you could include multiple user contexts, or exclude UpValues definitions, etc. – Mr.Wizard Apr 22 '14 at 21:49
  • Thanks, Mr. Wizard. I'm going through the tutorials on Mathematica's website (core language, etc.) to understand the language better so I can figure out functions like the one you wrote up. I hope I'll be able to understand them and use Mathematica to it's fullest (or at least up to the point where I can do anything I want on it). – Ismail Hameduddin Apr 24 '14 at 01:11
  • @Ismail I'll be glad to try to answer any questions about my code. Basically, any time you create a definition such as func[foo[x_, y_]] := bar[x] + y that rule is added to an internal table. You can recall that rule with e.g. DownValues[func] which should return: {HoldPattern[func[foo[x_, y_]]] :> bar[x] + y}. This list of rules won't behave exactly like the internal definitions but they are usually equivalent. My function simply finds all such rules for every Global symbol, then applies them with ReplaceAll. (continued) – Mr.Wizard Apr 24 '14 at 05:25
  • If you are not familiar with replacement rules yet that is a good place to start as they are foundational to Mathematica. – Mr.Wizard Apr 24 '14 at 05:25