Group Abstract Group Abstract

Message Boards Message Boards

Operations with Equal

Sometimes when we have some equations we wish to add a constant to both sides or multiply by a factor.

If you naively try:

eq1 = a == b;
eq2 = c == d;

eq1 + 1 (* Out: 1 + (a == b) *)
eq1 + eq2 (* Out: (a == b) + (c == d) *)
2*eq1 (* Out: 2*(a == b) *)

To augment the functionality of Equal, we need to change built-in functions (not a smart idea).

To do so we'll use the following lines of code:

SetEqual = (Unprotect@Equal;
(* HoldPattern is needed to avoid missinterpretation of the pattern *)
Equal /: HoldPattern@Plus[Equal[a_, b_], c : Except[Equal[__], _]] := a + c == b + c;
Equal /: HoldPattern@Plus[Equal[a_, b_], Equal[c_, d_]] := a + c == b + d;
Equal /: HoldPattern@Times[Equal[a_, b_], c : Except[Equal[__], _]] := a*c == b*c;
Equal /: HoldPattern@Power[Equal[a_, b_], c : Except[0, _]] := a^c == b^c;
HoldPattern@Equal[L : List[a_, b__], c_] := (# == c & /@ L);
Protect@Equal;)
(* Undo built-in modifications *)
ClearEqual := (Unprotect@Equal; Clear@Equal; Protect@Equal;)
(* Make Simplify not change sides *)
SimplifySides[Equal[a_, b_]] := Simplify@a == Simplify@b
SimplifySides[L_List, args___] := SimplifySides[#, args] & /@ L

With this (after calling SetEqual) we have:

eq1 + 1 (* Out: 1 + a == 1 + b *)
eq1 + eq2 (* Out: a + c == b + d *)
2*eq1 (* Out: 2*a == 2*b *)

And after we can just call ClearEqual to avoid any mishaps.

With this we can complete the square:

enter image description here

*Where the use of HoldForm is needed otherwise Simplify is not smart enough. Also, List is needed because of the Plus or Minus square roots of the equation.

POSTED BY: Thales Fernandes
18 Replies
Posted 7 years ago

I hope you noticed the new in 11.3 functions AddSides, MultiplySides, etc. These handle equations, inequalities, piecewise expressions, and more.

There are arguments for and against thread. I would say the main argument against is that the moment you get to multiplcation and division you need to incoroprate assumptions and/or conditions, and suddenly it is now a mathematical rather than structural operation. These new functions allow you to control this behavior (with carefully considered defaults, of course).

POSTED BY: Itai Seggev
POSTED BY: Vitaliy Kaurov

How about this:

Format[inactiveEqual[a_, b___]] := Inactive[Equal][a, b];
inactiveEqual /: (f_)[inactiveEqual[a___]] /; 
   MemberQ[Attributes[f], Listable] := Map[f, inactiveEqual[a]];
inactiveEqual /: inactiveEqual[a___] + b : Except[_inactiveEqual] := 
  Map[# + b &, inactiveEqual[a]];
inactiveEqual /: inactiveEqual[a___]*b : Except[_inactiveEqual] := 
  Map[#*b &, inactiveEqual[a]];
inactiveEqual /: 
 inactiveEqual[a___] + inactiveEqual[b___] /; 
  Length[{a}] == Length[{b}] := Apply[inactiveEqual, {a} + {b}]

You can do manipulations with automatic threading and nice formating:

inactiveEqual[a, b]
% // Exp
% + inactiveEqual[x, y]
% + 1
2 %
1 - %
POSTED BY: Gianluca Gorni

The Thread method fails in more complicated cases:

eq = a == c + b
eq2 = g == h + k
Thread[eq - eq2, Equal]
Thread[2 eq + 1, Equal]
POSTED BY: Gianluca Gorni

You can only do one operand at the time using the above code, so you would need nesting, e.g.:

Thread[eq + Thread[-eq2, Equal], Equal]

first 'minus' then 'add' or first multiply then addÂ…

POSTED BY: Sander Huisman
POSTED BY: Sander Huisman

You can 'edit' equations using Thread:

There are countless ways of parsing it. Thread is a very nice one (I'll be using it sometimes)! But I really don't like those large equations.

But I really don't get it. You can differentiate an Equal equation (you can't integrate though...), you can use Series with it, and possible others functions can operate on it, but you can't add a constant to both sides...

POSTED BY: Thales Fernandes
POSTED BY: Gianluca Gorni
POSTED BY: Sander Huisman

If an equation becomes True after some transformation, I stop there and have no reason to add 1. Or we could operate on Inactive[Equal], which would avoid the trap.

POSTED BY: Gianluca Gorni
POSTED BY: Thales Fernandes
POSTED BY: Sander Huisman

I don't understand yet why D does work to be honestÂ… seems, at first sight, 'off'

POSTED BY: Sander Huisman

We have been waiting decades already for a natural way of transforming equations in Mathematica. We can work around the problem without unprotecting Equal. Introduce this operator:

mapToSidesOfEquations[action_] := % /. eq_Equal :> Map[action, eq]

Then you can transform your equation in simple steps within a single cell:

a x^2 + b x + c == 0
(# - c)/a & // mapToSidesOfEquations
Expand // mapToSidesOfEquations
# + (b/(2 a))^2 & // mapToSidesOfEquations
Expand // mapToSidesOfEquations
% /. b -> HoldForm[b/(2 a)] 2 a
Factor // mapToSidesOfEquations
% // ReleaseHold
Simplify // mapToSidesOfEquations
% /. u_^2 == v_/z_^2 :> (u == Sqrt[v]/z) \[Or] (u == -Sqrt[v]/z)
# - b/(2 a) & // mapToSidesOfEquations
Together // mapToSidesOfEquations

It is less convenient to type.

POSTED BY: Gianluca Gorni

We have been waiting decades already for a natural way of transforming equations in Mathematica.

Yeup, I'm always solving equations by hand, so the trick of SetEqual and ClearEqual works, since I never call Solve while solving by hand (it would be an oxymoron).

I used to have a function wrapper loike yourself, but, it gets messy...

POSTED BY: Thales Fernandes

What happens when you call Solve[] with the modified equal? I never understood why I couldn't operate on equations in mathematica as nature intended :(

POSTED BY: Kay Herbert

Unprotect@Equal --- you like to live dangerously ;-)

POSTED BY: Kapio Letto

"Oh, behave!"

If you get the reference. ;)

POSTED BY: Thales Fernandes
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard