Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sympy: working with equalities manually

Tags:

python

sympy

I'm currently doing a maths course where my aim is to understand the concepts and process rather than crunch through problem sets as fast as possible. When solving equations, I'd like to be able to poke at them myself rather than have them solved for me.

Let's say we have the very simple equation z + 1 = 4- if I were to solve this myself, I would obviously subtract 1 from both sides, but I can't figure out if sympy provides a simple way to do this. At the moment the best solution I can come up with is:

from sympy import *
z = symbols('z')
eq1 = Eq(z + 1, 4)
Eq(eq1.lhs - 1, eq1.rhs - 1)
# Output:
# z == 3

Where the more obvious expression eq1 - 1 only subtracts from the left-hand side. How can I use sympy to work through equalities step-by-step like this (i.e. without getting the solve() method to just given me the answer)? Any pointers to the manipulations that are actually possible with sympy equalities would be appreciated.

like image 419
Marius Avatar asked Mar 07 '14 01:03

Marius


People also ask

How do you solve a system of equations using SymPy?

After the symbols and equations are defined, we can use SymPy's solve() function to compute the value of x and y. The first argument passed to the solve() function is a tuple of the two equations (eq1, eq2) . The second argument passed to the solve() function is a tuple of the variables we want to solve for (x, y) .

How do you solve for a variable SymPy in Python?

To solve the two equations for the two variables x and y , we'll use SymPy's solve() function. The solve() function takes two arguments, a tuple of the equations (eq1, eq2) and a tuple of the variables to solve for (x, y) . The SymPy solution object is a Python dictionary.

Can SymPy solve trigonometric equations?

These are a bunch of numbers of order 1e-15 or less, so yes, the equations hold within machine precision.


1 Answers

There is a "do" method and discussion at https://github.com/sympy/sympy/issues/5031#issuecomment-36996878 that would allow you to "do" operations to both sides of an Equality. It's not been accepted as an addition to SymPy but it is a simple add-on that you can use. It is pasted here for convenience:

def do(self, e, i=None, doit=False):
    """Return a new Eq using function given or a model
    model expression in which a variable represents each
    side of the expression.

    Examples
    ========

    >>> from sympy import Eq
    >>> from sympy.abc import i, x, y, z
    >>> eq = Eq(x, y)

    When the argument passed is an expression with one
    free symbol that symbol is used to indicate a "side"
    in the Eq and an Eq will be returned with the sides
    from self replaced in that expression. For example, to
    add 2 to both sides:

    >>> eq.do(i + 2)
    Eq(x + 2, y + 2)

    To add x to both sides:

    >>> eq.do(i + x)
    Eq(2*x, x + y)

    In the preceding it was actually ambiguous whether x or i
    was to be added but the rule is that any symbol that are
    already in the expression are not to be interpreted as the
    dummy variable. If we try to add z to each side, however, an 
    error is raised because now it is unclear whether i or z is being
    added:

    >>> eq.do(i + z)
    Traceback (most recent call last):
    ...
    ValueError: not sure what symbol is being used to represent a side

    The ambiguity must be resolved by indicating with another parameter 
    which is the dummy variable representing a side:

    >>> eq.do(i + z, i)
    Eq(x + z, y + z)

    Alternatively, if only one Dummy symbol appears in the expression then
    it will be automatically used to represent a side of the Eq.

    >>> eq.do(2*Dummy() + z)
    Eq(2*x + z, 2*y + z)

    Operations like differentiation must be passed as a
    lambda:

    >>> Eq(x, y).do(lambda i: i.diff(x))
    Eq(1, 0)

    Because doit=False by default, the result is not evaluated. to
    evaluate it, either use the doit method or pass doit=True.

    >>> _.doit == Eq(x, y).do(lambda i: i.diff(x), doit=True)
    True
    """
    if not isinstance(e, (FunctionClass, Lambda, type(lambda:1))):
      e = S(e)
      imaybe = e.free_symbols - self.free_symbols
      if not imaybe:
          raise ValueError('expecting a symbol')
      if imaybe and i and i not in imaybe:
          raise ValueError('indicated i not in given expression')
      if len(imaybe) != 1 and not i:
          d = [i for i in imaybe if isinstance(i, Dummy)]
          if len(d) != 1:
              raise ValueError(
                  'not sure what symbol is being used to represent a side')
          i = set(d)
      else:
          i = imaybe
      i = i.pop()
      f = lambda side: e.subs(i, side)
    else:
      f = e
    return self.func(*[f(side) for side in self.args], evaluate=doit)

from sympy.core.relational import Equality
Equality.do = do
like image 50
smichr Avatar answered Sep 19 '22 14:09

smichr