3
$\begingroup$

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?

$\endgroup$
3
  • $\begingroup$ 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? $\endgroup$
    – Rojo
    Mar 2, 2013 at 16:07
  • $\begingroup$ Or you want "find the x in whatever order and one by one try changing them and checking if the result is valid"? $\endgroup$
    – Rojo
    Mar 2, 2013 at 16:07
  • $\begingroup$ @Rojo One instance will be sufficient but if it will return every possible valid result that would be awesome. $\endgroup$
    – swish
    Mar 2, 2013 at 16:11

2 Answers 2

4
$\begingroup$

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))}
$\endgroup$
4
$\begingroup$

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))}*)
$\endgroup$
1
  • $\begingroup$ If this is based on Rolf Mertig's answer, as it appears to be, you should say so. $\endgroup$
    – m_goldberg
    Mar 2, 2013 at 18:04

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.