8
$\begingroup$

I sometimes need fine grain control over equations in Mathematica in order to help me understand how to solve a problem manually. A greatly simplified example of a session might be something like this:

2x + 3 == 5x - 7

2 x + 3 == 5 x - 7

% /. lhs_ == rhs_ -> lhs - 2x == rhs - 2x

3 == 3 x - 7

% /. lhs_ == rhs_ -> lhs + 7 == rhs + 7

10 == 3 x

% /. lhs_ == rhs_ -> lhs / 3 == rhs / 3

10 / 3 == x

Instead of constantly writing expressions like lhs_ == rhs_ -> lhs - 2x == rhs - 2x, I would like to write function calls like eqnx[e - 2x] where the e represents the expression being modified and is applied to both the lhs and rhs of the equation.

My intuition leads me to believe that this is exactly inline with Mathematica's strengths, but my rational mind cannot deduce anything close to a correctly working function. Is this possible? Or, should I be taking a different approach?

Edit: Xerxes gives an excellent method below for accomplishing this task using the built-in Distribute[expr, g] function. Now that I understand how Distribute works, I can see that it is very useful. I have been using his technique with a small tweak to reduce the amount of typing required and here is a sample session:

eqx[e_] := Distribute[e, Equal]

2 x + 3 == 5 x - 7
eqx[% - 2x]

3 = -7 + 5 x
eqx[% + 7]

10 = 3 x
eqx[% / 3]

10/3 = x

The intention of my original question, however, was a rule based technique so that I could more easily work with lines of input or output that already existed (I think my question states this but my detailed description did not reiterate that point). The function approach is efficient as long as you can use %, but in most of my work I am iteratively trying different things on the same input and I cannot reliable use % and must be remember to grab the correct In[#] or Out[#].

Based on the answers to this question and others on this forum, I was able to figure out a rule based solution. While the functionality is similar, the specifics of using the function make for a different user experience. Here is a sample session:

reqx[e_] := lhs_ == rhs_ -> (e /. expr -> lhs) == (e /. expr -> rhs)

2 x + 3 == 5 x - 7 /. reqx[expr - 2x]
3 == -7 + 3 x /. reqx[expr + 7]
10 == 3 x /. reqx[expr / 3]
10/3 == x

The one issue that I don't understand how to address relates to the placeholder expr that I use in calls to the reqx function. Inside the function this symbol gets replaced by the lhs and rhs expressions to produce the result. Its only function is to serve as a placeholder in the expression given to the reqx function.

As long as expr does not have a value (or rule in Mathematica parlance), everything works fine. Is there something I can do to mitigate or eliminate this potential snafu in usage?

Edit 2: I believe the following definition appropriately protects the placeholder from evaluation:

reqx[e_] := lhs_ == rhs_ -> (Unevaluated[e] /. HoldPattern[expr] -> lhs) 
    == (Unevaluated[e] /. HoldPattern[expr] -> rhs)
SetAttributes[reqx, HoldAllComplete]
$\endgroup$
4
  • $\begingroup$ I intend to close this as a duplicate of (15311) unless people make a case for me to leave it open. $\endgroup$
    – Mr.Wizard
    Feb 16, 2013 at 2:43
  • $\begingroup$ @m_goldberg How did you change the markup to produce the alternating colors? $\endgroup$
    – RandomBits
    Feb 16, 2013 at 6:43
  • $\begingroup$ @Mr.Wizard I think this question is a more general version of 15311. I also wanted something I could apply as a Rule. Based on the responses I have gotten so far, I now have some ideas on how to do that and will edit my post once I have something working. $\endgroup$
    – RandomBits
    Feb 16, 2013 at 6:46
  • 1
    $\begingroup$ @Mr.Wizard I don't see any particular difference between mathematica.stackexchange.com/questions/15311/… and this question, so I'm voting to close as duplicate. $\endgroup$
    – Ajasja
    Feb 16, 2013 at 9:00

2 Answers 2

12
$\begingroup$

This looks like a job for Distribute, like so:

2 x + 3 == 5 x - 7
Distribute[% - 2 x, Equal]
Distribute[% + 7, Equal]
Distribute[%/3, Equal]

(* 3 + 2 x == -7 + 5 x *)
(* 3 == -7 + 3 x *)
(* 10 == 3 x *)
(* 10/3 == x *)
$\endgroup$
2
  • $\begingroup$ This is exactly what I need. I read the documentation for distribute, but I am still a little unclear about how this is accomplishing the task. The first call Distribute[(2 x + 3 == 5 x - 7) - 2 x, Equal] applies the - 2x to both sides of the ==, but I am not sure why? $\endgroup$
    – RandomBits
    Feb 15, 2013 at 23:40
  • 1
    $\begingroup$ Distribute applies the topmost function to a list of expressions contained in some other specified function. The internal form of (2x+3==5x-7)-2x is Plus[Times[-2,x],Equal[Plus[3,Times[2,x]],Plus[-7,Times[5,x]]]], which you can see by applying FullForm to it. For our purposes, we should think of it as being Plus[-2x,Equal[3+2x,5x-7]]. So the top function is Plus[-2x,...]. Distribute takes that and applies it to each part of the Equal. $\endgroup$
    – Xerxes
    Feb 16, 2013 at 0:09
6
$\begingroup$

You can define :

f[equation_, transformation_] := transformation[#] & /@ equation 

f[2 x + 3 == 5 x - 7, # - 2 x &]
(* 3 == -7 + 3 x *)

f[%, # + 7 &]
(* 10 == 3 x *)

f[%, #/3 &]
10/3 == x
$\endgroup$
2
  • 1
    $\begingroup$ Is there any advantages / disadvantages to using this function versus the built in Distribute? $\endgroup$
    – RandomBits
    Feb 15, 2013 at 23:41
  • $\begingroup$ @RandomBits It's just an alternative, I thought it can be generalized if needed. $\endgroup$ Feb 16, 2013 at 8:30

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