I often work with a mixture of symbolic and concrete values as I develop teaching materials. I introduce variables symbolically and then need to instantiate them to specific values while continuing to use the original variables. My i
represents a vector {1, 0, 0}
but I don't want to replace i
with {1, 0, 0}
everywhere, just when convenient. Thus I lit upon the idea of using replacement rules rather than definitions. But things didn't work out too well:
{a, a + b} //. {a -> 4 i, b -> {0, -2, 2}, i -> {1, 0, 0}}
(* output: {{4, 0, 0}, {{4, 0, 0}, {2, -2, -2}, {6, 2, 2}}} *)
while I wanted this result instead:
{a /. {a -> 4 i}, (a /. {a -> 4 i}) + b} //. {b -> {0, -2, 2}, i -> {1, 0, 0}}
(* output: {{4, 0, 0}, {4, -2, 2}} *)
I now understand that 4 i
is treated as a constant in rewriting a + b
:
{a, a + b} /. {a -> 4 i, b -> {0, -2, 2}}
(* output: {4 i, {4 i, -2 + 4 i, 2 + 4 i}} *)
I could attempt to control the substitution order by doing something like
{a, a + b} //. ({a -> 4 i, b -> {0, -2, 2}} /. i -> {1, 0, 0}) //. {i -> {1, 0, 0}}
(* output: {{4, 0, 0}, {4, -2, 2}} *)
But this is not very robust and won't work if substitutions are nested more deeply.
I can prevent premature application of the problematic rule using conditions e.g.
{a, a + b} //. {a :> 4 i /; i ∈ Vectors[v], b -> {0, -2, 2}, i -> {1, 0, 0}}
But then the rule never gets used as the RHS of the rule is never rewritten.
I don't really want to recast all the vector operators I might need following the example of
this answer; this seems like overkill.
But I do already use a wrapper bv[i]
which prints as UnderBar[i]
. Can anyone suggest a lightweight solution? Could I make Plus
, Times
etc. (temporarily) un-listable?
BTW This issue is flagged in the documentation for Assuming
, which does not help in this situation as Plus
just goes ahead and uses its Listable
attribute:
Assuming[v ∈ Vectors[2], v + {1, 2}]
(* output: {1 + v, 2 + v} *)