SymPy - apply limits to an indefinite integral - python

In SymPy, is it possible to apply limits to an indefinite integral and evaluate it?
import sympy
from sympy.abc import theta
y = sympy.sin(theta)
Y_indef = sympy.Integral(y)
Y_def = sympy.Integral(y, (theta, 0, sympy.pi / 2))
Y_def.evalf() produces a number.
I'm looking for something like Y_indef.evalf((theta, 0, sympy.pi/2)) to get the same answer.

I do not know of a direct way, however you can extract the information from Y_indef in order to create a definite integral:
>>> indef = Integral(x)
>>> to_be_integrated, (free_var,) = indef.args
>>> definite = Integral(to_be_integrated, (free_var, 1, 2))
.args is a general attribute containing anything needed to construct most SymPy objects.
Edit: To address the comments to the questions.
SymPy may succeed evaluating definite integral and at the same time fail to solve their indefinite version. This is due to the existence of additional algorithms to be applied to definite integrals.
Both definite and indefinite integrals are instances of the same class. The only difference is what they contain in their .args. The need for different classes is not yet felt, given that SymPy mostly uses Integral as a flag to say that it can not solve the integral (i.e. the integrate function returns Integral when all of the implemented algorithms fail).

Related

Abstract Matrix Algebra and Calculus in sympy

I am doing control engineering and I often face problems of the type below and I want to know if there is a way to deal with this in sympy.
question:
tl:dr: I want to make a MatrixSymbol dependent on a scalar Symbol representing time, to allow differentiation w.r.t. time.
Actual problem: v(t)=[v1(t),v2(t),v3(t)] is a vector function of the time t and I want to calculate the Projection into the direction of v and it's time derivative. In the end I would love to get an expression of v, v.diff(t) and v.T (the transpose).
attempts:
I've tried different things and show the closest one:
This does the algebra I need, but I cannot take derivatives w.r.t. time
v = MatrixSymbol('v',3,1)
# here i'm building the terms I want
projection_v = v*sqrt(v.T*v).inverse()*v.T
orthogonal_v = Identity(3)-projection_v
orthogonal_v.as_explicit()
orthogonal_v shows the abstract equation form that I need. In the end - to check and see the result again, I'd also like to make it explicit and see the expression as a function of v[0,0], v[1,0], and v[2,0] for MatrixSymbol the function .as_explicit() does exactly that beginning with sympy version 1.10. (Thanks Francesco Bonazzi for pointing this out.)
The problem however is, that I cannot make these a function of t and take the derivative of projection_v w.r.t. the time t.
I also tried
t = Symbol('t',real=True,positive=True)
v1 = Function('v1',real=True)(t)
v2 = Function('v2',real=True)(t)
v3 = Function('v3',real=True)(t)
v_mat = FunctionMatrix(3,1,[v1,v2,v3]);
but it seems FunctionMatrix is meant to evaluate the functions directly instead of being an analog to the scalar Function.
Effectively I want to be able to calculate orthogonal_v.diff(t) and then see the component wise operations with something like orthogonal_v.diff(t).as_explicit(). Is this possible?

Python Sympy module NoConvergence: convergence to root failed; try n < 15 or maxsteps > 50

I encountered a problem when I using Sympy to solve problems
Here is my code:
from math import pi, hypot
from sympy import solve, solveset, sqrt, Symbol
one_x=-0.08
one_y=1.28
second_x=0
second_y=0
second_r=7
one_r=7.3
slopes=-16.0000000000 (maybe more trailing 0s)
intercepts=0.0
x=Symbol('x')
solveset(sqrt((x-second_x)**2+(slope*x+intercept-second_y)**2)+second_r-one_r-sqrt((x-one_x)**2+(slope*x+intercept-one_y)**2),x)
That's only part of my code but it raises a lot of errors
but instead, I replaced all of the variables with its value like
x=Symbol('x')
solveset(sqrt((x)**2+((-16)*x)**2)+7-7.3-sqrt((x+0.08)**2+((-16)*x-1.28)**2),x)
It works nicely and i can get an output {-0.0493567429232771}
I think It's because of the type of slopes(-16 compared with -16.000000), I really wanna know why an equation with float number cannot be calculated, and how I can fix it (cause I need it to be more precise so I cannot just ignore the number after the dot )
Thanks so much!
SymPy + algebraic equation + floating point numbers => trouble. Floating point math does not work like normal math, and SymPy is designed for the latter. Small things like 16 (integer) versus 16.0 (float) make a lot of difference in solving equations with SymPy: ideally, you would have no floating point numbers there, creating exact rational numbers instead, like this.
from sympy import S
one_x = S('-0.08')
However, you have floating point data and are looking for a floating point solution. This makes SymPy the wrong tool for the job. SymPy is for doing math with symbols, not for crunching floating point numbers. The correct solution is to use an appropriate solve from SciPy, such as brentq. It takes a bracketing interval as an input (where the function has different signs at both ends). For example:
from scipy.optimize import brentq
eq = lambda x: np.sqrt((x-second_x)**2 + (slope*x+intercept-second_y)**2) + second_r - one_r - np.sqrt((x-one_x)**2 + (slope*x + intercept - one_y)**2)
brentq(eq, -10, 10) # returns -0.049356742923277075
If you stick with SymPy, that means your equation is going outsourced to mpmath library, which is much more limited in the numerical root finding and optimization. To get a solution to converge with its methods, you'll need a really good starting point: apparently, one_x/2 is such a point.
from sympy import sqrt, Symbol, nsolve
# ... as in your code
nsolve(sqrt((x-second_x)**2+(slope*x+intercept-second_y)**2)+second_r-one_r-sqrt((x-one_x)**2+(slope*x+intercept-one_y)**2), one_x/2)
returns -0.0493567429232771.
By using sympy.solveset, which is intended for symbolic solution, you deprive yourself not only of SciPy's powerful numeric solvers, but also of an opportunity to set a good starting value for the numeric search which sympy.nsolve provides. Hence the lack of convergence in this numerically tricky problem. By the way, this is what makes it numerically tricky: the function is nearly constant most of the time, with one rapid change.

Solving a complicated multivariable function with Python

I have a very complicated function of two variables, let's call them x and y. I want to create a Python program where the user can input two values, a and b, where a is the value of that complicated function of x and y, and b = math.atan(y/x). This program should then output the values of x and y.
I am clueless as to where to start. I have tried to make the function into that of just one variable, then generate many random values for x and pick the closest one, but I have learnt that this is horribly inefficient and produces a result which is only accurate to about 2 significant figures, which is pretty horrible. Is there a better way to do this? Many thanks!
(P.S. I did not reveal the function here due to copyright issues. For the sake of example, you can consider the function
a = 4*math.atan(math.sqrt(math.tan(x)*math.tan(y)/math.tan(x+y)))
where y = x * math.tan(b).)
Edit: After using the approach of the sympy library, it appears as though the program ignores my second equation (the complicated one). I suspect it is too complicated for sympy to handle. Thus, I am asking for another approach which does not utilise sympy.
You could use sympy and import the trigonometric functions from sympy.
from sympy.core.symbol import symbols
from sympy.solvers.solveset import nonlinsolve
from sympy import sqrt, tan, atan
y = symbols('y', real=True)
a,b = 4,5 # user-given values
eq2 = a - 4*atan(sqrt(tan(y/tan(b))*tan(y)/tan((y/tan(b))+y)))
S = nonlinsolve( [eq2], [y] )
print(S)
It'll return you a series of conditions ( ConditionSet object ) for possible adequate results.
If that wasn't clear enough, you can read the docs for nonlinsolve.

How to check if a SymPy expression has analytical integral

I want to solve my other question here so I need sympy to return an error whenever there is no analytical/symbolic solution for and integral.
For example if I try :
from sympy import *
init_printing(use_unicode=False, wrap_line=False, no_global=True)
x = Symbol('x')
integrate(1/cos(x**2), x)
It just [pretty] prints the integral itself
without solving and/or giving an error about not being able to solve it!
P.S. I have also asked this question here on Reddit.
A "symbolic" solution always exists: I just invented a new function intcos(x), which by definition is the antiderivative of 1/cos(x**2). Now this integral has a symbolic solution!
For the question to be rigorously answerable, one has to restrict the class of functions allowed in the answer. Typically one considers elementary functions. As SymPy integral reference explains, the Risch algorithm it employs can prove that some functions do not have elementary antiderivatives. Use the option risch=True and check whether the return value is an instance of sympy.integrals.risch.NonElementaryIntegral
from sympy.integrals.risch import NonElementaryIntegral
isinstance(integrate(1/exp(x**2), x, risch=True), NonElementaryIntegral) # True
However, since Risch algorithm implementation is incomplete, in many cases like 1/cos(x**2) it returns an ordinary Integral object. This means it was not able to either find an elementary antiderivative or prove that one does not exist.
For this example, it helps to rewrite the trigonometric function in terms of exponential, with rewrite(cos, exp):
isinstance(integrate((1/cos(x**2)).rewrite(cos, exp), x, risch=True), NonElementaryIntegral)
returns True, so we know the integral is nonelementary.
Non-elementary antiderivatives
But often we don't really need an elementary function; something like Gamma or erf or Bessel functions may be okay; as long as it's some "known" function (which of course is a fuzzy term). The question becomes: how to tell if SymPy was able to integrate a specific expression or not? Use .has(Integral) check for that:
integrate(2/cos(x**2), x).has(Integral) # True
(not isinstance(Integral) because the return value can be, like here, 2*Integral(1/cos(x**2), x).) This does not prove anything other than SymPy's failure to find the antiderivative. The antiderivative may well be a known function, even an elementary one.

Derivative of a conjugate in sympy

When I try to differentiate a symbol with SymPy I get the following
In : x=Symbol('x')
In : diff(x,x)
Out: 1
When I differentiate the symbol respect to its conjugate the result is
In [55]: diff(x,x.conjugate())
Out[55]: 0
However, when I try to differentiate the conjugate of the symbol SymPy doesn't do it
In : diff(x.conjugate(),x)
Out: Derivative(conjugate(x), x)
This is still correct, but the result should be zero. How can I make SimPy perform the derivative of a conjugate?
I'm not sure about the mathematics if diff(conjugate(x), x) should be zero. The fact that diff(x,x.conjugate()) gives zero has nothing to do with mathematics (and might even be considered a SymPy bug). It gives zero simply because x does not contain conjugate(x) (symbolically), so it sees it as a constant with respect to it. This is probably wrong, since x is not a constant with respect to conjugate(x). The fact that SymPy lets you take derivatives with respect to defined functions is probably a bug, actually. It is supposed to allow things like diff(f(x)**2, f(x)), where f = Function('f') is an undefined function, but for defined functions, it is probably mathematically incorrect (or at least not what you expect).
See http://docs.sympy.org/latest/modules/core.html?highlight=derivative#sympy.core.function.Derivative, particularly the section on derivatives wrt non-Symbols. To paraphrase, taking derivatives with respect to a function is just a notational convenience and does not represent a mathematical chain rule. Rather, something like diff(x, conjugate(x)) should be thought of as something like diff(x.subs(conjugate(x), dummy), dummy).subs(dummy, conjugate(x)).
Regarding conjugate(x).diff(x), this gives an unevaluated derivative because no derivative is defined for conjugate. I'm not sure if any closed-form answer is possible here anyway. Probably this is the most useful thing that SymPy could return. I can't find any good answers anywhere as to what a reasonable answer for this should be (you should ask on math SE to get a better answer about it).

Categories

Resources