Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

How can I make a replacement rule that will only be applied to those parts of an expression that will not break a condition placed on the whole expression?

For example, suppose I have $\frac{xy}{(x-y)(x+y)}$ and I want to change $y$ to $x$ getting the result $\frac{x^2}{(x-y)2x}$; i.e., without turning original expression into infinity. Further, I don't want the replacement to raise warnings or errors.

At the least, I need a way to do a replacement just once, which seems like it should be very easy, but I have no idea how to do it.

I came up with

ReplaceOnce[expr_, rule_Rule] := MapAt[# /. rule &, expr, Position[expr, rule[[1]]][[1]]]

How can I get to my goal from here?

share|improve this question
    
I don't think this is well specified. For example, what if by turning some subset of the "x" you get the warning but with some others not, how do you decide which changes you want? –  Rojo Mar 2 '13 at 16:07
    
Or you want "find the x in whatever order and one by one try changing them and checking if the result is valid"? –  Rojo Mar 2 '13 at 16:07
    
@Rojo One instance will be sufficient but if it will return every possible valid result that would be awesome. –  swish Mar 2 '13 at 16:11
add comment

2 Answers

up vote 3 down vote accepted

Not perfect, but a start (I cannot quickly add a working FixedPoint at the end) :

   repl[expr_, rule_Rule] := Module[{ex, fun}, 
           fun[ex_] := Union[Flatten[Quiet[Select[
                      (ReplacePart[ex, #1 -> rule[[2]]] & ) /@ 
             Position[ex, 
                          rule[[1]]], FreeQ[#1, ComplexInfinity] & ]]]]; 
            Union[Flatten[fun /@ fun[expr]]]]; 
    repl[expr, y -> x]

(* ==> *)

{x/(2 (x - y))}
share|improve this answer
add comment

Finally made some progress:

ReplaceOnce[expr_, rule_Rule] :=
  MapAt[# /. rule &, expr, #] & /@ Position[expr, rule[[1]]]

ReplaceIf[expr_, rule_Rule, cond_] := 
 NestWhile[
    Flatten[(Select[ReplaceOnce[#, rule], cond]) & /@ #] &, {expr}, 
    cond[#] && # != {} &, 1, \[Infinity], -1] // Quiet // 
  DeleteDuplicates

ReplaceIf[(x y)/((x + y) (x - y)), y -> x, # =!= ComplexInfinity &]
(*{x/(2 (x - y))}*)
share|improve this answer
    
If this is based on Rolf Mertig's answer, as it appears to be, you should say so. –  m_goldberg Mar 2 '13 at 18:04
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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