# simplified solution for trigonometric equations. #11188

Open
wants to merge 25 commits into
from

## Conversation

Projects
None yet
7 participants
Member

### Shekharrajak commented Jun 2, 2016 • edited

###### Master Branch :
``````In [ ]: solveset(cos(x) + cos(3*x) + cos(5*x), x, S.Reals)
Out[ ]:
⎧        π        ⎫   ⎧        3⋅π        ⎫   ⎧        4⋅π        ⎫   ⎧        2⋅π        ⎫   ⎧        5⋅π        ⎫   ⎧        π        ⎫   ⎧
⎨2⋅n⋅π + ─ | n ∊ ℤ⎬ ∪ ⎨2⋅n⋅π + ─── | n ∊ ℤ⎬ ∪ ⎨2⋅n⋅π + ─── | n ∊ ℤ⎬ ∪ ⎨2⋅n⋅π + ─── | n ∊ ℤ⎬ ∪ ⎨2⋅n⋅π + ─── | n ∊ ℤ⎬ ∪ ⎨2⋅n⋅π + ─ | n ∊ ℤ⎬ ∪ ⎨2⋅n⋅π +
⎩        2        ⎭   ⎩         2         ⎭   ⎩         3         ⎭   ⎩         3         ⎭   ⎩         3         ⎭   ⎩        3        ⎭   ⎩

7⋅π        ⎫   ⎧        5⋅π        ⎫   ⎧        11⋅π        ⎫   ⎧        π        ⎫
─── | n ∊ ℤ⎬ ∪ ⎨2⋅n⋅π + ─── | n ∊ ℤ⎬ ∪ ⎨2⋅n⋅π + ──── | n ∊ ℤ⎬ ∪ ⎨2⋅n⋅π + ─ | n ∊ ℤ⎬
6         ⎭   ⎩         6         ⎭   ⎩         6          ⎭   ⎩        6        ⎭

In [ ]:  solveset(sin(x),  x, S.Reals)
Out[ ]: {2⋅n⋅π | n ∊ ℤ} ∪ {2⋅n⋅π + π | n ∊ ℤ}

In [ ]: solveset(tan(x) - 1, x, S.Reals)
Out[ ]:
⎧        5⋅π        ⎫   ⎧        π        ⎫
⎨2⋅n⋅π + ─── | n ∊ ℤ⎬ ∪ ⎨2⋅n⋅π + ─ | n ∊ ℤ⎬
⎩         4         ⎭   ⎩        4        ⎭

In [ ]: solveset(cos(x) , x , S.Reals
Out[ ]:
⎧        π        ⎫   ⎧        3⋅π        ⎫
⎨2⋅n⋅π + ─ | n ∊ ℤ⎬ ∪ ⎨2⋅n⋅π + ─── | n ∊ ℤ⎬
⎩        2        ⎭   ⎩         2         ⎭

In [ ]: solveset(cos(x) + sin(x),  x, S.Reals)
Out[ ]:
⎧        3⋅π        ⎫   ⎧        7⋅π        ⎫
⎨2⋅n⋅π + ─── | n ∊ ℤ⎬ ∪ ⎨2⋅n⋅π + ─── | n ∊ ℤ⎬
⎩         4         ⎭   ⎩         4         ⎭

``````
###### This branch :
``````In [ ]: solveset(cos(x) + cos(3*x) + cos(5*x), x, S.Reals)
Out[ ]:
⎧      π        ⎫   ⎧n⋅π   π        ⎫   ⎧n⋅π   π        ⎫
⎨n⋅π + ─ | n ∊ ℤ⎬ ∪ ⎨─── + ─ | n ∊ ℤ⎬ ∪ ⎨─── + ─ | n ∊ ℤ⎬
⎩      2        ⎭   ⎩ 2    6        ⎭   ⎩ 2    3        ⎭

In [ ]: solveset(sin(x),  x, S.Reals)
Out[ ]: {n⋅π | n ∊ ℤ}

In [ ]: solveset(tan(x) - 1,  x, S.Reals)
Out[ ]:
⎧      π        ⎫
⎨n⋅π + ─ | n ∊ ℤ⎬
⎩      4        ⎭

In [ ]: solveset(cos(x),  x, S.Reals)
Out[ ]:
⎧      π        ⎫
⎨n⋅π + ─ | n ∊ ℤ⎬
⎩      2        ⎭

In [ ]: solveset(cos(x) + sin(x),  x, S.Reals)
Out[ ]:
⎧      π        ⎫
⎨n⋅π - ─ | n ∊ ℤ⎬
⎩      4        ⎭

``````

Also Fixes #10671, #7914, #9606, #9531, #9824

• Description `imageset union`

Member Author

### hargup reviewed Jun 4, 2016

 def _reduce_imageset(soln):

#### hargup Jun 4, 2016

Member

If it is general function (no specific to solveset) it should go in the sets module. Also please add unit test for this function and add examples for this function in the docstring.

#### Shekharrajak Jun 4, 2016

Author Member

@hargup I moved this method into `sets/sets.py` and added tests,docstest.

### Shekharrajak reviewed Jun 5, 2016

 @@ -701,36 +701,34 @@ def test_solve_complex_sqrt(): def test_solveset_complex_tan(): s = solveset_complex(tan(x).rewrite(exp), x)

#### Shekharrajak Jun 5, 2016

Author Member

It is solved by `_solve_as_rational` and returned.

### Shekharrajak reviewed Jun 5, 2016

 @@ -746,19 +744,6 @@ def test_solve_invalid_sol(): @XFAIL def test_solve_trig_simplified():

#### Shekharrajak Jun 5, 2016

Author Member

These were the expected simplified solutions. I edited the `test_solve_trig`.

### Shekharrajak reviewed Jun 5, 2016

 @@ -878,7 +863,7 @@ def test_conditionset(): ConditionSet(x, True, S.Reals) assert solveset(Eq(x**2 + x*sin(x), 1), x, domain=S.Reals) == \ ConditionSet(x, Eq(x*(x + sin(x)) - 1, 0), S.Reals) ConditionSet(x, Eq(x**2 + x*sin(x) - 1, 0), S.Reals)

#### Shekharrajak Jun 5, 2016

Author Member

Both are same actually.

### Shekharrajak reviewed Jun 5, 2016

 @@ -909,7 +894,7 @@ def test_improve_coverage(): x = Symbol('x') y = exp(x+1/x**2) solution = solveset(y**2+y, x, S.Reals) unsolved_object = ConditionSet(x, Eq((exp((x**3 + 1)/x**2) + 1)*exp((x**3 + 1)/x**2), 0), S.Reals) unsolved_object = ConditionSet(x, Eq(exp(2/x**2)*exp(2*x) + exp(x**(-2))*exp(x), 0), S.Reals)

Author Member

Both are same.

### Shekharrajak reviewed Jun 5, 2016

 assert solveset(sinh(x), x, S.Reals) == FiniteSet(0) @SKIP("Comparison Error") def test_issue_7914():

#### Shekharrajak Jun 5, 2016

Author Member

comparison error. I think in LHS `ImageSet(Lambda(n, 2*n*pi - pi/2), S.Integers)` comes but in RHS `ImageSet(Lambda(n, 2*pi*n - pi/2), S.Integers)`. means `2*pi*n` and `2*n*pi` is making it false.

### Shekharrajak reviewed Jun 5, 2016

 assert solveset(sin(y), y, Interval(0, pi)) == \ Intersection(Interval(0, pi), ImageSet(Lambda(n, n*pi), S.Integers))

#### Shekharrajak Jun 5, 2016

Author Member

If you try these examples in current master branch we don't get these simplified solution.

### Shekharrajak reviewed Jun 5, 2016

 # try to solve without converting it into exp form # In this time if ConditionSet is returned then it's # expression will be in Trigonometric Function. return _solve_as_poly(f_orig, symbol, domain)

#### Shekharrajak Jun 5, 2016

Author Member

`_solve_as_poly` can solve some kind of trig equations in given `domain`.

### Shekharrajak reviewed Jun 7, 2016

 @XFAIL def test_simplifed_trig_solution_2():

#### Shekharrajak Jun 7, 2016

Author Member

There may be some cases where we need good way to separate 2-3 imageset to make it simple. Right now for these cases it is returning original solution.

Member Author

### Shekharrajak commented Jun 7, 2016

 A comparison error I didn't understand. Can we use `symbol('n')` instead of `Dummy('n')` . Some error comes because of these, when I union 2 solutions.
Member Author

### Shekharrajak commented Jun 7, 2016

 PR #11201 will remove extra if statement

### aktech reviewed Jun 9, 2016

 def reduce_imageset(soln): """ Try to reduce number of imageset in the args.

#### aktech Jun 9, 2016

Member

Use ~79 characters in a line.

#### Shekharrajak Jun 11, 2016

Author Member

Yeah I am maintaining.

### Shekharrajak reviewed Jun 11, 2016

 # issue #11198 if f.is_Mul: ind, f = f.as_independent(symbol) fact_list = factor_list(f)[1]

#### Shekharrajak Jun 11, 2016

Author Member

`factor` and `factor_list` is used in correct order to get simple solution: gist

Member Author

### Shekharrajak commented Jun 11, 2016

 Please have a look in these failed tests . It works fine. I hope I have replaced the ImageSet expressions `Dummy n` with one `Dummy`.

### Shekharrajak added some commits Jun 9, 2016

``` changes for radical trig eq ```
``` 96368ee ```
``` shifted reduce_imageset into _union of ImageSet ```
``` 48bb187 ```
``` new testcase added ```
``` 4327beb ```
``` new testcase added ```
``` 7632371 ```
``` minor changes ```
```minor changes

minor change2

minor change3

minor changes in docs

checking imageset for _union_simplify```
``` 67c7481 ```
``` minor changes ```
```is_ImageSet using

whitespace removed```
``` aa17c31 ```
``` _union modified ```
``` 547ee56 ```
``` new test added ```
``` 084fe08 ```
``` improved imageset union ```
``` 62c5609 ```
``` simplify the hyperbolic function in _solve_trig ```
``` b548e91 ```
``` hyperbolic testcase added ```
``` dc5052e ```
``` minor change in docs ```
``` 8ba69e1 ```
``` minor change ```
``` 77833cf ```
``` improved imageset union and more testcases added ```
``` 13639a2 ```
``` using is_superset when coeff of lambda variable is not same ```
`more testcases`
``` a42c94e ```
Member Author

### Shekharrajak commented Aug 16, 2016

 the solution is plain wrong, since 4 is in ImageSet(Lambda(n, n+2 ), S.Integers) but not in ImageSet(Lambda(n, 3*n ), S.Integers). ``````img1 = ImageSet(Lambda(n, n+2 ), S.Integers) img2 = ImageSet(Lambda(n, 3*n ), S.Integers) `````` union is img1, since img1 contains `x` where `x ∊ img1 or x ∊ img2` . Also, I don't understand the following logic you have given. Can you give a proof of it and illustrate why it should be true. I have removed this logic in this commit . Now I am using `issuperset`, which does the same thing in better way. In above case ``````In [6]: img1 = ImageSet(Lambda(n, n+2 ), S.Integers) In [7]: img2 = ImageSet(Lambda(n, 3*n ), S.Integers) In [8]: img1.issuperset(img2) Out[8]: True `````` We can get all the values of `img2` using `img1` so union of these is `img1`. Thanks for review. I am fixing conflict.
``` few xfail ```
``` 2f0cbfe ```

Member

### hargup commented Aug 16, 2016

 I'm sorry regarding the union thing, the result it correct.
Member Author

### Shekharrajak commented Aug 16, 2016

 No problem. Please restart this build https://travis-ci.org/sympy/sympy/builds/152597422

### Shekharrajak reviewed Aug 19, 2016

 new_set = s._union(t) # This returns None if s does not know how to intersect # with t. Returns the newly intersected set otherwise if new_set is not None: if not isinstance(new_set, set): new_set = set((new_set, )) new_args = (args - set((s, t))).union(new_set) remv = set((s, t)) new_args = (set(args) - remv).union(new_set)

#### Shekharrajak Aug 19, 2016

Author Member

If we get new set then inner for loop L1212 `break`.

### Shekharrajak reviewed Aug 19, 2016

 break if new_args: new_args = FiniteSet(*[ar for ar in new_args]) args = new_args break

#### Shekharrajak Aug 19, 2016 • edited

Author Member

After the break
it comes here and uses new `args`. Then `break` this `L1208` for loop and starts again(L1208).
So actually it is not removing or updating the elements during the iteration (When update is needed, it is starting fresh with new `args`).

#### Shekharrajak Aug 22, 2016

Author Member

@hargup , after the modification of `args` set , `for` loop will be started again. Is it good for now ?

### hargup reviewed Aug 23, 2016

 break if new_args: new_args = FiniteSet(*[ar for ar in new_args]) args = new_args

#### hargup Aug 23, 2016 • edited

Member

@Shekharrajak as I said above the actual issue is here, as this line modifies the list your are iterating. You need to rewrite the whole block so that this doesn't happen.

#### Shekharrajak Aug 23, 2016 • edited

Author Member

@hargup ,There is `break` after `args = new_args` . So it comes out of the Line 1208 `for` loop and since `while(new_args)` is not none, `for` loop [L1208] will start again with modified `args`.

Whenever `new_set = s._union(t)` new_set is not none (means reduced form comes) , it will modify the `new_args` and `break` the loop, to start again fresh .

`while(new_args)` -- new_args is for just ( `false` or not empty `FiniteSet`) to check whether `args` is modified or not.(means something reduced or not). If `args` is not modified(`new_args` remain `false`) then `while` loop Line 1207 ends.

The issue will come when we do something like this :

``````        while(new_args):
for s in args:
new_args = False
args_without_s = set(args) - set(FiniteSet(s))
args_without_s = FiniteSet(*[ar for ar in args_without_s])
for t in args_without_s:
new_set = s._union(t)
# This returns None if s does not know how to intersect
# with t. Returns the newly intersected set otherwise
if new_set is not None:
if not isinstance(new_set, set):
new_set = set((new_set, ))
remv = set((s, t))
new_args = (set(args) - remv).union(new_set)
# this new_args should be used next time. `new_args` length is `len(args) - 1`. so this loop break.
# and goes to next if condition `if new_args:`.
break
if new_args:
new_args = FiniteSet(*[ar for ar in new_args])
args = new_args
# if here is no break here, it will continue with the loop `for s in args` in Line 1208
# with this modified args. Which will return wrong result.

``````

Open

Open

Open

Open

Open