I am done

This commit is contained in:
2024-10-30 22:14:35 +01:00
parent 720dc28c09
commit 40e2a747cf
36901 changed files with 5011519 additions and 0 deletions

View File

@ -0,0 +1,35 @@
"""
rename this to test_assumptions.py when the old assumptions system is deleted
"""
from sympy.abc import x, y
from sympy.assumptions.assume import global_assumptions
from sympy.assumptions.ask import Q
from sympy.printing import pretty
def test_equal():
"""Test for equality"""
assert Q.positive(x) == Q.positive(x)
assert Q.positive(x) != ~Q.positive(x)
assert ~Q.positive(x) == ~Q.positive(x)
def test_pretty():
assert pretty(Q.positive(x)) == "Q.positive(x)"
assert pretty(
{Q.positive, Q.integer}) == "{Q.integer, Q.positive}"
def test_global():
"""Test for global assumptions"""
global_assumptions.add(x > 0)
assert (x > 0) in global_assumptions
global_assumptions.remove(x > 0)
assert not (x > 0) in global_assumptions
# same with multiple of assumptions
global_assumptions.add(x > 0, y > 0)
assert (x > 0) in global_assumptions
assert (y > 0) in global_assumptions
global_assumptions.clear()
assert not (x > 0) in global_assumptions
assert not (y > 0) in global_assumptions

View File

@ -0,0 +1,39 @@
from sympy.assumptions import ask, Q
from sympy.assumptions.assume import assuming, global_assumptions
from sympy.abc import x, y
def test_assuming():
with assuming(Q.integer(x)):
assert ask(Q.integer(x))
assert not ask(Q.integer(x))
def test_assuming_nested():
assert not ask(Q.integer(x))
assert not ask(Q.integer(y))
with assuming(Q.integer(x)):
assert ask(Q.integer(x))
assert not ask(Q.integer(y))
with assuming(Q.integer(y)):
assert ask(Q.integer(x))
assert ask(Q.integer(y))
assert ask(Q.integer(x))
assert not ask(Q.integer(y))
assert not ask(Q.integer(x))
assert not ask(Q.integer(y))
def test_finally():
try:
with assuming(Q.integer(x)):
1/0
except ZeroDivisionError:
pass
assert not ask(Q.integer(x))
def test_remove_safe():
global_assumptions.add(Q.integer(x))
with assuming():
assert ask(Q.integer(x))
global_assumptions.remove(Q.integer(x))
assert not ask(Q.integer(x))
assert ask(Q.integer(x))
global_assumptions.clear() # for the benefit of other tests

View File

@ -0,0 +1,283 @@
from sympy.assumptions.ask import (Q, ask)
from sympy.core.symbol import Symbol
from sympy.matrices.expressions.diagonal import (DiagMatrix, DiagonalMatrix)
from sympy.matrices.dense import Matrix
from sympy.matrices.expressions import (MatrixSymbol, Identity, ZeroMatrix,
OneMatrix, Trace, MatrixSlice, Determinant, BlockMatrix, BlockDiagMatrix)
from sympy.matrices.expressions.factorizations import LofLU
from sympy.testing.pytest import XFAIL
X = MatrixSymbol('X', 2, 2)
Y = MatrixSymbol('Y', 2, 3)
Z = MatrixSymbol('Z', 2, 2)
A1x1 = MatrixSymbol('A1x1', 1, 1)
B1x1 = MatrixSymbol('B1x1', 1, 1)
C0x0 = MatrixSymbol('C0x0', 0, 0)
V1 = MatrixSymbol('V1', 2, 1)
V2 = MatrixSymbol('V2', 2, 1)
def test_square():
assert ask(Q.square(X))
assert not ask(Q.square(Y))
assert ask(Q.square(Y*Y.T))
def test_invertible():
assert ask(Q.invertible(X), Q.invertible(X))
assert ask(Q.invertible(Y)) is False
assert ask(Q.invertible(X*Y), Q.invertible(X)) is False
assert ask(Q.invertible(X*Z), Q.invertible(X)) is None
assert ask(Q.invertible(X*Z), Q.invertible(X) & Q.invertible(Z)) is True
assert ask(Q.invertible(X.T)) is None
assert ask(Q.invertible(X.T), Q.invertible(X)) is True
assert ask(Q.invertible(X.I)) is True
assert ask(Q.invertible(Identity(3))) is True
assert ask(Q.invertible(ZeroMatrix(3, 3))) is False
assert ask(Q.invertible(OneMatrix(1, 1))) is True
assert ask(Q.invertible(OneMatrix(3, 3))) is False
assert ask(Q.invertible(X), Q.fullrank(X) & Q.square(X))
def test_singular():
assert ask(Q.singular(X)) is None
assert ask(Q.singular(X), Q.invertible(X)) is False
assert ask(Q.singular(X), ~Q.invertible(X)) is True
@XFAIL
def test_invertible_fullrank():
assert ask(Q.invertible(X), Q.fullrank(X)) is True
def test_invertible_BlockMatrix():
assert ask(Q.invertible(BlockMatrix([Identity(3)]))) == True
assert ask(Q.invertible(BlockMatrix([ZeroMatrix(3, 3)]))) == False
X = Matrix([[1, 2, 3], [3, 5, 4]])
Y = Matrix([[4, 2, 7], [2, 3, 5]])
# non-invertible A block
assert ask(Q.invertible(BlockMatrix([
[Matrix.ones(3, 3), Y.T],
[X, Matrix.eye(2)],
]))) == True
# non-invertible B block
assert ask(Q.invertible(BlockMatrix([
[Y.T, Matrix.ones(3, 3)],
[Matrix.eye(2), X],
]))) == True
# non-invertible C block
assert ask(Q.invertible(BlockMatrix([
[X, Matrix.eye(2)],
[Matrix.ones(3, 3), Y.T],
]))) == True
# non-invertible D block
assert ask(Q.invertible(BlockMatrix([
[Matrix.eye(2), X],
[Y.T, Matrix.ones(3, 3)],
]))) == True
def test_invertible_BlockDiagMatrix():
assert ask(Q.invertible(BlockDiagMatrix(Identity(3), Identity(5)))) == True
assert ask(Q.invertible(BlockDiagMatrix(ZeroMatrix(3, 3), Identity(5)))) == False
assert ask(Q.invertible(BlockDiagMatrix(Identity(3), OneMatrix(5, 5)))) == False
def test_symmetric():
assert ask(Q.symmetric(X), Q.symmetric(X))
assert ask(Q.symmetric(X*Z), Q.symmetric(X)) is None
assert ask(Q.symmetric(X*Z), Q.symmetric(X) & Q.symmetric(Z)) is True
assert ask(Q.symmetric(X + Z), Q.symmetric(X) & Q.symmetric(Z)) is True
assert ask(Q.symmetric(Y)) is False
assert ask(Q.symmetric(Y*Y.T)) is True
assert ask(Q.symmetric(Y.T*X*Y)) is None
assert ask(Q.symmetric(Y.T*X*Y), Q.symmetric(X)) is True
assert ask(Q.symmetric(X**10), Q.symmetric(X)) is True
assert ask(Q.symmetric(A1x1)) is True
assert ask(Q.symmetric(A1x1 + B1x1)) is True
assert ask(Q.symmetric(A1x1 * B1x1)) is True
assert ask(Q.symmetric(V1.T*V1)) is True
assert ask(Q.symmetric(V1.T*(V1 + V2))) is True
assert ask(Q.symmetric(V1.T*(V1 + V2) + A1x1)) is True
assert ask(Q.symmetric(MatrixSlice(Y, (0, 1), (1, 2)))) is True
assert ask(Q.symmetric(Identity(3))) is True
assert ask(Q.symmetric(ZeroMatrix(3, 3))) is True
assert ask(Q.symmetric(OneMatrix(3, 3))) is True
def _test_orthogonal_unitary(predicate):
assert ask(predicate(X), predicate(X))
assert ask(predicate(X.T), predicate(X)) is True
assert ask(predicate(X.I), predicate(X)) is True
assert ask(predicate(X**2), predicate(X))
assert ask(predicate(Y)) is False
assert ask(predicate(X)) is None
assert ask(predicate(X), ~Q.invertible(X)) is False
assert ask(predicate(X*Z*X), predicate(X) & predicate(Z)) is True
assert ask(predicate(Identity(3))) is True
assert ask(predicate(ZeroMatrix(3, 3))) is False
assert ask(Q.invertible(X), predicate(X))
assert not ask(predicate(X + Z), predicate(X) & predicate(Z))
def test_orthogonal():
_test_orthogonal_unitary(Q.orthogonal)
def test_unitary():
_test_orthogonal_unitary(Q.unitary)
assert ask(Q.unitary(X), Q.orthogonal(X))
def test_fullrank():
assert ask(Q.fullrank(X), Q.fullrank(X))
assert ask(Q.fullrank(X**2), Q.fullrank(X))
assert ask(Q.fullrank(X.T), Q.fullrank(X)) is True
assert ask(Q.fullrank(X)) is None
assert ask(Q.fullrank(Y)) is None
assert ask(Q.fullrank(X*Z), Q.fullrank(X) & Q.fullrank(Z)) is True
assert ask(Q.fullrank(Identity(3))) is True
assert ask(Q.fullrank(ZeroMatrix(3, 3))) is False
assert ask(Q.fullrank(OneMatrix(1, 1))) is True
assert ask(Q.fullrank(OneMatrix(3, 3))) is False
assert ask(Q.invertible(X), ~Q.fullrank(X)) == False
def test_positive_definite():
assert ask(Q.positive_definite(X), Q.positive_definite(X))
assert ask(Q.positive_definite(X.T), Q.positive_definite(X)) is True
assert ask(Q.positive_definite(X.I), Q.positive_definite(X)) is True
assert ask(Q.positive_definite(Y)) is False
assert ask(Q.positive_definite(X)) is None
assert ask(Q.positive_definite(X**3), Q.positive_definite(X))
assert ask(Q.positive_definite(X*Z*X),
Q.positive_definite(X) & Q.positive_definite(Z)) is True
assert ask(Q.positive_definite(X), Q.orthogonal(X))
assert ask(Q.positive_definite(Y.T*X*Y),
Q.positive_definite(X) & Q.fullrank(Y)) is True
assert not ask(Q.positive_definite(Y.T*X*Y), Q.positive_definite(X))
assert ask(Q.positive_definite(Identity(3))) is True
assert ask(Q.positive_definite(ZeroMatrix(3, 3))) is False
assert ask(Q.positive_definite(OneMatrix(1, 1))) is True
assert ask(Q.positive_definite(OneMatrix(3, 3))) is False
assert ask(Q.positive_definite(X + Z), Q.positive_definite(X) &
Q.positive_definite(Z)) is True
assert not ask(Q.positive_definite(-X), Q.positive_definite(X))
assert ask(Q.positive(X[1, 1]), Q.positive_definite(X))
def test_triangular():
assert ask(Q.upper_triangular(X + Z.T + Identity(2)), Q.upper_triangular(X) &
Q.lower_triangular(Z)) is True
assert ask(Q.upper_triangular(X*Z.T), Q.upper_triangular(X) &
Q.lower_triangular(Z)) is True
assert ask(Q.lower_triangular(Identity(3))) is True
assert ask(Q.lower_triangular(ZeroMatrix(3, 3))) is True
assert ask(Q.upper_triangular(ZeroMatrix(3, 3))) is True
assert ask(Q.lower_triangular(OneMatrix(1, 1))) is True
assert ask(Q.upper_triangular(OneMatrix(1, 1))) is True
assert ask(Q.lower_triangular(OneMatrix(3, 3))) is False
assert ask(Q.upper_triangular(OneMatrix(3, 3))) is False
assert ask(Q.triangular(X), Q.unit_triangular(X))
assert ask(Q.upper_triangular(X**3), Q.upper_triangular(X))
assert ask(Q.lower_triangular(X**3), Q.lower_triangular(X))
def test_diagonal():
assert ask(Q.diagonal(X + Z.T + Identity(2)), Q.diagonal(X) &
Q.diagonal(Z)) is True
assert ask(Q.diagonal(ZeroMatrix(3, 3)))
assert ask(Q.diagonal(OneMatrix(1, 1))) is True
assert ask(Q.diagonal(OneMatrix(3, 3))) is False
assert ask(Q.lower_triangular(X) & Q.upper_triangular(X), Q.diagonal(X))
assert ask(Q.diagonal(X), Q.lower_triangular(X) & Q.upper_triangular(X))
assert ask(Q.symmetric(X), Q.diagonal(X))
assert ask(Q.triangular(X), Q.diagonal(X))
assert ask(Q.diagonal(C0x0))
assert ask(Q.diagonal(A1x1))
assert ask(Q.diagonal(A1x1 + B1x1))
assert ask(Q.diagonal(A1x1*B1x1))
assert ask(Q.diagonal(V1.T*V2))
assert ask(Q.diagonal(V1.T*(X + Z)*V1))
assert ask(Q.diagonal(MatrixSlice(Y, (0, 1), (1, 2)))) is True
assert ask(Q.diagonal(V1.T*(V1 + V2))) is True
assert ask(Q.diagonal(X**3), Q.diagonal(X))
assert ask(Q.diagonal(Identity(3)))
assert ask(Q.diagonal(DiagMatrix(V1)))
assert ask(Q.diagonal(DiagonalMatrix(X)))
def test_non_atoms():
assert ask(Q.real(Trace(X)), Q.positive(Trace(X)))
@XFAIL
def test_non_trivial_implies():
X = MatrixSymbol('X', 3, 3)
Y = MatrixSymbol('Y', 3, 3)
assert ask(Q.lower_triangular(X+Y), Q.lower_triangular(X) &
Q.lower_triangular(Y)) is True
assert ask(Q.triangular(X), Q.lower_triangular(X)) is True
assert ask(Q.triangular(X+Y), Q.lower_triangular(X) &
Q.lower_triangular(Y)) is True
def test_MatrixSlice():
X = MatrixSymbol('X', 4, 4)
B = MatrixSlice(X, (1, 3), (1, 3))
C = MatrixSlice(X, (0, 3), (1, 3))
assert ask(Q.symmetric(B), Q.symmetric(X))
assert ask(Q.invertible(B), Q.invertible(X))
assert ask(Q.diagonal(B), Q.diagonal(X))
assert ask(Q.orthogonal(B), Q.orthogonal(X))
assert ask(Q.upper_triangular(B), Q.upper_triangular(X))
assert not ask(Q.symmetric(C), Q.symmetric(X))
assert not ask(Q.invertible(C), Q.invertible(X))
assert not ask(Q.diagonal(C), Q.diagonal(X))
assert not ask(Q.orthogonal(C), Q.orthogonal(X))
assert not ask(Q.upper_triangular(C), Q.upper_triangular(X))
def test_det_trace_positive():
X = MatrixSymbol('X', 4, 4)
assert ask(Q.positive(Trace(X)), Q.positive_definite(X))
assert ask(Q.positive(Determinant(X)), Q.positive_definite(X))
def test_field_assumptions():
X = MatrixSymbol('X', 4, 4)
Y = MatrixSymbol('Y', 4, 4)
assert ask(Q.real_elements(X), Q.real_elements(X))
assert not ask(Q.integer_elements(X), Q.real_elements(X))
assert ask(Q.complex_elements(X), Q.real_elements(X))
assert ask(Q.complex_elements(X**2), Q.real_elements(X))
assert ask(Q.real_elements(X**2), Q.integer_elements(X))
assert ask(Q.real_elements(X+Y), Q.real_elements(X)) is None
assert ask(Q.real_elements(X+Y), Q.real_elements(X) & Q.real_elements(Y))
from sympy.matrices.expressions.hadamard import HadamardProduct
assert ask(Q.real_elements(HadamardProduct(X, Y)),
Q.real_elements(X) & Q.real_elements(Y))
assert ask(Q.complex_elements(X+Y), Q.real_elements(X) & Q.complex_elements(Y))
assert ask(Q.real_elements(X.T), Q.real_elements(X))
assert ask(Q.real_elements(X.I), Q.real_elements(X) & Q.invertible(X))
assert ask(Q.real_elements(Trace(X)), Q.real_elements(X))
assert ask(Q.integer_elements(Determinant(X)), Q.integer_elements(X))
assert not ask(Q.integer_elements(X.I), Q.integer_elements(X))
alpha = Symbol('alpha')
assert ask(Q.real_elements(alpha*X), Q.real_elements(X) & Q.real(alpha))
assert ask(Q.real_elements(LofLU(X)), Q.real_elements(X))
e = Symbol('e', integer=True, negative=True)
assert ask(Q.real_elements(X**e), Q.real_elements(X) & Q.invertible(X))
assert ask(Q.real_elements(X**e), Q.real_elements(X)) is None
def test_matrix_element_sets():
X = MatrixSymbol('X', 4, 4)
assert ask(Q.real(X[1, 2]), Q.real_elements(X))
assert ask(Q.integer(X[1, 2]), Q.integer_elements(X))
assert ask(Q.complex(X[1, 2]), Q.complex_elements(X))
assert ask(Q.integer_elements(Identity(3)))
assert ask(Q.integer_elements(ZeroMatrix(3, 3)))
assert ask(Q.integer_elements(OneMatrix(3, 3)))
from sympy.matrices.expressions.fourier import DFT
assert ask(Q.complex_elements(DFT(3)))
def test_matrix_element_sets_slices_blocks():
X = MatrixSymbol('X', 4, 4)
assert ask(Q.integer_elements(X[:, 3]), Q.integer_elements(X))
assert ask(Q.integer_elements(BlockMatrix([[X], [X]])),
Q.integer_elements(X))
def test_matrix_element_sets_determinant_trace():
assert ask(Q.integer(Determinant(X)), Q.integer_elements(X))
assert ask(Q.integer(Trace(X)), Q.integer_elements(X))

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,227 @@
from sympy.assumptions.ask import Q
from sympy.assumptions.refine import refine
from sympy.core.expr import Expr
from sympy.core.numbers import (I, Rational, nan, pi)
from sympy.core.singleton import S
from sympy.core.symbol import Symbol
from sympy.functions.elementary.complexes import (Abs, arg, im, re, sign)
from sympy.functions.elementary.exponential import exp
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.functions.elementary.trigonometric import (atan, atan2)
from sympy.abc import w, x, y, z
from sympy.core.relational import Eq, Ne
from sympy.functions.elementary.piecewise import Piecewise
from sympy.matrices.expressions.matexpr import MatrixSymbol
def test_Abs():
assert refine(Abs(x), Q.positive(x)) == x
assert refine(1 + Abs(x), Q.positive(x)) == 1 + x
assert refine(Abs(x), Q.negative(x)) == -x
assert refine(1 + Abs(x), Q.negative(x)) == 1 - x
assert refine(Abs(x**2)) != x**2
assert refine(Abs(x**2), Q.real(x)) == x**2
def test_pow1():
assert refine((-1)**x, Q.even(x)) == 1
assert refine((-1)**x, Q.odd(x)) == -1
assert refine((-2)**x, Q.even(x)) == 2**x
# nested powers
assert refine(sqrt(x**2)) != Abs(x)
assert refine(sqrt(x**2), Q.complex(x)) != Abs(x)
assert refine(sqrt(x**2), Q.real(x)) == Abs(x)
assert refine(sqrt(x**2), Q.positive(x)) == x
assert refine((x**3)**Rational(1, 3)) != x
assert refine((x**3)**Rational(1, 3), Q.real(x)) != x
assert refine((x**3)**Rational(1, 3), Q.positive(x)) == x
assert refine(sqrt(1/x), Q.real(x)) != 1/sqrt(x)
assert refine(sqrt(1/x), Q.positive(x)) == 1/sqrt(x)
# powers of (-1)
assert refine((-1)**(x + y), Q.even(x)) == (-1)**y
assert refine((-1)**(x + y + z), Q.odd(x) & Q.odd(z)) == (-1)**y
assert refine((-1)**(x + y + 1), Q.odd(x)) == (-1)**y
assert refine((-1)**(x + y + 2), Q.odd(x)) == (-1)**(y + 1)
assert refine((-1)**(x + 3)) == (-1)**(x + 1)
# continuation
assert refine((-1)**((-1)**x/2 - S.Half), Q.integer(x)) == (-1)**x
assert refine((-1)**((-1)**x/2 + S.Half), Q.integer(x)) == (-1)**(x + 1)
assert refine((-1)**((-1)**x/2 + 5*S.Half), Q.integer(x)) == (-1)**(x + 1)
def test_pow2():
assert refine((-1)**((-1)**x/2 - 7*S.Half), Q.integer(x)) == (-1)**(x + 1)
assert refine((-1)**((-1)**x/2 - 9*S.Half), Q.integer(x)) == (-1)**x
# powers of Abs
assert refine(Abs(x)**2, Q.real(x)) == x**2
assert refine(Abs(x)**3, Q.real(x)) == Abs(x)**3
assert refine(Abs(x)**2) == Abs(x)**2
def test_exp():
x = Symbol('x', integer=True)
assert refine(exp(pi*I*2*x)) == 1
assert refine(exp(pi*I*2*(x + S.Half))) == -1
assert refine(exp(pi*I*2*(x + Rational(1, 4)))) == I
assert refine(exp(pi*I*2*(x + Rational(3, 4)))) == -I
def test_Piecewise():
assert refine(Piecewise((1, x < 0), (3, True)), (x < 0)) == 1
assert refine(Piecewise((1, x < 0), (3, True)), ~(x < 0)) == 3
assert refine(Piecewise((1, x < 0), (3, True)), (y < 0)) == \
Piecewise((1, x < 0), (3, True))
assert refine(Piecewise((1, x > 0), (3, True)), (x > 0)) == 1
assert refine(Piecewise((1, x > 0), (3, True)), ~(x > 0)) == 3
assert refine(Piecewise((1, x > 0), (3, True)), (y > 0)) == \
Piecewise((1, x > 0), (3, True))
assert refine(Piecewise((1, x <= 0), (3, True)), (x <= 0)) == 1
assert refine(Piecewise((1, x <= 0), (3, True)), ~(x <= 0)) == 3
assert refine(Piecewise((1, x <= 0), (3, True)), (y <= 0)) == \
Piecewise((1, x <= 0), (3, True))
assert refine(Piecewise((1, x >= 0), (3, True)), (x >= 0)) == 1
assert refine(Piecewise((1, x >= 0), (3, True)), ~(x >= 0)) == 3
assert refine(Piecewise((1, x >= 0), (3, True)), (y >= 0)) == \
Piecewise((1, x >= 0), (3, True))
assert refine(Piecewise((1, Eq(x, 0)), (3, True)), (Eq(x, 0)))\
== 1
assert refine(Piecewise((1, Eq(x, 0)), (3, True)), (Eq(0, x)))\
== 1
assert refine(Piecewise((1, Eq(x, 0)), (3, True)), ~(Eq(x, 0)))\
== 3
assert refine(Piecewise((1, Eq(x, 0)), (3, True)), ~(Eq(0, x)))\
== 3
assert refine(Piecewise((1, Eq(x, 0)), (3, True)), (Eq(y, 0)))\
== Piecewise((1, Eq(x, 0)), (3, True))
assert refine(Piecewise((1, Ne(x, 0)), (3, True)), (Ne(x, 0)))\
== 1
assert refine(Piecewise((1, Ne(x, 0)), (3, True)), ~(Ne(x, 0)))\
== 3
assert refine(Piecewise((1, Ne(x, 0)), (3, True)), (Ne(y, 0)))\
== Piecewise((1, Ne(x, 0)), (3, True))
def test_atan2():
assert refine(atan2(y, x), Q.real(y) & Q.positive(x)) == atan(y/x)
assert refine(atan2(y, x), Q.negative(y) & Q.positive(x)) == atan(y/x)
assert refine(atan2(y, x), Q.negative(y) & Q.negative(x)) == atan(y/x) - pi
assert refine(atan2(y, x), Q.positive(y) & Q.negative(x)) == atan(y/x) + pi
assert refine(atan2(y, x), Q.zero(y) & Q.negative(x)) == pi
assert refine(atan2(y, x), Q.positive(y) & Q.zero(x)) == pi/2
assert refine(atan2(y, x), Q.negative(y) & Q.zero(x)) == -pi/2
assert refine(atan2(y, x), Q.zero(y) & Q.zero(x)) is nan
def test_re():
assert refine(re(x), Q.real(x)) == x
assert refine(re(x), Q.imaginary(x)) is S.Zero
assert refine(re(x+y), Q.real(x) & Q.real(y)) == x + y
assert refine(re(x+y), Q.real(x) & Q.imaginary(y)) == x
assert refine(re(x*y), Q.real(x) & Q.real(y)) == x * y
assert refine(re(x*y), Q.real(x) & Q.imaginary(y)) == 0
assert refine(re(x*y*z), Q.real(x) & Q.real(y) & Q.real(z)) == x * y * z
def test_im():
assert refine(im(x), Q.imaginary(x)) == -I*x
assert refine(im(x), Q.real(x)) is S.Zero
assert refine(im(x+y), Q.imaginary(x) & Q.imaginary(y)) == -I*x - I*y
assert refine(im(x+y), Q.real(x) & Q.imaginary(y)) == -I*y
assert refine(im(x*y), Q.imaginary(x) & Q.real(y)) == -I*x*y
assert refine(im(x*y), Q.imaginary(x) & Q.imaginary(y)) == 0
assert refine(im(1/x), Q.imaginary(x)) == -I/x
assert refine(im(x*y*z), Q.imaginary(x) & Q.imaginary(y)
& Q.imaginary(z)) == -I*x*y*z
def test_complex():
assert refine(re(1/(x + I*y)), Q.real(x) & Q.real(y)) == \
x/(x**2 + y**2)
assert refine(im(1/(x + I*y)), Q.real(x) & Q.real(y)) == \
-y/(x**2 + y**2)
assert refine(re((w + I*x) * (y + I*z)), Q.real(w) & Q.real(x) & Q.real(y)
& Q.real(z)) == w*y - x*z
assert refine(im((w + I*x) * (y + I*z)), Q.real(w) & Q.real(x) & Q.real(y)
& Q.real(z)) == w*z + x*y
def test_sign():
x = Symbol('x', real = True)
assert refine(sign(x), Q.positive(x)) == 1
assert refine(sign(x), Q.negative(x)) == -1
assert refine(sign(x), Q.zero(x)) == 0
assert refine(sign(x), True) == sign(x)
assert refine(sign(Abs(x)), Q.nonzero(x)) == 1
x = Symbol('x', imaginary=True)
assert refine(sign(x), Q.positive(im(x))) == S.ImaginaryUnit
assert refine(sign(x), Q.negative(im(x))) == -S.ImaginaryUnit
assert refine(sign(x), True) == sign(x)
x = Symbol('x', complex=True)
assert refine(sign(x), Q.zero(x)) == 0
def test_arg():
x = Symbol('x', complex = True)
assert refine(arg(x), Q.positive(x)) == 0
assert refine(arg(x), Q.negative(x)) == pi
def test_func_args():
class MyClass(Expr):
# A class with nontrivial .func
def __init__(self, *args):
self.my_member = ""
@property
def func(self):
def my_func(*args):
obj = MyClass(*args)
obj.my_member = self.my_member
return obj
return my_func
x = MyClass()
x.my_member = "A very important value"
assert x.my_member == refine(x).my_member
def test_issue_refine_9384():
assert refine(Piecewise((1, x < 0), (0, True)), Q.positive(x)) == 0
assert refine(Piecewise((1, x < 0), (0, True)), Q.negative(x)) == 1
assert refine(Piecewise((1, x > 0), (0, True)), Q.positive(x)) == 1
assert refine(Piecewise((1, x > 0), (0, True)), Q.negative(x)) == 0
def test_eval_refine():
class MockExpr(Expr):
def _eval_refine(self, assumptions):
return True
mock_obj = MockExpr()
assert refine(mock_obj)
def test_refine_issue_12724():
expr1 = refine(Abs(x * y), Q.positive(x))
expr2 = refine(Abs(x * y * z), Q.positive(x))
assert expr1 == x * Abs(y)
assert expr2 == x * Abs(y * z)
y1 = Symbol('y1', real = True)
expr3 = refine(Abs(x * y1**2 * z), Q.positive(x))
assert expr3 == x * y1**2 * Abs(z)
def test_matrixelement():
x = MatrixSymbol('x', 3, 3)
i = Symbol('i', positive = True)
j = Symbol('j', positive = True)
assert refine(x[0, 1], Q.symmetric(x)) == x[0, 1]
assert refine(x[1, 0], Q.symmetric(x)) == x[0, 1]
assert refine(x[i, j], Q.symmetric(x)) == x[j, i]
assert refine(x[j, i], Q.symmetric(x)) == x[j, i]

View File

@ -0,0 +1,172 @@
from sympy.assumptions.lra_satask import lra_satask
from sympy.logic.algorithms.lra_theory import UnhandledInput
from sympy.assumptions.ask import Q, ask
from sympy.core import symbols, Symbol
from sympy.matrices.expressions.matexpr import MatrixSymbol
from sympy.core.numbers import I
from sympy.testing.pytest import raises, XFAIL
x, y, z = symbols("x y z", real=True)
def test_lra_satask():
im = Symbol('im', imaginary=True)
# test preprocessing of unequalities is working correctly
assert lra_satask(Q.eq(x, 1), ~Q.ne(x, 0)) is False
assert lra_satask(Q.eq(x, 0), ~Q.ne(x, 0)) is True
assert lra_satask(~Q.ne(x, 0), Q.eq(x, 0)) is True
assert lra_satask(~Q.eq(x, 0), Q.eq(x, 0)) is False
assert lra_satask(Q.ne(x, 0), Q.eq(x, 0)) is False
# basic tests
assert lra_satask(Q.ne(x, x)) is False
assert lra_satask(Q.eq(x, x)) is True
assert lra_satask(Q.gt(x, 0), Q.gt(x, 1)) is True
# check that True/False are handled
assert lra_satask(Q.gt(x, 0), True) is None
assert raises(ValueError, lambda: lra_satask(Q.gt(x, 0), False))
# check imaginary numbers are correctly handled
# (im * I).is_real returns True so this is an edge case
raises(UnhandledInput, lambda: lra_satask(Q.gt(im * I, 0), Q.gt(im * I, 0)))
# check matrix inputs
X = MatrixSymbol("X", 2, 2)
raises(UnhandledInput, lambda: lra_satask(Q.lt(X, 2) & Q.gt(X, 3)))
def test_old_assumptions():
# test unhandled old assumptions
w = symbols("w")
raises(UnhandledInput, lambda: lra_satask(Q.lt(w, 2) & Q.gt(w, 3)))
w = symbols("w", rational=False, real=True)
raises(UnhandledInput, lambda: lra_satask(Q.lt(w, 2) & Q.gt(w, 3)))
w = symbols("w", odd=True, real=True)
raises(UnhandledInput, lambda: lra_satask(Q.lt(w, 2) & Q.gt(w, 3)))
w = symbols("w", even=True, real=True)
raises(UnhandledInput, lambda: lra_satask(Q.lt(w, 2) & Q.gt(w, 3)))
w = symbols("w", prime=True, real=True)
raises(UnhandledInput, lambda: lra_satask(Q.lt(w, 2) & Q.gt(w, 3)))
w = symbols("w", composite=True, real=True)
raises(UnhandledInput, lambda: lra_satask(Q.lt(w, 2) & Q.gt(w, 3)))
w = symbols("w", integer=True, real=True)
raises(UnhandledInput, lambda: lra_satask(Q.lt(w, 2) & Q.gt(w, 3)))
w = symbols("w", integer=False, real=True)
raises(UnhandledInput, lambda: lra_satask(Q.lt(w, 2) & Q.gt(w, 3)))
# test handled
w = symbols("w", positive=True, real=True)
assert lra_satask(Q.le(w, 0)) is False
assert lra_satask(Q.gt(w, 0)) is True
w = symbols("w", negative=True, real=True)
assert lra_satask(Q.lt(w, 0)) is True
assert lra_satask(Q.ge(w, 0)) is False
w = symbols("w", zero=True, real=True)
assert lra_satask(Q.eq(w, 0)) is True
assert lra_satask(Q.ne(w, 0)) is False
w = symbols("w", nonzero=True, real=True)
assert lra_satask(Q.ne(w, 0)) is True
assert lra_satask(Q.eq(w, 1)) is None
w = symbols("w", nonpositive=True, real=True)
assert lra_satask(Q.le(w, 0)) is True
assert lra_satask(Q.gt(w, 0)) is False
w = symbols("w", nonnegative=True, real=True)
assert lra_satask(Q.ge(w, 0)) is True
assert lra_satask(Q.lt(w, 0)) is False
def test_rel_queries():
assert ask(Q.lt(x, 2) & Q.gt(x, 3)) is False
assert ask(Q.positive(x - z), (x > y) & (y > z)) is True
assert ask(x + y > 2, (x < 0) & (y <0)) is False
assert ask(x > z, (x > y) & (y > z)) is True
def test_unhandled_queries():
X = MatrixSymbol("X", 2, 2)
assert ask(Q.lt(X, 2) & Q.gt(X, 3)) is None
def test_all_pred():
# test usable pred
assert lra_satask(Q.extended_positive(x), (x > 2)) is True
assert lra_satask(Q.positive_infinite(x)) is False
assert lra_satask(Q.negative_infinite(x)) is False
# test disallowed pred
raises(UnhandledInput, lambda: lra_satask((x > 0), (x > 2) & Q.prime(x)))
raises(UnhandledInput, lambda: lra_satask((x > 0), (x > 2) & Q.composite(x)))
raises(UnhandledInput, lambda: lra_satask((x > 0), (x > 2) & Q.odd(x)))
raises(UnhandledInput, lambda: lra_satask((x > 0), (x > 2) & Q.even(x)))
raises(UnhandledInput, lambda: lra_satask((x > 0), (x > 2) & Q.integer(x)))
def test_number_line_properties():
# From:
# https://en.wikipedia.org/wiki/Inequality_(mathematics)#Properties_on_the_number_line
a, b, c = symbols("a b c", real=True)
# Transitivity
# If a <= b and b <= c, then a <= c.
assert ask(a <= c, (a <= b) & (b <= c)) is True
# If a <= b and b < c, then a < c.
assert ask(a < c, (a <= b) & (b < c)) is True
# If a < b and b <= c, then a < c.
assert ask(a < c, (a < b) & (b <= c)) is True
# Addition and subtraction
# If a <= b, then a + c <= b + c and a - c <= b - c.
assert ask(a + c <= b + c, a <= b) is True
assert ask(a - c <= b - c, a <= b) is True
@XFAIL
def test_failing_number_line_properties():
# From:
# https://en.wikipedia.org/wiki/Inequality_(mathematics)#Properties_on_the_number_line
a, b, c = symbols("a b c", real=True)
# Multiplication and division
# If a <= b and c > 0, then ac <= bc and a/c <= b/c. (True for non-zero c)
assert ask(a*c <= b*c, (a <= b) & (c > 0) & ~ Q.zero(c)) is True
assert ask(a/c <= b/c, (a <= b) & (c > 0) & ~ Q.zero(c)) is True
# If a <= b and c < 0, then ac >= bc and a/c >= b/c. (True for non-zero c)
assert ask(a*c >= b*c, (a <= b) & (c < 0) & ~ Q.zero(c)) is True
assert ask(a/c >= b/c, (a <= b) & (c < 0) & ~ Q.zero(c)) is True
# Additive inverse
# If a <= b, then -a >= -b.
assert ask(-a >= -b, a <= b) is True
# Multiplicative inverse
# For a, b that are both negative or both positive:
# If a <= b, then 1/a >= 1/b .
assert ask(1/a >= 1/b, (a <= b) & Q.positive(x) & Q.positive(b)) is True
assert ask(1/a >= 1/b, (a <= b) & Q.negative(x) & Q.negative(b)) is True
def test_equality():
# test symetry and reflexivity
assert ask(Q.eq(x, x)) is True
assert ask(Q.eq(y, x), Q.eq(x, y)) is True
assert ask(Q.eq(y, x), ~Q.eq(z, z) | Q.eq(x, y)) is True
# test transitivity
assert ask(Q.eq(x,z), Q.eq(x,y) & Q.eq(y,z)) is True
@XFAIL
def test_equality_failing():
# Note that implementing the substitution property of equality
# most likely requires a redesign of the new assumptions.
# See issue #25485 for why this is the case and general ideas
# about how things could be redesigned.
# test substitution property
assert ask(Q.prime(x), Q.eq(x, y) & Q.prime(y)) is True
assert ask(Q.real(x), Q.eq(x, y) & Q.real(y)) is True
assert ask(Q.imaginary(x), Q.eq(x, y) & Q.imaginary(y)) is True

View File

@ -0,0 +1,378 @@
from sympy.assumptions.ask import Q
from sympy.assumptions.assume import assuming
from sympy.core.numbers import (I, pi)
from sympy.core.relational import (Eq, Gt)
from sympy.core.singleton import S
from sympy.core.symbol import symbols
from sympy.functions.elementary.complexes import Abs
from sympy.logic.boolalg import Implies
from sympy.matrices.expressions.matexpr import MatrixSymbol
from sympy.assumptions.cnf import CNF, Literal
from sympy.assumptions.satask import (satask, extract_predargs,
get_relevant_clsfacts)
from sympy.testing.pytest import raises, XFAIL
x, y, z = symbols('x y z')
def test_satask():
# No relevant facts
assert satask(Q.real(x), Q.real(x)) is True
assert satask(Q.real(x), ~Q.real(x)) is False
assert satask(Q.real(x)) is None
assert satask(Q.real(x), Q.positive(x)) is True
assert satask(Q.positive(x), Q.real(x)) is None
assert satask(Q.real(x), ~Q.positive(x)) is None
assert satask(Q.positive(x), ~Q.real(x)) is False
raises(ValueError, lambda: satask(Q.real(x), Q.real(x) & ~Q.real(x)))
with assuming(Q.positive(x)):
assert satask(Q.real(x)) is True
assert satask(~Q.positive(x)) is False
raises(ValueError, lambda: satask(Q.real(x), ~Q.positive(x)))
assert satask(Q.zero(x), Q.nonzero(x)) is False
assert satask(Q.positive(x), Q.zero(x)) is False
assert satask(Q.real(x), Q.zero(x)) is True
assert satask(Q.zero(x), Q.zero(x*y)) is None
assert satask(Q.zero(x*y), Q.zero(x))
def test_zero():
"""
Everything in this test doesn't work with the ask handlers, and most
things would be very difficult or impossible to make work under that
model.
"""
assert satask(Q.zero(x) | Q.zero(y), Q.zero(x*y)) is True
assert satask(Q.zero(x*y), Q.zero(x) | Q.zero(y)) is True
assert satask(Implies(Q.zero(x), Q.zero(x*y))) is True
# This one in particular requires computing the fixed-point of the
# relevant facts, because going from Q.nonzero(x*y) -> ~Q.zero(x*y) and
# Q.zero(x*y) -> Equivalent(Q.zero(x*y), Q.zero(x) | Q.zero(y)) takes two
# steps.
assert satask(Q.zero(x) | Q.zero(y), Q.nonzero(x*y)) is False
assert satask(Q.zero(x), Q.zero(x**2)) is True
def test_zero_positive():
assert satask(Q.zero(x + y), Q.positive(x) & Q.positive(y)) is False
assert satask(Q.positive(x) & Q.positive(y), Q.zero(x + y)) is False
assert satask(Q.nonzero(x + y), Q.positive(x) & Q.positive(y)) is True
assert satask(Q.positive(x) & Q.positive(y), Q.nonzero(x + y)) is None
# This one requires several levels of forward chaining
assert satask(Q.zero(x*(x + y)), Q.positive(x) & Q.positive(y)) is False
assert satask(Q.positive(pi*x*y + 1), Q.positive(x) & Q.positive(y)) is True
assert satask(Q.positive(pi*x*y - 5), Q.positive(x) & Q.positive(y)) is None
def test_zero_pow():
assert satask(Q.zero(x**y), Q.zero(x) & Q.positive(y)) is True
assert satask(Q.zero(x**y), Q.nonzero(x) & Q.zero(y)) is False
assert satask(Q.zero(x), Q.zero(x**y)) is True
assert satask(Q.zero(x**y), Q.zero(x)) is None
@XFAIL
# Requires correct Q.square calculation first
def test_invertible():
A = MatrixSymbol('A', 5, 5)
B = MatrixSymbol('B', 5, 5)
assert satask(Q.invertible(A*B), Q.invertible(A) & Q.invertible(B)) is True
assert satask(Q.invertible(A), Q.invertible(A*B)) is True
assert satask(Q.invertible(A) & Q.invertible(B), Q.invertible(A*B)) is True
def test_prime():
assert satask(Q.prime(5)) is True
assert satask(Q.prime(6)) is False
assert satask(Q.prime(-5)) is False
assert satask(Q.prime(x*y), Q.integer(x) & Q.integer(y)) is None
assert satask(Q.prime(x*y), Q.prime(x) & Q.prime(y)) is False
def test_old_assump():
assert satask(Q.positive(1)) is True
assert satask(Q.positive(-1)) is False
assert satask(Q.positive(0)) is False
assert satask(Q.positive(I)) is False
assert satask(Q.positive(pi)) is True
assert satask(Q.negative(1)) is False
assert satask(Q.negative(-1)) is True
assert satask(Q.negative(0)) is False
assert satask(Q.negative(I)) is False
assert satask(Q.negative(pi)) is False
assert satask(Q.zero(1)) is False
assert satask(Q.zero(-1)) is False
assert satask(Q.zero(0)) is True
assert satask(Q.zero(I)) is False
assert satask(Q.zero(pi)) is False
assert satask(Q.nonzero(1)) is True
assert satask(Q.nonzero(-1)) is True
assert satask(Q.nonzero(0)) is False
assert satask(Q.nonzero(I)) is False
assert satask(Q.nonzero(pi)) is True
assert satask(Q.nonpositive(1)) is False
assert satask(Q.nonpositive(-1)) is True
assert satask(Q.nonpositive(0)) is True
assert satask(Q.nonpositive(I)) is False
assert satask(Q.nonpositive(pi)) is False
assert satask(Q.nonnegative(1)) is True
assert satask(Q.nonnegative(-1)) is False
assert satask(Q.nonnegative(0)) is True
assert satask(Q.nonnegative(I)) is False
assert satask(Q.nonnegative(pi)) is True
def test_rational_irrational():
assert satask(Q.irrational(2)) is False
assert satask(Q.rational(2)) is True
assert satask(Q.irrational(pi)) is True
assert satask(Q.rational(pi)) is False
assert satask(Q.irrational(I)) is False
assert satask(Q.rational(I)) is False
assert satask(Q.irrational(x*y*z), Q.irrational(x) & Q.irrational(y) &
Q.rational(z)) is None
assert satask(Q.irrational(x*y*z), Q.irrational(x) & Q.rational(y) &
Q.rational(z)) is True
assert satask(Q.irrational(pi*x*y), Q.rational(x) & Q.rational(y)) is True
assert satask(Q.irrational(x + y + z), Q.irrational(x) & Q.irrational(y) &
Q.rational(z)) is None
assert satask(Q.irrational(x + y + z), Q.irrational(x) & Q.rational(y) &
Q.rational(z)) is True
assert satask(Q.irrational(pi + x + y), Q.rational(x) & Q.rational(y)) is True
assert satask(Q.irrational(x*y*z), Q.rational(x) & Q.rational(y) &
Q.rational(z)) is False
assert satask(Q.rational(x*y*z), Q.rational(x) & Q.rational(y) &
Q.rational(z)) is True
assert satask(Q.irrational(x + y + z), Q.rational(x) & Q.rational(y) &
Q.rational(z)) is False
assert satask(Q.rational(x + y + z), Q.rational(x) & Q.rational(y) &
Q.rational(z)) is True
def test_even_satask():
assert satask(Q.even(2)) is True
assert satask(Q.even(3)) is False
assert satask(Q.even(x*y), Q.even(x) & Q.odd(y)) is True
assert satask(Q.even(x*y), Q.even(x) & Q.integer(y)) is True
assert satask(Q.even(x*y), Q.even(x) & Q.even(y)) is True
assert satask(Q.even(x*y), Q.odd(x) & Q.odd(y)) is False
assert satask(Q.even(x*y), Q.even(x)) is None
assert satask(Q.even(x*y), Q.odd(x) & Q.integer(y)) is None
assert satask(Q.even(x*y), Q.odd(x) & Q.odd(y)) is False
assert satask(Q.even(abs(x)), Q.even(x)) is True
assert satask(Q.even(abs(x)), Q.odd(x)) is False
assert satask(Q.even(x), Q.even(abs(x))) is None # x could be complex
def test_odd_satask():
assert satask(Q.odd(2)) is False
assert satask(Q.odd(3)) is True
assert satask(Q.odd(x*y), Q.even(x) & Q.odd(y)) is False
assert satask(Q.odd(x*y), Q.even(x) & Q.integer(y)) is False
assert satask(Q.odd(x*y), Q.even(x) & Q.even(y)) is False
assert satask(Q.odd(x*y), Q.odd(x) & Q.odd(y)) is True
assert satask(Q.odd(x*y), Q.even(x)) is None
assert satask(Q.odd(x*y), Q.odd(x) & Q.integer(y)) is None
assert satask(Q.odd(x*y), Q.odd(x) & Q.odd(y)) is True
assert satask(Q.odd(abs(x)), Q.even(x)) is False
assert satask(Q.odd(abs(x)), Q.odd(x)) is True
assert satask(Q.odd(x), Q.odd(abs(x))) is None # x could be complex
def test_integer():
assert satask(Q.integer(1)) is True
assert satask(Q.integer(S.Half)) is False
assert satask(Q.integer(x + y), Q.integer(x) & Q.integer(y)) is True
assert satask(Q.integer(x + y), Q.integer(x)) is None
assert satask(Q.integer(x + y), Q.integer(x) & ~Q.integer(y)) is False
assert satask(Q.integer(x + y + z), Q.integer(x) & Q.integer(y) &
~Q.integer(z)) is False
assert satask(Q.integer(x + y + z), Q.integer(x) & ~Q.integer(y) &
~Q.integer(z)) is None
assert satask(Q.integer(x + y + z), Q.integer(x) & ~Q.integer(y)) is None
assert satask(Q.integer(x + y), Q.integer(x) & Q.irrational(y)) is False
assert satask(Q.integer(x*y), Q.integer(x) & Q.integer(y)) is True
assert satask(Q.integer(x*y), Q.integer(x)) is None
assert satask(Q.integer(x*y), Q.integer(x) & ~Q.integer(y)) is None
assert satask(Q.integer(x*y), Q.integer(x) & ~Q.rational(y)) is False
assert satask(Q.integer(x*y*z), Q.integer(x) & Q.integer(y) &
~Q.rational(z)) is False
assert satask(Q.integer(x*y*z), Q.integer(x) & ~Q.rational(y) &
~Q.rational(z)) is None
assert satask(Q.integer(x*y*z), Q.integer(x) & ~Q.rational(y)) is None
assert satask(Q.integer(x*y), Q.integer(x) & Q.irrational(y)) is False
def test_abs():
assert satask(Q.nonnegative(abs(x))) is True
assert satask(Q.positive(abs(x)), ~Q.zero(x)) is True
assert satask(Q.zero(x), ~Q.zero(abs(x))) is False
assert satask(Q.zero(x), Q.zero(abs(x))) is True
assert satask(Q.nonzero(x), ~Q.zero(abs(x))) is None # x could be complex
assert satask(Q.zero(abs(x)), Q.zero(x)) is True
def test_imaginary():
assert satask(Q.imaginary(2*I)) is True
assert satask(Q.imaginary(x*y), Q.imaginary(x)) is None
assert satask(Q.imaginary(x*y), Q.imaginary(x) & Q.real(y)) is True
assert satask(Q.imaginary(x), Q.real(x)) is False
assert satask(Q.imaginary(1)) is False
assert satask(Q.imaginary(x*y), Q.real(x) & Q.real(y)) is False
assert satask(Q.imaginary(x + y), Q.real(x) & Q.real(y)) is False
def test_real():
assert satask(Q.real(x*y), Q.real(x) & Q.real(y)) is True
assert satask(Q.real(x + y), Q.real(x) & Q.real(y)) is True
assert satask(Q.real(x*y*z), Q.real(x) & Q.real(y) & Q.real(z)) is True
assert satask(Q.real(x*y*z), Q.real(x) & Q.real(y)) is None
assert satask(Q.real(x*y*z), Q.real(x) & Q.real(y) & Q.imaginary(z)) is False
assert satask(Q.real(x + y + z), Q.real(x) & Q.real(y) & Q.real(z)) is True
assert satask(Q.real(x + y + z), Q.real(x) & Q.real(y)) is None
def test_pos_neg():
assert satask(~Q.positive(x), Q.negative(x)) is True
assert satask(~Q.negative(x), Q.positive(x)) is True
assert satask(Q.positive(x + y), Q.positive(x) & Q.positive(y)) is True
assert satask(Q.negative(x + y), Q.negative(x) & Q.negative(y)) is True
assert satask(Q.positive(x + y), Q.negative(x) & Q.negative(y)) is False
assert satask(Q.negative(x + y), Q.positive(x) & Q.positive(y)) is False
def test_pow_pos_neg():
assert satask(Q.nonnegative(x**2), Q.positive(x)) is True
assert satask(Q.nonpositive(x**2), Q.positive(x)) is False
assert satask(Q.positive(x**2), Q.positive(x)) is True
assert satask(Q.negative(x**2), Q.positive(x)) is False
assert satask(Q.real(x**2), Q.positive(x)) is True
assert satask(Q.nonnegative(x**2), Q.negative(x)) is True
assert satask(Q.nonpositive(x**2), Q.negative(x)) is False
assert satask(Q.positive(x**2), Q.negative(x)) is True
assert satask(Q.negative(x**2), Q.negative(x)) is False
assert satask(Q.real(x**2), Q.negative(x)) is True
assert satask(Q.nonnegative(x**2), Q.nonnegative(x)) is True
assert satask(Q.nonpositive(x**2), Q.nonnegative(x)) is None
assert satask(Q.positive(x**2), Q.nonnegative(x)) is None
assert satask(Q.negative(x**2), Q.nonnegative(x)) is False
assert satask(Q.real(x**2), Q.nonnegative(x)) is True
assert satask(Q.nonnegative(x**2), Q.nonpositive(x)) is True
assert satask(Q.nonpositive(x**2), Q.nonpositive(x)) is None
assert satask(Q.positive(x**2), Q.nonpositive(x)) is None
assert satask(Q.negative(x**2), Q.nonpositive(x)) is False
assert satask(Q.real(x**2), Q.nonpositive(x)) is True
assert satask(Q.nonnegative(x**3), Q.positive(x)) is True
assert satask(Q.nonpositive(x**3), Q.positive(x)) is False
assert satask(Q.positive(x**3), Q.positive(x)) is True
assert satask(Q.negative(x**3), Q.positive(x)) is False
assert satask(Q.real(x**3), Q.positive(x)) is True
assert satask(Q.nonnegative(x**3), Q.negative(x)) is False
assert satask(Q.nonpositive(x**3), Q.negative(x)) is True
assert satask(Q.positive(x**3), Q.negative(x)) is False
assert satask(Q.negative(x**3), Q.negative(x)) is True
assert satask(Q.real(x**3), Q.negative(x)) is True
assert satask(Q.nonnegative(x**3), Q.nonnegative(x)) is True
assert satask(Q.nonpositive(x**3), Q.nonnegative(x)) is None
assert satask(Q.positive(x**3), Q.nonnegative(x)) is None
assert satask(Q.negative(x**3), Q.nonnegative(x)) is False
assert satask(Q.real(x**3), Q.nonnegative(x)) is True
assert satask(Q.nonnegative(x**3), Q.nonpositive(x)) is None
assert satask(Q.nonpositive(x**3), Q.nonpositive(x)) is True
assert satask(Q.positive(x**3), Q.nonpositive(x)) is False
assert satask(Q.negative(x**3), Q.nonpositive(x)) is None
assert satask(Q.real(x**3), Q.nonpositive(x)) is True
# If x is zero, x**negative is not real.
assert satask(Q.nonnegative(x**-2), Q.nonpositive(x)) is None
assert satask(Q.nonpositive(x**-2), Q.nonpositive(x)) is None
assert satask(Q.positive(x**-2), Q.nonpositive(x)) is None
assert satask(Q.negative(x**-2), Q.nonpositive(x)) is None
assert satask(Q.real(x**-2), Q.nonpositive(x)) is None
# We could deduce things for negative powers if x is nonzero, but it
# isn't implemented yet.
def test_prime_composite():
assert satask(Q.prime(x), Q.composite(x)) is False
assert satask(Q.composite(x), Q.prime(x)) is False
assert satask(Q.composite(x), ~Q.prime(x)) is None
assert satask(Q.prime(x), ~Q.composite(x)) is None
# since 1 is neither prime nor composite the following should hold
assert satask(Q.prime(x), Q.integer(x) & Q.positive(x) & ~Q.composite(x)) is None
assert satask(Q.prime(2)) is True
assert satask(Q.prime(4)) is False
assert satask(Q.prime(1)) is False
assert satask(Q.composite(1)) is False
def test_extract_predargs():
props = CNF.from_prop(Q.zero(Abs(x*y)) & Q.zero(x*y))
assump = CNF.from_prop(Q.zero(x))
context = CNF.from_prop(Q.zero(y))
assert extract_predargs(props) == {Abs(x*y), x*y}
assert extract_predargs(props, assump) == {Abs(x*y), x*y, x}
assert extract_predargs(props, assump, context) == {Abs(x*y), x*y, x, y}
props = CNF.from_prop(Eq(x, y))
assump = CNF.from_prop(Gt(y, z))
assert extract_predargs(props, assump) == {x, y, z}
def test_get_relevant_clsfacts():
exprs = {Abs(x*y)}
exprs, facts = get_relevant_clsfacts(exprs)
assert exprs == {x*y}
assert facts.clauses == \
{frozenset({Literal(Q.odd(Abs(x*y)), False), Literal(Q.odd(x*y), True)}),
frozenset({Literal(Q.zero(Abs(x*y)), False), Literal(Q.zero(x*y), True)}),
frozenset({Literal(Q.even(Abs(x*y)), False), Literal(Q.even(x*y), True)}),
frozenset({Literal(Q.zero(Abs(x*y)), True), Literal(Q.zero(x*y), False)}),
frozenset({Literal(Q.even(Abs(x*y)), False),
Literal(Q.odd(Abs(x*y)), False),
Literal(Q.odd(x*y), True)}),
frozenset({Literal(Q.even(Abs(x*y)), False),
Literal(Q.even(x*y), True),
Literal(Q.odd(Abs(x*y)), False)}),
frozenset({Literal(Q.positive(Abs(x*y)), False),
Literal(Q.zero(Abs(x*y)), False)})}

View File

@ -0,0 +1,50 @@
from sympy.assumptions.ask import Q
from sympy.core.basic import Basic
from sympy.core.expr import Expr
from sympy.core.mul import Mul
from sympy.core.symbol import symbols
from sympy.logic.boolalg import (And, Or)
from sympy.assumptions.sathandlers import (ClassFactRegistry, allargs,
anyarg, exactlyonearg,)
x, y, z = symbols('x y z')
def test_class_handler_registry():
my_handler_registry = ClassFactRegistry()
# The predicate doesn't matter here, so just pass
@my_handler_registry.register(Mul)
def fact1(expr):
pass
@my_handler_registry.multiregister(Expr)
def fact2(expr):
pass
assert my_handler_registry[Basic] == (frozenset(), frozenset())
assert my_handler_registry[Expr] == (frozenset(), frozenset({fact2}))
assert my_handler_registry[Mul] == (frozenset({fact1}), frozenset({fact2}))
def test_allargs():
assert allargs(x, Q.zero(x), x*y) == And(Q.zero(x), Q.zero(y))
assert allargs(x, Q.positive(x) | Q.negative(x), x*y) == And(Q.positive(x) | Q.negative(x), Q.positive(y) | Q.negative(y))
def test_anyarg():
assert anyarg(x, Q.zero(x), x*y) == Or(Q.zero(x), Q.zero(y))
assert anyarg(x, Q.positive(x) & Q.negative(x), x*y) == \
Or(Q.positive(x) & Q.negative(x), Q.positive(y) & Q.negative(y))
def test_exactlyonearg():
assert exactlyonearg(x, Q.zero(x), x*y) == \
Or(Q.zero(x) & ~Q.zero(y), Q.zero(y) & ~Q.zero(x))
assert exactlyonearg(x, Q.zero(x), x*y*z) == \
Or(Q.zero(x) & ~Q.zero(y) & ~Q.zero(z), Q.zero(y)
& ~Q.zero(x) & ~Q.zero(z), Q.zero(z) & ~Q.zero(x) & ~Q.zero(y))
assert exactlyonearg(x, Q.positive(x) | Q.negative(x), x*y) == \
Or((Q.positive(x) | Q.negative(x)) &
~(Q.positive(y) | Q.negative(y)), (Q.positive(y) | Q.negative(y)) &
~(Q.positive(x) | Q.negative(x)))

View File

@ -0,0 +1,39 @@
from sympy.assumptions.ask import Q
from sympy.assumptions.wrapper import (AssumptionsWrapper, is_infinite,
is_extended_real)
from sympy.core.symbol import Symbol
from sympy.core.assumptions import _assume_defined
def test_all_predicates():
for fact in _assume_defined:
method_name = f'_eval_is_{fact}'
assert hasattr(AssumptionsWrapper, method_name)
def test_AssumptionsWrapper():
x = Symbol('x', positive=True)
y = Symbol('y')
assert AssumptionsWrapper(x).is_positive
assert AssumptionsWrapper(y).is_positive is None
assert AssumptionsWrapper(y, Q.positive(y)).is_positive
def test_is_infinite():
x = Symbol('x', infinite=True)
y = Symbol('y', infinite=False)
z = Symbol('z')
assert is_infinite(x)
assert not is_infinite(y)
assert is_infinite(z) is None
assert is_infinite(z, Q.infinite(z))
def test_is_extended_real():
x = Symbol('x', extended_real=True)
y = Symbol('y', extended_real=False)
z = Symbol('z')
assert is_extended_real(x)
assert not is_extended_real(y)
assert is_extended_real(z) is None
assert is_extended_real(z, Q.extended_real(z))