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

solveset_real need to check symbol in piecewise-condition.Expression with multiple abs ,having Piecewise solution as 0 #10550

Open
wants to merge 22 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
35 changes: 34 additions & 1 deletion sympy/functions/elementary/tests/test_piecewise.py
Expand Up @@ -304,7 +304,40 @@ def test_piecewise_solve():
(-x + 2, x - 2 <= 0), (x - 2, x - 2 > 0))
assert solve(g, x) == [5]

# See issue 4352 (enhance the solver to handle inequalities).

def test_piecewise_solveset():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be in the solveset test suite; you aren't testing Piecewise, you are testing how solveset handles it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found test case for solve just above so copied the same cases for solveset to check it is working correctly or not.
I have shifted the both testcases.

from sympy.sets import FiniteSet
from sympy.solvers.solveset import (
solveset_real, domain_check, solveset_complex, linear_eq_to_matrix,
linsolve, _is_function_class_equation, invert_real, invert_complex,
solveset)

abs2 = Piecewise((-x, x <= 0), (x, x > 0))
f = abs2.subs(x, x - 2)
assert solveset(f, x, S.Reals) == FiniteSet(2)
assert solveset(f - 1, x, S.Reals) == FiniteSet(1, 3)

f = Piecewise(((x - 2)**2, x >= 0), (1, True))
assert solveset(f, x, S.Reals) == FiniteSet(2)

g = Piecewise(((x - 5)**5, x >= 4), (f, True))
assert solveset(g, x, S.Reals) == FiniteSet(2, 5)

g = Piecewise(((x - 5)**5, x >= 4), (f, x < 4))
assert solveset(g, x, S.Reals) == FiniteSet(2, 5)

g = Piecewise(((x - 5)**5, x >= 2), (f, x < 2))
assert solveset(g, x, S.Reals) == FiniteSet(5)

g = Piecewise(((x - 5)**5, x >= 2), (f, True))
assert solveset(g, x, S.Reals) == FiniteSet(5)

g = Piecewise(((x - 5)**5, x >= 2), (f, True), (10, False))
assert solveset(g, x, S.Reals) == FiniteSet(5)

g = Piecewise(((x - 5)**5, x >= 2),
(-x + 2, x - 2 <= 0), (x - 2, x - 2 > 0))
assert solveset(g, x, S.Reals) == FiniteSet(5)


@XFAIL
Expand Down
8 changes: 7 additions & 1 deletion sympy/solvers/solvers.py
Expand Up @@ -1345,7 +1345,10 @@ def _solve(f, *symbols, **flags):

elif f.is_Piecewise:
result = set()
result_added = {}
for n, (expr, cond) in enumerate(f.args):
# for 'cond' result is added : 1 ,not added :0
result_added[cond] = 0
candidates = _solve(piecewise_fold(expr), symbol, **flags)
for candidate in candidates:
if candidate in result:
Expand All @@ -1364,7 +1367,7 @@ def _solve(f, *symbols, **flags):
if other_cond == False:
continue
try:
if other_cond.subs(symbol, candidate) == True:
if (other_cond.subs(symbol, candidate) == True) and (result_added[other_cond] != 0):
matches_other_piece = True
break
except:
Expand All @@ -1377,6 +1380,7 @@ def _solve(f, *symbols, **flags):
(candidate, v),
(S.NaN, True)
))
result_added[cond] = 1
check = False
else:
# first see if it really depends on symbol and whether there
Expand All @@ -1389,6 +1393,8 @@ def _solve(f, *symbols, **flags):
if flags.get('simplify', True):
sol = simplify(sol)
return [sol]
elif f_num is None:
return []

result = False # no solution was obtained
msg = '' # there is no failure message
Expand Down
24 changes: 21 additions & 3 deletions sympy/solvers/solveset.py
Expand Up @@ -487,9 +487,27 @@ def solveset_real(f, symbol):
elif f.is_Piecewise:
result = EmptySet()
expr_set_pairs = f.as_expr_set_pairs()
for (expr, in_set) in expr_set_pairs:
solns = solveset_real(expr, symbol).intersect(in_set)
result = result + solns
expr_cond = {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just write expr_cond = dict(f.args)?

sym_interval ={}
for other_n, (expr_tmp, cond) in enumerate(f.args):
expr_cond[expr_tmp] = cond
for (expr, in_set_symbol) in expr_set_pairs:
solns_tmp = solveset_real(expr, symbol)
# by default symbol interval. many times cond symbols are expr symbols
for sym in expr.atoms(Symbol):
if expr_cond[expr] != True:
cond_symbol_set = expr_cond[expr].atoms(Symbol)
for cond_symbol in cond_symbol_set:
if sym == cond_symbol:
sym_interval[sym] = in_set_symbol
elif sym != cond_symbol:
sym_interval[sym] = (S.Reals)
if not expr.has(Symbol):
solns = solns_tmp.intersect(in_set_symbol)
result = result + solns
else:
solns = solns_tmp.intersect(sym_interval[symbol])
result = result + solns
else:
lhs, rhs_s = invert_real(f, 0, symbol)
if lhs == symbol:
Expand Down
13 changes: 13 additions & 0 deletions sympy/solvers/tests/test_solveset.py
Expand Up @@ -1058,6 +1058,19 @@ def test_issue_9953():
assert linsolve([ ], x) == S.EmptySet


def test_issue_10534():
assert solveset_real(Piecewise((x, y<0), (x + 1, True)), x) == FiniteSet(-1,0)

def test_issue_10122():
from sympy.logic.boolalg import (And, Or)
from sympy.solvers.solvers import solve
assert solveset(abs(x)+abs(1-x)-1>0,x,domain=S.Reals) == Union(Interval.open(-oo, 0), Interval.open(1, oo))
assert solveset(Piecewise((x,x>=0),(-x,True))+Piecewise((x-1,x>=1),(1-x,True))-1>0, x, \
domain=S.Reals) == Union(Interval.open(-oo, 0), Interval.open(1, oo))
# syntax error in below test case
# assert solve(Piecewise((x,x>=0),(-x,True))+Piecewise((x-1,x>=1),(1-x,True))-1>0,x) \
# == Or(And(-oo < x, x < 0), And(1 < x, x < oo))

def test_issue_9913():
assert solveset(2*x + 1/(x - 10)**2, x, S.Reals) == \
FiniteSet(-(3*sqrt(24081)/4 + S(4027)/4)**(S(1)/3)/3 - 100/
Expand Down