简体   繁体   中英

Comparing symbolic mathematical expressions with Python using Sympy

I would like to check which mathematical expressions are equal. I want to do this using Python I tried it with Sympy.

My idea was to use simplify in order to reduce the expressions such that a pair that is equal will be reduced to the same expression. Then I substract them all with each other in my two for loops and check if the result equals to zero.

Unfortunately no substraction results in zero which is very improbable to be correct. I think that probably the simplify function does not really do what I need. Is there a function in sympy to check if two expressions are indeed mathematically equal?

This is my code so far:

from sympy import *

a = symbols ('a')
b = symbols ('b')
n = symbols ('n')
m = symbols ('m')

x1=simplify(log(a,n**(log(b,a))))
x2=simplify(((a**n)/(b**m))**(1/b))
x3=simplify(b**(n*log(a)))
x4=simplify(log(b,n))
x5=simplify(a**((n-m)/b))
x6=simplify(n*(log(a)+log(b)))
x7=simplify(log((a**n)*(b**n)))
x8=simplify(a**(log(b**n)))

L=[x1,x2,x3,x4,x5,x6,x7,x8]



for i in range (0 , 6):

    for k in range (i+1 , 7):

        print(L[i]-L[k])

The a.equals(b) method will try really hard (including using random values for variables) to show that a == b . But be aware that two expressions might only be equal for a given range of values. So it might be better to indicate that your symbols are, for example, positive or integer as in Symbol('n', integer=True) or Symbol('a', positive=True) . If you do that then simplify(a - b) will more likely reduce to 0 as will a.equals(b) .

posify is a function which can replace symbols with symbols having positive assumptions; see below how x6 and x7 simplify when symbols are positive:

>>> from sympy import posify
>>> dif = x6 - x7
>>> dif.simplify() == 0
Ealse
>>> posify(dif)[0].simplify()  # [0] gets the the positive-symbol expression

You can also make numerical substitutions yourself using x._random(lo,LO,hi,HI) where (lo, hi) are the lower and upper limit for the real part of the number and (LO, HI) are the same for the imaginary part, eg x._random(0,0,1,0) will give a random value that is real between 0 and 1. Create a replacement dictionary and replace the values and check the absolute value of the difference in a and b . Something like this (using the loop as you presented it above):

for i in range (0 , 6):
  for k in range (i+1 , 7):
    v = L[i]-(L[k])
    reps = {i: i._random(0,0,1,0) for i in v.free_symbols}
    v = v.xreplace(reps).n()
    if abs(v) < 1e-9:
      print(L[i],L[k],abs(v))

Another way to check if functions are equal would be to evaluate them at maybe a few thousand points and check the outputs.

from sympy import *

def generateOutput(L, x):
    # x -> list of points to evaluate functions at (maybe randomly generated?)
    # L -> input list of functions
    # returns list of outputs of L[i] applied to x



a = symbols ('a')
b = symbols ('b')
n = symbols ('n')
m = symbols ('m')

x1=simplify(log(a,n**(log(b,a))))
x2=simplify(((a**n)/(b**m))**(1/b))
x3=simplify(b**(n*log(a)))
x4=simplify(log(b,n))
x5=simplify(a**((n-m)/b))
x6=simplify(n*(log(a)+log(b)))
x7=simplify(log((a**n)*(b**n)))
x8=simplify(a**(log(b**n)))

L=[x1,x2,x3,x4,x5,x6,x7,x8]

outputs = generateOutput(L)
# Compare outputs

From the docs :

The Eq function (from sympy.core.relational ) looks like it is what you want. Note that if it is given more complex arguments, you will have to simplify to get a result (see last code example in link).

Note: Those for loops don't look right. The first one will only go through indices 0-5 and the second only through i+1 to 6, so the last item in the list will be skipped completely.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM