# Solveset and Solver Module

This wiki contains ideas to improve `solveset` and `solver` module.

## Trigonometric Equation

I come across an idea (during discussion in google group ) that can solve the trigonometric equation g = 0 where g is a trigonometric polynomial. We can convert that into a polynomial system by expanding the sines and cosines in it, replacing `sin(x)` and `cos(x)` by two new variables `s` and `c`. before that need to check arguments are same or not.It should not be like `sin(x)` and `cos(x**2)`. So now we have two variables and 1 equation another equation we know is :`s2 + c2 − 1 = 0`.Means `sin(x)**2 + cos(x)**2 =1`. Similarly we can solve others like `tan`,`sec` ; `cot`,`cosec` .But I think it will be better if we convert all the trigonometric functions into `sin` and `cos` ,and solve them for all cases .Then we don't need to add same types of codes. It needed another method solveset_trig which converts the trigonometric equation to `sin`, `cos` form , if it is not in this form.Then polynomial system replacing `sin(x)` and `cos(x)` by two new variables `s` and `c`.Then using linsolve we will get solution(s) returned, Now replacing `s -> sin` and `c-> cos` and then solveset_real can easily solve Eq(sin(x),) types of expressions. If we have equations like : `sin(x)**3 + cos(3*x) = 0` then using fu module and trigsimp method we can get : `s**3 + 4*(c**3) - 3*c =0 #(cos(3*x) expand)` Similar things can be applied for hyperbolic functions. Failure case may occur when we have nested elements. and equations like :

``````1 − 2cosθ1 + 2cosθ2 − 2cosθ3 = −0.8
1 − 2cos(5*θ1) + 2cos(5*θ2) − 2cos(5*θ3) = 0
1 − 2cos(7*θ1) + 2cos(7*θ2) − 2cos(7*θ3) = 0
``````

The main issues on trigonometric I found are https://github.com/sympy/sympy/issues/10217 and https://github.com/sympy/sympy/issues/9824 (nested expressions)

One of the good way may be using general function decomposition https://github.com/sympy/sympy/pull/9831

`````` >>> decompogen(sin(cos(x)), x)
[sin(x), cos(x)]
>>> decompogen(sin(x)**2 + sin(x) + 1, x)
[x**2 + x + 1, sin(x)]
>>> decompogen(sqrt(6*x**2 - 5), x)
[sqrt(x), 6*x**2 - 5]
>>> decompogen(sin(sqrt(cos(x**2 + 1))), x)
[sin(x), sqrt(x), cos(x), x**2 + 1]
``````

so now we get the expressions in `x` and functions also.By solving these functions top to bottom recursively ,will lead to final result. This may solve all types of nested equations (right now solveset can't solve nested modulo/Trig equations properly ) problems. but to solve this

``````1 − 2cosθ1 + 2cosθ2 − 2cosθ3 = −0.8
1 − 2cos(5*θ1) + 2cos(5*θ2) − 2cos(5*θ3) = 0
1 − 2cos(7*θ1) + 2cos(7*θ2) − 2cos(7*θ3) = 0
``````

there is need of function solver in solveset and improved decompogen to solve some complicated nested linear system ,equations and trigonometric equations.I found that docs have some examples to solve simple functions like:

``````>>> solve(f(x) - x, f(x))
[x]
``````

but it can solve only simple equations.

``````>>> solve(Eq(-(f(x)**2 - 1)/f(x)**3,t - (x - 2)/x**2),f(x))
# take long long time
``````

Issue: 7914 Solveset is not able to solve simple trigonometric equations like

``````eq = sin(2*x)*cos(x) + cos(2*x)*sin(x)-1
print solveset(eq,x, S.Reals)
``````

Even it is not returning correct answer for : `solveset(sin(3*x),x, S.Reals)` types of simple equations.

This PR https://github.com/sympy/sympy/pull/10552 is returning

`````` >>> print solveset(sin(3*x)-1,x, S.Reals)
ImageSet(Lambda(_n, 2*_n*pi - pi/2), Integers()) U ImageSet(Lambda(_n, 2*_n*pi + pi/6), Integers())
U ImageSet(Lambda(_n, 2*_n*pi + 5*pi/6), Integers())
``````

Answer seems correct, but I feel something better changes should be there. It gives correct answer for this type of equations also

``````  >>> print solveset(sin(pi*(x-5)/3),x,S.Reals)
ImageSet(Lambda(_n, 3*(2*_n*pi - 2*pi/3)/(2*pi)), Integers())
``````

solving this type of equation is easy with exp form that sympy do, but before rewriting them into exp form need better expression in `sin`, `cos` form so that sympy can handle exp form of this and return exact answer ,that is needed.

fu module have few basic formulas for trig equations.We can add many basic formulas in it .

There are many more trigonometric identitieslike

``````   >>> Sum(sin(n*pi/n), (n,1,m)).doit()
0
>>> product(sin(n*pi/n), (n,1,m)).doit()
m
>>> asin(x) + acos(x)
acos(x) + asin(x)   # ans is pi/2
``````

11th revision addition: After some more research I found another good way to solve this:

``````1 − 2cosθ1 + 2cosθ2 − 2cosθ3 = −0.8
1 − 2cos(5*θ1) + 2cos(5*θ2) − 2cos(5*θ3) = 0
1 − 2cos(7*θ1) + 2cos(7*θ2) − 2cos(7*θ3) = 0
``````

Replace/substitute `θ1` to `t1` and `expand` `trig = true`. Now all is in `cos` ,substitute `cos(t1)` to `x` , `cos(t2)` to `y` ,`cos(t3)` to `z`. collect the equation in `(x,y,z)` now it is non-linear equation system, that can be solved using `solver`.

``````     eq1=(1 - 2*cos(t1) + 2*cos(t2) - 2*cos(t3) + 0.8).expand(trig=True)
eq2=(1 - 2*cos(5*t1) + 2*cos(5*t2) - 2*cos(5*t3) ).expand(trig=True)
eq3=(1 - 2*cos(7*t1) + 2*cos(7*t2) - 2*cos(7*t3) ).expand(trig=True)
``````

These step should be internal and return directly result.

## Inverse Trigonometric Function

If solveset is able to solve all types of inverse trig equations then using this we may get a way to solve `solveset(sin(3*x)-1,x, S.Reals)` this types of problem without converting them into exp form. Using fu module we can convert Mul, divide sin ,cos equation to single argument then it's inverse may lead to proper answer.

``````>>> acos(S(1)/2)
pi/3
>>> asin(-S(1)/2)
-pi/6
``````

so these should return general solution Some genral solutions

## Simplified general form for Trigonometric solution

Right now `Sympy` returns not simplified general form.If you paste this `solveset(cos(x) + cos(3*x) + cos(5*x),x)` then you will get

`ImageSet(Lambda(_n, 2*_n*pi + pi/2), Integers()) U ImageSet(Lambda(_n, 2*_n*pi - pi/2), Integers()) U ImageSet(Lambda(_n, 2*_n*pi - 2*pi/3), Integers()) U ImageSet(Lambda(_n, 2*_n*pi + 2*pi/3), Integers()) U ImageSet(Lambda(_n, 2*_n*pi - pi/3), Integers()) U ImageSet(Lambda(_n, 2*_n*pi + pi/3), Integers()) U ImageSet(Lambda(_n, 2*_n*pi - 5*pi/6), Integers()) U ImageSet(Lambda(_n, 2*_n*pi + 5*pi/6), Integers()) U ImageSet(Lambda(_n, 2*_n*pi - pi/6), Integers()) U ImageSet(Lambda(_n, 2*_n*pi + pi/6), Integers())`

which can be simplified as `(2*n +1)*pi/6`, `(2*n -1)*pi/6`. Similarly many other solutions can be simplified. I found a solution for this after some discussion in Quora, thanks to active Mathematicians in Quora:

If we have terms like `pi/6`, `pi/2`, `5*pi/6`, `7*pi/6`, `3*pi/2`. One way of approaching a sequence like this is this:

• Take differences until the differences are all equal. In this case, the first differences are all pi/3. This indicates that you can fit a linear function in nn . If it had been necessary to calculate the second differences then one would have had to fit a quadratic function in nn . And so on. Very often one can calculate all possible differences without reaching equal differences. Then it's necessary to try something else.
• Since a linear function will work fit `a*n+b`, where `a` and `b` are arbitrary constants. To do this, set: `pi/6=a+b` (using the first term) and `pi/2=2*a+b` (using the second term), then solve for `a` and `b` . Now you have a function that should represent all of the terms.

So actually we need a method that can make general from from the given terms. Some part of above steps,I tried to implement here : https://github.com/sympy/sympy/pull/10713

Right now `Sympy`

``````           >>> solveset(sin(x), x)
{2⋅n⋅π | n ∊ ℤ} ∪ {2⋅n⋅π + π | n ∊ ℤ}
``````

but this should be `imageset(Lambda(n, n*pi), S.Integers)`

I opened a PR https://github.com/sympy/sympy/pull/10552 which gives simplified answer for this simple equation, but not for all.It passes testcase .If we add above steps then it can returns simplified solution for all.

##Non linear system

I found that one of the good way may be substitution method (for simple cases ) and Using the Quadratic Formula ( some complicated cases ).

There are other ways also but to solve all types of Non linear system this method will be usefull and I have checked that many times we get multiple solution in non linear system and sympy is able to solve any type of equation that we get after the substitution.

## Integer solution of a linear equation having two variables

Right now

``````  >>> print solveset(172*x + 20*y -1000,x, S.Integers)
Intersection(Integers(), {-5*y/43 + 250/43})
>>> print solve(172*x + 20*y -1000)
[{x: -5*y/43 + 250/43}]
``````

`solve` returns correct answer but if we want to get solution for `S.Integers` then need to shift to `solveset`. Integer solution is `x = 8 + 22t` and `y = -1 - 5t` `solveset` is defined to solve only for single variable, need extension here, so that we get solution for multiple variable also like `solve`. one good example is https://github.com/sympy/sympy/pull/1790

``````    >>> solve(x**y - 1)
[{x: 1}, {y: 0}]
``````

and then implement _ Diophantine equation_ algorithm to solve `ax + by = c` for integer solution of `x`,`y`. It is easy to implement as we have to find `gcd(a,b)` and `n`,`m`.Some good ways are in below links, I hope these can be converted into code with some good effort. After the discussion found that `Diophantine` is implemented in `diophantine` module but not connected with solveset. To connect these; `solveset` must be able to pass more than 1 variable for solution. Another thing is we can add `Finiteset`, `ConditionSet`, `ImageSet` they are not implemented in `Diophantine`.

Reference :

## Inequalities

`````` >>> solveset(x**4 - 7*(x**2) + 4*x + 20 >=0,x ,S.Reals)
(-∞, ∞)  # ans is 2
>>> solve(x**4 - 7*(x**2) + 4*x + 20 >=0,x)
-∞ < x ∧ x < ∞   # ans is 2
``````

I found this example here : http://www.cantab.net/users/henry.liu/inequalities.pdf In this link almost all the examples can't be done using sympy right now. Some main feature that can be added is : `minimise`, `maximize` etc. Reference : https://reference.wolfram.com/language/tutorial/MinimizationAndMaximization.html

Also there is need of `checksol` for inequalities also , so that we can directly check whether a number satisfies the inequality or not.

``````   >>> checksol( 2*(x-5) <= 4*x , x ,-5)
raise TypeError("cannot determine truth value of Relational")
TypeError: cannot determine truth value of Relational
``````

more examples

## Solving Transcendental Equations

Right now `solver` and `solveset` can't solve exponential and logarithm equations, like :

``````   >>> print solveset(5**(x**2) - 5**(6-x),x, S.Reals)
ConditionSet(x, Eq(5**(x**2) - 5**(-x + 6), 0), (-oo, oo)
``````

but it can easily solve `x**2 - (6-x)` equation so just need some work ,here. To solve more complicated equations like

``````  solveset(2**(4*y+1)- 3**(y),y, S.Reals)
and
>>> solveset(log(10) + log(7-x) - log(x),x, S.Reals)
{x | x ∊ ℝ ∧ -log(x) + log(-x + 7) + log(10) = 0}
>>> solveset(log(10) + log(7-x) - log(x),x)
{x | x ∊ ℂ ∧ -log(x) + log(-x + 7) + log(10) = 0}
``````

need some change.It can solve these types of equations `solveset(10**(5-x) - 8,x, S.Reals)`. More examples are here : http://tutorial.math.lamar.edu/Classes/Alg/SolveExpEqns.aspx

``````         >>> solveset(x**(2*a) + 2*(x**a) +1,x,S.Reals)
⎧             2⋅a      a        ⎫
⎨x | x ∊ ℂ ∧ x    + 2⋅x  + 1 = 0⎬
⎩                               ⎭
>>> solve(x**(2*a) + 2*(x**a) +1,x)
⎡a ____⎤
⎣╲╱ -1 ⎦
``````

Need to implement `log`,`exp` and `Pow` type equation solver efficiently.

``````      >>> solveset((x+log(x))**2 - 5*(x+log(x)) + 6 ,x)
⎧                               2                   ⎫
⎨x | x ∊ ℂ ∧ -5⋅x + (x + log(x))  - 5⋅log(x) + 6 = 0⎬
⎩                                                   ⎭
``````

so `solveset` can't handle transcendental equation. So first need to implement transcendental equation solver in solveset.Then we can solve `solveset(x+log(x)-3,x)`.

``````      >>> solveset(x+log(x)-3,x)
{x | x ∊ ℂ ∧ x + log(x) - 3 = 0}
``````

We can solve above problem by factorizing `(x+log(x))**2 - 5*(x+log(x))`.

We can't solve `solveset(x+ log(x) -2,x)`, basically `LambertW` is not implemented. We need to rewrite `_tsolve` for `solveset` using `bivariate.py`.

## Multivariate polynomial equations

If we have large expression ,that can be factorized then it should be better that, first we factorize the expression and then solve each factor. Some good algorithms I found are

If we can't factorize then one of the good way is Solving Symbolic Equations with PRESS .

Right now solveset can't solve multivariate polynomial equation system . For example :

I found a good way to solve these types of equations in this link (page 9 example 2.2) http://people.math.gatech.edu/~aleykin3/math4803spr13/BOOK/chapter1.pdf

So here we need to construct a `Res(f1,f2 )` matrix.I hope this method will work for most of the equation. After the discussion I found that multivariate polynomial equation system can be solved using `solve_poly_system` in `polysys.py` so need to improve this method and implement in solveset.

As there is no issue in `solve_poly_system` so it is better to call the functions present in `polysys.py` inside the solveset and then convert the solution into the `Set` ,as solveset do.

## Handling large expression and nested operation

Priority : low. sympy stuck when it get many symbols and operators in single expression during the execution.but works fine if we do this one by one means

``````        >>> a =10**10
>>> a = a**10
>>> a =a**10
>>> print a
``````

To solve this ,one of the good way can be using `Expression tree` . tree construction. More info

This can solve some issue for solvers because in some cases it stuck,it can't store/execute next line for these large expression.Another way can be `split()` which will split the express into token.

### Previous discussion

##### Clone this wiki locally
You can’t perform that action at this time.
Press h to open a hovercard with more details.