How to handle exceptions raised from sympy integrate - sympy

I am starting to learn sympy. I tried one integration problem using sympy, and I get this exception:
File "/home/me/anaconda3/lib/python3.6/site-
packages/sympy/polys/domains/domain.py",
line 146,
in convert raise CoercionFailed("can't convert %s of type %s to %s" %
(element, type(element), self))
sympy.polys.polyerrors.CoercionFailed: can't convert (_x4*a + a)**0.5 of
type
<class 'sympy.core.power.Pow'> to RR(a,f,n,A,B)
[_A0,_A1,_A2,_A3,_A4,_A5,_A6,_A7,_A8,_A9,_A10,_A11,
_A12,_A13,_A14,_A15,_A16,_A17
...
raise ValueError("expected an expression convertible to a polynomial in %s,
got %s" % (self, expr))
ValueError: expected an expression convertible to a polynomial in
Polynomial ring in
The full message is very long. There is a good chance I am doing something wrong? as I just started learning sympy. This is the code I used
from sympy import *
import traceback
import logging
logging.basicConfig(filename='sympy_err.log')
x, A, B, f, e, c, d, a, b, n = symbols('x A B f e c d a b n', real=True)
try:
integrate((d*sin(f*x+e))**n*(a+a*sin(f*x+e))**(5/2)*(A+B*sin(f*x+e)),x)
except Exception as e:
logging.error(traceback.format_exc())
The expected antiderivative is
-((2*a^3*(2*B*(115 + 203*n + 104*n^2 + 16*n^3) + A*
(301 + 478*n + 224*n^2 + 32*n^3))*
Cos[e + f*x]*Hypergeometric2F1[1/2, -n, 3/2, 1 - Sin[e + f*x]]*
(d*Sin[e + f*x])^n)/
Sin[e + f*x]^n/(f*(3 + 2*n)*(5 + 2*n)*(7 + 2*n)*
Sqrt[a + a*Sin[e + f*x]])) -
(2*a^3*(2*B*(35 + 23*n + 4*n^2) + A*(77 + 50*n + 8*n^2))*
Cos[e + f*x]*
(d*Sin[e + f*x])^(1 + n))/(d*f*(3 + 2*n)*(5 + 2*n)*(7 + 2*n)*
Sqrt[a + a*Sin[e + f*x]]) -
(2*a^2*(2*B*(5 + n) + A*(7 + 2*n))*Cos[e + f*x]*
(d*Sin[e + f*x])^(1 + n)*
Sqrt[a + a*Sin[e + f*x]])/(d*f*(5 + 2*n)*
(7 + 2*n)) - (2*a*B*Cos[e + f*x]*(d*Sin[e + f*x])^(1 + n)*
(a + a*Sin[e + f*x])^(3/2))/(d*f*(7 + 2*n))
My question is: Is the way I am catching exceptions from sympy above OK? Since I do not know what exceptions will be raied. And is this something to be expected if sympy unable to solve an integral, to throw an exception?
I am using Linux, just installed latest Anaconda 64bit on Linux.
code>conda list sympy
# packages in environment at /home/me/anaconda3:
#
sympy 1.0 py36_0

The exception you're seeing should be considered a bug in SymPy.
But note that the 5/2 in the expression is being evaluated to a floating point number by Python, which makes SymPy have a harder time with it. It is usually a good idea to use rational powers in SymPy instead of floating point ones. So the right version would be integrate((d*sin(f*x+e))**n*(a+a*sin(f*x+e))**Rational(5, 2)*(A+B*sin(f*x+e)),x). However, SymPy currently hangs on this integral (don't bother letting it finish; it won't find the answer).
So the short of it is: the exception you're seeing is a bug, and SymPy can't compute the integral currently anyway.

Related

How in sympy Disable unnecessary parenthesis?

Tell me please, How to forbid to open brackets? For example,
8 * (x + 1) It should be that way, not 8 * x + 8
Using evaluate = False doesn't help
The global evaluate flag will allow you to do this in the most natural manner:
>>> with evaluate(False):
... 8*(x+1)
...
8*(x + 1)
Otherwise, Mul(8, x + 1, evaluate=False) is a lower level way to do this. And conversion from a string (already in that form) is possible as
>>> S('8*(x+1)',evaluate=False)
8*(x + 1)
In general, SymPy will convert the expression to its internal format, which includes some minimal simplifications. For example, sqrt is represented internally as Pow(x,1/2). Also, some reordering of terms may happen.
In your specific case, you could try:
from sympy import factor
from sympy.abc import x, y
y = x + 1
g = 8 * y
g = factor(g)
print(g) # "8 * (x + 1)"
But, if for example you have g = y * y, SymPy will either represent it as a second power ((x + 1)**2), or expand it to x**2 + 2*x + 1.
PS: See also this answer by SymPy's maintainer for some possible workarounds. (It might complicate things later when you would like to evaluate or simplify this expression in other calculations.)
How about sympy.collect_const(sympy.S("8 * (x + 1)"), 8)?
In general you might be interested in some of these expression manipulations: https://docs.sympy.org/0.7.1/modules/simplify/simplify.html

sympy CSE: avoid pow/powf

When Sympy generates C code,
is there a way to enforce CSE optimizations for pow (or powf) occurrences in an expression?
For example, this code snippet
c, s = symbols('c s')
myexpr = c**6/1800 - c**5/100 - 0.00833333333333333*c**4*s**2 + 19*c**4/200 + 0.1*c**3*s**2 - 9*c**3/20 + c**2*s**4/120 - 0.57*c**2*s**2 + 43*c**2/40 - c*s**4/20 + 1.35*c*s**2 + 23*c/50 - 0.000555555555555556*s**6 + 19*s**4/200 - 1.075*s**2 - 2107/1800
import sympy
from sympy.codegen.ast import real, float64
sub_exprs,final_expr = sympy.cse([myexpr])
for var,expr in sub_exprs : print "const real", printing.ccode(expr, standard='C99', assign_to=var, type_aliases={real: float64})
print "return ",printing.ccode(final_expr[0], standard='C99', type_aliases={real: float64}),";"
produces the following disappointing output:
const real x0 = pow(c, 2);
const real x1 = pow(c, 3);
const real x2 = pow(c, 4);
const real x3 = pow(s, 2);
const real x4 = pow(s, 4);
return (1.0/1800.0)*pow(c, 6) - 1.0/100.0*pow(c, 5) + 1.3500000000000001*c*x3 - 1.0/20.0*c*x4 + (23.0/50.0)*c - 0.00055555555555555599*pow(s, 6) - 0.56999999999999995*x0*x3 + (1.0/120.0)*x0*x4 + (43.0/40.0)*x0 + 0.10000000000000001*x1*x3 - 9.0/20.0*x1 - 0.0083333333333333297*x2*x3 + (19.0/200.0)*x2 - 1.075*x3 + (19.0/200.0)*x4 - 2107.0/1800.0 ;
Pow optimizations have been completely ignored.
What is the workaround for this?
Remark: I saw that this issue is partially mentioned here:
"The code printers don’t print optimal code in many cases. An example of this is powers in C. x**2 prints as pow(x, 2) instead of x*x. Other optimizations (like mathematical simplifications) should happen before the code printers."
The CSE routine in sympy is not perfect (improved CSE is listed as an area for improvement), e.g.:
>>> sympy.cse([x**4, x**3*y])
([], [x**4, x**3*y])
Expanding pow in the printer or before the printer has been discussed some time, there is now a create_expand_pow optimization which can help some:
>>> expand_opt = create_expand_pow_optimization(3)
>>> expand_opt(x**5 + x**3)
x**5 + x*x*x
Note however that most compilers will already generate optimal assembly (regardless of CSE in the source code) if you pass them the right optimization flags.

why sympy count_ops() fail on this result from integration?

I use sympy's count_opt as a way to estimate size (leaf count) of antiderivative returned by integrate.
http://docs.sympy.org/latest/modules/core.html
I found it fails on some expressions. This is using sympy 1.1.1 on
Python 3.6.5 |Anaconda, Inc.| (default, Apr 29 2018, 16:14:56)
[GCC 7.2.0] on linux
Here is an example
from sympy import *
x,n,a = symbols('x n a')
integrand = x**n*log(a*x)
anti= integrate(integrand,x)
count_ops(anti)
and now
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/opt/anaconda/lib/python3.6/site-packages/sympy/core/function.py",
line 2473, in count_ops
if a.is_Rational:
AttributeError: 'NoneType' object has no attribute 'is_Rational'
Something about this result it does not like
>>> anti
Piecewise((None, Eq(n, -1)), (n*x*x**n*log(a)/(n**2 + 2*n + 1) +
n*x*x**n*log(x)/(n**2 + 2*n + 1) + x*x**n*log(a)/(n**2 + 2*n + 1) +
x*x**n*log(x)/(n**2 + 2*n + 1) - x*x**n/(n**2 + 2*n + 1), True))
Is this a known issue? Why does it happen? Is this a bug? Should I report it? How?
The above is on linux Manjaro 17.1 XFCE
The function count_ops does not expect to see None, which sometimes appears in a Piecewise object. I'd say this is a bug. It was already reported on SymPy issue tracker.
A workaround is to pass conds='none' to integrate, which will cause it to ignore the special case n=-1 and return a single expression,
n*x*x**n*log(a)/(n**2 + 2*n + 1) + n*x*x**n*log(x)/(n**2 + 2*n + 1) + x*x**n*log(a)/(n**2 + 2*n + 1) + x*x**n*log(x)/(n**2 + 2*n + 1) - x*x**n/(n**2 + 2*n + 1)
Then count_ops works correctly.
anti = integrate(integrand, x, conds='none')
count_ops(anti) # 49

Solving ODE equation with assumptions with SymPy

I'm solving an ODE equation:
from sympy import *
E5 = Function('E5')
t = Symbol('t')
ode = Eq(Derivative(E5(t), t),
-3*E5(t)/(-10*sqrt(6) + 30)
+ sqrt(6)*E5(t)/(-10*sqrt(6) + 30)
- 67*sqrt(2)*exp(-sqrt(3)*t/10)/(200*(-sqrt(6) + 3))
+ sqrt(3)*exp(-sqrt(3)*t/10)/(10*(-sqrt(6) + 3))
+ 47*sqrt(2)*exp(-sqrt(2)*t/10)/(200*(-sqrt(6) + 3)))
dsolve(ode)
and it works (after waiting few minutes), but fails once I replace Function('E5') with Function('E5', real=True) or Symbol('t') with Symbol('t', real=True). Namely dsolve(ode) raises TypeError("eq should be an instance of Equality"). This is because dsolve(ode, simplify=False) returns False instead of an Equation. And the latter I don't know why. Is it impossible to use dsolve with assumptions? I need them because they let me symplify expressions and otherwise my expressions get too complicated and take too long to calculate.
Do you have any ideas why this could be happening?

Expression involving modular exponentiations in C++

I am wanting to evaluate the expression, (an + bn + cn) % 1000000003 , in C++. I a getting overflow errors when n is very large. Can someone help me with this ? More specifically a = q + 1, b = - 2 * q and c = q - 1. I have been following the function outlined in this
Can I break (an + bn + cn) % 1000000003 into (an) % 1000000003 + (bn) % 100000003 + (cn) % 1000000003 or something similar ?
Also I cannot use anything more than unsigned long long int
You can distribute your modulo. Mathematically, this will be sound:
( ((a^n)%1000000003) + ((b^n)%100000003) + ((c^n)%1000000003) ) % 1000000003;
This will prevent you from having to compute numbers that are out of bounds, allowing you to choose larger values for n.
Proof.
Just be sure to use pow in the math.h module:
( ((pow(a, n))%1000000003)
+ ((pow(b, n))%100000003)
+ ((pow(c, n))%1000000003) ) % 1000000003;