Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

simplified solution for trigonometric equations. #11188

Open
wants to merge 25 commits into
base: master
from

Conversation

Projects
None yet
7 participants
@Shekharrajak
Copy link
Member

Shekharrajak commented Jun 2, 2016

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

@Shekharrajak Shekharrajak force-pushed the Shekharrajak:gsoc_trig_general branch from f3f63eb to ee39527 Jun 3, 2016

@Shekharrajak

This comment has been minimized.

Copy link
Member Author

Shekharrajak commented Jun 3, 2016




def _reduce_imageset(soln):

This comment has been minimized.

@hargup

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.

This comment has been minimized.

@Shekharrajak

Shekharrajak Jun 4, 2016

Author Member

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

@Shekharrajak Shekharrajak force-pushed the Shekharrajak:gsoc_trig_general branch 3 times, most recently from 5c9d9ef to 190135b Jun 4, 2016

@@ -701,36 +701,34 @@ def test_solve_complex_sqrt():

def test_solveset_complex_tan():
s = solveset_complex(tan(x).rewrite(exp), x)

This comment has been minimized.

@Shekharrajak

Shekharrajak Jun 5, 2016

Author Member

It is solved by _solve_as_rational and returned.

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


@XFAIL
def test_solve_trig_simplified():

This comment has been minimized.

@Shekharrajak

Shekharrajak Jun 5, 2016

Author Member

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

@@ -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)

This comment has been minimized.

@Shekharrajak

Shekharrajak Jun 5, 2016

Author Member

Both are same actually.

@@ -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)

This comment has been minimized.

@Shekharrajak

Shekharrajak Jun 5, 2016

Author Member

Both are same.

assert solveset(sinh(x), x, S.Reals) == FiniteSet(0)

@SKIP("Comparison Error")
def test_issue_7914():

This comment has been minimized.

@Shekharrajak

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.

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


This comment has been minimized.

@Shekharrajak

Shekharrajak Jun 5, 2016

Author Member

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

@Shekharrajak Shekharrajak force-pushed the Shekharrajak:gsoc_trig_general branch from 17cc656 to 53f75da 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)

This comment has been minimized.

@Shekharrajak

Shekharrajak Jun 5, 2016

Author Member

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

@Shekharrajak Shekharrajak force-pushed the Shekharrajak:gsoc_trig_general branch 4 times, most recently from 0c5b2f6 to 2af99dd Jun 5, 2016

@aktech aktech added the GSoC label Jun 6, 2016



@XFAIL
def test_simplifed_trig_solution_2():

This comment has been minimized.

@Shekharrajak

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.

@Shekharrajak

This comment has been minimized.

Copy link
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.

@Shekharrajak

This comment has been minimized.

Copy link
Member Author

Shekharrajak commented Jun 7, 2016

PR #11201 will remove extra if statement

@Shekharrajak Shekharrajak changed the title simplified solution for trigonometric equations. [WIP] simplified solution for trigonometric equations. Jun 7, 2016


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

This comment has been minimized.

@aktech

aktech Jun 9, 2016

Member

Use ~79 characters in a line.

This comment has been minimized.

@Shekharrajak

Shekharrajak Jun 11, 2016

Author Member

Yeah I am maintaining.

@Shekharrajak Shekharrajak force-pushed the Shekharrajak:gsoc_trig_general branch 2 times, most recently from 846de37 to eb7cad6 Jun 10, 2016

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

This comment has been minimized.

@Shekharrajak

Shekharrajak Jun 11, 2016

Author Member

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

@Shekharrajak Shekharrajak changed the title [WIP] simplified solution for trigonometric equations. simplified solution for trigonometric equations. Jun 11, 2016

@Shekharrajak Shekharrajak force-pushed the Shekharrajak:gsoc_trig_general branch from 342e1f3 to 72e3af3 Jun 11, 2016

@Shekharrajak

This comment has been minimized.

Copy link
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

This comment has been minimized.

Copy link
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.

@Shekharrajak Shekharrajak force-pushed the Shekharrajak:gsoc_trig_general branch from 4fbc023 to 2f0cbfe Aug 16, 2016

@hargup

This comment has been minimized.

Copy link
Member

hargup commented Aug 16, 2016

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

@Shekharrajak

This comment has been minimized.

Copy link
Member Author

Shekharrajak commented Aug 16, 2016

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

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)

This comment has been minimized.

@Shekharrajak

Shekharrajak Aug 19, 2016

Author Member

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

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

This comment has been minimized.

@Shekharrajak

Shekharrajak Aug 19, 2016

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).

This comment has been minimized.

@Shekharrajak

Shekharrajak Aug 22, 2016

Author Member

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

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

This comment has been minimized.

@hargup

hargup Aug 23, 2016

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.

This comment has been minimized.

@Shekharrajak

Shekharrajak Aug 23, 2016

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.