5
$\begingroup$

The line of code

-E^(-I k) x /. {-x -> -x, -E^(-I k) x -> -E^(I k) x}

is not properly replacing the exponential of (-I k) with the exponential of (I k), as it should. The trivial replacement -x -> -x (which is not performed anyway) seems to be breaking the second replacement - if I exchange the order of the replacements, I get the correct answer. Can anyone help?

I tried FullForm on the expression -E^(-I k) x, and it gives

Times[-1, Power[E, Times[Complex[0, -1], k]], x].

Edit: This issue has nothing to do with complex numbers - the exact same problem occurs if you remove all of the I's. The first replacement is being performed, but the second one should be as well, because it does not apply to either the previous part that was replaced or to a subpart. For example, the line

x Exp[y] /. {x -> a, x Exp[y] -> b}

correctly evaluates to b. I believe that the fact that the second replacement is not being performed is a bug in Mathematica.

$\endgroup$
  • 2
    $\begingroup$ A look at the FullForm[] of the expression you're trying to change will prove illuminating. $\endgroup$ – J. M. will be back soon Jul 14 '15 at 21:26
  • 1
    $\begingroup$ Also note the Details section in ref/ReplaceAll: "The first rule that applies to a particular part is used; no further rules are tried on that part, or on any of its subparts. " $\endgroup$ – Stefan R Jul 14 '15 at 21:35
  • $\begingroup$ Take a look at this answer that deals with possible difficulties in writing replacement rules including the imaginary unit I. I think that should also clarify what @Guesswho was hinting at. $\endgroup$ – MarcoB Jul 14 '15 at 22:43
  • $\begingroup$ possible duplicate of Mathematica does not replace \‌[ImaginaryI] inside Hold $\endgroup$ – MarcoB Jul 14 '15 at 22:44
  • $\begingroup$ Related: (18060). And I think these Q&A's would be useful to read, even if they do not directly apply here: (22948), (25538), (57361), $\endgroup$ – Mr.Wizard Jul 15 '15 at 6:46
8
$\begingroup$

I think this may be what ilian is driving at, but I couldn't be sure in first answer. I thought that some elaboration would be helpful in any case. The behavior of flat and orderless functions in patterns is explained in tutorial/FlatAndOrderlessFunctions. While Orderless is significant here, I think it is the attribute Flat that one needs pay particular attention to.

Consider these examples:

2 x y /. {2 x -> a, 2 x y -> b}
(*  a y  *)

2 x y /. {x -> a, 2 x y -> b}
(*  b  *)

When we look at the FullForm, it is important to pay attention not just to 2 x y, but to the patterns that are potential matches, 2 x, 2 x y and x.

ReplaceAll[
 Times[2, x, y], 
 List[
  Rule[Times[2, x], a],
  Rule[Times[2, x, y], b]]]

ReplaceAll[
 Times[2, x, y],
 List[
  Rule[x, a],
  Rule[Times[2, x, y], b]]]

In the first case, there are four five possible expressions to match: Times[2, x, y] (first), then the part Times (the Head or part 0), and then parts 1 through 3, that is 2, x, y in any order. Because Times is Flat, the pattern Times[2, x] can be applied to the first one, Times[2, x, y], matching the subexpression as if the whole were (2 x) y. From the tutorial:

However, if you have a flat function, it is sometimes possible to apply transformation rules even though not all the arguments are covered.

In[13]:= a + b + c /. a + c -> p  

Out[13]= b + p

But since Times[2, x, y] was the whole expression, there is nothing left to apply the rules to. Note this explains why y is not replaced in this case, too:

2 x y /. {2 x -> a, y -> b}
(*  a y  *)

In the second example above, again a rule may be applied to Times[2, x, y], this time 2 x y -> b. Again ReplaceAll stops after this for the same reason.

Finally, both rules are applied below in

2 x y /. {x -> a, y -> b}
(*  2 a b  *)

because nothing can be applied to Times[2, x, y], but x -> a and y -> b can each be applied to one of the parts of the expression.

Update - I lost my Head (see above, too)

Examples related to the head of the expression, Times:

2 x y /. {Times -> List, 2 x -> a}   (* the whole transformed, part Times not replaced *)
(*  a y  *)

2 x y /. {Times -> List, x -> a}     (* Head and subpart transformed *)
(*  {2, a, y}  *)
$\endgroup$
  • $\begingroup$ This is a very helpful explanation! So if I understand correctly, by simply looking at your two example commands, we could not predict which of the two replacements Mathematica would choose to perform: it depends on whether or not each specific command is one of the (vaguely defined) cases where "it is sometimes possible" to treat one of the smaller substitutions as acting on the larger expression. Correct? $\endgroup$ – tparker Jul 15 '15 at 5:37
  • $\begingroup$ But here's another weird thing: if you run "ReplaceList" on your two examples rather than "ReplaceAll", both examples give that the only possible replacement is replacing the entire expression by b. For your first example, why is Mathematica choosing to perform a replacement that isn't even on the list of possible replacements given by ReplaceList? $\endgroup$ – tparker Jul 15 '15 at 5:45
  • 1
    $\begingroup$ @tparker (1) Sometimes principles aren't stated with perfect clarity and precision but might still be inferred (often only with experience). In this case, one has to come to understanding of how functions (e.g. Times) that are Flat and Orderless are used in pattern-matching. First replacement is tried on the whole, and there are several ways a pattern might match, Times[2,x,y], Times[Times[2,x],y], Times[Times[2,y],x] and Times[Times[x,y],2] (up to reordering). If one understands that (& maybe I'm not clear enough yet), I think one can predict which replacement will be applied... $\endgroup$ – Michael E2 Jul 15 '15 at 18:46
  • 1
    $\begingroup$ ...One tricky bit of wording that is not made clear in the docs is when a replacement can be "applied" and when a pattern "matches." These are not the same. When ReplaceAll tries to apply a replacement, it goes through all ways of arranging a flat, orderless function. It will replace a subpart that is created by rearranging, so to speak. I'm intentionally hedging because 2*x is not a subpart of 2*x*y. So when ReplaceAll replaces 2*x by a, it has applied a rule to the whole expression, even though it did not match the whole expression... $\endgroup$ – Michael E2 Jul 15 '15 at 18:55
  • 2
    $\begingroup$ @tparker (2) ReplaceList (seems to) only make replacements that match the whole expression. This distinction does not seem very clear in docs, although perhaps it is explained somewhere. Replace works the same way. $\endgroup$ – Michael E2 Jul 15 '15 at 18:58
11
$\begingroup$

Note that Times has the Flat and Orderless attributes, so the first replacement actually is performed.

Both of the following ReplaceAll results are correct:

-E^-y x /. {Times[-1, x] -> -x, -E^-y x -> -E^y x}
(* -E^-y x *)

where the whole expression is considered to match the first rule because of the Flat attribute, and the second rule is not applied similarly to this example

 SetAttributes[f, Flat];
 f[a, b, c] /. {f[a, b] -> x, f[a, b, c] -> y}
 (* f[x, c] *)

However, if the order is switched,

-E^-y x /. {-E^-y x -> -E^y x, Times[-1, x] -> -x}
(* -E^y x *)

where the whole expression is transformed by the first rule, similarly to

 f[a, b, c] /. {f[a, b, c] -> y, f[a, b] -> x}
 (* y *) 
$\endgroup$
  • $\begingroup$ I agree with you that the "the second rule does not apply to the second part" E^(-y). But it does apply to the entire expression as a whole, which is higher up in the FullForm[] tree. Once a part has had a rule performed on it, no further rules can be performed on that part or on a subpart. But further rules can be performed on "superparts" - parts that are higher up in the tree - so your answer doesn't explain why the second rule isn't performed on the entire expression after the first rule is performed. $\endgroup$ – tparker Jul 15 '15 at 5:53
  • $\begingroup$ Third time is the charm (?) $\endgroup$ – ilian Jul 15 '15 at 6:22
  • $\begingroup$ Okay, now I understand. The part I was missing was that Times's attribute Flat means that the first rule actually applies to the entire expression, not just the part Times[-1, x]. I still have the same two questions below Michael E2's answer: (1) Do Flat functions always treat rules that apply to more than one of, but not all of, their arguments as transforming the entire function, or only "sometimes", as the tutorial says? (2) In his first example, why doesn't ReplaceList say that the first rule can apply to the whole expression? $\endgroup$ – tparker Jul 15 '15 at 8:00
3
$\begingroup$

The other answers have addressed the question well, but I'd like to try to illustrate one of the confusing points.

Suppose we have the replacement operation

x y z /. {x -> a, x y -> b, x y z -> c}

Without a detailed understanding of the pattern matcher, it may be difficult to guess which rule will be applied. Knowing that the rules are applied in order, one might guess that the first rule will be applied, or knowing that the entire expression is considered first, followed by the subexpressions, one might guess that the last rule will be applied. In fact, the result is

b z

meaning that the second rule is applied.

We can print out the order that subexpressions are considered with

x y z /. {x_?Print -> Null};

x y z

Times

x

y

z

So the whole expression is considered first, followed by the head and then the arguments in order. But in our original replacement rules, the second and third patterns have head Times, which has attributes Flat and Orderless. So when the entire expression, which has head Times, is considered, the pattern matcher tries various permutations of the arguments. What order are the permutations tried in? We can see this for our original rules with

x y z /. {
   x_Symbol /; Print[x] -> Null,
   x_Symbol y_Symbol /; Print[x, y] -> Null,
   x_Symbol y_Symbol z_Symbol /; Print[x, y, z] -> Null
  };

xy

yx

xz

zx

yz

zy

xyz

xzy

yxz

yzx

zxy

zyx

Times

x

y

z

First the entire expression is considered, and the rules are tried in order. The pattern from the first rule doesn't have head Times, so it doesn't match. The pattern from the second rule has head Times and two arguments (with head Symbol) so all combinations of two arguments from the expression are tried. Then the third rule is tried, which has three arguments, so all combinations of three arguments are tried. Then the matcher moves on to the subexpressions, which match the first rule.

Incidentally, we can get the rule x -> a to match in the first step, when the entire expression is considered, by giving it the head Times, like so:

x y z /. {HoldPattern@Times[x] -> a, x y -> b, x y z -> c}

(* a y z *)

Now it takes precedence over the second rule.

$\endgroup$
2
$\begingroup$

Some insight can be obtained by using Trace.

Trace[-E^(-I k) x /. {-x -> -x, -E^(-I k) x -> -E^(I k) x}]//InputForm

The final few lines of the resulting lengthy expression are

(* HoldForm[-(x/E^(I*k)) /. {-x -> -x, -(x/E^(I*k)) -> -(E^(I*k)*x)}], 
   HoldForm[-x/E^(I*k)], HoldForm[-x/E^(I*k)], HoldForm[-(x/E^(I*k))] *)

We see that the first rule, -x -> -x. converts HoldForm[-(x/E^(I*k)) into HoldForm[-x/E^(I*k)], which is not the same as the second rule, -(x/E^(I*k)) -> -(E^(I*k)*x), so the second rule has no effect.

Consider, next, the same expression with the two rules reversed in order.

Trace[-E^(-I k) x /. {-E^(-I k) x -> -E^(I k) x, -x -> -x}]//InputForm

Again, focus on the final few lines of output.

(* HoldForm[-(x/E^(I*k)) /. {-(x/E^(I*k)) -> -(E^(I*k)*x), -x -> -x}], 
   HoldForm[-(E^(I*k)*x)] *)

Here, the first rule, -(x/E^(I*k)) -> -(E^(I*k)*x) matches and converts HoldForm[-(x/E^(I*k)) into HoldForm[-(E^(I*k)*x)]. The second rule has no effect.

$\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.