Parsing Symbolic Equations to Sympy functions - python

I am trying to pass image1 in my code when i copy and paste this as text it looks like this ∑(i=1,n)(a+m*x*(i)-y*(i))^2.
but it does not work.
following is my code which is working with a different syntax:
from sympy import symbols,sympify,solve,Eq,Symbol
from sympy import symbols,Eq,sympify,summation
expr = **('summation((m * x*(i) + a - y*(i))^2, (i, 0, n))')**
Eq1 = Eq(sympify(expr))
print(Eq1)
values = {2001,10,2,3,5}
arr_symbols = list(Eq1.free_symbols)
print(arr_symbols)
Method1(arr_symbols,values,expr)
def Method1(arr_symbols,Values,expr):
from sympy import symbols, Eq, solve, pprint, integrate, sympify
z = symbols('z')
Formula = Eq(sympify(expr),z)
print(Formula)
index = 0
for i in Values:
Formula = Formula.subs(arr_symbols[index],i)
index+=1
print(solve(Formula))
but what i want to do is to use ∑(i=1,n)(a+m*x*(i)-y*(i))^2 and ask sympy to convert it for me.

SymPy can represent this equation, but it can only parse Python. You might be able to write extensions to its parser to handle this sort of thing (see https://docs.sympy.org/latest/modules/parsing.html). It should be possible in principle, although it might not be straightforward. I would only recommend doing this the syntax of your expressions is already very close to Python. If it isn't (and it looks like it isn't), it would be better to a real parsing library like ANTLR to build up a grammar for your expressions. You can then use that to parse into SymPy (see for example how the sympy.parsing.latex module is written).
I don't know if there is pre-existing library in Python that handles your types of expressions. I'm not aware of any. At best you might be able to find a grammar that someone has already written, so you don't have to write it yourself.

If you are, given a, m and values for x and y and are trying to compute the sum of the squares of the residuals, then it would be better to write a function that does that or do something like this:
>>> x = [1, 2, 3]
>>> y = [4, 7, 11]
>>> a = 2
>>> m = 5
>>> sum((a + m*xi - yi)**2 for xi, yi in zip(x, y))
70

it cannot be done.
we have to pass latex code.

Related

I have a long expression which I want to simplify but assuming that an equation holds

In Mathematica, you can use the function FullSimplify[expression,assumptions] to simplify expressions using assumptions. For instance, if I do this:
FullSimplify[x^2-y^2,x^2-y^2==1],
then the result will be 1 because that's the 'simplest expression that is equivalent to the function I gave the software.
Now I need to do the same with Python, but I don't know how to do that. I have seen the documentation about the command sympy.refine on this page:
https://docs.sympy.org/latest/modules/assumptions/refine.html
However, I haven't been able to use equalities as assumptions. It doesn't seem possible to assume things like that with the Q function.
I have tried to do something like this:
import sympy as sp
x,y=sp.symbols('x y')
sp.refine(x**2-y**2,x==y)
However, this gives me the following error: ValueError: Inconsistent assumptions
Does someone have any ideas about this? Thank you.
Without some scope for what kind of expressions and assumptions you want to work with this is probably an unsolvable problem so I'll make some assumptions.
If you want to simplify a polynomial expression based on some other polynomial expression(s) being zero then you can do this in sympy using ratsimpmodprime:
In [1]: x, y = symbols('x, y')
In [2]: assumptions = [x**2 + y**2 - 1]
In [3]: expression = x**2 + y**2
In [4]: ratsimpmodprime(expression, assumptions)
Out[4]: 1
https://docs.sympy.org/latest/modules/simplify/simplify.html#ratsimpmodprime
I tried two approaches to the problem.
Assume that x - y = 0. This was the only way I could find to express the assumption that you want to make. Unfortunately, it doesn't seem to be smart enough to notice that this assumption allows it to substitute x for y.
print("refine:", sp.refine(x**2-y**2,Q.zero(x-y)))
This just returns the original expression.
Ask sympy to substitute the expression. This isn't as automatic - you're asking it to do the substitution instead of giving it the option of doing the substitution, but it does work for this toy example.
expr = (x**2-y**2)
print("substitution:", expr.subs(x**2-y**2, 1))
prints 1.

Convert symbolic expression to array in python

I'm trying to convert a symbolic expression to an array in python.
For example, I have this symbolic expression:
import sympy as sp
import numpy as np
A,B = sp.symbols("A B")
G = 3*A**2*B - 2*A*B + A**2
What I want is to convert this to an array looking as follows:
[3*A**2*B,-2*A*B,A**2]
I know how to do this in Matlab, but I need to do it in Python as well.
What I've tried:
I've converted the symbolic expression to a polynomial, which allowed me to collect the coefficients.
C = G.as_poly().coeffs()
This gets me halfway there:
C = [3,-2,1]
But I want to have at least a similar list for all the variables.
Does anyone have an idea?
You can use as_ordered_terms to get an ordered list of all the terms:
G.as_ordered_terms()
gives
[3*A**2*B, A**2, -2*A*B]
Alternatively, you can use args to get all the top-level arguments of the object.
G.args
This will give a tuple:
(A**2, -2*A*B, 3*A**2*B)

Sympy: solve for fraction

I have an equation and I need to solve it for a fraction.
I have more complex fomulas to solve but here is a minimal example: take the following simple function Y = X*a.
I want to solve for Y/X, so I expect Y/X =a.
Here is the code, it produces an empty set of answers
from sympy import *
X,Y,a = symbols('X Y a')
testEq = Eq(Y,X*a)
solve(testEq,Y/X)
I guess I'm misunderstanding something, any help appreciated!
The solve function can solve for sub-expressions provided they appear "as is" in the equation being solved. For example, in the following code, solve returns an empty solution for testEq but it returns the correct solution for testEq2 which is the same equation rearranged in terms of Y/X.
from sympy import *
X,Y,a = symbols('X Y a')
testEq = Eq(Y,X*a)
solve(testEq,Y/X)
testEq2 = Eq( Y/X, a )
sol = solve(testEq2,Y/X)
This is not weird or unreasonable at all. If you look at the source code of the solve function it uses code like
>>> testEq.has( Y/X ) # returns False
>>> testEq2.has( Y/X ) # returns True
to check if the symbol ( or sympy object ) that we are solving is present in the equation. If SymPy had to check for all possible ways in which the symbols of an expression can be combined into sub-expressions, the code would become extremely complicated for something which can be easily achieved in other ways ( like solving for Y and dividing by X, in this example ).
Packages for symbolic computations are there to help us handle complicated mathematical equations. But they are not a substitute for human intelligence. More often than not, we need to guide these packages to help them give the answer in a form we want while working around their limitations.
In this issue, a focus routine handles such a request once an auxiliary expression is added to the one of interest:
>>> eq = Eq(y, x*a)
>>> aux = Eq(b, y/x)
>>> focus((aux, eq), b)
{b: a}
Such a routine does not eliminate the need for human intervention, it just assists by allowing the user to state the relationship of interest and add that to the current equation(s) from which the implications are then deduced/solved.

sympy: Using Wild symbols as input for function

Consider the following expression in python/sympy:
from sympy.abc import x, y
expression = 3*x**2*y**1 + x**2*y**3
Now I want to replace x**n*y**m by max(n,m) by using pattern matching:
from sympy import Wild
n = Wild('n')
m = Wild('m')
expression = expression.replace(x**n*y**m,max(n,m))
However, I get a TypeError:
Traceback (most recent call last):
File "wild.py", line 15, in <module>
expression = expression.replace(x**n*y**m,max(n,m))
File "/usr/lib/python3/dist-packages/sympy/core/relational.py", line 103, in __nonzero__
raise TypeError("cannot determine truth value of\n%s" % self)
TypeError: cannot determine truth value of
m_ > n_
The Problem apparently is that upon matching the expression sympy does not convert the value of the Wild symbol to the matched value before forwarding it to the max-function. Is there any way to make this work?
Please note that this a simple example of a more general problem I have, so a workaround that does not generalize well is not very helpful. I especially hope that there is a solution using expression matching.
Update: Following sandwich's suggestion and replacing max(n,m) by (m+n+abs(m-n))/2 works, however, the function I am using in my real program is much more complicated.
Concerning the problem mentioned by sandwich that replace performs substitutions starting at the bottom of the expression tree: if I use exact=True and define f = sympy.Function('f') then the following works (except that I will have to deal with some cases separately):
expression = expression.replace(x**n*y**m,f(n,m),exact=True)
It still, however, does not work for max(n,m).
max is the built in Python function, which tries to evaluate immediately, hence the error (it can't determine which of n and m are larger when they are symbolic). You probably want the SymPy Max function, which works symbolically. The my_func you defined in your answer is effectively a basic implementation of Max.
In [14]: expression = expression.replace(x**n*y**m, Max(n,m))
In [15]: expression
Out[15]: 4
It seems this doesn't work (the answer 4 is wrong). The problem is that it's matching x**2 as x**2*y**0. Since the mathematical value of the replacement function depends on the form of the expression, this is problematic, since SymPy is trying to be smart. You can actually make n and m not match 0 with Wild('n', exclude=[x, 0]), but then there is an issue that it doesn't match x**2*y as x**2*y**1.
So I recommend converting your expression to a polynomial and doing the replacement exactly. Hopefully this generalizes well to what you are actually doing
In [18]: Poly(expression, x, y)
Out[18]: Poly(x**2*y**3 + 3*x**2*y, x, y, domain='ZZ')
In [19]: Poly(expression, x, y).terms()
Out[19]: [((2, 3), 1), ((2, 1), 3)]
In [20]: sum(max(pows)*coeff for pows, coeff in Poly(expression, x, y).terms())
Out[20]: 9
Ok, I have found a solution, it is note very pretty though which might have to do with the fact that I know little about writing functions that interact nicely with sympy.
At first I import everything relevant:
import sympy
from sympy.abc import x, y, a, b,z
from sympy import Wild
from sympy import Function
Then I define my own function which will return the maximum, here returning max(x,y) could be replaced by a more complicated function:
class my_func(Function):
#classmethod
def eval(cls, x, y):
if x.is_Number and y.is_Number:
return max(x,y)
The expression I want to modify is:
3*x**2*y**1 + x**2*y**3
The I define the necessary wild symbols and a sympy function which is used temporarily to make replacements without evaluation:
n = Wild('n')
m = Wild('m')
k = Wild('k')
f = Function('f')
expression = expression.replace(x,f(1,0),exact=True)
expression = expression.replace(y,f(0,1),exact=True)
expression = expression.replace(f(1,0)**n,f(n,0),exact=True)
expression = expression.replace(f(0,1)**n,f(0,n),exact=True)
expression = expression.replace(k*f(0,m)*f(n,0),k*f(n,m),exact=True)
These replacements catch all the cases which come up in my problem. In the last step I replace f by my_func which does the evaluation.
expression = expression.replace(f(n,m),my_func(n,m))
Maybe somebody will find a nicer solution....

compute x-component of vector in sympy

I'm sure this is a really basic question, but I've googled and haven't found it. Supposed I have a vector in sympy
z = 3*x + 4*y
How do I compute the x-component of the vector (i.e. the 3)? z/x doesn't give it (there's still the y-part), nor does z[x] or z.x. Surely there's a way to do this, right?
Is it as simple as:
>>> from sympy.abc import x, y
>>> z = 3*x + 4*y
>>> z.coeff(x)
3
I think that calling this expression a vector is somewhat incorrect. Indeed, if you keep in your mind the assumption that x and y are some base vectors, it will work in your mind. However the library will not provide any vector-like functionality because it does not know that you want to treat this as vectors.
For vector with all the nice helper methods you can use the diffgeom submodule of sympy which provides predefined R^2 and R^3 spaces with numerous coordinate systems.
However, for your case pattern matching seems a much more natural choice. After all pattern matching is one of the basic building blocks of CASes like Mathematica and others.
In SymPy as in all other CASes you work with symbolic expressions which are basically big trees with operators at each node and some symbols at the leafs. You can match trees against some predefined patterns much in the same way in which you can use regex on strings. In sympy you use Wild to do that:
x, y = Symbols("x y")
a, b = Wild('a', exclude=[x, y]), Wild('b', exclude=[x, y])
(2*x + 3*y).match(a*x + b*y)
For the special case of linear combinations check coeff which is described in the other answer.
See: https://github.com/sympy/sympy/wiki/Idioms-and-Antipatterns#wild-and-match

Categories

Resources