Closed oscarbenjamin closed 3 years ago
At the end of checksol
is the val-handling:
if val == was:
continue
elif val.is_Rational:
return val == 0
if numerical and val.is_number:
return (abs(val.n(18).n(12, chop=True)) < 1e-9) is S.true
was = val
A test for a boolean can be made there. if val is S.false, return False
, I think.
My first impression is that the problem is in the caller of checksol rather than checksol itself.
In this example checksol
is called as
In [1]: u = Dummy()
In [2]: checksol(u, u, S.false, minimal=True)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-2-0fdbce3c8e92> in <module>
----> 1 checksol(u, u, S.false, minimal=True)
~/current/sympy/sympy/sympy/solvers/solvers.py in checksol(f, symbol, sol, **flags)
300 elif attempt == 1:
301 if not val.is_number:
--> 302 if not val.is_constant(*list(sol.keys()), simplify=not minimal):
303 return False
304 # there are free symbols -- simple expansion might work
AttributeError: 'BooleanFalse' object has no attribute 'is_constant'
My interpretation of that is we want to check whether the equation u = 0
is solved by u
taking the value False
. Is that really meaningful? As far as I can tell the sol
argument is expected to be an Expr or otherwise the symbol
argument should be a dict mapping symbols to Expr.
I'm guessing this has showed up because of #19054 so this is another example where being cleaner about types shows up bugs.
here is a possible solution:
diff --git a/sympy/solvers/solvers.py b/sympy/solvers/solvers.py
index cdc7a72462..1daa180889 100644
--- a/sympy/solvers/solvers.py
+++ b/sympy/solvers/solvers.py
@@ -274,6 +274,8 @@ def checksol(f, symbol, sol=None, **flags):
if isinstance(f, BooleanAtom):
return bool(f)
+ if f == symbol and isinstance(sol[symbol], BooleanAtom):
+ return bool(f)
elif not f.is_Relational and not f:
return True
I meant to pick this one up, but it's already been resolved by #21602. This issue can be closed.
There is still a bug here because nonlinsolve
returns different numbers of solutions depending on whether the inputs are given as Eq
or as Expr
:
from sympy import *
syms = symbols('x_1:19', real=True)
(x_1, x_2, x_3, x_4, x_5, x_6, x_7, x_8, x_9, x_10,
x_11, x_12, x_13, x_14, x_15, x_16, x_17, x_18) = syms
eqs_expr = [
36*x_1 + 15*x_18**3 - 50*x_18**2 + 6*x_18 - 4,
15*x_18**3 - 50*x_18**2 + 114*x_18 + 36*x_2 - 40,
-15*x_18**3 + 50*x_18**2 - 54*x_18 + 12*x_3 + 28,
x_4 + 1,
-x_18 + x_5,
x_6 - 1,
-15*x_18**3 + 50*x_18**2 - 42*x_18 + 36*x_7 + 4,
15*x_18**3 - 50*x_18**2 + 6*x_18 + 36*x_8 - 4,
15*x_18**3 - 50*x_18**2 + 54*x_18 + 12*x_9 - 16,
x_10 - 3*x_18 + 2,
x_11 - 1,
x_12 + x_18 - 1,
36*x_13 + 15*x_18**3 - 50*x_18**2 + 114*x_18 - 76,
x_14 + 1,
18*x_15 - 15*x_18**3 + 50*x_18**2 - 24*x_18 + 4,
6*x_16 + 15*x_18**3 - 50*x_18**2 + 54*x_18 - 22,
x_17 + 2*x_18 - 1,
15*x_18**4 - 20*x_18**3 + 14*x_18**2 + 8*x_18 - 8
]
eqs_eq = [Eq(e, 0) for e in eqs_expr]
print(len(nonlinsolve(eqs_expr, syms))) # <-- prints 4
print(len(nonlinsolve(eqs_eq, syms))) # <-- prints 2
Looks like for Expr
input, complex/imaginary solutions are included but for Eq
input, they're not. Please see the results for the below code I tried to run.
x = Symbol('x')
y = Symbol('y')
syms = [x,y]
eqs_expr = [y**2 + 1, x + y - 1]
eqs_eq = [Eq(e, 0) for e in eqs_expr]
nonlinsolve(eqs_expr, syms)
---> {(1 - I, I), (1 + I, -I)}
nonlinsolve(eqs_eq, syms)
---> {(1 - y, y)}
Can I work on this issue? I'm a beginner, so would need some guidance. (Please let me know if in case this is not a beginner-friendly issue)
I have cloned the git repo, installed sympy + mpmath and verified that I am able to run sympy. I have also gone through the tutorials to get an overview. I am using PyCharm to navigate through the project. However, I am not sure how to run in debug mode in PyCharm for this project. (I am more comfortable debugging using an IDE rather than pdb, if possible).
Update -- able to run in debug mode now, and noticed that in case of Eq
input, poly equations are categorized as nonpolys. Is this intended?
Would it be correct to use Equality.as_poly()
in _separate_poly_nonpoly()
to convert the Eq
to poly expr instead of categorizing it as nonpoly?
Update -- seems like the above approach cannot handle denominators without tweaking the as_poly() code. Hence, considering converting Eq
to Expr
as below before processing the eq in _separate_poly_nonpoly()
:
# Convert equality to expression
if isinstance(eq, Equality):
eq = eq.lhs - eq.rhs
Update to above change:
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights and the repository exists.
I understand this error has nothing to do with the project but is caused by some authentication issue but any help if possible would be appreciated. Thank you.
What repo are you trying to push to?
@oscarbenjamin I was trying to push to the forked repo - https://github.com/alijosephine/sympy. Guess I had not configured SSH keys correctly. For now, I tried to commit the changes directly to github.
Could you please review the PR and comment in case the approach is wrong or needs further work on it? Also, would like to contribute more to SymPy in other active issues.
This could be closed now, right?
@oscargus there is an unresolved conversation in the PR about using rewrite()
instead of lhs - rhs
. Think that can be marked resolved and then the issue can be closed?
I don't think that discussion matters too much. If the issue is fixed this can be closed.
From stackoverflow: https://stackoverflow.com/questions/61280934/nonlinsolve-in-sympy-giving-imaginary-solutions-when-symbols-are-real
The code
On stackoverflow the reported problem is that real solutions are shown even though the symbols are declared as real. On master I find that an exception is raised: