I have a function that computes a large expression based on Sympy symbols passed as arguments. A very simplified version for readability is:
def expr(a):
return (1+a)/a
This generally works but if the passed argument is the infinity symbol then this becomes a NaN, whereas I'd prefer the result to be somehow evaluated as a limit and return 1 (in this simplified case).
Since in my actual code there are many arguments which could be infinite and the expression is quite large, I'd rather avoid an if-else sequence covering every possible combination of infinite-valued arguments.
I've tried using unevaluated expressions but that doesn't seem to work either. Is there a good workaround for this?
You could write the expression as a limit:
from sympy import oo, limit
from sympy.abc import a, x
def expr(a):
return limit((1 + x) / x, x, a)
print(expr(oo)) # 1
Related
I'm looking for an efficient way to compute the result of a (complex) mathematical function.
right now it looks comparable to:
def f(x):
return x**2
def g(x):
if not x: return 1
return f(x)*5
def h(x):
return g(x)
with concurrent.futures.ProcessPoolExecutor() as executor:
print(list(executor.map(h, params)))
since every function call is costly in Python, the code should already run faster if f(x) is merged with g(x). Unfortunately in that case the 'return ...' line of the g(x) function becomes very long already. Furthermore there are currently actually 6 functions defined in total, so the complete formula occupies several lines.
So, what's a clever way to compute the result of a physics formula?
EDIT:
Thank you so far, but my question is not really about this specific snippet of code but more about the way to implement physics formulas in Python. For example one could also define the expression as a string and evaluate it using eval() but that is obviously slower.
To be more specific I have a potential and want to implement it parallel. Therefore I call my version of "h(x)" using the map function of a ProcessPoolExecutor (with different values each time). But is it best practice to define the function as a function that calls other functions or uses variables? Is there a more efficient way?
def formula(x):
if not x :
return 1
return x*x*5
I don't think the line is in danger of being problematically long, but if you're concerned about the length of the return ... line you could use intermediate values, e.g.:
def g(x):
if x == 0:
return 1
x2 = x ** 2
return x2 * 5
As an aside, in this context it is incorrect to use the is operator as in x is 0. It does not check for numerical equality, which is what == does. The is operator checks that the two operands refer to exactly the same object in memory, which happens to have the same behaviour as == in this case because the Python interpreter is intelligently reusing number objects. It can lead to confusing errors, for example:
a = 1234
b = 1233
a == (b + 1) # True
a is (b + 1) # False
In practice, is is mainly used only to check if a value is None.
Is there a way to check if two expressions are mathematically equal? I expected
tg(x)cos(x) == sin(x) to output True, but it outputs False. Is there a way to make such comparisons with sympy? Another example is
(a+b)**2 == a**2 + 2*a*b + b**2 which surprisingly also outputs False.
I found some similar questions, but none covered this exact problem.
From the SymPy documentation
== represents exact structural equality testing. “Exact” here means that two expressions will compare equal with == only if they are exactly equal structurally. Here, (x+1)^2 and x^2+2x+1 are not the same symbolically. One is the power of an addition of two terms, and the other is the addition of three terms.
It turns out that when using SymPy as a library, having == test for exact symbolic equality is far more useful than having it represent symbolic equality, or having it test for mathematical equality. However, as a new user, you will probably care more about the latter two. We have already seen an alternative to representing equalities symbolically, Eq. To test if two things are equal, it is best to recall the basic fact that if a=b, then a−b=0. Thus, the best way to check if a=b is to take a−b and simplify it, and see if it goes to 0. We will learn later that the function to do this is called simplify. This method is not infallible—in fact, it can be theoretically proven that it is impossible to determine if two symbolic expressions are identically equal in general—but for most common expressions, it works quite well.
As a demo for your particular question, we can use the subtraction of equivalent expressions and compare to 0 like so
>>> from sympy import simplify
>>> from sympy.abc import x,y
>>> vers1 = (x+y)**2
>>> vers2 = x**2 + 2*x*y + y**2
>>> simplify(vers1-vers2) == 0
True
>>> simplify(vers1+vers2) == 0
False
Alternatively you can use the .equals method to compare expressions:
from sympy import *
x = symbols('x')
expr1 = tan(x) * cos(x)
expr2 = sin(x)
expr1.equals(expr2)
True
The solution with simplify was too slow for me (had to crosscheck multiple variables), so I wrote the following function, which does some simple checkes beforehand, to reduce computational time, to use simplify only in the last step.
import numpy as np
import sympy as sp
def check_equal(Expr1,Expr2):
if Expr1==None or Expr2==None:
return(False)
if Expr1.free_symbols!=Expr2.free_symbols:
return(False)
vars = Expr1.free_symbols
your_values=np.random.random(len(vars))
Expr1_num=Expr1
Expr2_num=Expr2
for symbol,number in zip(vars, your_values):
Expr1_num=Expr1_num.subs(symbol, sp.Float(number))
Expr2_num=Expr2_num.subs(symbol, sp.Float(number))
Expr1_num=float(Expr2_num)
Expr2_num=float(Expr2_num)
if not np.allclose(Expr1_num,Expr2_num):
return(False)
if (Expr1.equals(Expr2)):
return(True)
else:
return(False)
As previously stated, (expr1 - expr2).simplify() or expr1.equals(expr2) will sometimes fail to recognize equality for expressions that are complex to simplify. To deal with this, a numerical evaluation of the expressions with random numbers may constitute a relatively safe "brute force" test. I've adapted the excellent solution by #Okapi575 to:
Test the numerical equality N-times with different random numbers each time for a more confident diagnostic
Warn the user when a pair of expressions only passes the numeric test but not the symbolic equality test.
For example:
Hope it can prove useful:
import sympy as sp
import numpy as np
def check_equal(Expr1, Expr2, n=10, positive=False, strictly_positive=False):
# Determine over what range to generate random numbers
sample_min = -1
sample_max = 1
if positive:
sample_min = 0
sample_max = 1
if strictly_positive:
sample_min = 1
sample_max = 2
# Regroup all free symbols from both expressions
free_symbols = set(Expr1.free_symbols) | set(Expr2.free_symbols)
# Numeric (brute force) equality testing n-times
for i in range(n):
your_values=np.random.uniform(sample_min, sample_max, len(free_symbols))
Expr1_num=Expr1
Expr2_num=Expr2
for symbol,number in zip(free_symbols, your_values):
Expr1_num=Expr1_num.subs(symbol, sp.Float(number))
Expr2_num=Expr2_num.subs(symbol, sp.Float(number))
Expr1_num=float(Expr2_num)
Expr2_num=float(Expr2_num)
if not np.allclose(Expr1_num, Expr2_num):
print("Fails numerical test")
return(False)
# If all goes well so far, check symbolic equality
if (Expr1.equals(Expr2)):
return(True)
else:
print("Passes the numerical test but not the symbolic test")
# Still returns true though
return(True)
EDIT: code updated (1) to compare expressions with differing numbers of free symbols (for example, after symbols got cancelled out during a simplification), and (2) to allow for the specification of a positive or strictly positive random number range.
Check this out from the original sympy themselves.
https://github.com/sympy/sympy/wiki/Faq
Example of it working for me
I was wondering how I would go about converting Sympy's "Mod()" to Python's default syntax of the percent sign (%). I cannot find any "built-in" function (in the Sympy package). I could write one myself, except I want the result to be simplified. In the function that I would create, I've realized that I don't know how to avoid adding extra parentheses. Since I want it in its most simplified form, I would need to use Sympy's simplification. And that would then undo the conversion of "Mod()" to "%". So if there isn't an easy way to convert Sympy's Mod to Python's "%", please tell me there's a way in Sympy to simplify only parentheses. I've looked, and I haven't been able to find that either. I at least want a way to remove redundant parentheses without converting "%" back to "Mod".
Edit:
Here's an example, I want:
Mod(x + 1, 3)
to become:
(x+1)%3
But I don't want:
Mod(x, 3)
to be:
(x)%3
I want it to be:
x%3
Now that I have done a bit of looking into sympy's options for custom printing it looks like it is quite easy to implement:
from sympy.printing.precedence import precedence
from sympy.printing.str import StrPrinter
class MyPrinter(StrPrinter):
def _print_Mod(self,expr):
own_level = precedence(expr)
args = (self.parenthesize(arg, own_level) for arg in expr.args)
return "{} % {}".format(*args)
The printer's method parenthesize takes an expression and a "level" where the level represents the precedence threshold that causes it to actually add brackets around the argument, so it will only put parentheses around operations that need them:
from sympy.abc import x
printer = MyPrinter()
def test(expr):
print(printer.doprint(expr))
>>> test(x%3)
x % 3
>>> test((x+1)%3)
(x + 1) % 3
From my (extremely limited) testing seems to suggest this works fine, also see the note below about own_level.
as shown in the documentation for overriding printing, you can just override Basic.__str__ to use your custom printer when just printing out expressions:
from sympy import Basic
Basic.__str__ = lambda expr, printer=MyPrinter(): printer.doprint(expr)
>>> print(x%3)
x % 3
as a side note - the reason Mod doesn't / can't do this by default is because it apparently inherits from Function:
>>> issubclass(sympy.Mod, sympy.Function)
True
This is why it displays as a function call in pretty much every printing method there is, this also means that modulus has the same precedence as functions:
>>> precedence(x%3)
70
>>> f = sympy.Function("f")
>>> precedence(f(x))
70
>>> print( f(x)%x ) #so it thinks f(x) needs parens here
(f(x)) % x
if you find an appropriate precedence to use for own_level please share it with me as I would love to update my answer.
Hi I am writing Python code which returns the associated Legendre function.
Using numpy poly1d function on this part,
firstTerm = (np.poly1d([-1,0,1]))**(m/2.0) # HELP!
It yields an error since it can only be raised to integer.
Is there any other alternative where I can raise the desired function to power 1/2 and etc.?
The reason you can't raise your poly1d to half-integer power is that that would not be a polynomial, since it would contain square roots.
While in principle you could orthogonalize the functions yourself, or construct the functions from something like sympy.special.legendre, but your safest bet is symbolic math. And hey, we already have sympy.functions.special.polynomials.assoc_legendre! Since symbolic math is slow, you should probably use sympy.lambdify to turn each function into a numerical one:
import sympy as sym
x = sym.symbols('x')
n = 3
m = 1
legfun_sym = sym.functions.special.polynomials.assoc_legendre(n,m,x)
legfun_num = sym.lambdify(x,legfun_sym)
print(legfun_sym)
print(legfun_num)
x0 = 0.25
print(legfun_sym.evalf(subs={x:x0}) - legfun_num(x0))
This prints
-sqrt(-x**2 + 1)*(15*x**2/2 - 3/2)
<function <lambda> at 0x7f0a091976e0>
-1.11022302462516e-16
which seems to make sense (the first is the symbolic function at x, the second shows that lambdify indeed creates a lambda from the function, and the last one is the numerical difference of the two functions at the pseudorandom point x0 = 0.25, and is clearly zero within machine precision).
I tried to work out a python-like language which combined with the feature of MACRO(weird, but just for fun..), for example, the codes to calculate fibonacci seq analyticly is like this:
from math import *
def analytic_fibonacci(n):
sqrt_5 = sqrt(5);
p = (1 + sqrt_5) / 2;
q = 1/p;
return int( (p**n + q**n) / sqrt_5 + 0.5 )
print analytic_fibonacci(10),
And I can rewrite it in the python-like-with-MACRO language like this:
from math import sqrt
sqrt
def analytic_fibonacci(n):
_2(5)
(1+_1)/2
1/_1
return int((_2**n+_1**n)/_3+0.5)
print analytic_fibonacci(10)
The idea is to use line number to expand the expression so that no explicit assignment is needed. The _2 means to replace it with the expression appeared 2 lines smaller than the current line, so the _2 in the 4th line becomes the expression in the 2nd line, which is sqrt, and _2(5) is expanded to sqrt(5). (Lines before current line starts with _, after current line starts with |)
The example above is simple. When I tried to rewrite a more complex example, I encountered problem:
def fibIter(n):
if n < 2:
return n
fibPrev = 1
fib = 1
for num in xrange(2, n):
fibPrev, fib = fib, fib + fibPrev
return fib
I don't know how to use the line-number-based MACRO to express fibPrev, fib = fib, fib + fibPrev. I think some features is missing in this "MACRO langugage" , and fibPrev, fib = fib, fib+fibPrev is expressible if I fixed it.. (I heard that the MACRO in Lisp is Turing Complete so I think the example above should be expressed by MACRO) Does anyone have ideas about this?
I see two ways to interpret your language. Neither is very powerful.
The first way is to literally expand the macros to expressions, rather than values. Then analytic_fibonacci expands to
def analytic_fibonacci(n):
return int(((1+sqrt(5))/2**n+1/(1+sqrt(5))/2**n)/sqrt(5)+0.5)
You probably want some parentheses in there; depending on how you define the language, those may or may not be added for you.
This is pretty useless. Multiple-evaluation problems abound (where a function is reexecuted every time a macro refers to it), and it only lets you do things you could have done with ordinary expressions.
The second interpretation is that every statement consisting of a Python expression implicitly assigns that expression to a variable. This is also pretty useless, because only one statement can assign to any of these implicit variables. There's no way to do
x = 0
for i in range(5):
x += i
because you can't have the equivalent of x refer to either _2 or _0 depending on where the last assignment came from. Also, this really isn't a macro system at all.
Using the second interpretation, we can add a new operator to bring back the power of ordinary variable assignments. We'll call this the merge operator.
merge(_1, _2)
evaluates to either _1 or _2, depending on which was evaluated most recently. If one of the arguments hasn't yet been evaluated, it defaults to the other. fibIter then becomes
def fibIter(n):
if n < 2:
return n
1 # fibPrev
1 # fib
for num in xrange(2, n):
merge(_2, _-1) # temp
merge(_4, _-1) + merge(_3, _0) # fib
_2 # fibPrev
return merge(_2, _5)
This is quite awkward; essentially, we have to replace every use of a variable like x by a merge of every location it could have been assigned. It also requires awkward line counting, making it hard to tell which "variable" is which, and it doesn't handle multiple assignments, for loop targets, etc. I had to use negative indices to refer to future lines, because we need some way to refer to things assigned later.
Lisp macros are more powerful than your language because they let you apply arbitrary Lisp code to your Lisp code. Your language only allows a macro to expand to fixed expressions. A Lisp macro can take arbitrary code as arguments, cut it up, rearrange it, replace parts of it with different things depending on conditionals, recurse, etc. Your macros can't even take arguments.