-
Notifications
You must be signed in to change notification settings - Fork 0
solvers
- NOTE: The audit of the solvers module is not yet complete, so the description given here might not be complete or accurate.
Any univariate polynomial up to degree four can be solved by sympy. It is known that there can be no general formula for solving fifth or higher order polynomials in terms of their radical but nevertheless many special type of higher order polynomials that can be solved by sympy.
sympy.poly.polyroots
holds the code to solve polynomials.
They are basically solved by converting the expression into polynomials with suitable generator. Hyperbolics are rewriten in terms of exponentials and trigonometric functions are written in terms of tan. Then if the expression is a rational expression in tan with a single generator, it is solved as an univariate rational. If it isn't then it is converted to exponential with imaginary coefficients.
For example:
cos(x) + sin(x)
gets converted to (-tan(x/2)**2 + 1)/(tan(x/2)**2 + 1) + 2*tan(x/2)/(tan(x/2)**2 + 1)
This expression has -tan(x/2)**2 + 2*tan(x/2) + 1
as it's numerator. the
solution of this equations is tan(x/2) = 1 +- sqrt(2)
.
But for tan(x) + tan(x/2)
sympy sees it as a polynomial with two generators
viz, tan(x)
and tan(x/2)
, therefore it is further converts the expression
to rational function of exponentials with imaginary powers.
It's a great idea to convert the trigometric expression to rational in tan, but
further converting them to f(e**(I*x)
form can be avoided. For example sympy
cannot solve sin(3*x) + sin(6*x)
though it can solve sin(x) + sin(2*x)
.
A possibly reason is that the degree of the converted f(exp(a*I*x))
gets too
big to handle efficiently.
Any rational function f
with only trigonometric functions a generators can be
converted to another rational function g
with generators as tan(a_1*x)
,
tan(a_2*x)
, tan(a_3*x)
, ... then g
can be further converted to a rational
function h
with a single generator tan(a*x)
where a
is the greatest
common divisor of a_1, a_2, a_3, ...
. This can be solved using polynomial
solving techniques. This can be easily isolated to a single function
_solve_trig
or _trig_solve
.
First the functions is tried to inverted using the inverse attribute associated with the various functions and the _invert
If a total inversion is successful then the rhs is the solutions explain then the function is tried to combined by logcombine
if the expression if of form f(x)**g(x) then the only solution is where f(x) == 0 and g(x) != 0 at the same place. (This is step is complete). It is then converted to form g(x)*log(f(x))
After all this we try to recognize a lambert pattern in the equations and use
_solve_lambert
in to solve it.
As the last resort all the symbols are posified and the solving algo is tried again.
According to the docstring.
Return tuple (i, d) where i
is independent of symbols
and d
contains symbols. i
and d
are obtained after recursively using
algebraic inversion until an uninvertible d
remains. If there are no
free symbols then d
will be zero. Some (but not necessarily all, because
extrageneous roots might have evolved in the process of inversion),
solutions to the expression i - d
will be related to the solutions of
the original expression.
According to the docstring.
The equality, f(x, a..f) = a*log(b*X + c) + d*X - f = 0
has the solution,
X = -c/b + (a/d)*W(d/(a*b)*exp(c*d/a/b)*exp(f/a))
.
For piecewise expressions we find the solution for each expression and then check if it satisfies the conditions. The final solution is union of all the such solutions.
Remark: This is complete we are sure that the solvers will find all the solution of the expressions in the piecewise function.