15
$\begingroup$

Suppose I have an expression containing p,Subscript[p,1],Subscript[p,2],etc. I want to replace p with a numerical value while keeping the other two variables intact. How can I do it?

If I naively use /.{p->0.5} for example, I will get Subscript[0.5,1], Subscript[0.5,2] as a result.

$\endgroup$
0

3 Answers 3

26
$\begingroup$

You wish to make substitutions in all except Subscript expressions I believe. This can be done by leveraging the precedence of replacement rules, like this:

{p, Subscript[p, 1], Subscript[p, 2]} /. {x_Subscript :> x, p -> 1}
{1, Subscript[p, 1], Subscript[p, 2]}

Due to the traversal order of ReplaceAll the rule x_Subscript :> x acts first, "replacing" any expression with the head Subscript by itself. Since expressions that have already been replaced are not matched again, the second rule p -> 1 is never applied to these subexpressions.

$\endgroup$
7
$\begingroup$

You could also make one rule that is a bit more specific

{p, Subscript[p, 1], Subscript[p, 2]} //. 
 head_[x___, p, y___] /; head =!= Subscript :> head[x, 0.5, y]

-> {0.5, Subscript[p, 1], Subscript[p, 2]}

This does not work if p is the entire expression. i.e

p/.head_[x___, p, y___] /; head =!= Subscript :> head[x, 0.5, y]

-> p

In that case you will probably have to add another rule. Note also ReplaceRepeated in the above may make things slower than necessary.

Side remark

You could also do something with Block as follows, though this is not replacement but rather evaluation

Block[
 {p = 0.5, Subscript},
 SetAttributes[Subscript, HoldAllComplete];
 {p, Subscript[p, 1], Subscript[p, 2]}
 ]

-> {0.5, Subscript[p, 1], Subscript[p, 2]}

$\endgroup$
4
  • $\begingroup$ This also has a problem if p exists twice in an expression for the same reason that my answer works. For example, with expression (p + p^2)/Subscript[p, 1]. I suggest amending your answer to use //. but that can be inefficient. $\endgroup$
    – Mr.Wizard
    Commented May 20, 2013 at 12:55
  • $\begingroup$ @Mr.Wizard Thanks, I changed it. I guess in light of the new insights that Mathematica remembers if expressions have changed anyway, the "checking if the expression has changed" step of ReplaceRepeated must take negligable time. I suppose MMA just goes through the expression twice if use //., which is the same as in your answer where you use two rules. But then your rules are simpler, so your solution must be better in terms of speed, and I can see ever more desirable properties of your answer :). Anyway, +1 for you $\endgroup$ Commented May 20, 2013 at 13:50
  • $\begingroup$ That was silly of me. It goes through the expression much more often. Changing $\endgroup$ Commented May 20, 2013 at 13:52
  • 1
    $\begingroup$ +1 for the Block solution! A very nice addition. $\endgroup$
    – Mr.Wizard
    Commented May 20, 2013 at 14:45
2
$\begingroup$

Another way is to use level specification in Replace :

Replace[{p, Subscript[p, 1], Subscript[p, 2]} , p -> 0.5, 1]
(* {0.5, Subscript[p, 1], Subscript[p, 2]} *)
$\endgroup$
2
  • 1
    $\begingroup$ I don't think it is reasonable to assume that the replacements should happen on a particular level. Consider for example: p^2 + Subscript[p, 1] + Subscript[p, 2] $\endgroup$
    – Mr.Wizard
    Commented May 20, 2013 at 9:46
  • $\begingroup$ @Mr.Wizard I agree it's not the most generic solution. $\endgroup$ Commented May 20, 2013 at 9:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.