From: Matthias Fripp on
I am having trouble using ReplaceAll to replace symbols that already
have a delayed assignment.

e.g., this input:

In[287]:=
a := A c
b := B c
a /. {a -> x, b -> y}
b /. {a -> x, b -> y}
a + b /. {a -> x, b -> y}
a * b /. {a -> x, b -> y}

gives this output:

Out[289]= x

Out[290]= y

Out[291]= x + y

Out[292]= A B c^2

All of this works as expected except for the final term. I would have
expected to get the result "x y". Is there any way to force
Mathematica to produce that result?

If on the other hand the original assignment is a := A + c and b := B
+ c, I get an unexpected output for the sum, but the expected output
(x y) for the product. If I insert d instead of one of the c's, I get
various other (unpredictable) kinds of result.

My first guess is that Mathematica is doing a sort of "double
ReplaceAll", where it first tries the pattern given in the delayed
assignment, and any symbols matched by that are not tested against the
explicit ReplaceAll. But that doesn't explain why the sum works and
not the product. Am I thinking about this the wrong way?

Thanks for any help you can give!

Matthias Fripp

From: Albert Retey on
Am 24.06.2010 10:27, schrieb Matthias Fripp:
> I am having trouble using ReplaceAll to replace symbols that already
> have a delayed assignment.
>
> e.g., this input:
>
> In[287]:=
> a := A c
> b := B c
> a /. {a -> x, b -> y}
> b /. {a -> x, b -> y}
> a + b /. {a -> x, b -> y}
> a * b /. {a -> x, b -> y}
>
> gives this output:
>
> Out[289]= x
>
> Out[290]= y
>
> Out[291]= x + y
>
> Out[292]= A B c^2
>
> All of this works as expected except for the final term. I would have
> expected to get the result "x y". Is there any way to force
> Mathematica to produce that result?
>
> If on the other hand the original assignment is a := A + c and b := B
> + c, I get an unexpected output for the sum, but the expected output
> (x y) for the product. If I insert d instead of one of the c's, I get
> various other (unpredictable) kinds of result.
>
> My first guess is that Mathematica is doing a sort of "double
> ReplaceAll", where it first tries the pattern given in the delayed
> assignment, and any symbols matched by that are not tested against the
> explicit ReplaceAll. But that doesn't explain why the sum works and
> not the product. Am I thinking about this the wrong way?

No, what actually happens is that a and b are evaluated to A*c and B*c
respectively, even before the ReplaceAll sees them. Then the ReplaceAll
sees

A*c+B*c /. {A*c -> x, B*c -> y}
A*B*c^2 /. {A*c -> x, B*c -> y}

where it will find matches in the first case but not in the second and
so does nothing. There are two things you need to understand: first is
the evaluation order, second is the fact that replacement rules work on
structure, not on mathematical relations. Both are topics that you will
a lot of information in the documentation and in the archive of this
group. I would recommend to search for "evaluation order" and "pattern
matching" in the documentation and read, well as much as you want to
learn...

hth,

albert

From: Bill Rowe on
On 6/24/10 at 4:27 AM, mfripp(a)gmail.com (Matthias Fripp) wrote:

>I am having trouble using ReplaceAll to replace symbols that already
>have a delayed assignment.

>e.g., this input:

>In[287]:=
>a := A c
>b := B c
>a /. {a -> x, b -> y}
>b /. {a -> x, b -> y}
>a + b /. {a -> x, b -> y}
>a * b /. {a -> x, b -> y}

>gives this output:

>Out[289]= x

>Out[290]= y

>Out[291]= x + y

>Out[292]= A B c^2

>All of this works as expected except for the final term. I would
>have expected to get the result "x y". Is there any way to force
>Mathematica to produce that result?

In[10]:= a := A c
b := B c

In[12]:= a*b /. {A -> x/c, B -> y/c}

Out[12]= x y

The reason this needs to be different than the others is due to
the way Mathematica's evaluator works. In everyone of your
examples a,b are replaced by A c and B c when Mathematica
encounters them as expected by using SetDelayed. After the
replacement occurs, then evaluation of the specified operations
on the left hand side of /. occurs. In each case except for the
last, this leaves an expression with in terms of A c and B c.
So, in those cases when a,b on the right hand side get
evaluated, they match something on the left hand side and the
replacement occurs as you want.

But in the last case, the multiplication operation yields the
result (in FullForm) of

Times[A, B, Power[c,2]]

Since nothing in this matches either Times[A, c] or Times[B, c],
the replacement you are looking for does not occur. My work
around does what you want since there is a match for A and B.

>If on the other hand the original assignment is a := A + c and b :=
>B + c, I get an unexpected output for the sum, but the expected
>output (x y) for the product. If I insert d instead of one of the
>c's, I get various other (unpredictable) kinds of result.

This fails for the same reason a * b /. {a -> x, b -> y} failed.
That is, with these assignments,
a + b will evaluate to (in FullForm)

Plus[A, B, Times[2, c]]

Again, there will be nothing to match either A+c or B+c and the
replacement fails.

>My first guess is that Mathematica is doing a sort of "double
>ReplaceAll", where it first tries the pattern given in the delayed
>assignment, and any symbols matched by that are not tested against
>the explicit ReplaceAll. But that doesn't explain why the sum works
>and not the product. Am I thinking about this the wrong way?

Yes, your thinking here is incorrect. Note you can verify what
occurs by using Trace. For example,

In[18]:= a + b /. {a -> x, b -> y} // Trace

Out[18]= {{{a,A+c},{b,B+c},(A+c)+(B+c),A+c+B+c,A+B+c+c,A+B+2
c},{{{a,A+c},A+c->x,A+c->x},{{b,B+c},B+c->y,B+c->y},{A+c->x,B+c->y}},A+B+2=

c/.{A+c->x,B+c->y},A+B+2 c}

Here you can see the evaluation of a+b to A+B+2c occurs before
the replacement rule evaluates as I described above. The
consequence is, there is no match for either A+c or B+c.

A key point about replacement rules is these are implemented as
literal replacements. There is no mathematic operation being by
the replacement rules. Any mathematics is done on the left hand
side before the replacement. Further mathematics may be done
after the replacement depending on the nature of the
replacement. But the replacement itself does not do mathematic operations.


From: Leonid Shifrin on
Hi Matthias,

the problem is that in all rules you used, symbols <a> and <b> evaluated to
their respective values A*c and B*c before any rule substitution took place,
both in the rules and in the expressions to which you apply the rules. This
can be easily tracked by using Trace:

In[1]:=
a:=A c
b:=B c

In[3]:= Trace[a/.{a->x,b->y},ReplaceAll]

Out[3]= {A c/.{A c->x,B c->y},x}

In[4]:= Trace[b/.{a->x,b->y},ReplaceAll]

Out[4]= {B c/.{A c->x,B c->y},y}

In[5]:= Trace[a+b/.{a->x,b->y},ReplaceAll]

Out[5]= {A c+B c/.{A c->x,B c->y},x+y}

In[6]:= Trace[a*b/.{a->x,b->y},ReplaceAll]

Out[6]= {A B c^2/.{A c->x,B c->y},A B c^2}

So you see, the actual expressions used by ReplaceAll are not at all those
you started with, hence the results. Presumably, you wanted to prevent
evaluation of both expressions and rules, at least until the rule applies.
You can use Unevaluated and HoldPattern for this purpose:

In[7]:=
Unevaluated[a] /. {HoldPattern[a] -> x, HoldPattern[b] -> y}

Out[7]= x

In[8]:= Unevaluated[b] /. {HoldPattern[a] -> x, HoldPattern[b] -> y}

Out[8]= y

In[9]:= Unevaluated[a + b] /. {HoldPattern[a] -> x,
HoldPattern[b] -> y}

Out[9]= x + y

In[10]:= Unevaluated[a*b] /. {HoldPattern[a] -> x, HoldPattern[b] -> y}

Out[10]= x y

You can use Trace as above to see that now the actual expressions used in
ReplaceAll are what you probably had in mind. However, if you have a choice,
I wouldn't make the assignments to <a> and <b> in the first place, or make
them local rules and apply after all other rules have been applied.

Hope this helps.

Regards,
Leonid





On Thu, Jun 24, 2010 at 1:27 AM, Matthias Fripp <mfripp(a)gmail.com> wrote:

> I am having trouble using ReplaceAll to replace symbols that already
> have a delayed assignment.
>
> e.g., this input:
>
> In[287]:=
> a := A c
> b := B c
> a /. {a -> x, b -> y}
> b /. {a -> x, b -> y}
> a + b /. {a -> x, b -> y}
> a * b /. {a -> x, b -> y}
>
> gives this output:
>
> Out[289]= x
>
> Out[290]= y
>
> Out[291]= x + y
>
> Out[292]= A B c^2
>
> All of this works as expected except for the final term. I would have
> expected to get the result "x y". Is there any way to force
> Mathematica to produce that result?
>
> If on the other hand the original assignment is a := A + c and b := B
> + c, I get an unexpected output for the sum, but the expected output
> (x y) for the product. If I insert d instead of one of the c's, I get
> various other (unpredictable) kinds of result.
>
> My first guess is that Mathematica is doing a sort of "double
> ReplaceAll", where it first tries the pattern given in the delayed
> assignment, and any symbols matched by that are not tested against the
> explicit ReplaceAll. But that doesn't explain why the sum works and
> not the product. Am I thinking about this the wrong way?
>
> Thanks for any help you can give!
>
> Matthias Fripp
>
>
From: Matthias Fripp on
Hi Leonid,

Thanks -- your explanation is very helpful. The descriptions of the
Trace, Unevaluated and HoldPattern functions are also very useful. It
would have taken me a while to find them on my own!

I'm surprised to see that Mathematica evaluates the main expression as
far as possible before applying any replacement rules. It would seem
more "natural" to me to apply the replacements first, then go to work
on the expression. But I suppose there's a certain logic to this. At
least now I know how to apply the rules before the expression is
evaluated (which will be useful in other situations as well).

I'm equally surprised that Mathematica applies the delayed assignment
(a := A c) to the left hand side of the ReplaceAll rule (a -> x). But
at least now I know what to watch out for and how to work around it!

Thanks very much for your help.

Matthias

On Jun 24, 2010, at 12:59 PM, Leonid Shifrin wrote:

> Hi Matthias,
>
> the problem is that in all rules you used, symbols <a> and <b>
> evaluated to their respective values A*c and B*c before any rule
> substitution took place, both in the rules and in the expressions to
> which you apply the rules. This can be easily tracked by using Trace:
>
> In[1]:=
> a:=A c
> b:=B c
>
> In[3]:= Trace[a/.{a->x,b->y},ReplaceAll]
>
> Out[3]= {A c/.{A c->x,B c->y},x}
>
> In[4]:= Trace[b/.{a->x,b->y},ReplaceAll]
>
> Out[4]= {B c/.{A c->x,B c->y},y}
>
> In[5]:= Trace[a+b/.{a->x,b->y},ReplaceAll]
>
> Out[5]= {A c+B c/.{A c->x,B c->y},x+y}
>
> In[6]:= Trace[a*b/.{a->x,b->y},ReplaceAll]
>
> Out[6]= {A B c^2/.{A c->x,B c->y},A B c^2}
>
> So you see, the actual expressions used by ReplaceAll are not at
> all those you started with, hence the results. Presumably, you
> wanted to prevent evaluation of both expressions and rules, at least
> until the rule applies. You can use Unevaluated and HoldPattern for
> this purpose:
>
> In[7]:=
> Unevaluated[a] /. {HoldPattern[a] -> x, HoldPattern[b] -> y}
>
> Out[7]= x
>
> In[8]:= Unevaluated[b] /. {HoldPattern[a] -> x, HoldPattern[b] -> y}
>
> Out[8]= y
>
> In[9]:= Unevaluated[a + b] /. {HoldPattern[a] -> x,
> HoldPattern[b] -> y}
>
> Out[9]= x + y
>
> In[10]:= Unevaluated[a*b] /. {HoldPattern[a] -> x, HoldPattern[b] ->
> y}
>
> Out[10]= x y
>
> You can use Trace as above to see that now the actual expressions
> used in ReplaceAll are what you probably had in mind. However, if
> you have a choice, I wouldn't make the assignments to <a> and <b>
> in the first place, or make them local rules and apply after all
> other rules have been applied.
>
> Hope this helps.
>
> Regards,
> Leonid
>
>
>
>
>
> On Thu, Jun 24, 2010 at 1:27 AM, Matthias Fripp <mfripp(a)gmail.com>
> wrote:
> I am having trouble using ReplaceAll to replace symbols that already
> have a delayed assignment.
>
> e.g., this input:
>
> In[287]:=
> a := A c
> b := B c
> a /. {a -> x, b -> y}
> b /. {a -> x, b -> y}
> a + b /. {a -> x, b -> y}
> a * b /. {a -> x, b -> y}
>
> gives this output:
>
> Out[289]= x
>
> Out[290]= y
>
> Out[291]= x + y
>
> Out[292]= A B c^2
>
> All of this works as expected except for the final term. I would have
> expected to get the result "x y". Is there any way to force
> Mathematica to produce that result?
>
> If on the other hand the original assignment is a := A + c and b := B
> + c, I get an unexpected output for the sum, but the expected output
> (x y) for the product. If I insert d instead of one of the c's, I get
> various other (unpredictable) kinds of result.
>
> My first guess is that Mathematica is doing a sort of "double
> ReplaceAll", where it first tries the pattern given in the delayed
> assignment, and any symbols matched by that are not tested against the
> explicit ReplaceAll. But that doesn't explain why the sum works and
> not the product. Am I thinking about this the wrong way?
>
> Thanks for any help you can give!
>
> Matthias Fripp
>
>