chore: 添加虚拟环境到仓库
- 添加 backend_service/venv 虚拟环境 - 包含所有Python依赖包 - 注意:虚拟环境约393MB,包含12655个文件
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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]
|
||||
@@ -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 symmetry 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
|
||||
@@ -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)})}
|
||||
@@ -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)))
|
||||
@@ -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))
|
||||
Reference in New Issue
Block a user