Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using SymPy to generically parse and solve equations

Tags:

python

sympy

I want to be able to parse string equations (that are equal to 0) and then solve them by using a dictionary of variables that I have access to.

For example:

s = '(x/z)-y'
eq = parse(s)
eq.solve({'x': 10, 'y': 5})
print(eq)
>>> {'z': 2}

Now I had written code that did something like this a month ago, but I just can't find it. I do remember however that I used SymPy and its sympify function, along with its solve function. I have checked the documentation on these functions, but I've not been able to wrap my head around how to get them to work as I want.

And an extra question: Would it be possible to wrap the variables somehow so that I could use something more than just a letter for them? Example: Instead of just 'x' I could have '{myvar-42}'

EDIT:

Okay I finally succeeded writing some code that did what I wanted to:

eq = sympify('(x/y)-z', locals={'x': 10, 'z': 5})
solution = solve(eq, dict=True)
print(solution)
>>> [{'z': 2}]

But my "extra" question remains.

like image 303
fgblomqvist Avatar asked Jan 12 '14 15:01

fgblomqvist


People also ask

How do you solve equations using SymPy?

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

As you've discovered, sympify converts strings into SymPy expressions.

To answer your other question, Symbol names can be anything, but sympify will only parse valid Python identifiers to Symbol names. But you can do

>>> Symbol('{myvar-42}') + 1
{myvar-42} + 1

And note that valid Python idenfifiers do not have to be single letters. They can be any combination of letters, numbers, and underscores that does not start with a number, like x_2 or abc123.

If you need to still do string parsing but want non-valid Python identifiers as Symbol names, probably the cleanest way would be to use normal names and substitute them in for other ones, like

>>> expr = sympify('x + 1')
>>> expr.subs(Symbol('x'), Symbol('{myvar-42}')
{myvar-42} + 1

Finally, to replace the symbols with letters, you can use the locals argument to sympify, as you have done, or, if you want to replace them later, use subs:

>>> x, y, z = symbols('x y z')
>>> expr = sympify('x/z - y')
>>> expr.subs({x: 10, y: 5})
10/z - 5
like image 134
asmeurer Avatar answered Oct 19 '22 19:10

asmeurer