diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/algebras/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/algebras/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c86801b28ecc77b9709275201484cfa37a945c77 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/algebras/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/algebras/__pycache__/quaternion.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/algebras/__pycache__/quaternion.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0c89141261507e01c64ae8c3ef0b51e7b350d494 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/algebras/__pycache__/quaternion.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/algebras/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/algebras/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/algebras/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/algebras/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b7c3ad19f9cfbe10eb606e5e09bf0482cb1f0d5c Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/algebras/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/algebras/tests/__pycache__/test_quaternion.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/algebras/tests/__pycache__/test_quaternion.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e48efb336af7403af5efc35c1527b7473a90caf6 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/algebras/tests/__pycache__/test_quaternion.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/algebras/tests/test_quaternion.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/algebras/tests/test_quaternion.py new file mode 100644 index 0000000000000000000000000000000000000000..a4331cd6afa05c96e8e11d59df4b7520e4810930 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/algebras/tests/test_quaternion.py @@ -0,0 +1,437 @@ +from sympy.testing.pytest import slow +from sympy.core.function import diff +from sympy.core.function import expand +from sympy.core.numbers import (E, I, Rational, pi) +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.elementary.complexes import (Abs, conjugate, im, re, sign) +from sympy.functions.elementary.exponential import log +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (acos, asin, cos, sin, atan2, atan) +from sympy.integrals.integrals import integrate +from sympy.matrices.dense import Matrix +from sympy.simplify import simplify +from sympy.simplify.trigsimp import trigsimp +from sympy.algebras.quaternion import Quaternion +from sympy.testing.pytest import raises +import math +from itertools import permutations, product + +w, x, y, z = symbols('w:z') +phi = symbols('phi') + +def test_quaternion_construction(): + q = Quaternion(w, x, y, z) + assert q + q == Quaternion(2*w, 2*x, 2*y, 2*z) + + q2 = Quaternion.from_axis_angle((sqrt(3)/3, sqrt(3)/3, sqrt(3)/3), + pi*Rational(2, 3)) + assert q2 == Quaternion(S.Half, S.Half, + S.Half, S.Half) + + M = Matrix([[cos(phi), -sin(phi), 0], [sin(phi), cos(phi), 0], [0, 0, 1]]) + q3 = trigsimp(Quaternion.from_rotation_matrix(M)) + assert q3 == Quaternion( + sqrt(2)*sqrt(cos(phi) + 1)/2, 0, 0, sqrt(2 - 2*cos(phi))*sign(sin(phi))/2) + + nc = Symbol('nc', commutative=False) + raises(ValueError, lambda: Quaternion(w, x, nc, z)) + + +def test_quaternion_construction_norm(): + q1 = Quaternion(*symbols('a:d')) + + q2 = Quaternion(w, x, y, z) + assert expand((q1*q2).norm()**2 - (q1.norm()**2 * q2.norm()**2)) == 0 + + q3 = Quaternion(w, x, y, z, norm=1) + assert (q1 * q3).norm() == q1.norm() + + +def test_issue_25254(): + # calculating the inverse cached the norm which caused problems + # when multiplying + p = Quaternion(1, 0, 0, 0) + q = Quaternion.from_axis_angle((1, 1, 1), 3 * math.pi/4) + qi = q.inverse() # this operation cached the norm + test = q * p * qi + assert ((test - p).norm() < 1E-10) + + +def test_to_and_from_Matrix(): + q = Quaternion(w, x, y, z) + q_full = Quaternion.from_Matrix(q.to_Matrix()) + q_vect = Quaternion.from_Matrix(q.to_Matrix(True)) + assert (q - q_full).is_zero_quaternion() + assert (q.vector_part() - q_vect).is_zero_quaternion() + + +def test_product_matrices(): + q1 = Quaternion(w, x, y, z) + q2 = Quaternion(*(symbols("a:d"))) + assert (q1 * q2).to_Matrix() == q1.product_matrix_left * q2.to_Matrix() + assert (q1 * q2).to_Matrix() == q2.product_matrix_right * q1.to_Matrix() + + R1 = (q1.product_matrix_left * q1.product_matrix_right.T)[1:, 1:] + R2 = simplify(q1.to_rotation_matrix()*q1.norm()**2) + assert R1 == R2 + + +def test_quaternion_axis_angle(): + + test_data = [ # axis, angle, expected_quaternion + ((1, 0, 0), 0, (1, 0, 0, 0)), + ((1, 0, 0), pi/2, (sqrt(2)/2, sqrt(2)/2, 0, 0)), + ((0, 1, 0), pi/2, (sqrt(2)/2, 0, sqrt(2)/2, 0)), + ((0, 0, 1), pi/2, (sqrt(2)/2, 0, 0, sqrt(2)/2)), + ((1, 0, 0), pi, (0, 1, 0, 0)), + ((0, 1, 0), pi, (0, 0, 1, 0)), + ((0, 0, 1), pi, (0, 0, 0, 1)), + ((1, 1, 1), pi, (0, 1/sqrt(3),1/sqrt(3),1/sqrt(3))), + ((sqrt(3)/3, sqrt(3)/3, sqrt(3)/3), pi*2/3, (S.Half, S.Half, S.Half, S.Half)) + ] + + for axis, angle, expected in test_data: + assert Quaternion.from_axis_angle(axis, angle) == Quaternion(*expected) + + +def test_quaternion_axis_angle_simplification(): + result = Quaternion.from_axis_angle((1, 2, 3), asin(4)) + assert result.a == cos(asin(4)/2) + assert result.b == sqrt(14)*sin(asin(4)/2)/14 + assert result.c == sqrt(14)*sin(asin(4)/2)/7 + assert result.d == 3*sqrt(14)*sin(asin(4)/2)/14 + +def test_quaternion_complex_real_addition(): + a = symbols("a", complex=True) + b = symbols("b", real=True) + # This symbol is not complex: + c = symbols("c", commutative=False) + + q = Quaternion(w, x, y, z) + assert a + q == Quaternion(w + re(a), x + im(a), y, z) + assert 1 + q == Quaternion(1 + w, x, y, z) + assert I + q == Quaternion(w, 1 + x, y, z) + assert b + q == Quaternion(w + b, x, y, z) + raises(ValueError, lambda: c + q) + raises(ValueError, lambda: q * c) + raises(ValueError, lambda: c * q) + + assert -q == Quaternion(-w, -x, -y, -z) + + q1 = Quaternion(3 + 4*I, 2 + 5*I, 0, 7 + 8*I, real_field = False) + q2 = Quaternion(1, 4, 7, 8) + + assert q1 + (2 + 3*I) == Quaternion(5 + 7*I, 2 + 5*I, 0, 7 + 8*I) + assert q2 + (2 + 3*I) == Quaternion(3, 7, 7, 8) + assert q1 * (2 + 3*I) == \ + Quaternion((2 + 3*I)*(3 + 4*I), (2 + 3*I)*(2 + 5*I), 0, (2 + 3*I)*(7 + 8*I)) + assert q2 * (2 + 3*I) == Quaternion(-10, 11, 38, -5) + + q1 = Quaternion(1, 2, 3, 4) + q0 = Quaternion(0, 0, 0, 0) + assert q1 + q0 == q1 + assert q1 - q0 == q1 + assert q1 - q1 == q0 + + +def test_quaternion_subs(): + q = Quaternion.from_axis_angle((0, 0, 1), phi) + assert q.subs(phi, 0) == Quaternion(1, 0, 0, 0) + + +def test_quaternion_evalf(): + assert (Quaternion(sqrt(2), 0, 0, sqrt(3)).evalf() == + Quaternion(sqrt(2).evalf(), 0, 0, sqrt(3).evalf())) + assert (Quaternion(1/sqrt(2), 0, 0, 1/sqrt(2)).evalf() == + Quaternion((1/sqrt(2)).evalf(), 0, 0, (1/sqrt(2)).evalf())) + + +def test_quaternion_functions(): + q = Quaternion(w, x, y, z) + q1 = Quaternion(1, 2, 3, 4) + q0 = Quaternion(0, 0, 0, 0) + + assert conjugate(q) == Quaternion(w, -x, -y, -z) + assert q.norm() == sqrt(w**2 + x**2 + y**2 + z**2) + assert q.normalize() == Quaternion(w, x, y, z) / sqrt(w**2 + x**2 + y**2 + z**2) + assert q.inverse() == Quaternion(w, -x, -y, -z) / (w**2 + x**2 + y**2 + z**2) + assert q.inverse() == q.pow(-1) + raises(ValueError, lambda: q0.inverse()) + assert q.pow(2) == Quaternion(w**2 - x**2 - y**2 - z**2, 2*w*x, 2*w*y, 2*w*z) + assert q**(2) == Quaternion(w**2 - x**2 - y**2 - z**2, 2*w*x, 2*w*y, 2*w*z) + assert q1.pow(-2) == Quaternion( + Rational(-7, 225), Rational(-1, 225), Rational(-1, 150), Rational(-2, 225)) + assert q1**(-2) == Quaternion( + Rational(-7, 225), Rational(-1, 225), Rational(-1, 150), Rational(-2, 225)) + assert q1.pow(-0.5) == NotImplemented + raises(TypeError, lambda: q1**(-0.5)) + + assert q1.exp() == \ + Quaternion(E * cos(sqrt(29)), + 2 * sqrt(29) * E * sin(sqrt(29)) / 29, + 3 * sqrt(29) * E * sin(sqrt(29)) / 29, + 4 * sqrt(29) * E * sin(sqrt(29)) / 29) + assert q1.log() == \ + Quaternion(log(sqrt(30)), + 2 * sqrt(29) * acos(sqrt(30)/30) / 29, + 3 * sqrt(29) * acos(sqrt(30)/30) / 29, + 4 * sqrt(29) * acos(sqrt(30)/30) / 29) + + assert q1.pow_cos_sin(2) == \ + Quaternion(30 * cos(2 * acos(sqrt(30)/30)), + 60 * sqrt(29) * sin(2 * acos(sqrt(30)/30)) / 29, + 90 * sqrt(29) * sin(2 * acos(sqrt(30)/30)) / 29, + 120 * sqrt(29) * sin(2 * acos(sqrt(30)/30)) / 29) + + assert diff(Quaternion(x, x, x, x), x) == Quaternion(1, 1, 1, 1) + + assert integrate(Quaternion(x, x, x, x), x) == \ + Quaternion(x**2 / 2, x**2 / 2, x**2 / 2, x**2 / 2) + + assert Quaternion(1, x, x**2, x**3).integrate(x) == \ + Quaternion(x, x**2/2, x**3/3, x**4/4) + + assert Quaternion(sin(x), cos(x), sin(2*x), cos(2*x)).integrate(x) == \ + Quaternion(-cos(x), sin(x), -cos(2*x)/2, sin(2*x)/2) + + assert Quaternion(x**2, y**2, z**2, x*y*z).integrate(x, y) == \ + Quaternion(x**3*y/3, x*y**3/3, x*y*z**2, x**2*y**2*z/4) + + assert Quaternion.rotate_point((1, 1, 1), q1) == (S.One / 5, 1, S(7) / 5) + n = Symbol('n') + raises(TypeError, lambda: q1**n) + n = Symbol('n', integer=True) + raises(TypeError, lambda: q1**n) + + assert Quaternion(22, 23, 55, 8).scalar_part() == 22 + assert Quaternion(w, x, y, z).scalar_part() == w + + assert Quaternion(22, 23, 55, 8).vector_part() == Quaternion(0, 23, 55, 8) + assert Quaternion(w, x, y, z).vector_part() == Quaternion(0, x, y, z) + + assert q1.axis() == Quaternion(0, 2*sqrt(29)/29, 3*sqrt(29)/29, 4*sqrt(29)/29) + assert q1.axis().pow(2) == Quaternion(-1, 0, 0, 0) + assert q0.axis().scalar_part() == 0 + assert (q.axis() == Quaternion(0, + x/sqrt(x**2 + y**2 + z**2), + y/sqrt(x**2 + y**2 + z**2), + z/sqrt(x**2 + y**2 + z**2))) + + assert q0.is_pure() is True + assert q1.is_pure() is False + assert Quaternion(0, 0, 0, 3).is_pure() is True + assert Quaternion(0, 2, 10, 3).is_pure() is True + assert Quaternion(w, 2, 10, 3).is_pure() is None + + assert q1.angle() == 2*atan(sqrt(29)) + assert q.angle() == 2*atan2(sqrt(x**2 + y**2 + z**2), w) + + assert Quaternion.arc_coplanar(q1, Quaternion(2, 4, 6, 8)) is True + assert Quaternion.arc_coplanar(q1, Quaternion(1, -2, -3, -4)) is True + assert Quaternion.arc_coplanar(q1, Quaternion(1, 8, 12, 16)) is True + assert Quaternion.arc_coplanar(q1, Quaternion(1, 2, 3, 4)) is True + assert Quaternion.arc_coplanar(q1, Quaternion(w, 4, 6, 8)) is True + assert Quaternion.arc_coplanar(q1, Quaternion(2, 7, 4, 1)) is False + assert Quaternion.arc_coplanar(q1, Quaternion(w, x, y, z)) is None + raises(ValueError, lambda: Quaternion.arc_coplanar(q1, q0)) + + assert Quaternion.vector_coplanar( + Quaternion(0, 8, 12, 16), + Quaternion(0, 4, 6, 8), + Quaternion(0, 2, 3, 4)) is True + assert Quaternion.vector_coplanar( + Quaternion(0, 0, 0, 0), Quaternion(0, 4, 6, 8), Quaternion(0, 2, 3, 4)) is True + assert Quaternion.vector_coplanar( + Quaternion(0, 8, 2, 6), Quaternion(0, 1, 6, 6), Quaternion(0, 0, 3, 4)) is False + assert Quaternion.vector_coplanar( + Quaternion(0, 1, 3, 4), + Quaternion(0, 4, w, 6), + Quaternion(0, 6, 8, 1)) is None + raises(ValueError, lambda: + Quaternion.vector_coplanar(q0, Quaternion(0, 4, 6, 8), q1)) + + assert Quaternion(0, 1, 2, 3).parallel(Quaternion(0, 2, 4, 6)) is True + assert Quaternion(0, 1, 2, 3).parallel(Quaternion(0, 2, 2, 6)) is False + assert Quaternion(0, 1, 2, 3).parallel(Quaternion(w, x, y, 6)) is None + raises(ValueError, lambda: q0.parallel(q1)) + + assert Quaternion(0, 1, 2, 3).orthogonal(Quaternion(0, -2, 1, 0)) is True + assert Quaternion(0, 2, 4, 7).orthogonal(Quaternion(0, 2, 2, 6)) is False + assert Quaternion(0, 2, 4, 7).orthogonal(Quaternion(w, x, y, 6)) is None + raises(ValueError, lambda: q0.orthogonal(q1)) + + assert q1.index_vector() == Quaternion( + 0, 2*sqrt(870)/29, + 3*sqrt(870)/29, + 4*sqrt(870)/29) + assert Quaternion(0, 3, 9, 4).index_vector() == Quaternion(0, 3, 9, 4) + + assert Quaternion(4, 3, 9, 4).mensor() == log(sqrt(122)) + assert Quaternion(3, 3, 0, 2).mensor() == log(sqrt(22)) + + assert q0.is_zero_quaternion() is True + assert q1.is_zero_quaternion() is False + assert Quaternion(w, 0, 0, 0).is_zero_quaternion() is None + +def test_quaternion_conversions(): + q1 = Quaternion(1, 2, 3, 4) + + assert q1.to_axis_angle() == ((2 * sqrt(29)/29, + 3 * sqrt(29)/29, + 4 * sqrt(29)/29), + 2 * acos(sqrt(30)/30)) + + assert (q1.to_rotation_matrix() == + Matrix([[Rational(-2, 3), Rational(2, 15), Rational(11, 15)], + [Rational(2, 3), Rational(-1, 3), Rational(2, 3)], + [Rational(1, 3), Rational(14, 15), Rational(2, 15)]])) + + assert (q1.to_rotation_matrix((1, 1, 1)) == + Matrix([ + [Rational(-2, 3), Rational(2, 15), Rational(11, 15), Rational(4, 5)], + [Rational(2, 3), Rational(-1, 3), Rational(2, 3), S.Zero], + [Rational(1, 3), Rational(14, 15), Rational(2, 15), Rational(-2, 5)], + [S.Zero, S.Zero, S.Zero, S.One]])) + + theta = symbols("theta", real=True) + q2 = Quaternion(cos(theta/2), 0, 0, sin(theta/2)) + + assert trigsimp(q2.to_rotation_matrix()) == Matrix([ + [cos(theta), -sin(theta), 0], + [sin(theta), cos(theta), 0], + [0, 0, 1]]) + + assert q2.to_axis_angle() == ((0, 0, sin(theta/2)/Abs(sin(theta/2))), + 2*acos(cos(theta/2))) + + assert trigsimp(q2.to_rotation_matrix((1, 1, 1))) == Matrix([ + [cos(theta), -sin(theta), 0, sin(theta) - cos(theta) + 1], + [sin(theta), cos(theta), 0, -sin(theta) - cos(theta) + 1], + [0, 0, 1, 0], + [0, 0, 0, 1]]) + + +def test_rotation_matrix_homogeneous(): + q = Quaternion(w, x, y, z) + R1 = q.to_rotation_matrix(homogeneous=True) * q.norm()**2 + R2 = simplify(q.to_rotation_matrix(homogeneous=False) * q.norm()**2) + assert R1 == R2 + + +def test_quaternion_rotation_iss1593(): + """ + There was a sign mistake in the definition, + of the rotation matrix. This tests that particular sign mistake. + See issue 1593 for reference. + See wikipedia + https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation#Quaternion-derived_rotation_matrix + for the correct definition + """ + q = Quaternion(cos(phi/2), sin(phi/2), 0, 0) + assert(trigsimp(q.to_rotation_matrix()) == Matrix([ + [1, 0, 0], + [0, cos(phi), -sin(phi)], + [0, sin(phi), cos(phi)]])) + + +def test_quaternion_multiplication(): + q1 = Quaternion(3 + 4*I, 2 + 5*I, 0, 7 + 8*I, real_field = False) + q2 = Quaternion(1, 2, 3, 5) + q3 = Quaternion(1, 1, 1, y) + + assert Quaternion._generic_mul(S(4), S.One) == 4 + assert (Quaternion._generic_mul(S(4), q1) == + Quaternion(12 + 16*I, 8 + 20*I, 0, 28 + 32*I)) + assert q2.mul(2) == Quaternion(2, 4, 6, 10) + assert q2.mul(q3) == Quaternion(-5*y - 4, 3*y - 2, 9 - 2*y, y + 4) + assert q2.mul(q3) == q2*q3 + + z = symbols('z', complex=True) + z_quat = Quaternion(re(z), im(z), 0, 0) + q = Quaternion(*symbols('q:4', real=True)) + + assert z * q == z_quat * q + assert q * z == q * z_quat + + +def test_issue_16318(): + #for rtruediv + q0 = Quaternion(0, 0, 0, 0) + raises(ValueError, lambda: 1/q0) + #for rotate_point + q = Quaternion(1, 2, 3, 4) + (axis, angle) = q.to_axis_angle() + assert Quaternion.rotate_point((1, 1, 1), (axis, angle)) == (S.One / 5, 1, S(7) / 5) + #test for to_axis_angle + q = Quaternion(-1, 1, 1, 1) + axis = (-sqrt(3)/3, -sqrt(3)/3, -sqrt(3)/3) + angle = 2*pi/3 + assert (axis, angle) == q.to_axis_angle() + + +@slow +def test_to_euler(): + q = Quaternion(w, x, y, z) + q_normalized = q.normalize() + + seqs = ['zxy', 'zyx', 'zyz', 'zxz'] + seqs += [seq.upper() for seq in seqs] + + for seq in seqs: + euler_from_q = q.to_euler(seq) + q_back = simplify(Quaternion.from_euler(euler_from_q, seq)) + assert q_back == q_normalized + + +def test_to_euler_iss24504(): + """ + There was a mistake in the degenerate case testing + See issue 24504 for reference. + """ + q = Quaternion.from_euler((phi, 0, 0), 'zyz') + assert trigsimp(q.to_euler('zyz'), inverse=True) == (phi, 0, 0) + + +def test_to_euler_numerical_singilarities(): + + def test_one_case(angles, seq): + q = Quaternion.from_euler(angles, seq) + assert q.to_euler(seq) == angles + + # symmetric + test_one_case((pi/2, 0, 0), 'zyz') + test_one_case((pi/2, 0, 0), 'ZYZ') + test_one_case((pi/2, pi, 0), 'zyz') + test_one_case((pi/2, pi, 0), 'ZYZ') + + # asymmetric + test_one_case((pi/2, pi/2, 0), 'zyx') + test_one_case((pi/2, -pi/2, 0), 'zyx') + test_one_case((pi/2, pi/2, 0), 'ZYX') + test_one_case((pi/2, -pi/2, 0), 'ZYX') + + +@slow +def test_to_euler_options(): + def test_one_case(q): + angles1 = Matrix(q.to_euler(seq, True, True)) + angles2 = Matrix(q.to_euler(seq, False, False)) + angle_errors = simplify(angles1-angles2).evalf() + for angle_error in angle_errors: + # forcing angles to set {-pi, pi} + angle_error = (angle_error + pi) % (2 * pi) - pi + assert angle_error < 10e-7 + + for xyz in ('xyz', 'XYZ'): + for seq_tuple in permutations(xyz): + for symmetric in (True, False): + if symmetric: + seq = ''.join([seq_tuple[0], seq_tuple[1], seq_tuple[0]]) + else: + seq = ''.join(seq_tuple) + + for elements in product([-1, 0, 1], repeat=4): + q = Quaternion(*elements) + if not q.is_zero_quaternion(): + test_one_case(q) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..73a18e8c5aedc01b40d66e73765eb915d4f3fc19 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/__pycache__/accumulationbounds.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/__pycache__/accumulationbounds.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..69d243885e8bf30732a4d8b5a483bf9d70fab6ab Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/__pycache__/accumulationbounds.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/__pycache__/euler.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/__pycache__/euler.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d661c019996e1109f1369437fe8c91c06ea6adfc Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/__pycache__/euler.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/__pycache__/finite_diff.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/__pycache__/finite_diff.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8009bcd3a9bb26be3059e85a44504850f37fdfce Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/__pycache__/finite_diff.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/__pycache__/singularities.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/__pycache__/singularities.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b2352de9c76989ea7cdf64de5f533832222c8ee9 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/__pycache__/singularities.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/__pycache__/util.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/__pycache__/util.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7d0f29fda9a21c05048990009586597dc7b1d0da Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/__pycache__/util.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..414d2c3e3cae896c7c74a570ad95913a8a88f8e2 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/__pycache__/test_accumulationbounds.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/__pycache__/test_accumulationbounds.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8db89e5965e6fc0872cc99eb5fe77d0767599c46 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/__pycache__/test_accumulationbounds.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/__pycache__/test_euler.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/__pycache__/test_euler.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d9a9cfd32387562dce36bc860f04dbf4c3c4dceb Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/__pycache__/test_euler.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/__pycache__/test_finite_diff.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/__pycache__/test_finite_diff.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..49b8429ceec05ac9b53fc1369d4c9a64c034c82e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/__pycache__/test_finite_diff.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/__pycache__/test_singularities.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/__pycache__/test_singularities.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..730b17b8ca29f3c883e14bc2fc17f0275a983501 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/__pycache__/test_singularities.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/__pycache__/test_util.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/__pycache__/test_util.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b6a412fa832f19342765b7c6599ecc15e68af138 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/__pycache__/test_util.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/test_accumulationbounds.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/test_accumulationbounds.py new file mode 100644 index 0000000000000000000000000000000000000000..bcc47c66327fe21ddca3a6b73ca5914e0441b38e --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/test_accumulationbounds.py @@ -0,0 +1,336 @@ +from sympy.core.numbers import (E, Rational, oo, pi, zoo) +from sympy.core.singleton import S +from sympy.core.symbol import Symbol +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.miscellaneous import (Max, Min, sqrt) +from sympy.functions.elementary.trigonometric import (cos, sin, tan) +from sympy.calculus.accumulationbounds import AccumBounds +from sympy.core import Add, Mul, Pow +from sympy.core.expr import unchanged +from sympy.testing.pytest import raises, XFAIL +from sympy.abc import x + +a = Symbol('a', real=True) +B = AccumBounds + + +def test_AccumBounds(): + assert B(1, 2).args == (1, 2) + assert B(1, 2).delta is S.One + assert B(1, 2).mid == Rational(3, 2) + assert B(1, 3).is_real == True + + assert B(1, 1) is S.One + + assert B(1, 2) + 1 == B(2, 3) + assert 1 + B(1, 2) == B(2, 3) + assert B(1, 2) + B(2, 3) == B(3, 5) + + assert -B(1, 2) == B(-2, -1) + + assert B(1, 2) - 1 == B(0, 1) + assert 1 - B(1, 2) == B(-1, 0) + assert B(2, 3) - B(1, 2) == B(0, 2) + + assert x + B(1, 2) == Add(B(1, 2), x) + assert a + B(1, 2) == B(1 + a, 2 + a) + assert B(1, 2) - x == Add(B(1, 2), -x) + + assert B(-oo, 1) + oo == B(-oo, oo) + assert B(1, oo) + oo is oo + assert B(1, oo) - oo == B(-oo, oo) + assert (-oo - B(-1, oo)) is -oo + assert B(-oo, 1) - oo is -oo + + assert B(1, oo) - oo == B(-oo, oo) + assert B(-oo, 1) - (-oo) == B(-oo, oo) + assert (oo - B(1, oo)) == B(-oo, oo) + assert (-oo - B(1, oo)) is -oo + + assert B(1, 2)/2 == B(S.Half, 1) + assert 2/B(2, 3) == B(Rational(2, 3), 1) + assert 1/B(-1, 1) == B(-oo, oo) + + assert abs(B(1, 2)) == B(1, 2) + assert abs(B(-2, -1)) == B(1, 2) + assert abs(B(-2, 1)) == B(0, 2) + assert abs(B(-1, 2)) == B(0, 2) + c = Symbol('c') + raises(ValueError, lambda: B(0, c)) + raises(ValueError, lambda: B(1, -1)) + r = Symbol('r', real=True) + raises(ValueError, lambda: B(r, r - 1)) + + +def test_AccumBounds_mul(): + assert B(1, 2)*2 == B(2, 4) + assert 2*B(1, 2) == B(2, 4) + assert B(1, 2)*B(2, 3) == B(2, 6) + assert B(0, 2)*B(2, oo) == B(0, oo) + l, r = B(-oo, oo), B(-a, a) + assert l*r == B(-oo, oo) + assert r*l == B(-oo, oo) + l, r = B(1, oo), B(-3, -2) + assert l*r == B(-oo, -2) + assert r*l == B(-oo, -2) + assert B(1, 2)*0 == 0 + assert B(1, oo)*0 == B(0, oo) + assert B(-oo, 1)*0 == B(-oo, 0) + assert B(-oo, oo)*0 == B(-oo, oo) + + assert B(1, 2)*x == Mul(B(1, 2), x, evaluate=False) + + assert B(0, 2)*oo == B(0, oo) + assert B(-2, 0)*oo == B(-oo, 0) + assert B(0, 2)*(-oo) == B(-oo, 0) + assert B(-2, 0)*(-oo) == B(0, oo) + assert B(-1, 1)*oo == B(-oo, oo) + assert B(-1, 1)*(-oo) == B(-oo, oo) + assert B(-oo, oo)*oo == B(-oo, oo) + + +def test_AccumBounds_div(): + assert B(-1, 3)/B(3, 4) == B(Rational(-1, 3), 1) + assert B(-2, 4)/B(-3, 4) == B(-oo, oo) + assert B(-3, -2)/B(-4, 0) == B(S.Half, oo) + + # these two tests can have a better answer + # after Union of B is improved + assert B(-3, -2)/B(-2, 1) == B(-oo, oo) + assert B(2, 3)/B(-2, 2) == B(-oo, oo) + + assert B(-3, -2)/B(0, 4) == B(-oo, Rational(-1, 2)) + assert B(2, 4)/B(-3, 0) == B(-oo, Rational(-2, 3)) + assert B(2, 4)/B(0, 3) == B(Rational(2, 3), oo) + + assert B(0, 1)/B(0, 1) == B(0, oo) + assert B(-1, 0)/B(0, 1) == B(-oo, 0) + assert B(-1, 2)/B(-2, 2) == B(-oo, oo) + + assert 1/B(-1, 2) == B(-oo, oo) + assert 1/B(0, 2) == B(S.Half, oo) + assert (-1)/B(0, 2) == B(-oo, Rational(-1, 2)) + assert 1/B(-oo, 0) == B(-oo, 0) + assert 1/B(-1, 0) == B(-oo, -1) + assert (-2)/B(-oo, 0) == B(0, oo) + assert 1/B(-oo, -1) == B(-1, 0) + + assert B(1, 2)/a == Mul(B(1, 2), 1/a, evaluate=False) + + assert B(1, 2)/0 == B(1, 2)*zoo + assert B(1, oo)/oo == B(0, oo) + assert B(1, oo)/(-oo) == B(-oo, 0) + assert B(-oo, -1)/oo == B(-oo, 0) + assert B(-oo, -1)/(-oo) == B(0, oo) + assert B(-oo, oo)/oo == B(-oo, oo) + assert B(-oo, oo)/(-oo) == B(-oo, oo) + assert B(-1, oo)/oo == B(0, oo) + assert B(-1, oo)/(-oo) == B(-oo, 0) + assert B(-oo, 1)/oo == B(-oo, 0) + assert B(-oo, 1)/(-oo) == B(0, oo) + + +def test_issue_18795(): + r = Symbol('r', real=True) + a = B(-1,1) + c = B(7, oo) + b = B(-oo, oo) + assert c - tan(r) == B(7-tan(r), oo) + assert b + tan(r) == B(-oo, oo) + assert (a + r)/a == B(-oo, oo)*B(r - 1, r + 1) + assert (b + a)/a == B(-oo, oo) + + +def test_AccumBounds_func(): + assert (x**2 + 2*x + 1).subs(x, B(-1, 1)) == B(-1, 4) + assert exp(B(0, 1)) == B(1, E) + assert exp(B(-oo, oo)) == B(0, oo) + assert log(B(3, 6)) == B(log(3), log(6)) + + +@XFAIL +def test_AccumBounds_powf(): + nn = Symbol('nn', nonnegative=True) + assert B(1 + nn, 2 + nn)**B(1, 2) == B(1 + nn, (2 + nn)**2) + i = Symbol('i', integer=True, negative=True) + assert B(1, 2)**i == B(2**i, 1) + + +def test_AccumBounds_pow(): + assert B(0, 2)**2 == B(0, 4) + assert B(-1, 1)**2 == B(0, 1) + assert B(1, 2)**2 == B(1, 4) + assert B(-1, 2)**3 == B(-1, 8) + assert B(-1, 1)**0 == 1 + + assert B(1, 2)**Rational(5, 2) == B(1, 4*sqrt(2)) + assert B(0, 2)**S.Half == B(0, sqrt(2)) + + neg = Symbol('neg', negative=True) + assert unchanged(Pow, B(neg, 1), S.Half) + nn = Symbol('nn', nonnegative=True) + assert B(nn, nn + 1)**S.Half == B(sqrt(nn), sqrt(nn + 1)) + assert B(nn, nn + 1)**nn == B(nn**nn, (nn + 1)**nn) + assert unchanged(Pow, B(nn, nn + 1), x) + i = Symbol('i', integer=True) + assert B(1, 2)**i == B(Min(1, 2**i), Max(1, 2**i)) + i = Symbol('i', integer=True, nonnegative=True) + assert B(1, 2)**i == B(1, 2**i) + assert B(0, 1)**i == B(0**i, 1) + + assert B(1, 5)**(-2) == B(Rational(1, 25), 1) + assert B(-1, 3)**(-2) == B(0, oo) + assert B(0, 2)**(-3) == B(Rational(1, 8), oo) + assert B(-2, 0)**(-3) == B(-oo, -Rational(1, 8)) + assert B(0, 2)**(-2) == B(Rational(1, 4), oo) + assert B(-1, 2)**(-3) == B(-oo, oo) + assert B(-3, -2)**(-3) == B(Rational(-1, 8), Rational(-1, 27)) + assert B(-3, -2)**(-2) == B(Rational(1, 9), Rational(1, 4)) + assert B(0, oo)**S.Half == B(0, oo) + assert B(-oo, 0)**(-2) == B(0, oo) + assert B(-2, 0)**(-2) == B(Rational(1, 4), oo) + + assert B(Rational(1, 3), S.Half)**oo is S.Zero + assert B(0, S.Half)**oo is S.Zero + assert B(S.Half, 1)**oo == B(0, oo) + assert B(0, 1)**oo == B(0, oo) + assert B(2, 3)**oo is oo + assert B(1, 2)**oo == B(0, oo) + assert B(S.Half, 3)**oo == B(0, oo) + assert B(Rational(-1, 3), Rational(-1, 4))**oo is S.Zero + assert B(-1, Rational(-1, 2))**oo is S.NaN + assert B(-3, -2)**oo is zoo + assert B(-2, -1)**oo is S.NaN + assert B(-2, Rational(-1, 2))**oo is S.NaN + assert B(Rational(-1, 2), S.Half)**oo is S.Zero + assert B(Rational(-1, 2), 1)**oo == B(0, oo) + assert B(Rational(-2, 3), 2)**oo == B(0, oo) + assert B(-1, 1)**oo == B(-oo, oo) + assert B(-1, S.Half)**oo == B(-oo, oo) + assert B(-1, 2)**oo == B(-oo, oo) + assert B(-2, S.Half)**oo == B(-oo, oo) + + assert B(1, 2)**x == Pow(B(1, 2), x, evaluate=False) + + assert B(2, 3)**(-oo) is S.Zero + assert B(0, 2)**(-oo) == B(0, oo) + assert B(-1, 2)**(-oo) == B(-oo, oo) + + assert (tan(x)**sin(2*x)).subs(x, B(0, pi/2)) == \ + Pow(B(-oo, oo), B(0, 1)) + + +def test_AccumBounds_exponent(): + # base is 0 + z = 0**B(a, a + S.Half) + assert z.subs(a, 0) == B(0, 1) + assert z.subs(a, 1) == 0 + p = z.subs(a, -1) + assert p.is_Pow and p.args == (0, B(-1, -S.Half)) + # base > 0 + # when base is 1 the type of bounds does not matter + assert 1**B(a, a + 1) == 1 + # otherwise we need to know if 0 is in the bounds + assert S.Half**B(-2, 2) == B(S(1)/4, 4) + assert 2**B(-2, 2) == B(S(1)/4, 4) + + # +eps may introduce +oo + # if there is a negative integer exponent + assert B(0, 1)**B(S(1)/2, 1) == B(0, 1) + assert B(0, 1)**B(0, 1) == B(0, 1) + + # positive bases have positive bounds + assert B(2, 3)**B(-3, -2) == B(S(1)/27, S(1)/4) + assert B(2, 3)**B(-3, 2) == B(S(1)/27, 9) + + # bounds generating imaginary parts unevaluated + assert unchanged(Pow, B(-1, 1), B(1, 2)) + assert B(0, S(1)/2)**B(1, oo) == B(0, S(1)/2) + assert B(0, 1)**B(1, oo) == B(0, oo) + assert B(0, 2)**B(1, oo) == B(0, oo) + assert B(0, oo)**B(1, oo) == B(0, oo) + assert B(S(1)/2, 1)**B(1, oo) == B(0, oo) + assert B(S(1)/2, 1)**B(-oo, -1) == B(0, oo) + assert B(S(1)/2, 1)**B(-oo, oo) == B(0, oo) + assert B(S(1)/2, 2)**B(1, oo) == B(0, oo) + assert B(S(1)/2, 2)**B(-oo, -1) == B(0, oo) + assert B(S(1)/2, 2)**B(-oo, oo) == B(0, oo) + assert B(S(1)/2, oo)**B(1, oo) == B(0, oo) + assert B(S(1)/2, oo)**B(-oo, -1) == B(0, oo) + assert B(S(1)/2, oo)**B(-oo, oo) == B(0, oo) + assert B(1, 2)**B(1, oo) == B(0, oo) + assert B(1, 2)**B(-oo, -1) == B(0, oo) + assert B(1, 2)**B(-oo, oo) == B(0, oo) + assert B(1, oo)**B(1, oo) == B(0, oo) + assert B(1, oo)**B(-oo, -1) == B(0, oo) + assert B(1, oo)**B(-oo, oo) == B(0, oo) + assert B(2, oo)**B(1, oo) == B(2, oo) + assert B(2, oo)**B(-oo, -1) == B(0, S(1)/2) + assert B(2, oo)**B(-oo, oo) == B(0, oo) + + +def test_comparison_AccumBounds(): + assert (B(1, 3) < 4) == S.true + assert (B(1, 3) < -1) == S.false + assert (B(1, 3) < 2).rel_op == '<' + assert (B(1, 3) <= 2).rel_op == '<=' + + assert (B(1, 3) > 4) == S.false + assert (B(1, 3) > -1) == S.true + assert (B(1, 3) > 2).rel_op == '>' + assert (B(1, 3) >= 2).rel_op == '>=' + + assert (B(1, 3) < B(4, 6)) == S.true + assert (B(1, 3) < B(2, 4)).rel_op == '<' + assert (B(1, 3) < B(-2, 0)) == S.false + + assert (B(1, 3) <= B(4, 6)) == S.true + assert (B(1, 3) <= B(-2, 0)) == S.false + + assert (B(1, 3) > B(4, 6)) == S.false + assert (B(1, 3) > B(-2, 0)) == S.true + + assert (B(1, 3) >= B(4, 6)) == S.false + assert (B(1, 3) >= B(-2, 0)) == S.true + + # issue 13499 + assert (cos(x) > 0).subs(x, oo) == (B(-1, 1) > 0) + + c = Symbol('c') + raises(TypeError, lambda: (B(0, 1) < c)) + raises(TypeError, lambda: (B(0, 1) <= c)) + raises(TypeError, lambda: (B(0, 1) > c)) + raises(TypeError, lambda: (B(0, 1) >= c)) + + +def test_contains_AccumBounds(): + assert (1 in B(1, 2)) == S.true + raises(TypeError, lambda: a in B(1, 2)) + assert 0 in B(-1, 0) + raises(TypeError, lambda: + (cos(1)**2 + sin(1)**2 - 1) in B(-1, 0)) + assert (-oo in B(1, oo)) == S.true + assert (oo in B(-oo, 0)) == S.true + + # issue 13159 + assert Mul(0, B(-1, 1)) == Mul(B(-1, 1), 0) == 0 + import itertools + for perm in itertools.permutations([0, B(-1, 1), x]): + assert Mul(*perm) == 0 + + +def test_intersection_AccumBounds(): + assert B(0, 3).intersection(B(1, 2)) == B(1, 2) + assert B(0, 3).intersection(B(1, 4)) == B(1, 3) + assert B(0, 3).intersection(B(-1, 2)) == B(0, 2) + assert B(0, 3).intersection(B(-1, 4)) == B(0, 3) + assert B(0, 1).intersection(B(2, 3)) == S.EmptySet + raises(TypeError, lambda: B(0, 3).intersection(1)) + + +def test_union_AccumBounds(): + assert B(0, 3).union(B(1, 2)) == B(0, 3) + assert B(0, 3).union(B(1, 4)) == B(0, 4) + assert B(0, 3).union(B(-1, 2)) == B(-1, 3) + assert B(0, 3).union(B(-1, 4)) == B(-1, 4) + raises(TypeError, lambda: B(0, 3).union(1)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/test_euler.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/test_euler.py new file mode 100644 index 0000000000000000000000000000000000000000..56371c8c787d9459d1390e18c306fddde94d2745 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/test_euler.py @@ -0,0 +1,74 @@ +from sympy.core.function import (Derivative as D, Function) +from sympy.core.relational import Eq +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.testing.pytest import raises +from sympy.calculus.euler import euler_equations as euler + + +def test_euler_interface(): + x = Function('x') + y = Symbol('y') + t = Symbol('t') + raises(TypeError, lambda: euler()) + raises(TypeError, lambda: euler(D(x(t), t)*y(t), [x(t), y])) + raises(ValueError, lambda: euler(D(x(t), t)*x(y), [x(t), x(y)])) + raises(TypeError, lambda: euler(D(x(t), t)**2, x(0))) + raises(TypeError, lambda: euler(D(x(t), t)*y(t), [t])) + assert euler(D(x(t), t)**2/2, {x(t)}) == [Eq(-D(x(t), t, t), 0)] + assert euler(D(x(t), t)**2/2, x(t), {t}) == [Eq(-D(x(t), t, t), 0)] + + +def test_euler_pendulum(): + x = Function('x') + t = Symbol('t') + L = D(x(t), t)**2/2 + cos(x(t)) + assert euler(L, x(t), t) == [Eq(-sin(x(t)) - D(x(t), t, t), 0)] + + +def test_euler_henonheiles(): + x = Function('x') + y = Function('y') + t = Symbol('t') + L = sum(D(z(t), t)**2/2 - z(t)**2/2 for z in [x, y]) + L += -x(t)**2*y(t) + y(t)**3/3 + assert euler(L, [x(t), y(t)], t) == [Eq(-2*x(t)*y(t) - x(t) - + D(x(t), t, t), 0), + Eq(-x(t)**2 + y(t)**2 - + y(t) - D(y(t), t, t), 0)] + + +def test_euler_sineg(): + psi = Function('psi') + t = Symbol('t') + x = Symbol('x') + L = D(psi(t, x), t)**2/2 - D(psi(t, x), x)**2/2 + cos(psi(t, x)) + assert euler(L, psi(t, x), [t, x]) == [Eq(-sin(psi(t, x)) - + D(psi(t, x), t, t) + + D(psi(t, x), x, x), 0)] + + +def test_euler_high_order(): + # an example from hep-th/0309038 + m = Symbol('m') + k = Symbol('k') + x = Function('x') + y = Function('y') + t = Symbol('t') + L = (m*D(x(t), t)**2/2 + m*D(y(t), t)**2/2 - + k*D(x(t), t)*D(y(t), t, t) + k*D(y(t), t)*D(x(t), t, t)) + assert euler(L, [x(t), y(t)]) == [Eq(2*k*D(y(t), t, t, t) - + m*D(x(t), t, t), 0), + Eq(-2*k*D(x(t), t, t, t) - + m*D(y(t), t, t), 0)] + + w = Symbol('w') + L = D(x(t, w), t, w)**2/2 + assert euler(L) == [Eq(D(x(t, w), t, t, w, w), 0)] + +def test_issue_18653(): + x, y, z = symbols("x y z") + f, g, h = symbols("f g h", cls=Function, args=(x, y)) + f, g, h = f(), g(), h() + expr2 = f.diff(x)*h.diff(z) + assert euler(expr2, (f,), (x, y)) == [] diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/test_finite_diff.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/test_finite_diff.py new file mode 100644 index 0000000000000000000000000000000000000000..e9ecfbdd61b15f516c54bd6d716ba1f264ee2ca0 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/test_finite_diff.py @@ -0,0 +1,164 @@ +from itertools import product + +from sympy.core.function import (Function, diff) +from sympy.core.numbers import Rational +from sympy.core.singleton import S +from sympy.core.symbol import symbols +from sympy.functions.elementary.exponential import exp +from sympy.calculus.finite_diff import ( + apply_finite_diff, differentiate_finite, finite_diff_weights, + _as_finite_diff +) +from sympy.testing.pytest import raises, warns_deprecated_sympy + + +def test_apply_finite_diff(): + x, h = symbols('x h') + f = Function('f') + assert (apply_finite_diff(1, [x-h, x+h], [f(x-h), f(x+h)], x) - + (f(x+h)-f(x-h))/(2*h)).simplify() == 0 + + assert (apply_finite_diff(1, [5, 6, 7], [f(5), f(6), f(7)], 5) - + (Rational(-3, 2)*f(5) + 2*f(6) - S.Half*f(7))).simplify() == 0 + raises(ValueError, lambda: apply_finite_diff(1, [x, h], [f(x)])) + + +def test_finite_diff_weights(): + + d = finite_diff_weights(1, [5, 6, 7], 5) + assert d[1][2] == [Rational(-3, 2), 2, Rational(-1, 2)] + + # Table 1, p. 702 in doi:10.1090/S0025-5718-1988-0935077-0 + # -------------------------------------------------------- + xl = [0, 1, -1, 2, -2, 3, -3, 4, -4] + + # d holds all coefficients + d = finite_diff_weights(4, xl, S.Zero) + + # Zeroeth derivative + for i in range(5): + assert d[0][i] == [S.One] + [S.Zero]*8 + + # First derivative + assert d[1][0] == [S.Zero]*9 + assert d[1][2] == [S.Zero, S.Half, Rational(-1, 2)] + [S.Zero]*6 + assert d[1][4] == [S.Zero, Rational(2, 3), Rational(-2, 3), Rational(-1, 12), Rational(1, 12)] + [S.Zero]*4 + assert d[1][6] == [S.Zero, Rational(3, 4), Rational(-3, 4), Rational(-3, 20), Rational(3, 20), + Rational(1, 60), Rational(-1, 60)] + [S.Zero]*2 + assert d[1][8] == [S.Zero, Rational(4, 5), Rational(-4, 5), Rational(-1, 5), Rational(1, 5), + Rational(4, 105), Rational(-4, 105), Rational(-1, 280), Rational(1, 280)] + + # Second derivative + for i in range(2): + assert d[2][i] == [S.Zero]*9 + assert d[2][2] == [-S(2), S.One, S.One] + [S.Zero]*6 + assert d[2][4] == [Rational(-5, 2), Rational(4, 3), Rational(4, 3), Rational(-1, 12), Rational(-1, 12)] + [S.Zero]*4 + assert d[2][6] == [Rational(-49, 18), Rational(3, 2), Rational(3, 2), Rational(-3, 20), Rational(-3, 20), + Rational(1, 90), Rational(1, 90)] + [S.Zero]*2 + assert d[2][8] == [Rational(-205, 72), Rational(8, 5), Rational(8, 5), Rational(-1, 5), Rational(-1, 5), + Rational(8, 315), Rational(8, 315), Rational(-1, 560), Rational(-1, 560)] + + # Third derivative + for i in range(3): + assert d[3][i] == [S.Zero]*9 + assert d[3][4] == [S.Zero, -S.One, S.One, S.Half, Rational(-1, 2)] + [S.Zero]*4 + assert d[3][6] == [S.Zero, Rational(-13, 8), Rational(13, 8), S.One, -S.One, + Rational(-1, 8), Rational(1, 8)] + [S.Zero]*2 + assert d[3][8] == [S.Zero, Rational(-61, 30), Rational(61, 30), Rational(169, 120), Rational(-169, 120), + Rational(-3, 10), Rational(3, 10), Rational(7, 240), Rational(-7, 240)] + + # Fourth derivative + for i in range(4): + assert d[4][i] == [S.Zero]*9 + assert d[4][4] == [S(6), -S(4), -S(4), S.One, S.One] + [S.Zero]*4 + assert d[4][6] == [Rational(28, 3), Rational(-13, 2), Rational(-13, 2), S(2), S(2), + Rational(-1, 6), Rational(-1, 6)] + [S.Zero]*2 + assert d[4][8] == [Rational(91, 8), Rational(-122, 15), Rational(-122, 15), Rational(169, 60), Rational(169, 60), + Rational(-2, 5), Rational(-2, 5), Rational(7, 240), Rational(7, 240)] + + # Table 2, p. 703 in doi:10.1090/S0025-5718-1988-0935077-0 + # -------------------------------------------------------- + xl = [[j/S(2) for j in list(range(-i*2+1, 0, 2))+list(range(1, i*2+1, 2))] + for i in range(1, 5)] + + # d holds all coefficients + d = [finite_diff_weights({0: 1, 1: 2, 2: 4, 3: 4}[i], xl[i], 0) for + i in range(4)] + + # Zeroth derivative + assert d[0][0][1] == [S.Half, S.Half] + assert d[1][0][3] == [Rational(-1, 16), Rational(9, 16), Rational(9, 16), Rational(-1, 16)] + assert d[2][0][5] == [Rational(3, 256), Rational(-25, 256), Rational(75, 128), Rational(75, 128), + Rational(-25, 256), Rational(3, 256)] + assert d[3][0][7] == [Rational(-5, 2048), Rational(49, 2048), Rational(-245, 2048), Rational(1225, 2048), + Rational(1225, 2048), Rational(-245, 2048), Rational(49, 2048), Rational(-5, 2048)] + + # First derivative + assert d[0][1][1] == [-S.One, S.One] + assert d[1][1][3] == [Rational(1, 24), Rational(-9, 8), Rational(9, 8), Rational(-1, 24)] + assert d[2][1][5] == [Rational(-3, 640), Rational(25, 384), Rational(-75, 64), + Rational(75, 64), Rational(-25, 384), Rational(3, 640)] + assert d[3][1][7] == [Rational(5, 7168), Rational(-49, 5120), + Rational(245, 3072), Rational(-1225, 1024), + Rational(1225, 1024), Rational(-245, 3072), + Rational(49, 5120), Rational(-5, 7168)] + + # Reasonably the rest of the table is also correct... (testing of that + # deemed excessive at the moment) + raises(ValueError, lambda: finite_diff_weights(-1, [1, 2])) + raises(ValueError, lambda: finite_diff_weights(1.2, [1, 2])) + x = symbols('x') + raises(ValueError, lambda: finite_diff_weights(x, [1, 2])) + + +def test_as_finite_diff(): + x = symbols('x') + f = Function('f') + dx = Function('dx') + + _as_finite_diff(f(x).diff(x), [x-2, x-1, x, x+1, x+2]) + + # Use of undefined functions in ``points`` + df_true = -f(x+dx(x)/2-dx(x+dx(x)/2)/2) / dx(x+dx(x)/2) \ + + f(x+dx(x)/2+dx(x+dx(x)/2)/2) / dx(x+dx(x)/2) + df_test = diff(f(x), x).as_finite_difference(points=dx(x), x0=x+dx(x)/2) + assert (df_test - df_true).simplify() == 0 + + +def test_differentiate_finite(): + x, y, h = symbols('x y h') + f = Function('f') + with warns_deprecated_sympy(): + res0 = differentiate_finite(f(x, y) + exp(42), x, y, evaluate=True) + xm, xp, ym, yp = [v + sign*S.Half for v, sign in product([x, y], [-1, 1])] + ref0 = f(xm, ym) + f(xp, yp) - f(xm, yp) - f(xp, ym) + assert (res0 - ref0).simplify() == 0 + + g = Function('g') + with warns_deprecated_sympy(): + res1 = differentiate_finite(f(x)*g(x) + 42, x, evaluate=True) + ref1 = (-f(x - S.Half) + f(x + S.Half))*g(x) + \ + (-g(x - S.Half) + g(x + S.Half))*f(x) + assert (res1 - ref1).simplify() == 0 + + res2 = differentiate_finite(f(x) + x**3 + 42, x, points=[x-1, x+1]) + ref2 = (f(x + 1) + (x + 1)**3 - f(x - 1) - (x - 1)**3)/2 + assert (res2 - ref2).simplify() == 0 + raises(TypeError, lambda: differentiate_finite(f(x)*g(x), x, + pints=[x-1, x+1])) + + res3 = differentiate_finite(f(x)*g(x).diff(x), x) + ref3 = (-g(x) + g(x + 1))*f(x + S.Half) - (g(x) - g(x - 1))*f(x - S.Half) + assert res3 == ref3 + + res4 = differentiate_finite(f(x)*g(x).diff(x).diff(x), x) + ref4 = -((g(x - Rational(3, 2)) - 2*g(x - S.Half) + g(x + S.Half))*f(x - S.Half)) \ + + (g(x - S.Half) - 2*g(x + S.Half) + g(x + Rational(3, 2)))*f(x + S.Half) + assert res4 == ref4 + + res5_expr = f(x).diff(x)*g(x).diff(x) + res5 = differentiate_finite(res5_expr, points=[x-h, x, x+h]) + ref5 = (-2*f(x)/h + f(-h + x)/(2*h) + 3*f(h + x)/(2*h))*(-2*g(x)/h + g(-h + x)/(2*h) \ + + 3*g(h + x)/(2*h))/(2*h) - (2*f(x)/h - 3*f(-h + x)/(2*h) - \ + f(h + x)/(2*h))*(2*g(x)/h - 3*g(-h + x)/(2*h) - g(h + x)/(2*h))/(2*h) + assert res5 == ref5 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/test_singularities.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/test_singularities.py new file mode 100644 index 0000000000000000000000000000000000000000..19a042332326658021ce12a38f4e058f55903869 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/test_singularities.py @@ -0,0 +1,122 @@ +from sympy.core.numbers import (I, Rational, pi, oo) +from sympy.core.singleton import S +from sympy.core.symbol import Symbol, Dummy +from sympy.core.function import Lambda +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.trigonometric import sec, csc +from sympy.functions.elementary.hyperbolic import (coth, sech, + atanh, asech, acoth, acsch) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.calculus.singularities import ( + singularities, + is_increasing, + is_strictly_increasing, + is_decreasing, + is_strictly_decreasing, + is_monotonic +) +from sympy.sets import Interval, FiniteSet, Union, ImageSet +from sympy.testing.pytest import raises +from sympy.abc import x, y + + +def test_singularities(): + x = Symbol('x') + assert singularities(x**2, x) == S.EmptySet + assert singularities(x/(x**2 + 3*x + 2), x) == FiniteSet(-2, -1) + assert singularities(1/(x**2 + 1), x) == FiniteSet(I, -I) + assert singularities(x/(x**3 + 1), x) == \ + FiniteSet(-1, (1 - sqrt(3) * I) / 2, (1 + sqrt(3) * I) / 2) + assert singularities(1/(y**2 + 2*I*y + 1), y) == \ + FiniteSet(-I + sqrt(2)*I, -I - sqrt(2)*I) + _n = Dummy('n') + assert singularities(sech(x), x).dummy_eq(Union( + ImageSet(Lambda(_n, 2*_n*I*pi + I*pi/2), S.Integers), + ImageSet(Lambda(_n, 2*_n*I*pi + 3*I*pi/2), S.Integers))) + assert singularities(coth(x), x).dummy_eq(Union( + ImageSet(Lambda(_n, 2*_n*I*pi + I*pi), S.Integers), + ImageSet(Lambda(_n, 2*_n*I*pi), S.Integers))) + assert singularities(atanh(x), x) == FiniteSet(-1, 1) + assert singularities(acoth(x), x) == FiniteSet(-1, 1) + assert singularities(asech(x), x) == FiniteSet(0) + assert singularities(acsch(x), x) == FiniteSet(0) + + x = Symbol('x', real=True) + assert singularities(1/(x**2 + 1), x) == S.EmptySet + assert singularities(exp(1/x), x, S.Reals) == FiniteSet(0) + assert singularities(exp(1/x), x, Interval(1, 2)) == S.EmptySet + assert singularities(log((x - 2)**2), x, Interval(1, 3)) == FiniteSet(2) + raises(NotImplementedError, lambda: singularities(x**-oo, x)) + assert singularities(sec(x), x, Interval(0, 3*pi)) == FiniteSet( + pi/2, 3*pi/2, 5*pi/2) + assert singularities(csc(x), x, Interval(0, 3*pi)) == FiniteSet( + 0, pi, 2*pi, 3*pi) + + +def test_is_increasing(): + """Test whether is_increasing returns correct value.""" + a = Symbol('a', negative=True) + + assert is_increasing(x**3 - 3*x**2 + 4*x, S.Reals) + assert is_increasing(-x**2, Interval(-oo, 0)) + assert not is_increasing(-x**2, Interval(0, oo)) + assert not is_increasing(4*x**3 - 6*x**2 - 72*x + 30, Interval(-2, 3)) + assert is_increasing(x**2 + y, Interval(1, oo), x) + assert is_increasing(-x**2*a, Interval(1, oo), x) + assert is_increasing(1) + + assert is_increasing(4*x**3 - 6*x**2 - 72*x + 30, Interval(-2, 3)) is False + + +def test_is_strictly_increasing(): + """Test whether is_strictly_increasing returns correct value.""" + assert is_strictly_increasing( + 4*x**3 - 6*x**2 - 72*x + 30, Interval.Ropen(-oo, -2)) + assert is_strictly_increasing( + 4*x**3 - 6*x**2 - 72*x + 30, Interval.Lopen(3, oo)) + assert not is_strictly_increasing( + 4*x**3 - 6*x**2 - 72*x + 30, Interval.open(-2, 3)) + assert not is_strictly_increasing(-x**2, Interval(0, oo)) + assert not is_strictly_decreasing(1) + + assert is_strictly_increasing(4*x**3 - 6*x**2 - 72*x + 30, Interval.open(-2, 3)) is False + + +def test_is_decreasing(): + """Test whether is_decreasing returns correct value.""" + b = Symbol('b', positive=True) + + assert is_decreasing(1/(x**2 - 3*x), Interval.open(Rational(3,2), 3)) + assert is_decreasing(1/(x**2 - 3*x), Interval.open(1.5, 3)) + assert is_decreasing(1/(x**2 - 3*x), Interval.Lopen(3, oo)) + assert not is_decreasing(1/(x**2 - 3*x), Interval.Ropen(-oo, Rational(3, 2))) + assert not is_decreasing(-x**2, Interval(-oo, 0)) + assert not is_decreasing(-x**2*b, Interval(-oo, 0), x) + + +def test_is_strictly_decreasing(): + """Test whether is_strictly_decreasing returns correct value.""" + assert is_strictly_decreasing(1/(x**2 - 3*x), Interval.Lopen(3, oo)) + assert not is_strictly_decreasing( + 1/(x**2 - 3*x), Interval.Ropen(-oo, Rational(3, 2))) + assert not is_strictly_decreasing(-x**2, Interval(-oo, 0)) + assert not is_strictly_decreasing(1) + assert is_strictly_decreasing(1/(x**2 - 3*x), Interval.open(Rational(3,2), 3)) + assert is_strictly_decreasing(1/(x**2 - 3*x), Interval.open(1.5, 3)) + + +def test_is_monotonic(): + """Test whether is_monotonic returns correct value.""" + assert is_monotonic(1/(x**2 - 3*x), Interval.open(Rational(3,2), 3)) + assert is_monotonic(1/(x**2 - 3*x), Interval.open(1.5, 3)) + assert is_monotonic(1/(x**2 - 3*x), Interval.Lopen(3, oo)) + assert is_monotonic(x**3 - 3*x**2 + 4*x, S.Reals) + assert not is_monotonic(-x**2, S.Reals) + assert is_monotonic(x**2 + y + 1, Interval(1, 2), x) + raises(NotImplementedError, lambda: is_monotonic(x**2 + y + 1)) + + +def test_issue_23401(): + x = Symbol('x') + expr = (x + 1)/(-1.0e-3*x**2 + 0.1*x + 0.1) + assert is_increasing(expr, Interval(1,2), x) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/test_util.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/test_util.py new file mode 100644 index 0000000000000000000000000000000000000000..c18b7a79fd54fdb2638cc746d43ab26753fc72a9 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/calculus/tests/test_util.py @@ -0,0 +1,392 @@ +from sympy.core.function import Lambda +from sympy.core.numbers import (E, I, Rational, oo, pi) +from sympy.core.relational import Eq +from sympy.core.singleton import S +from sympy.core.symbol import (Dummy, Symbol) +from sympy.functions.elementary.complexes import (Abs, re) +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.integers import frac +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.piecewise import Piecewise +from sympy.functions.elementary.trigonometric import ( + cos, cot, csc, sec, sin, tan, asin, acos, atan, acot, asec, acsc) +from sympy.functions.elementary.hyperbolic import (sinh, cosh, tanh, coth, + sech, csch, asinh, acosh, atanh, acoth, asech, acsch) +from sympy.functions.special.gamma_functions import gamma +from sympy.functions.special.error_functions import expint +from sympy.matrices.expressions.matexpr import MatrixSymbol +from sympy.simplify.simplify import simplify +from sympy.calculus.util import (function_range, continuous_domain, not_empty_in, + periodicity, lcim, is_convex, + stationary_points, minimum, maximum) +from sympy.sets.sets import (Interval, FiniteSet, Complement, Union) +from sympy.sets.fancysets import ImageSet +from sympy.sets.conditionset import ConditionSet +from sympy.testing.pytest import XFAIL, raises, _both_exp_pow, slow +from sympy.abc import x, y + +a = Symbol('a', real=True) + +def test_function_range(): + assert function_range(sin(x), x, Interval(-pi/2, pi/2) + ) == Interval(-1, 1) + assert function_range(sin(x), x, Interval(0, pi) + ) == Interval(0, 1) + assert function_range(tan(x), x, Interval(0, pi) + ) == Interval(-oo, oo) + assert function_range(tan(x), x, Interval(pi/2, pi) + ) == Interval(-oo, 0) + assert function_range((x + 3)/(x - 2), x, Interval(-5, 5) + ) == Union(Interval(-oo, Rational(2, 7)), Interval(Rational(8, 3), oo)) + assert function_range(1/(x**2), x, Interval(-1, 1) + ) == Interval(1, oo) + assert function_range(exp(x), x, Interval(-1, 1) + ) == Interval(exp(-1), exp(1)) + assert function_range(log(x) - x, x, S.Reals + ) == Interval(-oo, -1) + assert function_range(sqrt(3*x - 1), x, Interval(0, 2) + ) == Interval(0, sqrt(5)) + assert function_range(x*(x - 1) - (x**2 - x), x, S.Reals + ) == FiniteSet(0) + assert function_range(x*(x - 1) - (x**2 - x) + y, x, S.Reals + ) == FiniteSet(y) + assert function_range(sin(x), x, Union(Interval(-5, -3), FiniteSet(4)) + ) == Union(Interval(-sin(3), 1), FiniteSet(sin(4))) + assert function_range(cos(x), x, Interval(-oo, -4) + ) == Interval(-1, 1) + assert function_range(cos(x), x, S.EmptySet) == S.EmptySet + assert function_range(x/sqrt(x**2+1), x, S.Reals) == Interval.open(-1,1) + raises(NotImplementedError, lambda : function_range( + exp(x)*(sin(x) - cos(x))/2 - x, x, S.Reals)) + raises(NotImplementedError, lambda : function_range( + sin(x) + x, x, S.Reals)) # issue 13273 + raises(NotImplementedError, lambda : function_range( + log(x), x, S.Integers)) + raises(NotImplementedError, lambda : function_range( + sin(x)/2, x, S.Naturals)) + + +@slow +def test_function_range1(): + assert function_range(tan(x)**2 + tan(3*x)**2 + 1, x, S.Reals) == Interval(1,oo) + + +def test_continuous_domain(): + assert continuous_domain(sin(x), x, Interval(0, 2*pi)) == Interval(0, 2*pi) + assert continuous_domain(tan(x), x, Interval(0, 2*pi)) == \ + Union(Interval(0, pi/2, False, True), Interval(pi/2, pi*Rational(3, 2), True, True), + Interval(pi*Rational(3, 2), 2*pi, True, False)) + assert continuous_domain(cot(x), x, Interval(0, 2*pi)) == Union( + Interval.open(0, pi), Interval.open(pi, 2*pi)) + assert continuous_domain((x - 1)/((x - 1)**2), x, S.Reals) == \ + Union(Interval(-oo, 1, True, True), Interval(1, oo, True, True)) + assert continuous_domain(log(x) + log(4*x - 1), x, S.Reals) == \ + Interval(Rational(1, 4), oo, True, True) + assert continuous_domain(1/sqrt(x - 3), x, S.Reals) == Interval(3, oo, True, True) + assert continuous_domain(1/x - 2, x, S.Reals) == \ + Union(Interval.open(-oo, 0), Interval.open(0, oo)) + assert continuous_domain(1/(x**2 - 4) + 2, x, S.Reals) == \ + Union(Interval.open(-oo, -2), Interval.open(-2, 2), Interval.open(2, oo)) + assert continuous_domain((x+1)**pi, x, S.Reals) == Interval(-1, oo) + assert continuous_domain((x+1)**(pi/2), x, S.Reals) == Interval(-1, oo) + assert continuous_domain(x**x, x, S.Reals) == Interval(0, oo) + assert continuous_domain((x+1)**log(x**2), x, S.Reals) == Union( + Interval.Ropen(-1, 0), Interval.open(0, oo)) + domain = continuous_domain(log(tan(x)**2 + 1), x, S.Reals) + assert not domain.contains(3*pi/2) + assert domain.contains(5) + d = Symbol('d', even=True, zero=False) + assert continuous_domain(x**(1/d), x, S.Reals) == Interval(0, oo) + n = Dummy('n') + assert continuous_domain(1/sin(x), x, S.Reals).dummy_eq(Complement( + S.Reals, Union(ImageSet(Lambda(n, 2*n*pi + pi), S.Integers), + ImageSet(Lambda(n, 2*n*pi), S.Integers)))) + assert continuous_domain(sin(x) + cos(x), x, S.Reals) == S.Reals + assert continuous_domain(asin(x), x, S.Reals) == Interval(-1, 1) # issue #21786 + assert continuous_domain(1/acos(log(x)), x, S.Reals) == Interval.Ropen(exp(-1), E) + assert continuous_domain(sinh(x)+cosh(x), x, S.Reals) == S.Reals + assert continuous_domain(tanh(x)+sech(x), x, S.Reals) == S.Reals + assert continuous_domain(atan(x)+asinh(x), x, S.Reals) == S.Reals + assert continuous_domain(acosh(x), x, S.Reals) == Interval(1, oo) + assert continuous_domain(atanh(x), x, S.Reals) == Interval.open(-1, 1) + assert continuous_domain(atanh(x)+acosh(x), x, S.Reals) == S.EmptySet + assert continuous_domain(asech(x), x, S.Reals) == Interval.Lopen(0, 1) + assert continuous_domain(acoth(x), x, S.Reals) == Union( + Interval.open(-oo, -1), Interval.open(1, oo)) + assert continuous_domain(asec(x), x, S.Reals) == Union( + Interval(-oo, -1), Interval(1, oo)) + assert continuous_domain(acsc(x), x, S.Reals) == Union( + Interval(-oo, -1), Interval(1, oo)) + for f in (coth, acsch, csch): + assert continuous_domain(f(x), x, S.Reals) == Union( + Interval.open(-oo, 0), Interval.open(0, oo)) + assert continuous_domain(acot(x), x, S.Reals).contains(0) == False + assert continuous_domain(1/(exp(x) - x), x, S.Reals) == Complement( + S.Reals, ConditionSet(x, Eq(-x + exp(x), 0), S.Reals)) + assert continuous_domain(frac(x**2), x, Interval(-2,-1)) == Union( + Interval.open(-2, -sqrt(3)), Interval.open(-sqrt(2), -1), + Interval.open(-sqrt(3), -sqrt(2))) + assert continuous_domain(frac(x), x, S.Reals) == Complement( + S.Reals, S.Integers) + raises(NotImplementedError, lambda : continuous_domain( + 1/(x**2+1), x, S.Complexes)) + raises(NotImplementedError, lambda : continuous_domain( + gamma(x), x, Interval(-5,0))) + assert continuous_domain(x + gamma(pi), x, S.Reals) == S.Reals + + +@XFAIL +def test_continuous_domain_acot(): + acot_cont = Piecewise((pi+acot(x), x<0), (acot(x), True)) + assert continuous_domain(acot_cont, x, S.Reals) == S.Reals + +@XFAIL +def test_continuous_domain_gamma(): + assert continuous_domain(gamma(x), x, S.Reals).contains(-1) == False + +@XFAIL +def test_continuous_domain_neg_power(): + assert continuous_domain((x-2)**(1-x), x, S.Reals) == Interval.open(2, oo) + + +def test_not_empty_in(): + assert not_empty_in(FiniteSet(x, 2*x).intersect(Interval(1, 2, True, False)), x) == \ + Interval(S.Half, 2, True, False) + assert not_empty_in(FiniteSet(x, x**2).intersect(Interval(1, 2)), x) == \ + Union(Interval(-sqrt(2), -1), Interval(1, 2)) + assert not_empty_in(FiniteSet(x**2 + x, x).intersect(Interval(2, 4)), x) == \ + Union(Interval(-sqrt(17)/2 - S.Half, -2), + Interval(1, Rational(-1, 2) + sqrt(17)/2), Interval(2, 4)) + assert not_empty_in(FiniteSet(x/(x - 1)).intersect(S.Reals), x) == \ + Complement(S.Reals, FiniteSet(1)) + assert not_empty_in(FiniteSet(a/(a - 1)).intersect(S.Reals), a) == \ + Complement(S.Reals, FiniteSet(1)) + assert not_empty_in(FiniteSet((x**2 - 3*x + 2)/(x - 1)).intersect(S.Reals), x) == \ + Complement(S.Reals, FiniteSet(1)) + assert not_empty_in(FiniteSet(3, 4, x/(x - 1)).intersect(Interval(2, 3)), x) == \ + Interval(-oo, oo) + assert not_empty_in(FiniteSet(4, x/(x - 1)).intersect(Interval(2, 3)), x) == \ + Interval(S(3)/2, 2) + assert not_empty_in(FiniteSet(x/(x**2 - 1)).intersect(S.Reals), x) == \ + Complement(S.Reals, FiniteSet(-1, 1)) + assert not_empty_in(FiniteSet(x, x**2).intersect(Union(Interval(1, 3, True, True), + Interval(4, 5))), x) == \ + Union(Interval(-sqrt(5), -2), Interval(-sqrt(3), -1, True, True), + Interval(1, 3, True, True), Interval(4, 5)) + assert not_empty_in(FiniteSet(1).intersect(Interval(3, 4)), x) == S.EmptySet + assert not_empty_in(FiniteSet(x**2/(x + 2)).intersect(Interval(1, oo)), x) == \ + Union(Interval(-2, -1, True, False), Interval(2, oo)) + raises(ValueError, lambda: not_empty_in(x)) + raises(ValueError, lambda: not_empty_in(Interval(0, 1), x)) + raises(NotImplementedError, + lambda: not_empty_in(FiniteSet(x).intersect(S.Reals), x, a)) + + +@_both_exp_pow +def test_periodicity(): + assert periodicity(sin(2*x), x) == pi + assert periodicity((-2)*tan(4*x), x) == pi/4 + assert periodicity(sin(x)**2, x) == 2*pi + assert periodicity(3**tan(3*x), x) == pi/3 + assert periodicity(tan(x)*cos(x), x) == 2*pi + assert periodicity(sin(x)**(tan(x)), x) == 2*pi + assert periodicity(tan(x)*sec(x), x) == 2*pi + assert periodicity(sin(2*x)*cos(2*x) - y, x) == pi/2 + assert periodicity(tan(x) + cot(x), x) == pi + assert periodicity(sin(x) - cos(2*x), x) == 2*pi + assert periodicity(sin(x) - 1, x) == 2*pi + assert periodicity(sin(4*x) + sin(x)*cos(x), x) == pi + assert periodicity(exp(sin(x)), x) == 2*pi + assert periodicity(log(cot(2*x)) - sin(cos(2*x)), x) == pi + assert periodicity(sin(2*x)*exp(tan(x) - csc(2*x)), x) == pi + assert periodicity(cos(sec(x) - csc(2*x)), x) == 2*pi + assert periodicity(tan(sin(2*x)), x) == pi + assert periodicity(2*tan(x)**2, x) == pi + assert periodicity(sin(x%4), x) == 4 + assert periodicity(sin(x)%4, x) == 2*pi + assert periodicity(tan((3*x-2)%4), x) == Rational(4, 3) + assert periodicity((sqrt(2)*(x+1)+x) % 3, x) == 3 / (sqrt(2)+1) + assert periodicity((x**2+1) % x, x) is None + assert periodicity(sin(re(x)), x) == 2*pi + assert periodicity(sin(x)**2 + cos(x)**2, x) is S.Zero + assert periodicity(tan(x), y) is S.Zero + assert periodicity(sin(x) + I*cos(x), x) == 2*pi + assert periodicity(x - sin(2*y), y) == pi + + assert periodicity(exp(x), x) is None + assert periodicity(exp(I*x), x) == 2*pi + assert periodicity(exp(I*a), a) == 2*pi + assert periodicity(exp(a), a) is None + assert periodicity(exp(log(sin(a) + I*cos(2*a)), evaluate=False), a) == 2*pi + assert periodicity(exp(log(sin(2*a) + I*cos(a)), evaluate=False), a) == 2*pi + assert periodicity(exp(sin(a)), a) == 2*pi + assert periodicity(exp(2*I*a), a) == pi + assert periodicity(exp(a + I*sin(a)), a) is None + assert periodicity(exp(cos(a/2) + sin(a)), a) == 4*pi + assert periodicity(log(x), x) is None + assert periodicity(exp(x)**sin(x), x) is None + assert periodicity(sin(x)**y, y) is None + + assert periodicity(Abs(sin(Abs(sin(x)))), x) == pi + assert all(periodicity(Abs(f(x)), x) == pi for f in ( + cos, sin, sec, csc, tan, cot)) + assert periodicity(Abs(sin(tan(x))), x) == pi + assert periodicity(Abs(sin(sin(x) + tan(x))), x) == 2*pi + assert periodicity(sin(x) > S.Half, x) == 2*pi + + assert periodicity(x > 2, x) is None + assert periodicity(x**3 - x**2 + 1, x) is None + assert periodicity(Abs(x), x) is None + assert periodicity(Abs(x**2 - 1), x) is None + + assert periodicity((x**2 + 4)%2, x) is None + assert periodicity((E**x)%3, x) is None + + assert periodicity(sin(expint(1, x))/expint(1, x), x) is None + # returning `None` for any Piecewise + p = Piecewise((0, x < -1), (x**2, x <= 1), (log(x), True)) + assert periodicity(p, x) is None + + m = MatrixSymbol('m', 3, 3) + raises(NotImplementedError, lambda: periodicity(sin(m), m)) + raises(NotImplementedError, lambda: periodicity(sin(m[0, 0]), m)) + raises(NotImplementedError, lambda: periodicity(sin(m), m[0, 0])) + raises(NotImplementedError, lambda: periodicity(sin(m[0, 0]), m[0, 0])) + + +def test_periodicity_check(): + assert periodicity(tan(x), x, check=True) == pi + assert periodicity(sin(x) + cos(x), x, check=True) == 2*pi + assert periodicity(sec(x), x) == 2*pi + assert periodicity(sin(x*y), x) == 2*pi/abs(y) + assert periodicity(Abs(sec(sec(x))), x) == pi + + +def test_lcim(): + assert lcim([S.Half, S(2), S(3)]) == 6 + assert lcim([pi/2, pi/4, pi]) == pi + assert lcim([2*pi, pi/2]) == 2*pi + assert lcim([S.One, 2*pi]) is None + assert lcim([S(2) + 2*E, E/3 + Rational(1, 3), S.One + E]) == S(2) + 2*E + + +def test_is_convex(): + assert is_convex(1/x, x, domain=Interval.open(0, oo)) == True + assert is_convex(1/x, x, domain=Interval(-oo, 0)) == False + assert is_convex(x**2, x, domain=Interval(0, oo)) == True + assert is_convex(1/x**3, x, domain=Interval.Lopen(0, oo)) == True + assert is_convex(-1/x**3, x, domain=Interval.Ropen(-oo, 0)) == True + assert is_convex(log(x) ,x) == False + assert is_convex(x**2+y**2, x, y) == True + assert is_convex(cos(x) + cos(y), x) == False + assert is_convex(8*x**2 - 2*y**2, x, y) == False + + +def test_stationary_points(): + assert stationary_points(sin(x), x, Interval(-pi/2, pi/2) + ) == {-pi/2, pi/2} + assert stationary_points(sin(x), x, Interval.Ropen(0, pi/4) + ) is S.EmptySet + assert stationary_points(tan(x), x, + ) is S.EmptySet + assert stationary_points(sin(x)*cos(x), x, Interval(0, pi) + ) == {pi/4, pi*Rational(3, 4)} + assert stationary_points(sec(x), x, Interval(0, pi) + ) == {0, pi} + assert stationary_points((x+3)*(x-2), x + ) == FiniteSet(Rational(-1, 2)) + assert stationary_points((x + 3)/(x - 2), x, Interval(-5, 5) + ) is S.EmptySet + assert stationary_points((x**2+3)/(x-2), x + ) == {2 - sqrt(7), 2 + sqrt(7)} + assert stationary_points((x**2+3)/(x-2), x, Interval(0, 5) + ) == {2 + sqrt(7)} + assert stationary_points(x**4 + x**3 - 5*x**2, x, S.Reals + ) == FiniteSet(-2, 0, Rational(5, 4)) + assert stationary_points(exp(x), x + ) is S.EmptySet + assert stationary_points(log(x) - x, x, S.Reals + ) == {1} + assert stationary_points(cos(x), x, Union(Interval(0, 5), Interval(-6, -3)) + ) == {0, -pi, pi} + assert stationary_points(y, x, S.Reals + ) == S.Reals + assert stationary_points(y, x, S.EmptySet) == S.EmptySet + + +def test_maximum(): + assert maximum(sin(x), x) is S.One + assert maximum(sin(x), x, Interval(0, 1)) == sin(1) + assert maximum(tan(x), x) is oo + assert maximum(tan(x), x, Interval(-pi/4, pi/4)) is S.One + assert maximum(sin(x)*cos(x), x, S.Reals) == S.Half + assert simplify(maximum(sin(x)*cos(x), x, Interval(pi*Rational(3, 8), pi*Rational(5, 8))) + ) == sqrt(2)/4 + assert maximum((x+3)*(x-2), x) is oo + assert maximum((x+3)*(x-2), x, Interval(-5, 0)) == S(14) + assert maximum((x+3)/(x-2), x, Interval(-5, 0)) == Rational(2, 7) + assert simplify(maximum(-x**4-x**3+x**2+10, x) + ) == 41*sqrt(41)/512 + Rational(5419, 512) + assert maximum(exp(x), x, Interval(-oo, 2)) == exp(2) + assert maximum(log(x) - x, x, S.Reals) is S.NegativeOne + assert maximum(cos(x), x, Union(Interval(0, 5), Interval(-6, -3)) + ) is S.One + assert maximum(cos(x)-sin(x), x, S.Reals) == sqrt(2) + assert maximum(y, x, S.Reals) == y + assert maximum(abs(a**3 + a), a, Interval(0, 2)) == 10 + assert maximum(abs(60*a**3 + 24*a), a, Interval(0, 2)) == 528 + assert maximum(abs(12*a*(5*a**2 + 2)), a, Interval(0, 2)) == 528 + assert maximum(x/sqrt(x**2+1), x, S.Reals) == 1 + + raises(ValueError, lambda : maximum(sin(x), x, S.EmptySet)) + raises(ValueError, lambda : maximum(log(cos(x)), x, S.EmptySet)) + raises(ValueError, lambda : maximum(1/(x**2 + y**2 + 1), x, S.EmptySet)) + raises(ValueError, lambda : maximum(sin(x), sin(x))) + raises(ValueError, lambda : maximum(sin(x), x*y, S.EmptySet)) + raises(ValueError, lambda : maximum(sin(x), S.One)) + + +def test_minimum(): + assert minimum(sin(x), x) is S.NegativeOne + assert minimum(sin(x), x, Interval(1, 4)) == sin(4) + assert minimum(tan(x), x) is -oo + assert minimum(tan(x), x, Interval(-pi/4, pi/4)) is S.NegativeOne + assert minimum(sin(x)*cos(x), x, S.Reals) == Rational(-1, 2) + assert simplify(minimum(sin(x)*cos(x), x, Interval(pi*Rational(3, 8), pi*Rational(5, 8))) + ) == -sqrt(2)/4 + assert minimum((x+3)*(x-2), x) == Rational(-25, 4) + assert minimum((x+3)/(x-2), x, Interval(-5, 0)) == Rational(-3, 2) + assert minimum(x**4-x**3+x**2+10, x) == S(10) + assert minimum(exp(x), x, Interval(-2, oo)) == exp(-2) + assert minimum(log(x) - x, x, S.Reals) is -oo + assert minimum(cos(x), x, Union(Interval(0, 5), Interval(-6, -3)) + ) is S.NegativeOne + assert minimum(cos(x)-sin(x), x, S.Reals) == -sqrt(2) + assert minimum(y, x, S.Reals) == y + assert minimum(x/sqrt(x**2+1), x, S.Reals) == -1 + + raises(ValueError, lambda : minimum(sin(x), x, S.EmptySet)) + raises(ValueError, lambda : minimum(log(cos(x)), x, S.EmptySet)) + raises(ValueError, lambda : minimum(1/(x**2 + y**2 + 1), x, S.EmptySet)) + raises(ValueError, lambda : minimum(sin(x), sin(x))) + raises(ValueError, lambda : minimum(sin(x), x*y, S.EmptySet)) + raises(ValueError, lambda : minimum(sin(x), S.One)) + + +def test_issue_19869(): + assert (maximum(sqrt(3)*(x - 1)/(3*sqrt(x**2 + 1)), x) + ) == sqrt(3)/3 + + +def test_issue_16469(): + f = abs(a) + assert function_range(f, a, S.Reals) == Interval(0, oo, False, True) + + +@_both_exp_pow +def test_issue_18747(): + assert periodicity(exp(pi*I*(x/4 + S.Half/2)), x) == 8 + + +def test_issue_25942(): + assert (acos(x) > pi/3).as_set() == Interval.Ropen(-1, S(1)/2) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f8254daed76c138019bc9a5ce53655103f05dc2b Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/coset_table.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/coset_table.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..278afd362ca49ad1712611205d769bd8dc4d00ea Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/coset_table.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/fp_groups.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/fp_groups.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..259335d66b5294db66e142df4df2fd94de5aad37 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/fp_groups.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/free_groups.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/free_groups.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5f2b2ba5b3aef4677aa67fbd3fff25a0ae85673b Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/free_groups.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/galois.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/galois.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c52e2d9d778c9f083c331267755b60b23cc3ef63 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/galois.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/generators.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/generators.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4efecb405c59de4b9fff8b323477d5ec248fcb64 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/generators.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/graycode.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/graycode.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cf75d659e4c17cf796e668fdf77df2690eb864b4 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/graycode.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/group_constructs.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/group_constructs.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9334cc802b8cdf0eee4302ab0f20dbfb39e1f2cd Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/group_constructs.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/group_numbers.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/group_numbers.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4c3ec77a015b05ad388d8d6963c186f9872b840c Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/group_numbers.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/homomorphisms.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/homomorphisms.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..56094a6a119cc67806fd88ec0503f6db59b5c687 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/homomorphisms.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/named_groups.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/named_groups.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2d79b1011cbc134a97e1c1ede57c3f6af3f92f08 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/named_groups.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/partitions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/partitions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e06c0901bffc5bac2e94faadbb39328b91885e71 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/partitions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/pc_groups.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/pc_groups.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..80fb51f8258f3c3f833bea223bab88810f5ed2b8 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/pc_groups.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/polyhedron.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/polyhedron.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9c82a2987c7e2c1c1d2cbb7104b842fddbcf2eda Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/polyhedron.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/prufer.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/prufer.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..480c839b6af3282326fd84c883fe19aa9d30a097 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/prufer.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/rewritingsystem.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/rewritingsystem.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fc47a2b7566defa6f06b0c92240caf79b725664e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/rewritingsystem.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/rewritingsystem_fsm.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/rewritingsystem_fsm.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..46f6019ec219639c2a53089681ca7e5965e87b10 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/rewritingsystem_fsm.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/schur_number.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/schur_number.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0c385b62499f6ba6c0da262be9164332a9fc5615 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/schur_number.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/subsets.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/subsets.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..97a6174bd3119ca1942f017d02e8bc74f44b53df Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/subsets.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/tensor_can.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/tensor_can.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3ea6638b68edb89d4932e988ba67f37061fd7fa0 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/tensor_can.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/testutil.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/testutil.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d31bea5c20cf93da03ade4f90114664b19258182 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/testutil.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/util.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/util.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8736930208532e5edfdd732fafd9fd378ee5b544 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/__pycache__/util.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f2a5f2502ebb8a5dd23389cca6f7f2f31604b016 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_coset_table.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_coset_table.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4eb4f17cd55abfa096303105d5b1c81d8cb5a1b0 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_coset_table.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_fp_groups.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_fp_groups.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..71ebb96bb1ada85e0485ba0981820294b01698c4 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_fp_groups.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_free_groups.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_free_groups.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4dc321c7026128eab5b67e66926e4a8c46d3b50b Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_free_groups.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_galois.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_galois.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..65a3a3dfcb6fa8686a6393e759b14f47416c69dd Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_galois.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_generators.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_generators.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0b40708164c1961f95ee5a9493078b320be4a7b4 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_generators.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_graycode.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_graycode.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8529e014dfd02b243d635bbcf27b52e87fe13dc1 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_graycode.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_group_constructs.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_group_constructs.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ced76ea82abc896c4ed435e6acfc833b17bb95f2 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_group_constructs.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_group_numbers.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_group_numbers.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fc4e5b2cabb93da643a31c2674909ea5acb9a9d1 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_group_numbers.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_homomorphisms.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_homomorphisms.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d15356b8c00e349b80e32a4c140f5ae2c0c6f3b7 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_homomorphisms.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_named_groups.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_named_groups.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a61e92d2bfec593868b8e34ead12ed204674a501 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_named_groups.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_partitions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_partitions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c9c4e3b6f3a341ba915e275f43dd2e018630b389 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_partitions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_pc_groups.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_pc_groups.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6fa0c8b6096b5f4398cf5aacbfd533f4b2487a7e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_pc_groups.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_perm_groups.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_perm_groups.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..331ae46a832c8ea1432d8a728d46e477bd5cf4e7 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_perm_groups.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_permutations.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_permutations.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..525df2d1163c0c4b2aaaa62cf9429b8331a79c10 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_permutations.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_polyhedron.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_polyhedron.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..71d7225a05ec7e7ca0fadd8ca8597e680dd61a7c Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_polyhedron.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_prufer.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_prufer.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c3d3c8e63a2fb489e50b4ceab387a82f0a66317c Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_prufer.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_rewriting.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_rewriting.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ddf226a435539ca5371adc5f86e1810a2998509a Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_rewriting.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_schur_number.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_schur_number.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8d5cec571a6f8430c0971385139070cffad88a41 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_schur_number.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_subsets.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_subsets.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4928efff1949875f1865efc3ebf6f7f26a5b2dd2 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_subsets.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_tensor_can.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_tensor_can.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bcee5ffe79114c9fe5fb526aea43fb0082528fed Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_tensor_can.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_testutil.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_testutil.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..626d7e2177f4cfc57bfeb12b2e845f21d95c1f83 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_testutil.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_util.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_util.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5d31574cf0bc624f30aa4291a6d410bcf9b68e4a Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/__pycache__/test_util.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_coset_table.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_coset_table.py new file mode 100644 index 0000000000000000000000000000000000000000..ab3f62880445c5deb526797ee0623fe3510bcbc3 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_coset_table.py @@ -0,0 +1,825 @@ +from sympy.combinatorics.fp_groups import FpGroup +from sympy.combinatorics.coset_table import (CosetTable, + coset_enumeration_r, coset_enumeration_c) +from sympy.combinatorics.coset_table import modified_coset_enumeration_r +from sympy.combinatorics.free_groups import free_group + +from sympy.testing.pytest import slow + +""" +References +========== + +[1] Holt, D., Eick, B., O'Brien, E. +"Handbook of Computational Group Theory" + +[2] John J. Cannon; Lucien A. Dimino; George Havas; Jane M. Watson +Mathematics of Computation, Vol. 27, No. 123. (Jul., 1973), pp. 463-490. +"Implementation and Analysis of the Todd-Coxeter Algorithm" + +""" + +def test_scan_1(): + # Example 5.1 from [1] + F, x, y = free_group("x, y") + f = FpGroup(F, [x**3, y**3, x**-1*y**-1*x*y]) + c = CosetTable(f, [x]) + + c.scan_and_fill(0, x) + assert c.table == [[0, 0, None, None]] + assert c.p == [0] + assert c.n == 1 + assert c.omega == [0] + + c.scan_and_fill(0, x**3) + assert c.table == [[0, 0, None, None]] + assert c.p == [0] + assert c.n == 1 + assert c.omega == [0] + + c.scan_and_fill(0, y**3) + assert c.table == [[0, 0, 1, 2], [None, None, 2, 0], [None, None, 0, 1]] + assert c.p == [0, 1, 2] + assert c.n == 3 + assert c.omega == [0, 1, 2] + + c.scan_and_fill(0, x**-1*y**-1*x*y) + assert c.table == [[0, 0, 1, 2], [None, None, 2, 0], [2, 2, 0, 1]] + assert c.p == [0, 1, 2] + assert c.n == 3 + assert c.omega == [0, 1, 2] + + c.scan_and_fill(1, x**3) + assert c.table == [[0, 0, 1, 2], [3, 4, 2, 0], [2, 2, 0, 1], \ + [4, 1, None, None], [1, 3, None, None]] + assert c.p == [0, 1, 2, 3, 4] + assert c.n == 5 + assert c.omega == [0, 1, 2, 3, 4] + + c.scan_and_fill(1, y**3) + assert c.table == [[0, 0, 1, 2], [3, 4, 2, 0], [2, 2, 0, 1], \ + [4, 1, None, None], [1, 3, None, None]] + assert c.p == [0, 1, 2, 3, 4] + assert c.n == 5 + assert c.omega == [0, 1, 2, 3, 4] + + c.scan_and_fill(1, x**-1*y**-1*x*y) + assert c.table == [[0, 0, 1, 2], [1, 1, 2, 0], [2, 2, 0, 1], \ + [None, 1, None, None], [1, 3, None, None]] + assert c.p == [0, 1, 2, 1, 1] + assert c.n == 3 + assert c.omega == [0, 1, 2] + + # Example 5.2 from [1] + f = FpGroup(F, [x**2, y**3, (x*y)**3]) + c = CosetTable(f, [x*y]) + + c.scan_and_fill(0, x*y) + assert c.table == [[1, None, None, 1], [None, 0, 0, None]] + assert c.p == [0, 1] + assert c.n == 2 + assert c.omega == [0, 1] + + c.scan_and_fill(0, x**2) + assert c.table == [[1, 1, None, 1], [0, 0, 0, None]] + assert c.p == [0, 1] + assert c.n == 2 + assert c.omega == [0, 1] + + c.scan_and_fill(0, y**3) + assert c.table == [[1, 1, 2, 1], [0, 0, 0, 2], [None, None, 1, 0]] + assert c.p == [0, 1, 2] + assert c.n == 3 + assert c.omega == [0, 1, 2] + + c.scan_and_fill(0, (x*y)**3) + assert c.table == [[1, 1, 2, 1], [0, 0, 0, 2], [None, None, 1, 0]] + assert c.p == [0, 1, 2] + assert c.n == 3 + assert c.omega == [0, 1, 2] + + c.scan_and_fill(1, x**2) + assert c.table == [[1, 1, 2, 1], [0, 0, 0, 2], [None, None, 1, 0]] + assert c.p == [0, 1, 2] + assert c.n == 3 + assert c.omega == [0, 1, 2] + + c.scan_and_fill(1, y**3) + assert c.table == [[1, 1, 2, 1], [0, 0, 0, 2], [None, None, 1, 0]] + assert c.p == [0, 1, 2] + assert c.n == 3 + assert c.omega == [0, 1, 2] + + c.scan_and_fill(1, (x*y)**3) + assert c.table == [[1, 1, 2, 1], [0, 0, 0, 2], [3, 4, 1, 0], [None, 2, 4, None], [2, None, None, 3]] + assert c.p == [0, 1, 2, 3, 4] + assert c.n == 5 + assert c.omega == [0, 1, 2, 3, 4] + + c.scan_and_fill(2, x**2) + assert c.table == [[1, 1, 2, 1], [0, 0, 0, 2], [3, 3, 1, 0], [2, 2, 3, 3], [2, None, None, 3]] + assert c.p == [0, 1, 2, 3, 3] + assert c.n == 4 + assert c.omega == [0, 1, 2, 3] + + +@slow +def test_coset_enumeration(): + # this test function contains the combined tests for the two strategies + # i.e. HLT and Felsch strategies. + + # Example 5.1 from [1] + F, x, y = free_group("x, y") + f = FpGroup(F, [x**3, y**3, x**-1*y**-1*x*y]) + C_r = coset_enumeration_r(f, [x]) + C_r.compress(); C_r.standardize() + C_c = coset_enumeration_c(f, [x]) + C_c.compress(); C_c.standardize() + table1 = [[0, 0, 1, 2], [1, 1, 2, 0], [2, 2, 0, 1]] + assert C_r.table == table1 + assert C_c.table == table1 + + # E1 from [2] Pg. 474 + F, r, s, t = free_group("r, s, t") + E1 = FpGroup(F, [t**-1*r*t*r**-2, r**-1*s*r*s**-2, s**-1*t*s*t**-2]) + C_r = coset_enumeration_r(E1, []) + C_r.compress() + C_c = coset_enumeration_c(E1, []) + C_c.compress() + table2 = [[0, 0, 0, 0, 0, 0]] + assert C_r.table == table2 + # test for issue #11449 + assert C_c.table == table2 + + # Cox group from [2] Pg. 474 + F, a, b = free_group("a, b") + Cox = FpGroup(F, [a**6, b**6, (a*b)**2, (a**2*b**2)**2, (a**3*b**3)**5]) + C_r = coset_enumeration_r(Cox, [a]) + C_r.compress(); C_r.standardize() + C_c = coset_enumeration_c(Cox, [a]) + C_c.compress(); C_c.standardize() + table3 = [[0, 0, 1, 2], + [2, 3, 4, 0], + [5, 1, 0, 6], + [1, 7, 8, 9], + [9, 10, 11, 1], + [12, 2, 9, 13], + [14, 9, 2, 11], + [3, 12, 15, 16], + [16, 17, 18, 3], + [6, 4, 3, 5], + [4, 19, 20, 21], + [21, 22, 6, 4], + [7, 5, 23, 24], + [25, 23, 5, 18], + [19, 6, 22, 26], + [24, 27, 28, 7], + [29, 8, 7, 30], + [8, 31, 32, 33], + [33, 34, 13, 8], + [10, 14, 35, 35], + [35, 36, 37, 10], + [30, 11, 10, 29], + [11, 38, 39, 14], + [13, 39, 38, 12], + [40, 15, 12, 41], + [42, 13, 34, 43], + [44, 35, 14, 45], + [15, 46, 47, 34], + [34, 48, 49, 15], + [50, 16, 21, 51], + [52, 21, 16, 49], + [17, 50, 53, 54], + [54, 55, 56, 17], + [41, 18, 17, 40], + [18, 28, 27, 25], + [26, 20, 19, 19], + [20, 57, 58, 59], + [59, 60, 51, 20], + [22, 52, 61, 23], + [23, 62, 63, 22], + [64, 24, 33, 65], + [48, 33, 24, 61], + [62, 25, 54, 66], + [67, 54, 25, 68], + [57, 26, 59, 69], + [70, 59, 26, 63], + [27, 64, 71, 72], + [72, 73, 68, 27], + [28, 41, 74, 75], + [75, 76, 30, 28], + [31, 29, 77, 78], + [79, 77, 29, 37], + [38, 30, 76, 80], + [78, 81, 82, 31], + [43, 32, 31, 42], + [32, 83, 84, 85], + [85, 86, 65, 32], + [36, 44, 87, 88], + [88, 89, 90, 36], + [45, 37, 36, 44], + [37, 82, 81, 79], + [80, 74, 41, 38], + [39, 42, 91, 92], + [92, 93, 45, 39], + [46, 40, 94, 95], + [96, 94, 40, 56], + [97, 91, 42, 82], + [83, 43, 98, 99], + [100, 98, 43, 47], + [101, 87, 44, 90], + [82, 45, 93, 97], + [95, 102, 103, 46], + [104, 47, 46, 105], + [47, 106, 107, 100], + [61, 108, 109, 48], + [105, 49, 48, 104], + [49, 110, 111, 52], + [51, 111, 110, 50], + [112, 53, 50, 113], + [114, 51, 60, 115], + [116, 61, 52, 117], + [53, 118, 119, 60], + [60, 70, 66, 53], + [55, 67, 120, 121], + [121, 122, 123, 55], + [113, 56, 55, 112], + [56, 103, 102, 96], + [69, 124, 125, 57], + [115, 58, 57, 114], + [58, 126, 127, 128], + [128, 128, 69, 58], + [66, 129, 130, 62], + [117, 63, 62, 116], + [63, 125, 124, 70], + [65, 109, 108, 64], + [131, 71, 64, 132], + [133, 65, 86, 134], + [135, 66, 70, 136], + [68, 130, 129, 67], + [137, 120, 67, 138], + [132, 68, 73, 131], + [139, 69, 128, 140], + [71, 141, 142, 86], + [86, 143, 144, 71], + [145, 72, 75, 146], + [147, 75, 72, 144], + [73, 145, 148, 120], + [120, 149, 150, 73], + [74, 151, 152, 94], + [94, 153, 146, 74], + [76, 147, 154, 77], + [77, 155, 156, 76], + [157, 78, 85, 158], + [143, 85, 78, 154], + [155, 79, 88, 159], + [160, 88, 79, 161], + [151, 80, 92, 162], + [163, 92, 80, 156], + [81, 157, 164, 165], + [165, 166, 161, 81], + [99, 107, 106, 83], + [134, 84, 83, 133], + [84, 167, 168, 169], + [169, 170, 158, 84], + [87, 171, 172, 93], + [93, 163, 159, 87], + [89, 160, 173, 174], + [174, 175, 176, 89], + [90, 90, 89, 101], + [91, 177, 178, 98], + [98, 179, 162, 91], + [180, 95, 100, 181], + [179, 100, 95, 152], + [153, 96, 121, 148], + [182, 121, 96, 183], + [177, 97, 165, 184], + [185, 165, 97, 172], + [186, 99, 169, 187], + [188, 169, 99, 178], + [171, 101, 174, 189], + [190, 174, 101, 176], + [102, 180, 191, 192], + [192, 193, 183, 102], + [103, 113, 194, 195], + [195, 196, 105, 103], + [106, 104, 197, 198], + [199, 197, 104, 109], + [110, 105, 196, 200], + [198, 201, 133, 106], + [107, 186, 202, 203], + [203, 204, 181, 107], + [108, 116, 205, 206], + [206, 207, 132, 108], + [109, 133, 201, 199], + [200, 194, 113, 110], + [111, 114, 208, 209], + [209, 210, 117, 111], + [118, 112, 211, 212], + [213, 211, 112, 123], + [214, 208, 114, 125], + [126, 115, 215, 216], + [217, 215, 115, 119], + [218, 205, 116, 130], + [125, 117, 210, 214], + [212, 219, 220, 118], + [136, 119, 118, 135], + [119, 221, 222, 217], + [122, 182, 223, 224], + [224, 225, 226, 122], + [138, 123, 122, 137], + [123, 220, 219, 213], + [124, 139, 227, 228], + [228, 229, 136, 124], + [216, 222, 221, 126], + [140, 127, 126, 139], + [127, 230, 231, 232], + [232, 233, 140, 127], + [129, 135, 234, 235], + [235, 236, 138, 129], + [130, 132, 207, 218], + [141, 131, 237, 238], + [239, 237, 131, 150], + [167, 134, 240, 241], + [242, 240, 134, 142], + [243, 234, 135, 220], + [221, 136, 229, 244], + [149, 137, 245, 246], + [247, 245, 137, 226], + [220, 138, 236, 243], + [244, 227, 139, 221], + [230, 140, 233, 248], + [238, 249, 250, 141], + [251, 142, 141, 252], + [142, 253, 254, 242], + [154, 255, 256, 143], + [252, 144, 143, 251], + [144, 257, 258, 147], + [146, 258, 257, 145], + [259, 148, 145, 260], + [261, 146, 153, 262], + [263, 154, 147, 264], + [148, 265, 266, 153], + [246, 267, 268, 149], + [260, 150, 149, 259], + [150, 250, 249, 239], + [162, 269, 270, 151], + [262, 152, 151, 261], + [152, 271, 272, 179], + [159, 273, 274, 155], + [264, 156, 155, 263], + [156, 270, 269, 163], + [158, 256, 255, 157], + [275, 164, 157, 276], + [277, 158, 170, 278], + [279, 159, 163, 280], + [161, 274, 273, 160], + [281, 173, 160, 282], + [276, 161, 166, 275], + [283, 162, 179, 284], + [164, 285, 286, 170], + [170, 188, 184, 164], + [166, 185, 189, 173], + [173, 287, 288, 166], + [241, 254, 253, 167], + [278, 168, 167, 277], + [168, 289, 290, 291], + [291, 292, 187, 168], + [189, 293, 294, 171], + [280, 172, 171, 279], + [172, 295, 296, 185], + [175, 190, 297, 297], + [297, 298, 299, 175], + [282, 176, 175, 281], + [176, 294, 293, 190], + [184, 296, 295, 177], + [284, 178, 177, 283], + [178, 300, 301, 188], + [181, 272, 271, 180], + [302, 191, 180, 303], + [304, 181, 204, 305], + [183, 266, 265, 182], + [306, 223, 182, 307], + [303, 183, 193, 302], + [308, 184, 188, 309], + [310, 189, 185, 311], + [187, 301, 300, 186], + [305, 202, 186, 304], + [312, 187, 292, 313], + [314, 297, 190, 315], + [191, 316, 317, 204], + [204, 318, 319, 191], + [320, 192, 195, 321], + [322, 195, 192, 319], + [193, 320, 323, 223], + [223, 324, 325, 193], + [194, 326, 327, 211], + [211, 328, 321, 194], + [196, 322, 329, 197], + [197, 330, 331, 196], + [332, 198, 203, 333], + [318, 203, 198, 329], + [330, 199, 206, 334], + [335, 206, 199, 336], + [326, 200, 209, 337], + [338, 209, 200, 331], + [201, 332, 339, 240], + [240, 340, 336, 201], + [202, 341, 342, 292], + [292, 343, 333, 202], + [205, 344, 345, 210], + [210, 338, 334, 205], + [207, 335, 346, 237], + [237, 347, 348, 207], + [208, 349, 350, 215], + [215, 351, 337, 208], + [352, 212, 217, 353], + [351, 217, 212, 327], + [328, 213, 224, 323], + [354, 224, 213, 355], + [349, 214, 228, 356], + [357, 228, 214, 345], + [358, 216, 232, 359], + [360, 232, 216, 350], + [344, 218, 235, 361], + [362, 235, 218, 348], + [219, 352, 363, 364], + [364, 365, 355, 219], + [222, 358, 366, 367], + [367, 368, 353, 222], + [225, 354, 369, 370], + [370, 371, 372, 225], + [307, 226, 225, 306], + [226, 268, 267, 247], + [227, 373, 374, 233], + [233, 360, 356, 227], + [229, 357, 361, 234], + [234, 375, 376, 229], + [248, 231, 230, 230], + [231, 377, 378, 379], + [379, 380, 359, 231], + [236, 362, 381, 245], + [245, 382, 383, 236], + [384, 238, 242, 385], + [340, 242, 238, 346], + [347, 239, 246, 381], + [386, 246, 239, 387], + [388, 241, 291, 389], + [343, 291, 241, 339], + [375, 243, 364, 390], + [391, 364, 243, 383], + [373, 244, 367, 392], + [393, 367, 244, 376], + [382, 247, 370, 394], + [395, 370, 247, 396], + [377, 248, 379, 397], + [398, 379, 248, 374], + [249, 384, 399, 400], + [400, 401, 387, 249], + [250, 260, 402, 403], + [403, 404, 252, 250], + [253, 251, 405, 406], + [407, 405, 251, 256], + [257, 252, 404, 408], + [406, 409, 277, 253], + [254, 388, 410, 411], + [411, 412, 385, 254], + [255, 263, 413, 414], + [414, 415, 276, 255], + [256, 277, 409, 407], + [408, 402, 260, 257], + [258, 261, 416, 417], + [417, 418, 264, 258], + [265, 259, 419, 420], + [421, 419, 259, 268], + [422, 416, 261, 270], + [271, 262, 423, 424], + [425, 423, 262, 266], + [426, 413, 263, 274], + [270, 264, 418, 422], + [420, 427, 307, 265], + [266, 303, 428, 425], + [267, 386, 429, 430], + [430, 431, 396, 267], + [268, 307, 427, 421], + [269, 283, 432, 433], + [433, 434, 280, 269], + [424, 428, 303, 271], + [272, 304, 435, 436], + [436, 437, 284, 272], + [273, 279, 438, 439], + [439, 440, 282, 273], + [274, 276, 415, 426], + [285, 275, 441, 442], + [443, 441, 275, 288], + [289, 278, 444, 445], + [446, 444, 278, 286], + [447, 438, 279, 294], + [295, 280, 434, 448], + [287, 281, 449, 450], + [451, 449, 281, 299], + [294, 282, 440, 447], + [448, 432, 283, 295], + [300, 284, 437, 452], + [442, 453, 454, 285], + [309, 286, 285, 308], + [286, 455, 456, 446], + [450, 457, 458, 287], + [311, 288, 287, 310], + [288, 454, 453, 443], + [445, 456, 455, 289], + [313, 290, 289, 312], + [290, 459, 460, 461], + [461, 462, 389, 290], + [293, 310, 463, 464], + [464, 465, 315, 293], + [296, 308, 466, 467], + [467, 468, 311, 296], + [298, 314, 469, 470], + [470, 471, 472, 298], + [315, 299, 298, 314], + [299, 458, 457, 451], + [452, 435, 304, 300], + [301, 312, 473, 474], + [474, 475, 309, 301], + [316, 302, 476, 477], + [478, 476, 302, 325], + [341, 305, 479, 480], + [481, 479, 305, 317], + [324, 306, 482, 483], + [484, 482, 306, 372], + [485, 466, 308, 454], + [455, 309, 475, 486], + [487, 463, 310, 458], + [454, 311, 468, 485], + [486, 473, 312, 455], + [459, 313, 488, 489], + [490, 488, 313, 342], + [491, 469, 314, 472], + [458, 315, 465, 487], + [477, 492, 485, 316], + [463, 317, 316, 468], + [317, 487, 493, 481], + [329, 447, 464, 318], + [468, 319, 318, 463], + [319, 467, 448, 322], + [321, 448, 467, 320], + [475, 323, 320, 466], + [432, 321, 328, 437], + [438, 329, 322, 434], + [323, 474, 452, 328], + [483, 494, 486, 324], + [466, 325, 324, 475], + [325, 485, 492, 478], + [337, 422, 433, 326], + [437, 327, 326, 432], + [327, 436, 424, 351], + [334, 426, 439, 330], + [434, 331, 330, 438], + [331, 433, 422, 338], + [333, 464, 447, 332], + [449, 339, 332, 440], + [465, 333, 343, 469], + [413, 334, 338, 418], + [336, 439, 426, 335], + [441, 346, 335, 415], + [440, 336, 340, 449], + [416, 337, 351, 423], + [339, 451, 470, 343], + [346, 443, 450, 340], + [480, 493, 487, 341], + [469, 342, 341, 465], + [342, 491, 495, 490], + [361, 407, 414, 344], + [418, 345, 344, 413], + [345, 417, 408, 357], + [381, 446, 442, 347], + [415, 348, 347, 441], + [348, 414, 407, 362], + [356, 408, 417, 349], + [423, 350, 349, 416], + [350, 425, 420, 360], + [353, 424, 436, 352], + [479, 363, 352, 435], + [428, 353, 368, 476], + [355, 452, 474, 354], + [488, 369, 354, 473], + [435, 355, 365, 479], + [402, 356, 360, 419], + [405, 361, 357, 404], + [359, 420, 425, 358], + [476, 366, 358, 428], + [427, 359, 380, 482], + [444, 381, 362, 409], + [363, 481, 477, 368], + [368, 393, 390, 363], + [365, 391, 394, 369], + [369, 490, 480, 365], + [366, 478, 483, 380], + [380, 398, 392, 366], + [371, 395, 496, 497], + [497, 498, 489, 371], + [473, 372, 371, 488], + [372, 486, 494, 484], + [392, 400, 403, 373], + [419, 374, 373, 402], + [374, 421, 430, 398], + [390, 411, 406, 375], + [404, 376, 375, 405], + [376, 403, 400, 393], + [397, 430, 421, 377], + [482, 378, 377, 427], + [378, 484, 497, 499], + [499, 499, 397, 378], + [394, 461, 445, 382], + [409, 383, 382, 444], + [383, 406, 411, 391], + [385, 450, 443, 384], + [492, 399, 384, 453], + [457, 385, 412, 493], + [387, 442, 446, 386], + [494, 429, 386, 456], + [453, 387, 401, 492], + [389, 470, 451, 388], + [493, 410, 388, 457], + [471, 389, 462, 495], + [412, 390, 393, 399], + [462, 394, 391, 410], + [401, 392, 398, 429], + [396, 445, 461, 395], + [498, 496, 395, 460], + [456, 396, 431, 494], + [431, 397, 499, 496], + [399, 477, 481, 412], + [429, 483, 478, 401], + [410, 480, 490, 462], + [496, 497, 484, 431], + [489, 495, 491, 459], + [495, 460, 459, 471], + [460, 489, 498, 498], + [472, 472, 471, 491]] + + assert C_r.table == table3 + assert C_c.table == table3 + + # Group denoted by B2,4 from [2] Pg. 474 + F, a, b = free_group("a, b") + B_2_4 = FpGroup(F, [a**4, b**4, (a*b)**4, (a**-1*b)**4, (a**2*b)**4, \ + (a*b**2)**4, (a**2*b**2)**4, (a**-1*b*a*b)**4, (a*b**-1*a*b)**4]) + C_r = coset_enumeration_r(B_2_4, [a]) + C_c = coset_enumeration_c(B_2_4, [a]) + index_r = 0 + for i in range(len(C_r.p)): + if C_r.p[i] == i: + index_r += 1 + assert index_r == 1024 + + index_c = 0 + for i in range(len(C_c.p)): + if C_c.p[i] == i: + index_c += 1 + assert index_c == 1024 + + # trivial Macdonald group G(2,2) from [2] Pg. 480 + M = FpGroup(F, [b**-1*a**-1*b*a*b**-1*a*b*a**-2, a**-1*b**-1*a*b*a**-1*b*a*b**-2]) + C_r = coset_enumeration_r(M, [a]) + C_r.compress(); C_r.standardize() + C_c = coset_enumeration_c(M, [a]) + C_c.compress(); C_c.standardize() + table4 = [[0, 0, 0, 0]] + assert C_r.table == table4 + assert C_c.table == table4 + + +def test_look_ahead(): + # Section 3.2 [Test Example] Example (d) from [2] + F, a, b, c = free_group("a, b, c") + f = FpGroup(F, [a**11, b**5, c**4, (a*c)**3, b**2*c**-1*b**-1*c, a**4*b**-1*a**-1*b]) + H = [c, b, c**2] + table0 = [[1, 2, 0, 0, 0, 0], + [3, 0, 4, 5, 6, 7], + [0, 8, 9, 10, 11, 12], + [5, 1, 10, 13, 14, 15], + [16, 5, 16, 1, 17, 18], + [4, 3, 1, 8, 19, 20], + [12, 21, 22, 23, 24, 1], + [25, 26, 27, 28, 1, 24], + [2, 10, 5, 16, 22, 28], + [10, 13, 13, 2, 29, 30]] + CosetTable.max_stack_size = 10 + C_c = coset_enumeration_c(f, H) + C_c.compress(); C_c.standardize() + assert C_c.table[: 10] == table0 + +def test_modified_methods(): + ''' + Tests for modified coset table methods. + Example 5.7 from [1] Holt, D., Eick, B., O'Brien + "Handbook of Computational Group Theory". + + ''' + F, x, y = free_group("x, y") + f = FpGroup(F, [x**3, y**5, (x*y)**2]) + H = [x*y, x**-1*y**-1*x*y*x] + C = CosetTable(f, H) + C.modified_define(0, x) + identity = C._grp.identity + a_0 = C._grp.generators[0] + a_1 = C._grp.generators[1] + + assert C.P == [[identity, None, None, None], + [None, identity, None, None]] + assert C.table == [[1, None, None, None], + [None, 0, None, None]] + + C.modified_define(1, x) + assert C.table == [[1, None, None, None], + [2, 0, None, None], + [None, 1, None, None]] + assert C.P == [[identity, None, None, None], + [identity, identity, None, None], + [None, identity, None, None]] + + C.modified_scan(0, x**3, C._grp.identity, fill=False) + assert C.P == [[identity, identity, None, None], + [identity, identity, None, None], + [identity, identity, None, None]] + assert C.table == [[1, 2, None, None], + [2, 0, None, None], + [0, 1, None, None]] + + C.modified_scan(0, x*y, C._grp.generators[0], fill=False) + assert C.P == [[identity, identity, None, a_0**-1], + [identity, identity, a_0, None], + [identity, identity, None, None]] + assert C.table == [[1, 2, None, 1], + [2, 0, 0, None], + [0, 1, None, None]] + + C.modified_define(2, y**-1) + assert C.table == [[1, 2, None, 1], + [2, 0, 0, None], + [0, 1, None, 3], + [None, None, 2, None]] + assert C.P == [[identity, identity, None, a_0**-1], + [identity, identity, a_0, None], + [identity, identity, None, identity], + [None, None, identity, None]] + + C.modified_scan(0, x**-1*y**-1*x*y*x, C._grp.generators[1]) + assert C.table == [[1, 2, None, 1], + [2, 0, 0, None], + [0, 1, None, 3], + [3, 3, 2, None]] + assert C.P == [[identity, identity, None, a_0**-1], + [identity, identity, a_0, None], + [identity, identity, None, identity], + [a_1, a_1**-1, identity, None]] + + C.modified_scan(2, (x*y)**2, C._grp.identity) + assert C.table == [[1, 2, 3, 1], + [2, 0, 0, None], + [0, 1, None, 3], + [3, 3, 2, 0]] + assert C.P == [[identity, identity, a_1**-1, a_0**-1], + [identity, identity, a_0, None], + [identity, identity, None, identity], + [a_1, a_1**-1, identity, a_1]] + + C.modified_define(2, y) + assert C.table == [[1, 2, 3, 1], + [2, 0, 0, None], + [0, 1, 4, 3], + [3, 3, 2, 0], + [None, None, None, 2]] + assert C.P == [[identity, identity, a_1**-1, a_0**-1], + [identity, identity, a_0, None], + [identity, identity, identity, identity], + [a_1, a_1**-1, identity, a_1], + [None, None, None, identity]] + + C.modified_scan(0, y**5, C._grp.identity) + assert C.table == [[1, 2, 3, 1], [2, 0, 0, 4], [0, 1, 4, 3], [3, 3, 2, 0], [None, None, 1, 2]] + assert C.P == [[identity, identity, a_1**-1, a_0**-1], + [identity, identity, a_0, a_0*a_1**-1], + [identity, identity, identity, identity], + [a_1, a_1**-1, identity, a_1], + [None, None, a_1*a_0**-1, identity]] + + C.modified_scan(1, (x*y)**2, C._grp.identity) + assert C.table == [[1, 2, 3, 1], + [2, 0, 0, 4], + [0, 1, 4, 3], + [3, 3, 2, 0], + [4, 4, 1, 2]] + assert C.P == [[identity, identity, a_1**-1, a_0**-1], + [identity, identity, a_0, a_0*a_1**-1], + [identity, identity, identity, identity], + [a_1, a_1**-1, identity, a_1], + [a_0*a_1**-1, a_1*a_0**-1, a_1*a_0**-1, identity]] + + # Modified coset enumeration test + f = FpGroup(F, [x**3, y**3, x**-1*y**-1*x*y]) + C = coset_enumeration_r(f, [x]) + C_m = modified_coset_enumeration_r(f, [x]) + assert C_m.table == C.table diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_fp_groups.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_fp_groups.py new file mode 100644 index 0000000000000000000000000000000000000000..3f57bdf8eff92a3022d8e01cd74ce98575987929 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_fp_groups.py @@ -0,0 +1,257 @@ +from sympy.core.singleton import S +from sympy.combinatorics.fp_groups import (FpGroup, low_index_subgroups, + reidemeister_presentation, FpSubgroup, + simplify_presentation) +from sympy.combinatorics.free_groups import (free_group, FreeGroup) + +from sympy.testing.pytest import slow + +""" +References +========== + +[1] Holt, D., Eick, B., O'Brien, E. +"Handbook of Computational Group Theory" + +[2] John J. Cannon; Lucien A. Dimino; George Havas; Jane M. Watson +Mathematics of Computation, Vol. 27, No. 123. (Jul., 1973), pp. 463-490. +"Implementation and Analysis of the Todd-Coxeter Algorithm" + +[3] PROC. SECOND INTERNAT. CONF. THEORY OF GROUPS, CANBERRA 1973, +pp. 347-356. "A Reidemeister-Schreier program" by George Havas. +http://staff.itee.uq.edu.au/havas/1973cdhw.pdf + +""" + +def test_low_index_subgroups(): + F, x, y = free_group("x, y") + + # Example 5.10 from [1] Pg. 194 + f = FpGroup(F, [x**2, y**3, (x*y)**4]) + L = low_index_subgroups(f, 4) + t1 = [[[0, 0, 0, 0]], + [[0, 0, 1, 2], [1, 1, 2, 0], [3, 3, 0, 1], [2, 2, 3, 3]], + [[0, 0, 1, 2], [2, 2, 2, 0], [1, 1, 0, 1]], + [[1, 1, 0, 0], [0, 0, 1, 1]]] + for i in range(len(t1)): + assert L[i].table == t1[i] + + f = FpGroup(F, [x**2, y**3, (x*y)**7]) + L = low_index_subgroups(f, 15) + t2 = [[[0, 0, 0, 0]], + [[0, 0, 1, 2], [1, 1, 2, 0], [3, 3, 0, 1], [2, 2, 4, 5], + [4, 4, 5, 3], [6, 6, 3, 4], [5, 5, 6, 6]], + [[0, 0, 1, 2], [1, 1, 2, 0], [3, 3, 0, 1], [2, 2, 4, 5], + [6, 6, 5, 3], [5, 5, 3, 4], [4, 4, 6, 6]], + [[0, 0, 1, 2], [1, 1, 2, 0], [3, 3, 0, 1], [2, 2, 4, 5], + [6, 6, 5, 3], [7, 7, 3, 4], [4, 4, 8, 9], [5, 5, 10, 11], + [11, 11, 9, 6], [9, 9, 6, 8], [12, 12, 11, 7], [8, 8, 7, 10], + [10, 10, 13, 14], [14, 14, 14, 12], [13, 13, 12, 13]], + [[0, 0, 1, 2], [1, 1, 2, 0], [3, 3, 0, 1], [2, 2, 4, 5], + [6, 6, 5, 3], [7, 7, 3, 4], [4, 4, 8, 9], [5, 5, 10, 11], + [11, 11, 9, 6], [12, 12, 6, 8], [10, 10, 11, 7], [8, 8, 7, 10], + [9, 9, 13, 14], [14, 14, 14, 12], [13, 13, 12, 13]], + [[0, 0, 1, 2], [1, 1, 2, 0], [3, 3, 0, 1], [2, 2, 4, 5], + [6, 6, 5, 3], [7, 7, 3, 4], [4, 4, 8, 9], [5, 5, 10, 11], + [11, 11, 9, 6], [12, 12, 6, 8], [13, 13, 11, 7], [8, 8, 7, 10], + [9, 9, 12, 12], [10, 10, 13, 13]], + [[0, 0, 1, 2], [3, 3, 2, 0], [4, 4, 0, 1], [1, 1, 3, 3], [2, 2, 5, 6] + , [7, 7, 6, 4], [8, 8, 4, 5], [5, 5, 8, 9], [6, 6, 9, 7], + [10, 10, 7, 8], [9, 9, 11, 12], [11, 11, 12, 10], [13, 13, 10, 11], + [12, 12, 13, 13]], + [[0, 0, 1, 2], [3, 3, 2, 0], [4, 4, 0, 1], [1, 1, 3, 3], [2, 2, 5, 6] + , [7, 7, 6, 4], [8, 8, 4, 5], [5, 5, 8, 9], [6, 6, 9, 7], + [10, 10, 7, 8], [9, 9, 11, 12], [13, 13, 12, 10], [12, 12, 10, 11], + [11, 11, 13, 13]], + [[0, 0, 1, 2], [3, 3, 2, 0], [4, 4, 0, 1], [1, 1, 5, 6], [2, 2, 4, 4] + , [7, 7, 6, 3], [8, 8, 3, 5], [5, 5, 8, 9], [6, 6, 9, 7], + [10, 10, 7, 8], [9, 9, 11, 12], [13, 13, 12, 10], [12, 12, 10, 11], + [11, 11, 13, 13]], + [[0, 0, 1, 2], [3, 3, 2, 0], [4, 4, 0, 1], [1, 1, 5, 6], [2, 2, 7, 8] + , [5, 5, 6, 3], [9, 9, 3, 5], [10, 10, 8, 4], [8, 8, 4, 7], + [6, 6, 10, 11], [7, 7, 11, 9], [12, 12, 9, 10], [11, 11, 13, 14], + [14, 14, 14, 12], [13, 13, 12, 13]], + [[0, 0, 1, 2], [3, 3, 2, 0], [4, 4, 0, 1], [1, 1, 5, 6], [2, 2, 7, 8] + , [6, 6, 6, 3], [5, 5, 3, 5], [8, 8, 8, 4], [7, 7, 4, 7]], + [[0, 0, 1, 2], [3, 3, 2, 0], [4, 4, 0, 1], [1, 1, 5, 6], [2, 2, 7, 8] + , [9, 9, 6, 3], [6, 6, 3, 5], [10, 10, 8, 4], [11, 11, 4, 7], + [5, 5, 10, 12], [7, 7, 12, 9], [8, 8, 11, 11], [13, 13, 9, 10], + [12, 12, 13, 13]], + [[0, 0, 1, 2], [3, 3, 2, 0], [4, 4, 0, 1], [1, 1, 5, 6], [2, 2, 7, 8] + , [9, 9, 6, 3], [6, 6, 3, 5], [10, 10, 8, 4], [11, 11, 4, 7], + [5, 5, 12, 11], [7, 7, 10, 10], [8, 8, 9, 12], [13, 13, 11, 9], + [12, 12, 13, 13]], + [[0, 0, 1, 2], [3, 3, 2, 0], [4, 4, 0, 1], [1, 1, 5, 6], [2, 2, 7, 8] + , [9, 9, 6, 3], [10, 10, 3, 5], [7, 7, 8, 4], [11, 11, 4, 7], + [5, 5, 9, 9], [6, 6, 11, 12], [8, 8, 12, 10], [13, 13, 10, 11], + [12, 12, 13, 13]], + [[0, 0, 1, 2], [3, 3, 2, 0], [4, 4, 0, 1], [1, 1, 5, 6], [2, 2, 7, 8] + , [9, 9, 6, 3], [10, 10, 3, 5], [7, 7, 8, 4], [11, 11, 4, 7], + [5, 5, 12, 11], [6, 6, 10, 10], [8, 8, 9, 12], [13, 13, 11, 9], + [12, 12, 13, 13]], + [[0, 0, 1, 2], [3, 3, 2, 0], [4, 4, 0, 1], [1, 1, 5, 6], [2, 2, 7, 8] + , [9, 9, 6, 3], [10, 10, 3, 5], [11, 11, 8, 4], [12, 12, 4, 7], + [5, 5, 9, 9], [6, 6, 12, 13], [7, 7, 11, 11], [8, 8, 13, 10], + [13, 13, 10, 12]], + [[1, 1, 0, 0], [0, 0, 2, 3], [4, 4, 3, 1], [5, 5, 1, 2], [2, 2, 4, 4] + , [3, 3, 6, 7], [7, 7, 7, 5], [6, 6, 5, 6]]] + for i in range(len(t2)): + assert L[i].table == t2[i] + + f = FpGroup(F, [x**2, y**3, (x*y)**7]) + L = low_index_subgroups(f, 10, [x]) + t3 = [[[0, 0, 0, 0]], + [[0, 0, 1, 2], [1, 1, 2, 0], [3, 3, 0, 1], [2, 2, 4, 5], [4, 4, 5, 3], + [6, 6, 3, 4], [5, 5, 6, 6]], + [[0, 0, 1, 2], [1, 1, 2, 0], [3, 3, 0, 1], [2, 2, 4, 5], [6, 6, 5, 3], + [5, 5, 3, 4], [4, 4, 6, 6]], + [[0, 0, 1, 2], [3, 3, 2, 0], [4, 4, 0, 1], [1, 1, 5, 6], [2, 2, 7, 8], + [6, 6, 6, 3], [5, 5, 3, 5], [8, 8, 8, 4], [7, 7, 4, 7]]] + for i in range(len(t3)): + assert L[i].table == t3[i] + + +def test_subgroup_presentations(): + F, x, y = free_group("x, y") + f = FpGroup(F, [x**3, y**5, (x*y)**2]) + H = [x*y, x**-1*y**-1*x*y*x] + p1 = reidemeister_presentation(f, H) + assert str(p1) == "((y_1, y_2), (y_1**2, y_2**3, y_2*y_1*y_2*y_1*y_2*y_1))" + + H = f.subgroup(H) + assert (H.generators, H.relators) == p1 + + f = FpGroup(F, [x**3, y**3, (x*y)**3]) + H = [x*y, x*y**-1] + p2 = reidemeister_presentation(f, H) + assert str(p2) == "((x_0, y_0), (x_0**3, y_0**3, x_0*y_0*x_0*y_0*x_0*y_0))" + + f = FpGroup(F, [x**2*y**2, y**-1*x*y*x**-3]) + H = [x] + p3 = reidemeister_presentation(f, H) + assert str(p3) == "((x_0,), (x_0**4,))" + + f = FpGroup(F, [x**3*y**-3, (x*y)**3, (x*y**-1)**2]) + H = [x] + p4 = reidemeister_presentation(f, H) + assert str(p4) == "((x_0,), (x_0**6,))" + + # this presentation can be improved, the most simplified form + # of presentation is + # See [2] Pg 474 group PSL_2(11) + # This is the group PSL_2(11) + F, a, b, c = free_group("a, b, c") + f = FpGroup(F, [a**11, b**5, c**4, (b*c**2)**2, (a*b*c)**3, (a**4*c**2)**3, b**2*c**-1*b**-1*c, a**4*b**-1*a**-1*b]) + H = [a, b, c**2] + gens, rels = reidemeister_presentation(f, H) + assert str(gens) == "(b_1, c_3)" + assert len(rels) == 18 + + +@slow +def test_order(): + F, x, y = free_group("x, y") + f = FpGroup(F, [x**4, y**2, x*y*x**-1*y]) + assert f.order() == 8 + + f = FpGroup(F, [x*y*x**-1*y**-1, y**2]) + assert f.order() is S.Infinity + + F, a, b, c = free_group("a, b, c") + f = FpGroup(F, [a**250, b**2, c*b*c**-1*b, c**4, c**-1*a**-1*c*a, a**-1*b**-1*a*b]) + assert f.order() == 2000 + + F, x = free_group("x") + f = FpGroup(F, []) + assert f.order() is S.Infinity + + f = FpGroup(free_group('')[0], []) + assert f.order() == 1 + +def test_fp_subgroup(): + def _test_subgroup(K, T, S): + _gens = T(K.generators) + assert all(elem in S for elem in _gens) + assert T.is_injective() + assert T.image().order() == S.order() + F, x, y = free_group("x, y") + f = FpGroup(F, [x**4, y**2, x*y*x**-1*y]) + S = FpSubgroup(f, [x*y]) + assert (x*y)**-3 in S + K, T = f.subgroup([x*y], homomorphism=True) + assert T(K.generators) == [y*x**-1] + _test_subgroup(K, T, S) + + S = FpSubgroup(f, [x**-1*y*x]) + assert x**-1*y**4*x in S + assert x**-1*y**4*x**2 not in S + K, T = f.subgroup([x**-1*y*x], homomorphism=True) + assert T(K.generators[0]**3) == y**3 + _test_subgroup(K, T, S) + + f = FpGroup(F, [x**3, y**5, (x*y)**2]) + H = [x*y, x**-1*y**-1*x*y*x] + K, T = f.subgroup(H, homomorphism=True) + S = FpSubgroup(f, H) + _test_subgroup(K, T, S) + +def test_permutation_methods(): + F, x, y = free_group("x, y") + # DihedralGroup(8) + G = FpGroup(F, [x**2, y**8, x*y*x**-1*y]) + T = G._to_perm_group()[1] + assert T.is_isomorphism() + assert G.center() == [y**4] + + # DiheadralGroup(4) + G = FpGroup(F, [x**2, y**4, x*y*x**-1*y]) + S = FpSubgroup(G, G.normal_closure([x])) + assert x in S + assert y**-1*x*y in S + + # Z_5xZ_4 + G = FpGroup(F, [x*y*x**-1*y**-1, y**5, x**4]) + assert G.is_abelian + assert G.is_solvable + + # AlternatingGroup(5) + G = FpGroup(F, [x**3, y**2, (x*y)**5]) + assert not G.is_solvable + + # AlternatingGroup(4) + G = FpGroup(F, [x**3, y**2, (x*y)**3]) + assert len(G.derived_series()) == 3 + S = FpSubgroup(G, G.derived_subgroup()) + assert S.order() == 4 + + +def test_simplify_presentation(): + # ref #16083 + G = simplify_presentation(FpGroup(FreeGroup([]), [])) + assert not G.generators + assert not G.relators + + # CyclicGroup(3) + # The second generator in is trivial due to relators {x^2, x^5} + F, x, y = free_group("x, y") + G = simplify_presentation(FpGroup(F, [x**2, x**5, y**3])) + assert x in G.relators + +def test_cyclic(): + F, x, y = free_group("x, y") + f = FpGroup(F, [x*y, x**-1*y**-1*x*y*x]) + assert f.is_cyclic + f = FpGroup(F, [x*y, x*y**-1]) + assert f.is_cyclic + f = FpGroup(F, [x**4, y**2, x*y*x**-1*y]) + assert not f.is_cyclic + + +def test_abelian_invariants(): + F, x, y = free_group("x, y") + f = FpGroup(F, [x*y, x**-1*y**-1*x*y*x]) + assert f.abelian_invariants() == [] + f = FpGroup(F, [x*y, x*y**-1]) + assert f.abelian_invariants() == [2] + f = FpGroup(F, [x**4, y**2, x*y*x**-1*y]) + assert f.abelian_invariants() == [2, 4] diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_free_groups.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_free_groups.py new file mode 100644 index 0000000000000000000000000000000000000000..439be4b7c5e8bb5ff592c9b7f07773e82952b3d5 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_free_groups.py @@ -0,0 +1,226 @@ +from sympy.combinatorics.free_groups import free_group, FreeGroup +from sympy.core import Symbol +from sympy.testing.pytest import raises +from sympy.core.numbers import oo + +F, x, y, z = free_group("x, y, z") + + +def test_FreeGroup__init__(): + x, y, z = map(Symbol, "xyz") + + assert len(FreeGroup("x, y, z").generators) == 3 + assert len(FreeGroup(x).generators) == 1 + assert len(FreeGroup(("x", "y", "z"))) == 3 + assert len(FreeGroup((x, y, z)).generators) == 3 + + +def test_FreeGroup__getnewargs__(): + x, y, z = map(Symbol, "xyz") + assert FreeGroup("x, y, z").__getnewargs__() == ((x, y, z),) + + +def test_free_group(): + G, a, b, c = free_group("a, b, c") + assert F.generators == (x, y, z) + assert x*z**2 in F + assert x in F + assert y*z**-1 in F + assert (y*z)**0 in F + assert a not in F + assert a**0 not in F + assert len(F) == 3 + assert str(F) == '' + assert not F == G + assert F.order() is oo + assert F.is_abelian == False + assert F.center() == {F.identity} + + (e,) = free_group("") + assert e.order() == 1 + assert e.generators == () + assert e.elements == {e.identity} + assert e.is_abelian == True + + +def test_FreeGroup__hash__(): + assert hash(F) + + +def test_FreeGroup__eq__(): + assert free_group("x, y, z")[0] == free_group("x, y, z")[0] + assert free_group("x, y, z")[0] is free_group("x, y, z")[0] + + assert free_group("x, y, z")[0] != free_group("a, x, y")[0] + assert free_group("x, y, z")[0] is not free_group("a, x, y")[0] + + assert free_group("x, y")[0] != free_group("x, y, z")[0] + assert free_group("x, y")[0] is not free_group("x, y, z")[0] + + assert free_group("x, y, z")[0] != free_group("x, y")[0] + assert free_group("x, y, z")[0] is not free_group("x, y")[0] + + +def test_FreeGroup__getitem__(): + assert F[0:] == FreeGroup("x, y, z") + assert F[1:] == FreeGroup("y, z") + assert F[2:] == FreeGroup("z") + + +def test_FreeGroupElm__hash__(): + assert hash(x*y*z) + + +def test_FreeGroupElm_copy(): + f = x*y*z**3 + g = f.copy() + h = x*y*z**7 + + assert f == g + assert f != h + + +def test_FreeGroupElm_inverse(): + assert x.inverse() == x**-1 + assert (x*y).inverse() == y**-1*x**-1 + assert (y*x*y**-1).inverse() == y*x**-1*y**-1 + assert (y**2*x**-1).inverse() == x*y**-2 + + +def test_FreeGroupElm_type_error(): + raises(TypeError, lambda: 2/x) + raises(TypeError, lambda: x**2 + y**2) + raises(TypeError, lambda: x/2) + + +def test_FreeGroupElm_methods(): + assert (x**0).order() == 1 + assert (y**2).order() is oo + assert (x**-1*y).commutator(x) == y**-1*x**-1*y*x + assert len(x**2*y**-1) == 3 + assert len(x**-1*y**3*z) == 5 + + +def test_FreeGroupElm_eliminate_word(): + w = x**5*y*x**2*y**-4*x + assert w.eliminate_word( x, x**2 ) == x**10*y*x**4*y**-4*x**2 + w3 = x**2*y**3*x**-1*y + assert w3.eliminate_word(x, x**2) == x**4*y**3*x**-2*y + assert w3.eliminate_word(x, y) == y**5 + assert w3.eliminate_word(x, y**4) == y**8 + assert w3.eliminate_word(y, x**-1) == x**-3 + assert w3.eliminate_word(x, y*z) == y*z*y*z*y**3*z**-1 + assert (y**-3).eliminate_word(y, x**-1*z**-1) == z*x*z*x*z*x + #assert w3.eliminate_word(x, y*x) == y*x*y*x**2*y*x*y*x*y*x*z**3 + #assert w3.eliminate_word(x, x*y) == x*y*x**2*y*x*y*x*y*x*y*z**3 + + +def test_FreeGroupElm_array_form(): + assert (x*z).array_form == ((Symbol('x'), 1), (Symbol('z'), 1)) + assert (x**2*z*y*x**-2).array_form == \ + ((Symbol('x'), 2), (Symbol('z'), 1), (Symbol('y'), 1), (Symbol('x'), -2)) + assert (x**-2*y**-1).array_form == ((Symbol('x'), -2), (Symbol('y'), -1)) + + +def test_FreeGroupElm_letter_form(): + assert (x**3).letter_form == (Symbol('x'), Symbol('x'), Symbol('x')) + assert (x**2*z**-2*x).letter_form == \ + (Symbol('x'), Symbol('x'), -Symbol('z'), -Symbol('z'), Symbol('x')) + + +def test_FreeGroupElm_ext_rep(): + assert (x**2*z**-2*x).ext_rep == \ + (Symbol('x'), 2, Symbol('z'), -2, Symbol('x'), 1) + assert (x**-2*y**-1).ext_rep == (Symbol('x'), -2, Symbol('y'), -1) + assert (x*z).ext_rep == (Symbol('x'), 1, Symbol('z'), 1) + + +def test_FreeGroupElm__mul__pow__(): + x1 = x.group.dtype(((Symbol('x'), 1),)) + assert x**2 == x1*x + + assert (x**2*y*x**-2)**4 == x**2*y**4*x**-2 + assert (x**2)**2 == x**4 + assert (x**-1)**-1 == x + assert (x**-1)**0 == F.identity + assert (y**2)**-2 == y**-4 + + assert x**2*x**-1 == x + assert x**2*y**2*y**-1 == x**2*y + assert x*x**-1 == F.identity + + assert x/x == F.identity + assert x/x**2 == x**-1 + assert (x**2*y)/(x**2*y**-1) == x**2*y**2*x**-2 + assert (x**2*y)/(y**-1*x**2) == x**2*y*x**-2*y + + assert x*(x**-1*y*z*y**-1) == y*z*y**-1 + assert x**2*(x**-2*y**-1*z**2*y) == y**-1*z**2*y + + a = F.identity + for n in range(10): + assert a == x**n + assert a**-1 == x**-n + a *= x + + +def test_FreeGroupElm__len__(): + assert len(x**5*y*x**2*y**-4*x) == 13 + assert len(x**17) == 17 + assert len(y**0) == 0 + + +def test_FreeGroupElm_comparison(): + assert not (x*y == y*x) + assert x**0 == y**0 + + assert x**2 < y**3 + assert not x**3 < y**2 + assert x*y < x**2*y + assert x**2*y**2 < y**4 + assert not y**4 < y**-4 + assert not y**4 < x**-4 + assert y**-2 < y**2 + + assert x**2 <= y**2 + assert x**2 <= x**2 + + assert not y*z > z*y + assert x > x**-1 + + assert not x**2 >= y**2 + + +def test_FreeGroupElm_syllables(): + w = x**5*y*x**2*y**-4*x + assert w.number_syllables() == 5 + assert w.exponent_syllable(2) == 2 + assert w.generator_syllable(3) == Symbol('y') + assert w.sub_syllables(1, 2) == y + assert w.sub_syllables(3, 3) == F.identity + + +def test_FreeGroup_exponents(): + w1 = x**2*y**3 + assert w1.exponent_sum(x) == 2 + assert w1.exponent_sum(x**-1) == -2 + assert w1.generator_count(x) == 2 + + w2 = x**2*y**4*x**-3 + assert w2.exponent_sum(x) == -1 + assert w2.generator_count(x) == 5 + + +def test_FreeGroup_generators(): + assert (x**2*y**4*z**-1).contains_generators() == {x, y, z} + assert (x**-1*y**3).contains_generators() == {x, y} + + +def test_FreeGroupElm_words(): + w = x**5*y*x**2*y**-4*x + assert w.subword(2, 6) == x**3*y + assert w.subword(3, 2) == F.identity + assert w.subword(6, 10) == x**2*y**-2 + + assert w.substituted_word(0, 7, y**-1) == y**-1*x*y**-4*x + assert w.substituted_word(0, 7, y**2*x) == y**2*x**2*y**-4*x diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_galois.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_galois.py new file mode 100644 index 0000000000000000000000000000000000000000..0d2ac29a846db88444d275b72a85ce3debaeaf05 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_galois.py @@ -0,0 +1,82 @@ +"""Test groups defined by the galois module. """ + +from sympy.combinatorics.galois import ( + S4TransitiveSubgroups, S5TransitiveSubgroups, S6TransitiveSubgroups, + find_transitive_subgroups_of_S6, +) +from sympy.combinatorics.homomorphisms import is_isomorphic +from sympy.combinatorics.named_groups import ( + SymmetricGroup, AlternatingGroup, CyclicGroup, +) + + +def test_four_group(): + G = S4TransitiveSubgroups.V.get_perm_group() + A4 = AlternatingGroup(4) + assert G.is_subgroup(A4) + assert G.degree == 4 + assert G.is_transitive() + assert G.order() == 4 + assert not G.is_cyclic + + +def test_M20(): + G = S5TransitiveSubgroups.M20.get_perm_group() + S5 = SymmetricGroup(5) + A5 = AlternatingGroup(5) + assert G.is_subgroup(S5) + assert not G.is_subgroup(A5) + assert G.degree == 5 + assert G.is_transitive() + assert G.order() == 20 + + +# Setting this True means that for each of the transitive subgroups of S6, +# we run a test not only on the fixed representation, but also on one freshly +# generated by the search procedure. +INCLUDE_SEARCH_REPS = False +S6_randomized = {} +if INCLUDE_SEARCH_REPS: + S6_randomized = find_transitive_subgroups_of_S6(*list(S6TransitiveSubgroups)) + + +def get_versions_of_S6_subgroup(name): + vers = [name.get_perm_group()] + if INCLUDE_SEARCH_REPS: + vers.append(S6_randomized[name]) + return vers + + +def test_S6_transitive_subgroups(): + """ + Test enough characteristics to distinguish all 16 transitive subgroups. + """ + ts = S6TransitiveSubgroups + A6 = AlternatingGroup(6) + for name, alt, order, is_isom, not_isom in [ + (ts.C6, False, 6, CyclicGroup(6), None), + (ts.S3, False, 6, SymmetricGroup(3), None), + (ts.D6, False, 12, None, None), + (ts.A4, True, 12, None, None), + (ts.G18, False, 18, None, None), + (ts.A4xC2, False, 24, None, SymmetricGroup(4)), + (ts.S4m, False, 24, SymmetricGroup(4), None), + (ts.S4p, True, 24, None, None), + (ts.G36m, False, 36, None, None), + (ts.G36p, True, 36, None, None), + (ts.S4xC2, False, 48, None, None), + (ts.PSL2F5, True, 60, None, None), + (ts.G72, False, 72, None, None), + (ts.PGL2F5, False, 120, None, None), + (ts.A6, True, 360, None, None), + (ts.S6, False, 720, None, None), + ]: + for G in get_versions_of_S6_subgroup(name): + assert G.is_transitive() + assert G.degree == 6 + assert G.is_subgroup(A6) is alt + assert G.order() == order + if is_isom: + assert is_isomorphic(G, is_isom) + if not_isom: + assert not is_isomorphic(G, not_isom) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_generators.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_generators.py new file mode 100644 index 0000000000000000000000000000000000000000..795ef8f08f6ec212879f528c6a0c2f0bd73037f0 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_generators.py @@ -0,0 +1,105 @@ +from sympy.combinatorics.generators import symmetric, cyclic, alternating, \ + dihedral, rubik +from sympy.combinatorics.permutations import Permutation +from sympy.testing.pytest import raises + +def test_generators(): + + assert list(cyclic(6)) == [ + Permutation([0, 1, 2, 3, 4, 5]), + Permutation([1, 2, 3, 4, 5, 0]), + Permutation([2, 3, 4, 5, 0, 1]), + Permutation([3, 4, 5, 0, 1, 2]), + Permutation([4, 5, 0, 1, 2, 3]), + Permutation([5, 0, 1, 2, 3, 4])] + + assert list(cyclic(10)) == [ + Permutation([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), + Permutation([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]), + Permutation([2, 3, 4, 5, 6, 7, 8, 9, 0, 1]), + Permutation([3, 4, 5, 6, 7, 8, 9, 0, 1, 2]), + Permutation([4, 5, 6, 7, 8, 9, 0, 1, 2, 3]), + Permutation([5, 6, 7, 8, 9, 0, 1, 2, 3, 4]), + Permutation([6, 7, 8, 9, 0, 1, 2, 3, 4, 5]), + Permutation([7, 8, 9, 0, 1, 2, 3, 4, 5, 6]), + Permutation([8, 9, 0, 1, 2, 3, 4, 5, 6, 7]), + Permutation([9, 0, 1, 2, 3, 4, 5, 6, 7, 8])] + + assert list(alternating(4)) == [ + Permutation([0, 1, 2, 3]), + Permutation([0, 2, 3, 1]), + Permutation([0, 3, 1, 2]), + Permutation([1, 0, 3, 2]), + Permutation([1, 2, 0, 3]), + Permutation([1, 3, 2, 0]), + Permutation([2, 0, 1, 3]), + Permutation([2, 1, 3, 0]), + Permutation([2, 3, 0, 1]), + Permutation([3, 0, 2, 1]), + Permutation([3, 1, 0, 2]), + Permutation([3, 2, 1, 0])] + + assert list(symmetric(3)) == [ + Permutation([0, 1, 2]), + Permutation([0, 2, 1]), + Permutation([1, 0, 2]), + Permutation([1, 2, 0]), + Permutation([2, 0, 1]), + Permutation([2, 1, 0])] + + assert list(symmetric(4)) == [ + Permutation([0, 1, 2, 3]), + Permutation([0, 1, 3, 2]), + Permutation([0, 2, 1, 3]), + Permutation([0, 2, 3, 1]), + Permutation([0, 3, 1, 2]), + Permutation([0, 3, 2, 1]), + Permutation([1, 0, 2, 3]), + Permutation([1, 0, 3, 2]), + Permutation([1, 2, 0, 3]), + Permutation([1, 2, 3, 0]), + Permutation([1, 3, 0, 2]), + Permutation([1, 3, 2, 0]), + Permutation([2, 0, 1, 3]), + Permutation([2, 0, 3, 1]), + Permutation([2, 1, 0, 3]), + Permutation([2, 1, 3, 0]), + Permutation([2, 3, 0, 1]), + Permutation([2, 3, 1, 0]), + Permutation([3, 0, 1, 2]), + Permutation([3, 0, 2, 1]), + Permutation([3, 1, 0, 2]), + Permutation([3, 1, 2, 0]), + Permutation([3, 2, 0, 1]), + Permutation([3, 2, 1, 0])] + + assert list(dihedral(1)) == [ + Permutation([0, 1]), Permutation([1, 0])] + + assert list(dihedral(2)) == [ + Permutation([0, 1, 2, 3]), + Permutation([1, 0, 3, 2]), + Permutation([2, 3, 0, 1]), + Permutation([3, 2, 1, 0])] + + assert list(dihedral(3)) == [ + Permutation([0, 1, 2]), + Permutation([2, 1, 0]), + Permutation([1, 2, 0]), + Permutation([0, 2, 1]), + Permutation([2, 0, 1]), + Permutation([1, 0, 2])] + + assert list(dihedral(5)) == [ + Permutation([0, 1, 2, 3, 4]), + Permutation([4, 3, 2, 1, 0]), + Permutation([1, 2, 3, 4, 0]), + Permutation([0, 4, 3, 2, 1]), + Permutation([2, 3, 4, 0, 1]), + Permutation([1, 0, 4, 3, 2]), + Permutation([3, 4, 0, 1, 2]), + Permutation([2, 1, 0, 4, 3]), + Permutation([4, 0, 1, 2, 3]), + Permutation([3, 2, 1, 0, 4])] + + raises(ValueError, lambda: rubik(1)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_graycode.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_graycode.py new file mode 100644 index 0000000000000000000000000000000000000000..a754a3c401b07c9c12cb9bdeeefdfc94f6cb8b5c --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_graycode.py @@ -0,0 +1,72 @@ +from sympy.combinatorics.graycode import (GrayCode, bin_to_gray, + random_bitstring, get_subset_from_bitstring, graycode_subsets, + gray_to_bin) +from sympy.testing.pytest import raises + +def test_graycode(): + g = GrayCode(2) + got = [] + for i in g.generate_gray(): + if i.startswith('0'): + g.skip() + got.append(i) + assert got == '00 11 10'.split() + a = GrayCode(6) + assert a.current == '0'*6 + assert a.rank == 0 + assert len(list(a.generate_gray())) == 64 + codes = ['011001', '011011', '011010', + '011110', '011111', '011101', '011100', '010100', '010101', '010111', + '010110', '010010', '010011', '010001', '010000', '110000', '110001', + '110011', '110010', '110110', '110111', '110101', '110100', '111100', + '111101', '111111', '111110', '111010', '111011', '111001', '111000', + '101000', '101001', '101011', '101010', '101110', '101111', '101101', + '101100', '100100', '100101', '100111', '100110', '100010', '100011', + '100001', '100000'] + assert list(a.generate_gray(start='011001')) == codes + assert list( + a.generate_gray(rank=GrayCode(6, start='011001').rank)) == codes + assert a.next().current == '000001' + assert a.next(2).current == '000011' + assert a.next(-1).current == '100000' + + a = GrayCode(5, start='10010') + assert a.rank == 28 + a = GrayCode(6, start='101000') + assert a.rank == 48 + + assert GrayCode(6, rank=4).current == '000110' + assert GrayCode(6, rank=4).rank == 4 + assert [GrayCode(4, start=s).rank for s in + GrayCode(4).generate_gray()] == [0, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15] + a = GrayCode(15, rank=15) + assert a.current == '000000000001000' + + assert bin_to_gray('111') == '100' + + a = random_bitstring(5) + assert type(a) is str + assert len(a) == 5 + assert all(i in ['0', '1'] for i in a) + + assert get_subset_from_bitstring( + ['a', 'b', 'c', 'd'], '0011') == ['c', 'd'] + assert get_subset_from_bitstring('abcd', '1001') == ['a', 'd'] + assert list(graycode_subsets(['a', 'b', 'c'])) == \ + [[], ['c'], ['b', 'c'], ['b'], ['a', 'b'], ['a', 'b', 'c'], + ['a', 'c'], ['a']] + + raises(ValueError, lambda: GrayCode(0)) + raises(ValueError, lambda: GrayCode(2.2)) + raises(ValueError, lambda: GrayCode(2, start=[1, 1, 0])) + raises(ValueError, lambda: GrayCode(2, rank=2.5)) + raises(ValueError, lambda: get_subset_from_bitstring(['c', 'a', 'c'], '1100')) + raises(ValueError, lambda: list(GrayCode(3).generate_gray(start="1111"))) + + +def test_live_issue_117(): + assert bin_to_gray('0100') == '0110' + assert bin_to_gray('0101') == '0111' + for bits in ('0100', '0101'): + assert gray_to_bin(bin_to_gray(bits)) == bits diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_group_constructs.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_group_constructs.py new file mode 100644 index 0000000000000000000000000000000000000000..d0f7d6394bbc2e285650ea95d36be8e2ed5ea69e --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_group_constructs.py @@ -0,0 +1,15 @@ +from sympy.combinatorics.group_constructs import DirectProduct +from sympy.combinatorics.named_groups import CyclicGroup, DihedralGroup + + +def test_direct_product_n(): + C = CyclicGroup(4) + D = DihedralGroup(4) + G = DirectProduct(C, C, C) + assert G.order() == 64 + assert G.degree == 12 + assert len(G.orbits()) == 3 + assert G.is_abelian is True + H = DirectProduct(D, C) + assert H.order() == 32 + assert H.is_abelian is False diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_group_numbers.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_group_numbers.py new file mode 100644 index 0000000000000000000000000000000000000000..743f1dcc8b642c19706687eeeddf6c9070b59166 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_group_numbers.py @@ -0,0 +1,110 @@ +from sympy.combinatorics.group_numbers import (is_nilpotent_number, + is_abelian_number, is_cyclic_number, _holder_formula, groups_count) +from sympy.ntheory.factor_ import factorint +from sympy.ntheory.generate import prime +from sympy.testing.pytest import raises +from sympy import randprime + + +def test_is_nilpotent_number(): + assert is_nilpotent_number(21) == False + assert is_nilpotent_number(randprime(1, 30)**12) == True + raises(ValueError, lambda: is_nilpotent_number(-5)) + + A056867 = [1, 2, 3, 4, 5, 7, 8, 9, 11, 13, 15, 16, 17, 19, + 23, 25, 27, 29, 31, 32, 33, 35, 37, 41, 43, 45, + 47, 49, 51, 53, 59, 61, 64, 65, 67, 69, 71, 73, + 77, 79, 81, 83, 85, 87, 89, 91, 95, 97, 99] + for n in range(1, 100): + assert is_nilpotent_number(n) == (n in A056867) + + +def test_is_abelian_number(): + assert is_abelian_number(4) == True + assert is_abelian_number(randprime(1, 2000)**2) == True + assert is_abelian_number(randprime(1000, 100000)) == True + assert is_abelian_number(60) == False + assert is_abelian_number(24) == False + raises(ValueError, lambda: is_abelian_number(-5)) + + A051532 = [1, 2, 3, 4, 5, 7, 9, 11, 13, 15, 17, 19, 23, 25, + 29, 31, 33, 35, 37, 41, 43, 45, 47, 49, 51, 53, + 59, 61, 65, 67, 69, 71, 73, 77, 79, 83, 85, 87, + 89, 91, 95, 97, 99] + for n in range(1, 100): + assert is_abelian_number(n) == (n in A051532) + + +A003277 = [1, 2, 3, 5, 7, 11, 13, 15, 17, 19, 23, 29, + 31, 33, 35, 37, 41, 43, 47, 51, 53, 59, 61, + 65, 67, 69, 71, 73, 77, 79, 83, 85, 87, 89, + 91, 95, 97] + + +def test_is_cyclic_number(): + assert is_cyclic_number(15) == True + assert is_cyclic_number(randprime(1, 2000)**2) == False + assert is_cyclic_number(randprime(1000, 100000)) == True + assert is_cyclic_number(4) == False + raises(ValueError, lambda: is_cyclic_number(-5)) + + for n in range(1, 100): + assert is_cyclic_number(n) == (n in A003277) + + +def test_holder_formula(): + # semiprime + assert _holder_formula({3, 5}) == 1 + assert _holder_formula({5, 11}) == 2 + # n in A003277 is always 1 + for n in A003277: + assert _holder_formula(set(factorint(n).keys())) == 1 + # otherwise + assert _holder_formula({2, 3, 5, 7}) == 12 + + +def test_groups_count(): + A000001 = [0, 1, 1, 1, 2, 1, 2, 1, 5, 2, 2, 1, 5, 1, + 2, 1, 14, 1, 5, 1, 5, 2, 2, 1, 15, 2, 2, + 5, 4, 1, 4, 1, 51, 1, 2, 1, 14, 1, 2, 2, + 14, 1, 6, 1, 4, 2, 2, 1, 52, 2, 5, 1, 5, + 1, 15, 2, 13, 2, 2, 1, 13, 1, 2, 4, 267, + 1, 4, 1, 5, 1, 4, 1, 50, 1, 2, 3, 4, 1, + 6, 1, 52, 15, 2, 1, 15, 1, 2, 1, 12, 1, + 10, 1, 4, 2] + for n in range(1, len(A000001)): + try: + assert groups_count(n) == A000001[n] + except ValueError: + pass + + A000679 = [1, 1, 2, 5, 14, 51, 267, 2328, 56092, 10494213, 49487367289] + for e in range(1, len(A000679)): + assert groups_count(2**e) == A000679[e] + + A090091 = [1, 1, 2, 5, 15, 67, 504, 9310, 1396077, 5937876645] + for e in range(1, len(A090091)): + assert groups_count(3**e) == A090091[e] + + A090130 = [1, 1, 2, 5, 15, 77, 684, 34297] + for e in range(1, len(A090130)): + assert groups_count(5**e) == A090130[e] + + A090140 = [1, 1, 2, 5, 15, 83, 860, 113147] + for e in range(1, len(A090140)): + assert groups_count(7**e) == A090140[e] + + A232105 = [51, 67, 77, 83, 87, 97, 101, 107, 111, 125, 131, + 145, 149, 155, 159, 173, 183, 193, 203, 207, 217] + for i in range(len(A232105)): + assert groups_count(prime(i+1)**5) == A232105[i] + + A232106 = [267, 504, 684, 860, 1192, 1476, 1944, 2264, 2876, + 4068, 4540, 6012, 7064, 7664, 8852, 10908, 13136] + for i in range(len(A232106)): + assert groups_count(prime(i+1)**6) == A232106[i] + + A232107 = [2328, 9310, 34297, 113147, 750735, 1600573, + 5546909, 9380741, 23316851, 71271069, 98488755] + for i in range(len(A232107)): + assert groups_count(prime(i+1)**7) == A232107[i] diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_homomorphisms.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_homomorphisms.py new file mode 100644 index 0000000000000000000000000000000000000000..0936bbddf46a16dccdfbaebda8d1c675c131f05a --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_homomorphisms.py @@ -0,0 +1,114 @@ +from sympy.combinatorics import Permutation +from sympy.combinatorics.perm_groups import PermutationGroup +from sympy.combinatorics.homomorphisms import homomorphism, group_isomorphism, is_isomorphic +from sympy.combinatorics.free_groups import free_group +from sympy.combinatorics.fp_groups import FpGroup +from sympy.combinatorics.named_groups import AlternatingGroup, DihedralGroup, CyclicGroup +from sympy.testing.pytest import raises + +def test_homomorphism(): + # FpGroup -> PermutationGroup + F, a, b = free_group("a, b") + G = FpGroup(F, [a**3, b**3, (a*b)**2]) + + c = Permutation(3)(0, 1, 2) + d = Permutation(3)(1, 2, 3) + A = AlternatingGroup(4) + T = homomorphism(G, A, [a, b], [c, d]) + assert T(a*b**2*a**-1) == c*d**2*c**-1 + assert T.is_isomorphism() + assert T(T.invert(Permutation(3)(0, 2, 3))) == Permutation(3)(0, 2, 3) + + T = homomorphism(G, AlternatingGroup(4), G.generators) + assert T.is_trivial() + assert T.kernel().order() == G.order() + + E, e = free_group("e") + G = FpGroup(E, [e**8]) + P = PermutationGroup([Permutation(0, 1, 2, 3), Permutation(0, 2)]) + T = homomorphism(G, P, [e], [Permutation(0, 1, 2, 3)]) + assert T.image().order() == 4 + assert T(T.invert(Permutation(0, 2)(1, 3))) == Permutation(0, 2)(1, 3) + + T = homomorphism(E, AlternatingGroup(4), E.generators, [c]) + assert T.invert(c**2) == e**-1 #order(c) == 3 so c**2 == c**-1 + + # FreeGroup -> FreeGroup + T = homomorphism(F, E, [a], [e]) + assert T(a**-2*b**4*a**2).is_identity + + # FreeGroup -> FpGroup + G = FpGroup(F, [a*b*a**-1*b**-1]) + T = homomorphism(F, G, F.generators, G.generators) + assert T.invert(a**-1*b**-1*a**2) == a*b**-1 + + # PermutationGroup -> PermutationGroup + D = DihedralGroup(8) + p = Permutation(0, 1, 2, 3, 4, 5, 6, 7) + P = PermutationGroup(p) + T = homomorphism(P, D, [p], [p]) + assert T.is_injective() + assert not T.is_isomorphism() + assert T.invert(p**3) == p**3 + + T2 = homomorphism(F, P, [F.generators[0]], P.generators) + T = T.compose(T2) + assert T.domain == F + assert T.codomain == D + assert T(a*b) == p + + D3 = DihedralGroup(3) + T = homomorphism(D3, D3, D3.generators, D3.generators) + assert T.is_isomorphism() + + +def test_isomorphisms(): + + F, a, b = free_group("a, b") + E, c, d = free_group("c, d") + # Infinite groups with differently ordered relators. + G = FpGroup(F, [a**2, b**3]) + H = FpGroup(F, [b**3, a**2]) + assert is_isomorphic(G, H) + + # Trivial Case + # FpGroup -> FpGroup + H = FpGroup(F, [a**3, b**3, (a*b)**2]) + F, c, d = free_group("c, d") + G = FpGroup(F, [c**3, d**3, (c*d)**2]) + check, T = group_isomorphism(G, H) + assert check + assert T(c**3*d**2) == a**3*b**2 + + # FpGroup -> PermutationGroup + # FpGroup is converted to the equivalent isomorphic group. + F, a, b = free_group("a, b") + G = FpGroup(F, [a**3, b**3, (a*b)**2]) + H = AlternatingGroup(4) + check, T = group_isomorphism(G, H) + assert check + assert T(b*a*b**-1*a**-1*b**-1) == Permutation(0, 2, 3) + assert T(b*a*b*a**-1*b**-1) == Permutation(0, 3, 2) + + # PermutationGroup -> PermutationGroup + D = DihedralGroup(8) + p = Permutation(0, 1, 2, 3, 4, 5, 6, 7) + P = PermutationGroup(p) + assert not is_isomorphic(D, P) + + A = CyclicGroup(5) + B = CyclicGroup(7) + assert not is_isomorphic(A, B) + + # Two groups of the same prime order are isomorphic to each other. + G = FpGroup(F, [a, b**5]) + H = CyclicGroup(5) + assert G.order() == H.order() + assert is_isomorphic(G, H) + + +def test_check_homomorphism(): + a = Permutation(1,2,3,4) + b = Permutation(1,3) + G = PermutationGroup([a, b]) + raises(ValueError, lambda: homomorphism(G, G, [a], [a])) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_named_groups.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_named_groups.py new file mode 100644 index 0000000000000000000000000000000000000000..59bcb6ef3f020335de76d7a72152a0b58cbc6976 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_named_groups.py @@ -0,0 +1,70 @@ +from sympy.combinatorics.named_groups import (SymmetricGroup, CyclicGroup, + DihedralGroup, AlternatingGroup, + AbelianGroup, RubikGroup) +from sympy.testing.pytest import raises + + +def test_SymmetricGroup(): + G = SymmetricGroup(5) + elements = list(G.generate()) + assert (G.generators[0]).size == 5 + assert len(elements) == 120 + assert G.is_solvable is False + assert G.is_abelian is False + assert G.is_nilpotent is False + assert G.is_transitive() is True + H = SymmetricGroup(1) + assert H.order() == 1 + L = SymmetricGroup(2) + assert L.order() == 2 + + +def test_CyclicGroup(): + G = CyclicGroup(10) + elements = list(G.generate()) + assert len(elements) == 10 + assert (G.derived_subgroup()).order() == 1 + assert G.is_abelian is True + assert G.is_solvable is True + assert G.is_nilpotent is True + H = CyclicGroup(1) + assert H.order() == 1 + L = CyclicGroup(2) + assert L.order() == 2 + + +def test_DihedralGroup(): + G = DihedralGroup(6) + elements = list(G.generate()) + assert len(elements) == 12 + assert G.is_transitive() is True + assert G.is_abelian is False + assert G.is_solvable is True + assert G.is_nilpotent is False + H = DihedralGroup(1) + assert H.order() == 2 + L = DihedralGroup(2) + assert L.order() == 4 + assert L.is_abelian is True + assert L.is_nilpotent is True + + +def test_AlternatingGroup(): + G = AlternatingGroup(5) + elements = list(G.generate()) + assert len(elements) == 60 + assert [perm.is_even for perm in elements] == [True]*60 + H = AlternatingGroup(1) + assert H.order() == 1 + L = AlternatingGroup(2) + assert L.order() == 1 + + +def test_AbelianGroup(): + A = AbelianGroup(3, 3, 3) + assert A.order() == 27 + assert A.is_abelian is True + + +def test_RubikGroup(): + raises(ValueError, lambda: RubikGroup(1)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_partitions.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_partitions.py new file mode 100644 index 0000000000000000000000000000000000000000..32e70e53a53aadbb17c8292bbef8f52d1144d6e0 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_partitions.py @@ -0,0 +1,118 @@ +from sympy.core.sorting import ordered, default_sort_key +from sympy.combinatorics.partitions import (Partition, IntegerPartition, + RGS_enum, RGS_unrank, RGS_rank, + random_integer_partition) +from sympy.testing.pytest import raises +from sympy.utilities.iterables import partitions +from sympy.sets.sets import Set, FiniteSet + + +def test_partition_constructor(): + raises(ValueError, lambda: Partition([1, 1, 2])) + raises(ValueError, lambda: Partition([1, 2, 3], [2, 3, 4])) + raises(ValueError, lambda: Partition(1, 2, 3)) + raises(ValueError, lambda: Partition(*list(range(3)))) + + assert Partition([1, 2, 3], [4, 5]) == Partition([4, 5], [1, 2, 3]) + assert Partition({1, 2, 3}, {4, 5}) == Partition([1, 2, 3], [4, 5]) + + a = FiniteSet(1, 2, 3) + b = FiniteSet(4, 5) + assert Partition(a, b) == Partition([1, 2, 3], [4, 5]) + assert Partition({a, b}) == Partition(FiniteSet(a, b)) + assert Partition({a, b}) != Partition(a, b) + +def test_partition(): + from sympy.abc import x + + a = Partition([1, 2, 3], [4]) + b = Partition([1, 2], [3, 4]) + c = Partition([x]) + l = [a, b, c] + l.sort(key=default_sort_key) + assert l == [c, a, b] + l.sort(key=lambda w: default_sort_key(w, order='rev-lex')) + assert l == [c, a, b] + + assert (a == b) is False + assert a <= b + assert (a > b) is False + assert a != b + assert a < b + + assert (a + 2).partition == [[1, 2], [3, 4]] + assert (b - 1).partition == [[1, 2, 4], [3]] + + assert (a - 1).partition == [[1, 2, 3, 4]] + assert (a + 1).partition == [[1, 2, 4], [3]] + assert (b + 1).partition == [[1, 2], [3], [4]] + + assert a.rank == 1 + assert b.rank == 3 + + assert a.RGS == (0, 0, 0, 1) + assert b.RGS == (0, 0, 1, 1) + + +def test_integer_partition(): + # no zeros in partition + raises(ValueError, lambda: IntegerPartition(list(range(3)))) + # check fails since 1 + 2 != 100 + raises(ValueError, lambda: IntegerPartition(100, list(range(1, 3)))) + a = IntegerPartition(8, [1, 3, 4]) + b = a.next_lex() + c = IntegerPartition([1, 3, 4]) + d = IntegerPartition(8, {1: 3, 3: 1, 2: 1}) + assert a == c + assert a.integer == d.integer + assert a.conjugate == [3, 2, 2, 1] + assert (a == b) is False + assert a <= b + assert (a > b) is False + assert a != b + + for i in range(1, 11): + next = set() + prev = set() + a = IntegerPartition([i]) + ans = {IntegerPartition(p) for p in partitions(i)} + n = len(ans) + for j in range(n): + next.add(a) + a = a.next_lex() + IntegerPartition(i, a.partition) # check it by giving i + for j in range(n): + prev.add(a) + a = a.prev_lex() + IntegerPartition(i, a.partition) # check it by giving i + assert next == ans + assert prev == ans + + assert IntegerPartition([1, 2, 3]).as_ferrers() == '###\n##\n#' + assert IntegerPartition([1, 1, 3]).as_ferrers('o') == 'ooo\no\no' + assert str(IntegerPartition([1, 1, 3])) == '[3, 1, 1]' + assert IntegerPartition([1, 1, 3]).partition == [3, 1, 1] + + raises(ValueError, lambda: random_integer_partition(-1)) + assert random_integer_partition(1) == [1] + assert random_integer_partition(10, seed=[1, 3, 2, 1, 5, 1] + ) == [5, 2, 1, 1, 1] + + +def test_rgs(): + raises(ValueError, lambda: RGS_unrank(-1, 3)) + raises(ValueError, lambda: RGS_unrank(3, 0)) + raises(ValueError, lambda: RGS_unrank(10, 1)) + + raises(ValueError, lambda: Partition.from_rgs(list(range(3)), list(range(2)))) + raises(ValueError, lambda: Partition.from_rgs(list(range(1, 3)), list(range(2)))) + assert RGS_enum(-1) == 0 + assert RGS_enum(1) == 1 + assert RGS_unrank(7, 5) == [0, 0, 1, 0, 2] + assert RGS_unrank(23, 14) == [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 2] + assert RGS_rank(RGS_unrank(40, 100)) == 40 + +def test_ordered_partition_9608(): + a = Partition([1, 2, 3], [4]) + b = Partition([1, 2], [3, 4]) + assert list(ordered([a,b], Set._infimum_key)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_pc_groups.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_pc_groups.py new file mode 100644 index 0000000000000000000000000000000000000000..b0c146279921e1e6499534fe9e33b993348d1503 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_pc_groups.py @@ -0,0 +1,87 @@ +from sympy.combinatorics.permutations import Permutation +from sympy.combinatorics.named_groups import SymmetricGroup, AlternatingGroup, DihedralGroup +from sympy.matrices import Matrix + +def test_pc_presentation(): + Groups = [SymmetricGroup(3), SymmetricGroup(4), SymmetricGroup(9).sylow_subgroup(3), + SymmetricGroup(9).sylow_subgroup(2), SymmetricGroup(8).sylow_subgroup(2), DihedralGroup(10)] + + S = SymmetricGroup(125).sylow_subgroup(5) + G = S.derived_series()[2] + Groups.append(G) + + G = SymmetricGroup(25).sylow_subgroup(5) + Groups.append(G) + + S = SymmetricGroup(11**2).sylow_subgroup(11) + G = S.derived_series()[2] + Groups.append(G) + + for G in Groups: + PcGroup = G.polycyclic_group() + collector = PcGroup.collector + pc_presentation = collector.pc_presentation + + pcgs = PcGroup.pcgs + free_group = collector.free_group + free_to_perm = {} + for s, g in zip(free_group.symbols, pcgs): + free_to_perm[s] = g + + for k, v in pc_presentation.items(): + k_array = k.array_form + if v != (): + v_array = v.array_form + + lhs = Permutation() + for gen in k_array: + s = gen[0] + e = gen[1] + lhs = lhs*free_to_perm[s]**e + + if v == (): + assert lhs.is_identity + continue + + rhs = Permutation() + for gen in v_array: + s = gen[0] + e = gen[1] + rhs = rhs*free_to_perm[s]**e + + assert lhs == rhs + + +def test_exponent_vector(): + + Groups = [SymmetricGroup(3), SymmetricGroup(4), SymmetricGroup(9).sylow_subgroup(3), + SymmetricGroup(9).sylow_subgroup(2), SymmetricGroup(8).sylow_subgroup(2)] + + for G in Groups: + PcGroup = G.polycyclic_group() + collector = PcGroup.collector + + pcgs = PcGroup.pcgs + # free_group = collector.free_group + + for gen in G.generators: + exp = collector.exponent_vector(gen) + g = Permutation() + for i in range(len(exp)): + g = g*pcgs[i]**exp[i] if exp[i] else g + assert g == gen + + +def test_induced_pcgs(): + G = [SymmetricGroup(9).sylow_subgroup(3), SymmetricGroup(20).sylow_subgroup(2), AlternatingGroup(4), + DihedralGroup(4), DihedralGroup(10), DihedralGroup(9), SymmetricGroup(3), SymmetricGroup(4)] + + for g in G: + PcGroup = g.polycyclic_group() + collector = PcGroup.collector + gens = list(g.generators) + ipcgs = collector.induced_pcgs(gens) + m = [] + for i in ipcgs: + m.append(collector.exponent_vector(i)) + assert Matrix(m).is_upper diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_perm_groups.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_perm_groups.py new file mode 100644 index 0000000000000000000000000000000000000000..763b8fb0ae357500d68c29fe1c9e6b156e224949 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_perm_groups.py @@ -0,0 +1,1243 @@ +from sympy.core.containers import Tuple +from sympy.combinatorics.generators import rubik_cube_generators +from sympy.combinatorics.homomorphisms import is_isomorphic +from sympy.combinatorics.named_groups import SymmetricGroup, CyclicGroup,\ + DihedralGroup, AlternatingGroup, AbelianGroup, RubikGroup +from sympy.combinatorics.perm_groups import (PermutationGroup, + _orbit_transversal, Coset, SymmetricPermutationGroup) +from sympy.combinatorics.permutations import Permutation +from sympy.combinatorics.polyhedron import tetrahedron as Tetra, cube +from sympy.combinatorics.testutil import _verify_bsgs, _verify_centralizer,\ + _verify_normal_closure +from sympy.testing.pytest import skip, XFAIL, slow + +rmul = Permutation.rmul + + +def test_has(): + a = Permutation([1, 0]) + G = PermutationGroup([a]) + assert G.is_abelian + a = Permutation([2, 0, 1]) + b = Permutation([2, 1, 0]) + G = PermutationGroup([a, b]) + assert not G.is_abelian + + G = PermutationGroup([a]) + assert G.has(a) + assert not G.has(b) + + a = Permutation([2, 0, 1, 3, 4, 5]) + b = Permutation([0, 2, 1, 3, 4]) + assert PermutationGroup(a, b).degree == \ + PermutationGroup(a, b).degree == 6 + + g = PermutationGroup(Permutation(0, 2, 1)) + assert Tuple(1, g).has(g) + + +def test_generate(): + a = Permutation([1, 0]) + g = list(PermutationGroup([a]).generate()) + assert g == [Permutation([0, 1]), Permutation([1, 0])] + assert len(list(PermutationGroup(Permutation((0, 1))).generate())) == 1 + g = PermutationGroup([a]).generate(method='dimino') + assert list(g) == [Permutation([0, 1]), Permutation([1, 0])] + a = Permutation([2, 0, 1]) + b = Permutation([2, 1, 0]) + G = PermutationGroup([a, b]) + g = G.generate() + v1 = [p.array_form for p in list(g)] + v1.sort() + assert v1 == [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, + 1], [2, 1, 0]] + v2 = list(G.generate(method='dimino', af=True)) + assert v1 == sorted(v2) + a = Permutation([2, 0, 1, 3, 4, 5]) + b = Permutation([2, 1, 3, 4, 5, 0]) + g = PermutationGroup([a, b]).generate(af=True) + assert len(list(g)) == 360 + + +def test_order(): + a = Permutation([2, 0, 1, 3, 4, 5, 6, 7, 8, 9]) + b = Permutation([2, 1, 3, 4, 5, 6, 7, 8, 9, 0]) + g = PermutationGroup([a, b]) + assert g.order() == 1814400 + assert PermutationGroup().order() == 1 + + +def test_equality(): + p_1 = Permutation(0, 1, 3) + p_2 = Permutation(0, 2, 3) + p_3 = Permutation(0, 1, 2) + p_4 = Permutation(0, 1, 3) + g_1 = PermutationGroup(p_1, p_2) + g_2 = PermutationGroup(p_3, p_4) + g_3 = PermutationGroup(p_2, p_1) + g_4 = PermutationGroup(p_1, p_2) + + assert g_1 != g_2 + assert g_1.generators != g_2.generators + assert g_1.equals(g_2) + assert g_1 != g_3 + assert g_1.equals(g_3) + assert g_1 == g_4 + + +def test_stabilizer(): + S = SymmetricGroup(2) + H = S.stabilizer(0) + assert H.generators == [Permutation(1)] + a = Permutation([2, 0, 1, 3, 4, 5]) + b = Permutation([2, 1, 3, 4, 5, 0]) + G = PermutationGroup([a, b]) + G0 = G.stabilizer(0) + assert G0.order() == 60 + + gens_cube = [[1, 3, 5, 7, 0, 2, 4, 6], [1, 3, 0, 2, 5, 7, 4, 6]] + gens = [Permutation(p) for p in gens_cube] + G = PermutationGroup(gens) + G2 = G.stabilizer(2) + assert G2.order() == 6 + G2_1 = G2.stabilizer(1) + v = list(G2_1.generate(af=True)) + assert v == [[0, 1, 2, 3, 4, 5, 6, 7], [3, 1, 2, 0, 7, 5, 6, 4]] + + gens = ( + (1, 2, 0, 4, 5, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19), + (0, 1, 2, 3, 4, 5, 19, 6, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 7, 17, 18), + (0, 1, 2, 3, 4, 5, 6, 7, 9, 18, 16, 11, 12, 13, 14, 15, 8, 17, 10, 19)) + gens = [Permutation(p) for p in gens] + G = PermutationGroup(gens) + G2 = G.stabilizer(2) + assert G2.order() == 181440 + S = SymmetricGroup(3) + assert [G.order() for G in S.basic_stabilizers] == [6, 2] + + +def test_center(): + # the center of the dihedral group D_n is of order 2 for even n + for i in (4, 6, 10): + D = DihedralGroup(i) + assert (D.center()).order() == 2 + # the center of the dihedral group D_n is of order 1 for odd n>2 + for i in (3, 5, 7): + D = DihedralGroup(i) + assert (D.center()).order() == 1 + # the center of an abelian group is the group itself + for i in (2, 3, 5): + for j in (1, 5, 7): + for k in (1, 1, 11): + G = AbelianGroup(i, j, k) + assert G.center().is_subgroup(G) + # the center of a nonabelian simple group is trivial + for i in(1, 5, 9): + A = AlternatingGroup(i) + assert (A.center()).order() == 1 + # brute-force verifications + D = DihedralGroup(5) + A = AlternatingGroup(3) + C = CyclicGroup(4) + G.is_subgroup(D*A*C) + assert _verify_centralizer(G, G) + + +def test_centralizer(): + # the centralizer of the trivial group is the entire group + S = SymmetricGroup(2) + assert S.centralizer(Permutation(list(range(2)))).is_subgroup(S) + A = AlternatingGroup(5) + assert A.centralizer(Permutation(list(range(5)))).is_subgroup(A) + # a centralizer in the trivial group is the trivial group itself + triv = PermutationGroup([Permutation([0, 1, 2, 3])]) + D = DihedralGroup(4) + assert triv.centralizer(D).is_subgroup(triv) + # brute-force verifications for centralizers of groups + for i in (4, 5, 6): + S = SymmetricGroup(i) + A = AlternatingGroup(i) + C = CyclicGroup(i) + D = DihedralGroup(i) + for gp in (S, A, C, D): + for gp2 in (S, A, C, D): + if not gp2.is_subgroup(gp): + assert _verify_centralizer(gp, gp2) + # verify the centralizer for all elements of several groups + S = SymmetricGroup(5) + elements = list(S.generate_dimino()) + for element in elements: + assert _verify_centralizer(S, element) + A = AlternatingGroup(5) + elements = list(A.generate_dimino()) + for element in elements: + assert _verify_centralizer(A, element) + D = DihedralGroup(7) + elements = list(D.generate_dimino()) + for element in elements: + assert _verify_centralizer(D, element) + # verify centralizers of small groups within small groups + small = [] + for i in (1, 2, 3): + small.append(SymmetricGroup(i)) + small.append(AlternatingGroup(i)) + small.append(DihedralGroup(i)) + small.append(CyclicGroup(i)) + for gp in small: + for gp2 in small: + if gp.degree == gp2.degree: + assert _verify_centralizer(gp, gp2) + + +def test_coset_rank(): + gens_cube = [[1, 3, 5, 7, 0, 2, 4, 6], [1, 3, 0, 2, 5, 7, 4, 6]] + gens = [Permutation(p) for p in gens_cube] + G = PermutationGroup(gens) + i = 0 + for h in G.generate(af=True): + rk = G.coset_rank(h) + assert rk == i + h1 = G.coset_unrank(rk, af=True) + assert h == h1 + i += 1 + assert G.coset_unrank(48) is None + assert G.coset_unrank(G.coset_rank(gens[0])) == gens[0] + + +def test_coset_factor(): + a = Permutation([0, 2, 1]) + G = PermutationGroup([a]) + c = Permutation([2, 1, 0]) + assert not G.coset_factor(c) + assert G.coset_rank(c) is None + + a = Permutation([2, 0, 1, 3, 4, 5]) + b = Permutation([2, 1, 3, 4, 5, 0]) + g = PermutationGroup([a, b]) + assert g.order() == 360 + d = Permutation([1, 0, 2, 3, 4, 5]) + assert not g.coset_factor(d.array_form) + assert not g.contains(d) + assert Permutation(2) in G + c = Permutation([1, 0, 2, 3, 5, 4]) + v = g.coset_factor(c, True) + tr = g.basic_transversals + p = Permutation.rmul(*[tr[i][v[i]] for i in range(len(g.base))]) + assert p == c + v = g.coset_factor(c) + p = Permutation.rmul(*v) + assert p == c + assert g.contains(c) + G = PermutationGroup([Permutation([2, 1, 0])]) + p = Permutation([1, 0, 2]) + assert G.coset_factor(p) == [] + + +def test_orbits(): + a = Permutation([2, 0, 1]) + b = Permutation([2, 1, 0]) + g = PermutationGroup([a, b]) + assert g.orbit(0) == {0, 1, 2} + assert g.orbits() == [{0, 1, 2}] + assert g.is_transitive() and g.is_transitive(strict=False) + assert g.orbit_transversal(0) == \ + [Permutation( + [0, 1, 2]), Permutation([2, 0, 1]), Permutation([1, 2, 0])] + assert g.orbit_transversal(0, True) == \ + [(0, Permutation([0, 1, 2])), (2, Permutation([2, 0, 1])), + (1, Permutation([1, 2, 0]))] + + G = DihedralGroup(6) + transversal, slps = _orbit_transversal(G.degree, G.generators, 0, True, slp=True) + for i, t in transversal: + slp = slps[i] + w = G.identity + for s in slp: + w = G.generators[s]*w + assert w == t + + a = Permutation(list(range(1, 100)) + [0]) + G = PermutationGroup([a]) + assert [min(o) for o in G.orbits()] == [0] + G = PermutationGroup(rubik_cube_generators()) + assert [min(o) for o in G.orbits()] == [0, 1] + assert not G.is_transitive() and not G.is_transitive(strict=False) + G = PermutationGroup([Permutation(0, 1, 3), Permutation(3)(0, 1)]) + assert not G.is_transitive() and G.is_transitive(strict=False) + assert PermutationGroup( + Permutation(3)).is_transitive(strict=False) is False + + +def test_is_normal(): + gens_s5 = [Permutation(p) for p in [[1, 2, 3, 4, 0], [2, 1, 4, 0, 3]]] + G1 = PermutationGroup(gens_s5) + assert G1.order() == 120 + gens_a5 = [Permutation(p) for p in [[1, 0, 3, 2, 4], [2, 1, 4, 3, 0]]] + G2 = PermutationGroup(gens_a5) + assert G2.order() == 60 + assert G2.is_normal(G1) + gens3 = [Permutation(p) for p in [[2, 1, 3, 0, 4], [1, 2, 0, 3, 4]]] + G3 = PermutationGroup(gens3) + assert not G3.is_normal(G1) + assert G3.order() == 12 + G4 = G1.normal_closure(G3.generators) + assert G4.order() == 60 + gens5 = [Permutation(p) for p in [[1, 2, 3, 0, 4], [1, 2, 0, 3, 4]]] + G5 = PermutationGroup(gens5) + assert G5.order() == 24 + G6 = G1.normal_closure(G5.generators) + assert G6.order() == 120 + assert G1.is_subgroup(G6) + assert not G1.is_subgroup(G4) + assert G2.is_subgroup(G4) + I5 = PermutationGroup(Permutation(4)) + assert I5.is_normal(G5) + assert I5.is_normal(G6, strict=False) + p1 = Permutation([1, 0, 2, 3, 4]) + p2 = Permutation([0, 1, 2, 4, 3]) + p3 = Permutation([3, 4, 2, 1, 0]) + id_ = Permutation([0, 1, 2, 3, 4]) + H = PermutationGroup([p1, p3]) + H_n1 = PermutationGroup([p1, p2]) + H_n2_1 = PermutationGroup(p1) + H_n2_2 = PermutationGroup(p2) + H_id = PermutationGroup(id_) + assert H_n1.is_normal(H) + assert H_n2_1.is_normal(H_n1) + assert H_n2_2.is_normal(H_n1) + assert H_id.is_normal(H_n2_1) + assert H_id.is_normal(H_n1) + assert H_id.is_normal(H) + assert not H_n2_1.is_normal(H) + assert not H_n2_2.is_normal(H) + + +def test_eq(): + a = [[1, 2, 0, 3, 4, 5], [1, 0, 2, 3, 4, 5], [2, 1, 0, 3, 4, 5], [ + 1, 2, 0, 3, 4, 5]] + a = [Permutation(p) for p in a + [[1, 2, 3, 4, 5, 0]]] + g = Permutation([1, 2, 3, 4, 5, 0]) + G1, G2, G3 = [PermutationGroup(x) for x in [a[:2], a[2:4], [g, g**2]]] + assert G1.order() == G2.order() == G3.order() == 6 + assert G1.is_subgroup(G2) + assert not G1.is_subgroup(G3) + G4 = PermutationGroup([Permutation([0, 1])]) + assert not G1.is_subgroup(G4) + assert G4.is_subgroup(G1, 0) + assert PermutationGroup(g, g).is_subgroup(PermutationGroup(g)) + assert SymmetricGroup(3).is_subgroup(SymmetricGroup(4), 0) + assert SymmetricGroup(3).is_subgroup(SymmetricGroup(3)*CyclicGroup(5), 0) + assert not CyclicGroup(5).is_subgroup(SymmetricGroup(3)*CyclicGroup(5), 0) + assert CyclicGroup(3).is_subgroup(SymmetricGroup(3)*CyclicGroup(5), 0) + + +def test_derived_subgroup(): + a = Permutation([1, 0, 2, 4, 3]) + b = Permutation([0, 1, 3, 2, 4]) + G = PermutationGroup([a, b]) + C = G.derived_subgroup() + assert C.order() == 3 + assert C.is_normal(G) + assert C.is_subgroup(G, 0) + assert not G.is_subgroup(C, 0) + gens_cube = [[1, 3, 5, 7, 0, 2, 4, 6], [1, 3, 0, 2, 5, 7, 4, 6]] + gens = [Permutation(p) for p in gens_cube] + G = PermutationGroup(gens) + C = G.derived_subgroup() + assert C.order() == 12 + + +def test_is_solvable(): + a = Permutation([1, 2, 0]) + b = Permutation([1, 0, 2]) + G = PermutationGroup([a, b]) + assert G.is_solvable + G = PermutationGroup([a]) + assert G.is_solvable + a = Permutation([1, 2, 3, 4, 0]) + b = Permutation([1, 0, 2, 3, 4]) + G = PermutationGroup([a, b]) + assert not G.is_solvable + P = SymmetricGroup(10) + S = P.sylow_subgroup(3) + assert S.is_solvable + +def test_rubik1(): + gens = rubik_cube_generators() + gens1 = [gens[-1]] + [p**2 for p in gens[1:]] + G1 = PermutationGroup(gens1) + assert G1.order() == 19508428800 + gens2 = [p**2 for p in gens] + G2 = PermutationGroup(gens2) + assert G2.order() == 663552 + assert G2.is_subgroup(G1, 0) + C1 = G1.derived_subgroup() + assert C1.order() == 4877107200 + assert C1.is_subgroup(G1, 0) + assert not G2.is_subgroup(C1, 0) + + G = RubikGroup(2) + assert G.order() == 3674160 + + +@XFAIL +def test_rubik(): + skip('takes too much time') + G = PermutationGroup(rubik_cube_generators()) + assert G.order() == 43252003274489856000 + G1 = PermutationGroup(G[:3]) + assert G1.order() == 170659735142400 + assert not G1.is_normal(G) + G2 = G.normal_closure(G1.generators) + assert G2.is_subgroup(G) + + +def test_direct_product(): + C = CyclicGroup(4) + D = DihedralGroup(4) + G = C*C*C + assert G.order() == 64 + assert G.degree == 12 + assert len(G.orbits()) == 3 + assert G.is_abelian is True + H = D*C + assert H.order() == 32 + assert H.is_abelian is False + + +def test_orbit_rep(): + G = DihedralGroup(6) + assert G.orbit_rep(1, 3) in [Permutation([2, 3, 4, 5, 0, 1]), + Permutation([4, 3, 2, 1, 0, 5])] + H = CyclicGroup(4)*G + assert H.orbit_rep(1, 5) is False + + +def test_schreier_vector(): + G = CyclicGroup(50) + v = [0]*50 + v[23] = -1 + assert G.schreier_vector(23) == v + H = DihedralGroup(8) + assert H.schreier_vector(2) == [0, 1, -1, 0, 0, 1, 0, 0] + L = SymmetricGroup(4) + assert L.schreier_vector(1) == [1, -1, 0, 0] + + +def test_random_pr(): + D = DihedralGroup(6) + r = 11 + n = 3 + _random_prec_n = {} + _random_prec_n[0] = {'s': 7, 't': 3, 'x': 2, 'e': -1} + _random_prec_n[1] = {'s': 5, 't': 5, 'x': 1, 'e': -1} + _random_prec_n[2] = {'s': 3, 't': 4, 'x': 2, 'e': 1} + D._random_pr_init(r, n, _random_prec_n=_random_prec_n) + assert D._random_gens[11] == [0, 1, 2, 3, 4, 5] + _random_prec = {'s': 2, 't': 9, 'x': 1, 'e': -1} + assert D.random_pr(_random_prec=_random_prec) == \ + Permutation([0, 5, 4, 3, 2, 1]) + + +def test_is_alt_sym(): + G = DihedralGroup(10) + assert G.is_alt_sym() is False + assert G._eval_is_alt_sym_naive() is False + assert G._eval_is_alt_sym_naive(only_alt=True) is False + assert G._eval_is_alt_sym_naive(only_sym=True) is False + + S = SymmetricGroup(10) + assert S._eval_is_alt_sym_naive() is True + assert S._eval_is_alt_sym_naive(only_alt=True) is False + assert S._eval_is_alt_sym_naive(only_sym=True) is True + + N_eps = 10 + _random_prec = {'N_eps': N_eps, + 0: Permutation([[2], [1, 4], [0, 6, 7, 8, 9, 3, 5]]), + 1: Permutation([[1, 8, 7, 6, 3, 5, 2, 9], [0, 4]]), + 2: Permutation([[5, 8], [4, 7], [0, 1, 2, 3, 6, 9]]), + 3: Permutation([[3], [0, 8, 2, 7, 4, 1, 6, 9, 5]]), + 4: Permutation([[8], [4, 7, 9], [3, 6], [0, 5, 1, 2]]), + 5: Permutation([[6], [0, 2, 4, 5, 1, 8, 3, 9, 7]]), + 6: Permutation([[6, 9, 8], [4, 5], [1, 3, 7], [0, 2]]), + 7: Permutation([[4], [0, 2, 9, 1, 3, 8, 6, 5, 7]]), + 8: Permutation([[1, 5, 6, 3], [0, 2, 7, 8, 4, 9]]), + 9: Permutation([[8], [6, 7], [2, 3, 4, 5], [0, 1, 9]])} + assert S.is_alt_sym(_random_prec=_random_prec) is True + + A = AlternatingGroup(10) + assert A._eval_is_alt_sym_naive() is True + assert A._eval_is_alt_sym_naive(only_alt=True) is True + assert A._eval_is_alt_sym_naive(only_sym=True) is False + + _random_prec = {'N_eps': N_eps, + 0: Permutation([[1, 6, 4, 2, 7, 8, 5, 9, 3], [0]]), + 1: Permutation([[1], [0, 5, 8, 4, 9, 2, 3, 6, 7]]), + 2: Permutation([[1, 9, 8, 3, 2, 5], [0, 6, 7, 4]]), + 3: Permutation([[6, 8, 9], [4, 5], [1, 3, 7, 2], [0]]), + 4: Permutation([[8], [5], [4], [2, 6, 9, 3], [1], [0, 7]]), + 5: Permutation([[3, 6], [0, 8, 1, 7, 5, 9, 4, 2]]), + 6: Permutation([[5], [2, 9], [1, 8, 3], [0, 4, 7, 6]]), + 7: Permutation([[1, 8, 4, 7, 2, 3], [0, 6, 9, 5]]), + 8: Permutation([[5, 8, 7], [3], [1, 4, 2, 6], [0, 9]]), + 9: Permutation([[4, 9, 6], [3, 8], [1, 2], [0, 5, 7]])} + assert A.is_alt_sym(_random_prec=_random_prec) is False + + G = PermutationGroup( + Permutation(1, 3, size=8)(0, 2, 4, 6), + Permutation(5, 7, size=8)(0, 2, 4, 6)) + assert G.is_alt_sym() is False + + # Tests for monte-carlo c_n parameter setting, and which guarantees + # to give False. + G = DihedralGroup(10) + assert G._eval_is_alt_sym_monte_carlo() is False + G = DihedralGroup(20) + assert G._eval_is_alt_sym_monte_carlo() is False + + # A dry-running test to check if it looks up for the updated cache. + G = DihedralGroup(6) + G.is_alt_sym() + assert G.is_alt_sym() is False + + +def test_minimal_block(): + D = DihedralGroup(6) + block_system = D.minimal_block([0, 3]) + for i in range(3): + assert block_system[i] == block_system[i + 3] + S = SymmetricGroup(6) + assert S.minimal_block([0, 1]) == [0, 0, 0, 0, 0, 0] + + assert Tetra.pgroup.minimal_block([0, 1]) == [0, 0, 0, 0] + + P1 = PermutationGroup(Permutation(1, 5)(2, 4), Permutation(0, 1, 2, 3, 4, 5)) + P2 = PermutationGroup(Permutation(0, 1, 2, 3, 4, 5), Permutation(1, 5)(2, 4)) + assert P1.minimal_block([0, 2]) == [0, 1, 0, 1, 0, 1] + assert P2.minimal_block([0, 2]) == [0, 1, 0, 1, 0, 1] + + +def test_minimal_blocks(): + P = PermutationGroup(Permutation(1, 5)(2, 4), Permutation(0, 1, 2, 3, 4, 5)) + assert P.minimal_blocks() == [[0, 1, 0, 1, 0, 1], [0, 1, 2, 0, 1, 2]] + + P = SymmetricGroup(5) + assert P.minimal_blocks() == [[0]*5] + + P = PermutationGroup(Permutation(0, 3)) + assert P.minimal_blocks() is False + + +def test_max_div(): + S = SymmetricGroup(10) + assert S.max_div == 5 + + +def test_is_primitive(): + S = SymmetricGroup(5) + assert S.is_primitive() is True + C = CyclicGroup(7) + assert C.is_primitive() is True + + a = Permutation(0, 1, 2, size=6) + b = Permutation(3, 4, 5, size=6) + G = PermutationGroup(a, b) + assert G.is_primitive() is False + + +def test_random_stab(): + S = SymmetricGroup(5) + _random_el = Permutation([1, 3, 2, 0, 4]) + _random_prec = {'rand': _random_el} + g = S.random_stab(2, _random_prec=_random_prec) + assert g == Permutation([1, 3, 2, 0, 4]) + h = S.random_stab(1) + assert h(1) == 1 + + +def test_transitivity_degree(): + perm = Permutation([1, 2, 0]) + C = PermutationGroup([perm]) + assert C.transitivity_degree == 1 + gen1 = Permutation([1, 2, 0, 3, 4]) + gen2 = Permutation([1, 2, 3, 4, 0]) + # alternating group of degree 5 + Alt = PermutationGroup([gen1, gen2]) + assert Alt.transitivity_degree == 3 + + +def test_schreier_sims_random(): + assert sorted(Tetra.pgroup.base) == [0, 1] + + S = SymmetricGroup(3) + base = [0, 1] + strong_gens = [Permutation([1, 2, 0]), Permutation([1, 0, 2]), + Permutation([0, 2, 1])] + assert S.schreier_sims_random(base, strong_gens, 5) == (base, strong_gens) + D = DihedralGroup(3) + _random_prec = {'g': [Permutation([2, 0, 1]), Permutation([1, 2, 0]), + Permutation([1, 0, 2])]} + base = [0, 1] + strong_gens = [Permutation([1, 2, 0]), Permutation([2, 1, 0]), + Permutation([0, 2, 1])] + assert D.schreier_sims_random([], D.generators, 2, + _random_prec=_random_prec) == (base, strong_gens) + + +def test_baseswap(): + S = SymmetricGroup(4) + S.schreier_sims() + base = S.base + strong_gens = S.strong_gens + assert base == [0, 1, 2] + deterministic = S.baseswap(base, strong_gens, 1, randomized=False) + randomized = S.baseswap(base, strong_gens, 1) + assert deterministic[0] == [0, 2, 1] + assert _verify_bsgs(S, deterministic[0], deterministic[1]) is True + assert randomized[0] == [0, 2, 1] + assert _verify_bsgs(S, randomized[0], randomized[1]) is True + + +def test_schreier_sims_incremental(): + identity = Permutation([0, 1, 2, 3, 4]) + TrivialGroup = PermutationGroup([identity]) + base, strong_gens = TrivialGroup.schreier_sims_incremental(base=[0, 1, 2]) + assert _verify_bsgs(TrivialGroup, base, strong_gens) is True + S = SymmetricGroup(5) + base, strong_gens = S.schreier_sims_incremental(base=[0, 1, 2]) + assert _verify_bsgs(S, base, strong_gens) is True + D = DihedralGroup(2) + base, strong_gens = D.schreier_sims_incremental(base=[1]) + assert _verify_bsgs(D, base, strong_gens) is True + A = AlternatingGroup(7) + gens = A.generators[:] + gen0 = gens[0] + gen1 = gens[1] + gen1 = rmul(gen1, ~gen0) + gen0 = rmul(gen0, gen1) + gen1 = rmul(gen0, gen1) + base, strong_gens = A.schreier_sims_incremental(base=[0, 1], gens=gens) + assert _verify_bsgs(A, base, strong_gens) is True + C = CyclicGroup(11) + gen = C.generators[0] + base, strong_gens = C.schreier_sims_incremental(gens=[gen**3]) + assert _verify_bsgs(C, base, strong_gens) is True + + +def _subgroup_search(i, j, k): + prop_true = lambda x: True + prop_fix_points = lambda x: [x(point) for point in points] == points + prop_comm_g = lambda x: rmul(x, g) == rmul(g, x) + prop_even = lambda x: x.is_even + for i in range(i, j, k): + S = SymmetricGroup(i) + A = AlternatingGroup(i) + C = CyclicGroup(i) + Sym = S.subgroup_search(prop_true) + assert Sym.is_subgroup(S) + Alt = S.subgroup_search(prop_even) + assert Alt.is_subgroup(A) + Sym = S.subgroup_search(prop_true, init_subgroup=C) + assert Sym.is_subgroup(S) + points = [7] + assert S.stabilizer(7).is_subgroup(S.subgroup_search(prop_fix_points)) + points = [3, 4] + assert S.stabilizer(3).stabilizer(4).is_subgroup( + S.subgroup_search(prop_fix_points)) + points = [3, 5] + fix35 = A.subgroup_search(prop_fix_points) + points = [5] + fix5 = A.subgroup_search(prop_fix_points) + assert A.subgroup_search(prop_fix_points, init_subgroup=fix35 + ).is_subgroup(fix5) + base, strong_gens = A.schreier_sims_incremental() + g = A.generators[0] + comm_g = \ + A.subgroup_search(prop_comm_g, base=base, strong_gens=strong_gens) + assert _verify_bsgs(comm_g, base, comm_g.generators) is True + assert [prop_comm_g(gen) is True for gen in comm_g.generators] + + +def test_subgroup_search(): + _subgroup_search(10, 15, 2) + + +@XFAIL +def test_subgroup_search2(): + skip('takes too much time') + _subgroup_search(16, 17, 1) + + +def test_normal_closure(): + # the normal closure of the trivial group is trivial + S = SymmetricGroup(3) + identity = Permutation([0, 1, 2]) + closure = S.normal_closure(identity) + assert closure.is_trivial + # the normal closure of the entire group is the entire group + A = AlternatingGroup(4) + assert A.normal_closure(A).is_subgroup(A) + # brute-force verifications for subgroups + for i in (3, 4, 5): + S = SymmetricGroup(i) + A = AlternatingGroup(i) + D = DihedralGroup(i) + C = CyclicGroup(i) + for gp in (A, D, C): + assert _verify_normal_closure(S, gp) + # brute-force verifications for all elements of a group + S = SymmetricGroup(5) + elements = list(S.generate_dimino()) + for element in elements: + assert _verify_normal_closure(S, element) + # small groups + small = [] + for i in (1, 2, 3): + small.append(SymmetricGroup(i)) + small.append(AlternatingGroup(i)) + small.append(DihedralGroup(i)) + small.append(CyclicGroup(i)) + for gp in small: + for gp2 in small: + if gp2.is_subgroup(gp, 0) and gp2.degree == gp.degree: + assert _verify_normal_closure(gp, gp2) + + +def test_derived_series(): + # the derived series of the trivial group consists only of the trivial group + triv = PermutationGroup([Permutation([0, 1, 2])]) + assert triv.derived_series()[0].is_subgroup(triv) + # the derived series for a simple group consists only of the group itself + for i in (5, 6, 7): + A = AlternatingGroup(i) + assert A.derived_series()[0].is_subgroup(A) + # the derived series for S_4 is S_4 > A_4 > K_4 > triv + S = SymmetricGroup(4) + series = S.derived_series() + assert series[1].is_subgroup(AlternatingGroup(4)) + assert series[2].is_subgroup(DihedralGroup(2)) + assert series[3].is_trivial + + +def test_lower_central_series(): + # the lower central series of the trivial group consists of the trivial + # group + triv = PermutationGroup([Permutation([0, 1, 2])]) + assert triv.lower_central_series()[0].is_subgroup(triv) + # the lower central series of a simple group consists of the group itself + for i in (5, 6, 7): + A = AlternatingGroup(i) + assert A.lower_central_series()[0].is_subgroup(A) + # GAP-verified example + S = SymmetricGroup(6) + series = S.lower_central_series() + assert len(series) == 2 + assert series[1].is_subgroup(AlternatingGroup(6)) + + +def test_commutator(): + # the commutator of the trivial group and the trivial group is trivial + S = SymmetricGroup(3) + triv = PermutationGroup([Permutation([0, 1, 2])]) + assert S.commutator(triv, triv).is_subgroup(triv) + # the commutator of the trivial group and any other group is again trivial + A = AlternatingGroup(3) + assert S.commutator(triv, A).is_subgroup(triv) + # the commutator is commutative + for i in (3, 4, 5): + S = SymmetricGroup(i) + A = AlternatingGroup(i) + D = DihedralGroup(i) + assert S.commutator(A, D).is_subgroup(S.commutator(D, A)) + # the commutator of an abelian group is trivial + S = SymmetricGroup(7) + A1 = AbelianGroup(2, 5) + A2 = AbelianGroup(3, 4) + triv = PermutationGroup([Permutation([0, 1, 2, 3, 4, 5, 6])]) + assert S.commutator(A1, A1).is_subgroup(triv) + assert S.commutator(A2, A2).is_subgroup(triv) + # examples calculated by hand + S = SymmetricGroup(3) + A = AlternatingGroup(3) + assert S.commutator(A, S).is_subgroup(A) + + +def test_is_nilpotent(): + # every abelian group is nilpotent + for i in (1, 2, 3): + C = CyclicGroup(i) + Ab = AbelianGroup(i, i + 2) + assert C.is_nilpotent + assert Ab.is_nilpotent + Ab = AbelianGroup(5, 7, 10) + assert Ab.is_nilpotent + # A_5 is not solvable and thus not nilpotent + assert AlternatingGroup(5).is_nilpotent is False + + +def test_is_trivial(): + for i in range(5): + triv = PermutationGroup([Permutation(list(range(i)))]) + assert triv.is_trivial + + +def test_pointwise_stabilizer(): + S = SymmetricGroup(2) + stab = S.pointwise_stabilizer([0]) + assert stab.generators == [Permutation(1)] + S = SymmetricGroup(5) + points = [] + stab = S + for point in (2, 0, 3, 4, 1): + stab = stab.stabilizer(point) + points.append(point) + assert S.pointwise_stabilizer(points).is_subgroup(stab) + + +def test_make_perm(): + assert cube.pgroup.make_perm(5, seed=list(range(5))) == \ + Permutation([4, 7, 6, 5, 0, 3, 2, 1]) + assert cube.pgroup.make_perm(7, seed=list(range(7))) == \ + Permutation([6, 7, 3, 2, 5, 4, 0, 1]) + + +def test_elements(): + from sympy.sets.sets import FiniteSet + + p = Permutation(2, 3) + assert set(PermutationGroup(p).elements) == {Permutation(3), Permutation(2, 3)} + assert FiniteSet(*PermutationGroup(p).elements) \ + == FiniteSet(Permutation(2, 3), Permutation(3)) + + +def test_is_group(): + assert PermutationGroup(Permutation(1,2), Permutation(2,4)).is_group is True + assert SymmetricGroup(4).is_group is True + + +def test_PermutationGroup(): + assert PermutationGroup() == PermutationGroup(Permutation()) + assert (PermutationGroup() == 0) is False + + +def test_coset_transvesal(): + G = AlternatingGroup(5) + H = PermutationGroup(Permutation(0,1,2),Permutation(1,2)(3,4)) + assert G.coset_transversal(H) == \ + [Permutation(4), Permutation(2, 3, 4), Permutation(2, 4, 3), + Permutation(1, 2, 4), Permutation(4)(1, 2, 3), Permutation(1, 3)(2, 4), + Permutation(0, 1, 2, 3, 4), Permutation(0, 1, 2, 4, 3), + Permutation(0, 1, 3, 2, 4), Permutation(0, 2, 4, 1, 3)] + + +def test_coset_table(): + G = PermutationGroup(Permutation(0,1,2,3), Permutation(0,1,2), + Permutation(0,4,2,7), Permutation(5,6), Permutation(0,7)) + H = PermutationGroup(Permutation(0,1,2,3), Permutation(0,7)) + assert G.coset_table(H) == \ + [[0, 0, 0, 0, 1, 2, 3, 3, 0, 0], [4, 5, 2, 5, 6, 0, 7, 7, 1, 1], + [5, 4, 5, 1, 0, 6, 8, 8, 6, 6], [3, 3, 3, 3, 7, 8, 0, 0, 3, 3], + [2, 1, 4, 4, 4, 4, 9, 9, 4, 4], [1, 2, 1, 2, 5, 5, 10, 10, 5, 5], + [6, 6, 6, 6, 2, 1, 11, 11, 2, 2], [9, 10, 8, 10, 11, 3, 1, 1, 7, 7], + [10, 9, 10, 7, 3, 11, 2, 2, 11, 11], [8, 7, 9, 9, 9, 9, 4, 4, 9, 9], + [7, 8, 7, 8, 10, 10, 5, 5, 10, 10], [11, 11, 11, 11, 8, 7, 6, 6, 8, 8]] + + +def test_subgroup(): + G = PermutationGroup(Permutation(0,1,2), Permutation(0,2,3)) + H = G.subgroup([Permutation(0,1,3)]) + assert H.is_subgroup(G) + + +def test_generator_product(): + G = SymmetricGroup(5) + p = Permutation(0, 2, 3)(1, 4) + gens = G.generator_product(p) + assert all(g in G.strong_gens for g in gens) + w = G.identity + for g in gens: + w = g*w + assert w == p + + +def test_sylow_subgroup(): + P = PermutationGroup(Permutation(1, 5)(2, 4), Permutation(0, 1, 2, 3, 4, 5)) + S = P.sylow_subgroup(2) + assert S.order() == 4 + + P = DihedralGroup(12) + S = P.sylow_subgroup(3) + assert S.order() == 3 + + P = PermutationGroup( + Permutation(1, 5)(2, 4), Permutation(0, 1, 2, 3, 4, 5), Permutation(0, 2)) + S = P.sylow_subgroup(3) + assert S.order() == 9 + S = P.sylow_subgroup(2) + assert S.order() == 8 + + P = SymmetricGroup(10) + S = P.sylow_subgroup(2) + assert S.order() == 256 + S = P.sylow_subgroup(3) + assert S.order() == 81 + S = P.sylow_subgroup(5) + assert S.order() == 25 + + # the length of the lower central series + # of a p-Sylow subgroup of Sym(n) grows with + # the highest exponent exp of p such + # that n >= p**exp + exp = 1 + length = 0 + for i in range(2, 9): + P = SymmetricGroup(i) + S = P.sylow_subgroup(2) + ls = S.lower_central_series() + if i // 2**exp > 0: + # length increases with exponent + assert len(ls) > length + length = len(ls) + exp += 1 + else: + assert len(ls) == length + + G = SymmetricGroup(100) + S = G.sylow_subgroup(3) + assert G.order() % S.order() == 0 + assert G.order()/S.order() % 3 > 0 + + G = AlternatingGroup(100) + S = G.sylow_subgroup(2) + assert G.order() % S.order() == 0 + assert G.order()/S.order() % 2 > 0 + + G = DihedralGroup(18) + S = G.sylow_subgroup(p=2) + assert S.order() == 4 + + G = DihedralGroup(50) + S = G.sylow_subgroup(p=2) + assert S.order() == 4 + + +@slow +def test_presentation(): + def _test(P): + G = P.presentation() + return G.order() == P.order() + + def _strong_test(P): + G = P.strong_presentation() + chk = len(G.generators) == len(P.strong_gens) + return chk and G.order() == P.order() + + P = PermutationGroup(Permutation(0,1,5,2)(3,7,4,6), Permutation(0,3,5,4)(1,6,2,7)) + assert _test(P) + + P = AlternatingGroup(5) + assert _test(P) + + P = SymmetricGroup(5) + assert _test(P) + + P = PermutationGroup( + [Permutation(0,3,1,2), Permutation(3)(0,1), Permutation(0,1)(2,3)]) + assert _strong_test(P) + + P = DihedralGroup(6) + assert _strong_test(P) + + a = Permutation(0,1)(2,3) + b = Permutation(0,2)(3,1) + c = Permutation(4,5) + P = PermutationGroup(c, a, b) + assert _strong_test(P) + + +def test_polycyclic(): + a = Permutation([0, 1, 2]) + b = Permutation([2, 1, 0]) + G = PermutationGroup([a, b]) + assert G.is_polycyclic is True + + a = Permutation([1, 2, 3, 4, 0]) + b = Permutation([1, 0, 2, 3, 4]) + G = PermutationGroup([a, b]) + assert G.is_polycyclic is False + + +def test_elementary(): + a = Permutation([1, 5, 2, 0, 3, 6, 4]) + G = PermutationGroup([a]) + assert G.is_elementary(7) is False + + a = Permutation(0, 1)(2, 3) + b = Permutation(0, 2)(3, 1) + G = PermutationGroup([a, b]) + assert G.is_elementary(2) is True + c = Permutation(4, 5, 6) + G = PermutationGroup([a, b, c]) + assert G.is_elementary(2) is False + + G = SymmetricGroup(4).sylow_subgroup(2) + assert G.is_elementary(2) is False + H = AlternatingGroup(4).sylow_subgroup(2) + assert H.is_elementary(2) is True + + +def test_perfect(): + G = AlternatingGroup(3) + assert G.is_perfect is False + G = AlternatingGroup(5) + assert G.is_perfect is True + + +def test_index(): + G = PermutationGroup(Permutation(0,1,2), Permutation(0,2,3)) + H = G.subgroup([Permutation(0,1,3)]) + assert G.index(H) == 4 + + +def test_cyclic(): + G = SymmetricGroup(2) + assert G.is_cyclic + G = AbelianGroup(3, 7) + assert G.is_cyclic + G = AbelianGroup(7, 7) + assert not G.is_cyclic + G = AlternatingGroup(3) + assert G.is_cyclic + G = AlternatingGroup(4) + assert not G.is_cyclic + + # Order less than 6 + G = PermutationGroup(Permutation(0, 1, 2), Permutation(0, 2, 1)) + assert G.is_cyclic + G = PermutationGroup( + Permutation(0, 1, 2, 3), + Permutation(0, 2)(1, 3) + ) + assert G.is_cyclic + G = PermutationGroup( + Permutation(3), + Permutation(0, 1)(2, 3), + Permutation(0, 2)(1, 3), + Permutation(0, 3)(1, 2) + ) + assert G.is_cyclic is False + + # Order 15 + G = PermutationGroup( + Permutation(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14), + Permutation(0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13) + ) + assert G.is_cyclic + + # Distinct prime orders + assert PermutationGroup._distinct_primes_lemma([3, 5]) is True + assert PermutationGroup._distinct_primes_lemma([5, 7]) is True + assert PermutationGroup._distinct_primes_lemma([2, 3]) is None + assert PermutationGroup._distinct_primes_lemma([3, 5, 7]) is None + assert PermutationGroup._distinct_primes_lemma([5, 7, 13]) is True + + G = PermutationGroup( + Permutation(0, 1, 2, 3), + Permutation(0, 2)(1, 3)) + assert G.is_cyclic + assert G._is_abelian + + # Non-abelian and therefore not cyclic + G = PermutationGroup(*SymmetricGroup(3).generators) + assert G.is_cyclic is False + + # Abelian and cyclic + G = PermutationGroup( + Permutation(0, 1, 2, 3), + Permutation(4, 5, 6) + ) + assert G.is_cyclic + + # Abelian but not cyclic + G = PermutationGroup( + Permutation(0, 1), + Permutation(2, 3), + Permutation(4, 5, 6) + ) + assert G.is_cyclic is False + + +def test_dihedral(): + G = SymmetricGroup(2) + assert G.is_dihedral + G = SymmetricGroup(3) + assert G.is_dihedral + + G = AbelianGroup(2, 2) + assert G.is_dihedral + G = CyclicGroup(4) + assert not G.is_dihedral + + G = AbelianGroup(3, 5) + assert not G.is_dihedral + G = AbelianGroup(2) + assert G.is_dihedral + G = AbelianGroup(6) + assert not G.is_dihedral + + # D6, generated by two adjacent flips + G = PermutationGroup( + Permutation(1, 5)(2, 4), + Permutation(0, 1)(3, 4)(2, 5)) + assert G.is_dihedral + + # D7, generated by a flip and a rotation + G = PermutationGroup( + Permutation(1, 6)(2, 5)(3, 4), + Permutation(0, 1, 2, 3, 4, 5, 6)) + assert G.is_dihedral + + # S4, presented by three generators, fails due to having exactly 9 + # elements of order 2: + G = PermutationGroup( + Permutation(0, 1), Permutation(0, 2), + Permutation(0, 3)) + assert not G.is_dihedral + + # D7, given by three generators + G = PermutationGroup( + Permutation(1, 6)(2, 5)(3, 4), + Permutation(2, 0)(3, 6)(4, 5), + Permutation(0, 1, 2, 3, 4, 5, 6)) + assert G.is_dihedral + + +def test_abelian_invariants(): + G = AbelianGroup(2, 3, 4) + assert G.abelian_invariants() == [2, 3, 4] + G=PermutationGroup([Permutation(1, 2, 3, 4), Permutation(1, 2), Permutation(5, 6)]) + assert G.abelian_invariants() == [2, 2] + G = AlternatingGroup(7) + assert G.abelian_invariants() == [] + G = AlternatingGroup(4) + assert G.abelian_invariants() == [3] + G = DihedralGroup(4) + assert G.abelian_invariants() == [2, 2] + + G = PermutationGroup([Permutation(1, 2, 3, 4, 5, 6, 7)]) + assert G.abelian_invariants() == [7] + G = DihedralGroup(12) + S = G.sylow_subgroup(3) + assert S.abelian_invariants() == [3] + G = PermutationGroup(Permutation(0, 1, 2), Permutation(0, 2, 3)) + assert G.abelian_invariants() == [3] + G = PermutationGroup([Permutation(0, 1), Permutation(0, 2, 4, 6)(1, 3, 5, 7)]) + assert G.abelian_invariants() == [2, 4] + G = SymmetricGroup(30) + S = G.sylow_subgroup(2) + assert S.abelian_invariants() == [2, 2, 2, 2, 2, 2, 2, 2, 2, 2] + S = G.sylow_subgroup(3) + assert S.abelian_invariants() == [3, 3, 3, 3] + S = G.sylow_subgroup(5) + assert S.abelian_invariants() == [5, 5, 5] + + +def test_composition_series(): + a = Permutation(1, 2, 3) + b = Permutation(1, 2) + G = PermutationGroup([a, b]) + comp_series = G.composition_series() + assert comp_series == G.derived_series() + # The first group in the composition series is always the group itself and + # the last group in the series is the trivial group. + S = SymmetricGroup(4) + assert S.composition_series()[0] == S + assert len(S.composition_series()) == 5 + A = AlternatingGroup(4) + assert A.composition_series()[0] == A + assert len(A.composition_series()) == 4 + + # the composition series for C_8 is C_8 > C_4 > C_2 > triv + G = CyclicGroup(8) + series = G.composition_series() + assert is_isomorphic(series[1], CyclicGroup(4)) + assert is_isomorphic(series[2], CyclicGroup(2)) + assert series[3].is_trivial + + +def test_is_symmetric(): + a = Permutation(0, 1, 2) + b = Permutation(0, 1, size=3) + assert PermutationGroup(a, b).is_symmetric is True + + a = Permutation(0, 2, 1) + b = Permutation(1, 2, size=3) + assert PermutationGroup(a, b).is_symmetric is True + + a = Permutation(0, 1, 2, 3) + b = Permutation(0, 3)(1, 2) + assert PermutationGroup(a, b).is_symmetric is False + +def test_conjugacy_class(): + S = SymmetricGroup(4) + x = Permutation(1, 2, 3) + C = {Permutation(0, 1, 2, size = 4), Permutation(0, 1, 3), + Permutation(0, 2, 1, size = 4), Permutation(0, 2, 3), + Permutation(0, 3, 1), Permutation(0, 3, 2), + Permutation(1, 2, 3), Permutation(1, 3, 2)} + assert S.conjugacy_class(x) == C + +def test_conjugacy_classes(): + S = SymmetricGroup(3) + expected = [{Permutation(size = 3)}, + {Permutation(0, 1, size = 3), Permutation(0, 2), Permutation(1, 2)}, + {Permutation(0, 1, 2), Permutation(0, 2, 1)}] + computed = S.conjugacy_classes() + + assert len(expected) == len(computed) + assert all(e in computed for e in expected) + +def test_coset_class(): + a = Permutation(1, 2) + b = Permutation(0, 1) + G = PermutationGroup([a, b]) + #Creating right coset + rht_coset = G*a + #Checking whether it is left coset or right coset + assert rht_coset.is_right_coset + assert not rht_coset.is_left_coset + #Creating list representation of coset + list_repr = rht_coset.as_list() + expected = [Permutation(0, 2), Permutation(0, 2, 1), Permutation(1, 2), + Permutation(2), Permutation(2)(0, 1), Permutation(0, 1, 2)] + for ele in list_repr: + assert ele in expected + #Creating left coset + left_coset = a*G + #Checking whether it is left coset or right coset + assert not left_coset.is_right_coset + assert left_coset.is_left_coset + #Creating list representation of Coset + list_repr = left_coset.as_list() + expected = [Permutation(2)(0, 1), Permutation(0, 1, 2), Permutation(1, 2), + Permutation(2), Permutation(0, 2), Permutation(0, 2, 1)] + for ele in list_repr: + assert ele in expected + + G = PermutationGroup(Permutation(1, 2, 3, 4), Permutation(2, 3, 4)) + H = PermutationGroup(Permutation(1, 2, 3, 4)) + g = Permutation(1, 3)(2, 4) + rht_coset = Coset(g, H, G, dir='+') + assert rht_coset.is_right_coset + list_repr = rht_coset.as_list() + expected = [Permutation(1, 2, 3, 4), Permutation(4), Permutation(1, 3)(2, 4), + Permutation(1, 4, 3, 2)] + for ele in list_repr: + assert ele in expected + +def test_symmetricpermutationgroup(): + a = SymmetricPermutationGroup(5) + assert a.degree == 5 + assert a.order() == 120 + assert a.identity() == Permutation(4) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_permutations.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_permutations.py new file mode 100644 index 0000000000000000000000000000000000000000..b52fcfec0e2fb3be872efaa814077760e121c748 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_permutations.py @@ -0,0 +1,564 @@ +from itertools import permutations +from copy import copy + +from sympy.core.expr import unchanged +from sympy.core.numbers import Integer +from sympy.core.relational import Eq +from sympy.core.symbol import Symbol +from sympy.core.singleton import S +from sympy.combinatorics.permutations import \ + Permutation, _af_parity, _af_rmul, _af_rmuln, AppliedPermutation, Cycle +from sympy.printing import sstr, srepr, pretty, latex +from sympy.testing.pytest import raises, warns_deprecated_sympy + + +rmul = Permutation.rmul +a = Symbol('a', integer=True) + + +def test_Permutation(): + # don't auto fill 0 + raises(ValueError, lambda: Permutation([1])) + p = Permutation([0, 1, 2, 3]) + # call as bijective + assert [p(i) for i in range(p.size)] == list(p) + # call as operator + assert p(list(range(p.size))) == list(p) + # call as function + assert list(p(1, 2)) == [0, 2, 1, 3] + raises(TypeError, lambda: p(-1)) + raises(TypeError, lambda: p(5)) + # conversion to list + assert list(p) == list(range(4)) + assert p.copy() == p + assert copy(p) == p + assert Permutation(size=4) == Permutation(3) + assert Permutation(Permutation(3), size=5) == Permutation(4) + # cycle form with size + assert Permutation([[1, 2]], size=4) == Permutation([[1, 2], [0], [3]]) + # random generation + assert Permutation.random(2) in (Permutation([1, 0]), Permutation([0, 1])) + + p = Permutation([2, 5, 1, 6, 3, 0, 4]) + q = Permutation([[1], [0, 3, 5, 6, 2, 4]]) + assert len({p, p}) == 1 + r = Permutation([1, 3, 2, 0, 4, 6, 5]) + ans = Permutation(_af_rmuln(*[w.array_form for w in (p, q, r)])).array_form + assert rmul(p, q, r).array_form == ans + # make sure no other permutation of p, q, r could have given + # that answer + for a, b, c in permutations((p, q, r)): + if (a, b, c) == (p, q, r): + continue + assert rmul(a, b, c).array_form != ans + + assert p.support() == list(range(7)) + assert q.support() == [0, 2, 3, 4, 5, 6] + assert Permutation(p.cyclic_form).array_form == p.array_form + assert p.cardinality == 5040 + assert q.cardinality == 5040 + assert q.cycles == 2 + assert rmul(q, p) == Permutation([4, 6, 1, 2, 5, 3, 0]) + assert rmul(p, q) == Permutation([6, 5, 3, 0, 2, 4, 1]) + assert _af_rmul(p.array_form, q.array_form) == \ + [6, 5, 3, 0, 2, 4, 1] + + assert rmul(Permutation([[1, 2, 3], [0, 4]]), + Permutation([[1, 2, 4], [0], [3]])).cyclic_form == \ + [[0, 4, 2], [1, 3]] + assert q.array_form == [3, 1, 4, 5, 0, 6, 2] + assert q.cyclic_form == [[0, 3, 5, 6, 2, 4]] + assert q.full_cyclic_form == [[0, 3, 5, 6, 2, 4], [1]] + assert p.cyclic_form == [[0, 2, 1, 5], [3, 6, 4]] + t = p.transpositions() + assert t == [(0, 5), (0, 1), (0, 2), (3, 4), (3, 6)] + assert Permutation.rmul(*[Permutation(Cycle(*ti)) for ti in (t)]) + assert Permutation([1, 0]).transpositions() == [(0, 1)] + + assert p**13 == p + assert q**0 == Permutation(list(range(q.size))) + assert q**-2 == ~q**2 + assert q**2 == Permutation([5, 1, 0, 6, 3, 2, 4]) + assert q**3 == q**2*q + assert q**4 == q**2*q**2 + + a = Permutation(1, 3) + b = Permutation(2, 0, 3) + I = Permutation(3) + assert ~a == a**-1 + assert a*~a == I + assert a*b**-1 == a*~b + + ans = Permutation(0, 5, 3, 1, 6)(2, 4) + assert (p + q.rank()).rank() == ans.rank() + assert (p + q.rank())._rank == ans.rank() + assert (q + p.rank()).rank() == ans.rank() + raises(TypeError, lambda: p + Permutation(list(range(10)))) + + assert (p - q.rank()).rank() == Permutation(0, 6, 3, 1, 2, 5, 4).rank() + assert p.rank() - q.rank() < 0 # for coverage: make sure mod is used + assert (q - p.rank()).rank() == Permutation(1, 4, 6, 2)(3, 5).rank() + + assert p*q == Permutation(_af_rmuln(*[list(w) for w in (q, p)])) + assert p*Permutation([]) == p + assert Permutation([])*p == p + assert p*Permutation([[0, 1]]) == Permutation([2, 5, 0, 6, 3, 1, 4]) + assert Permutation([[0, 1]])*p == Permutation([5, 2, 1, 6, 3, 0, 4]) + + pq = p ^ q + assert pq == Permutation([5, 6, 0, 4, 1, 2, 3]) + assert pq == rmul(q, p, ~q) + qp = q ^ p + assert qp == Permutation([4, 3, 6, 2, 1, 5, 0]) + assert qp == rmul(p, q, ~p) + raises(ValueError, lambda: p ^ Permutation([])) + + assert p.commutator(q) == Permutation(0, 1, 3, 4, 6, 5, 2) + assert q.commutator(p) == Permutation(0, 2, 5, 6, 4, 3, 1) + assert p.commutator(q) == ~q.commutator(p) + raises(ValueError, lambda: p.commutator(Permutation([]))) + + assert len(p.atoms()) == 7 + assert q.atoms() == {0, 1, 2, 3, 4, 5, 6} + + assert p.inversion_vector() == [2, 4, 1, 3, 1, 0] + assert q.inversion_vector() == [3, 1, 2, 2, 0, 1] + + assert Permutation.from_inversion_vector(p.inversion_vector()) == p + assert Permutation.from_inversion_vector(q.inversion_vector()).array_form\ + == q.array_form + raises(ValueError, lambda: Permutation.from_inversion_vector([0, 2])) + assert Permutation(list(range(500, -1, -1))).inversions() == 125250 + + s = Permutation([0, 4, 1, 3, 2]) + assert s.parity() == 0 + _ = s.cyclic_form # needed to create a value for _cyclic_form + assert len(s._cyclic_form) != s.size and s.parity() == 0 + assert not s.is_odd + assert s.is_even + assert Permutation([0, 1, 4, 3, 2]).parity() == 1 + assert _af_parity([0, 4, 1, 3, 2]) == 0 + assert _af_parity([0, 1, 4, 3, 2]) == 1 + + s = Permutation([0]) + + assert s.is_Singleton + assert Permutation([]).is_Empty + + r = Permutation([3, 2, 1, 0]) + assert (r**2).is_Identity + + assert rmul(~p, p).is_Identity + assert (~p)**13 == Permutation([5, 2, 0, 4, 6, 1, 3]) + assert p.max() == 6 + assert p.min() == 0 + + q = Permutation([[6], [5], [0, 1, 2, 3, 4]]) + + assert q.max() == 4 + assert q.min() == 0 + + p = Permutation([1, 5, 2, 0, 3, 6, 4]) + q = Permutation([[1, 2, 3, 5, 6], [0, 4]]) + + assert p.ascents() == [0, 3, 4] + assert q.ascents() == [1, 2, 4] + assert r.ascents() == [] + + assert p.descents() == [1, 2, 5] + assert q.descents() == [0, 3, 5] + assert Permutation(r.descents()).is_Identity + + assert p.inversions() == 7 + # test the merge-sort with a longer permutation + big = list(p) + list(range(p.max() + 1, p.max() + 130)) + assert Permutation(big).inversions() == 7 + assert p.signature() == -1 + assert q.inversions() == 11 + assert q.signature() == -1 + assert rmul(p, ~p).inversions() == 0 + assert rmul(p, ~p).signature() == 1 + + assert p.order() == 6 + assert q.order() == 10 + assert (p**(p.order())).is_Identity + + assert p.length() == 6 + assert q.length() == 7 + assert r.length() == 4 + + assert p.runs() == [[1, 5], [2], [0, 3, 6], [4]] + assert q.runs() == [[4], [2, 3, 5], [0, 6], [1]] + assert r.runs() == [[3], [2], [1], [0]] + + assert p.index() == 8 + assert q.index() == 8 + assert r.index() == 3 + + assert p.get_precedence_distance(q) == q.get_precedence_distance(p) + assert p.get_adjacency_distance(q) == p.get_adjacency_distance(q) + assert p.get_positional_distance(q) == p.get_positional_distance(q) + p = Permutation([0, 1, 2, 3]) + q = Permutation([3, 2, 1, 0]) + assert p.get_precedence_distance(q) == 6 + assert p.get_adjacency_distance(q) == 3 + assert p.get_positional_distance(q) == 8 + p = Permutation([0, 3, 1, 2, 4]) + q = Permutation.josephus(4, 5, 2) + assert p.get_adjacency_distance(q) == 3 + raises(ValueError, lambda: p.get_adjacency_distance(Permutation([]))) + raises(ValueError, lambda: p.get_positional_distance(Permutation([]))) + raises(ValueError, lambda: p.get_precedence_distance(Permutation([]))) + + a = [Permutation.unrank_nonlex(4, i) for i in range(5)] + iden = Permutation([0, 1, 2, 3]) + for i in range(5): + for j in range(i + 1, 5): + assert a[i].commutes_with(a[j]) == \ + (rmul(a[i], a[j]) == rmul(a[j], a[i])) + if a[i].commutes_with(a[j]): + assert a[i].commutator(a[j]) == iden + assert a[j].commutator(a[i]) == iden + + a = Permutation(3) + b = Permutation(0, 6, 3)(1, 2) + assert a.cycle_structure == {1: 4} + assert b.cycle_structure == {2: 1, 3: 1, 1: 2} + # issue 11130 + raises(ValueError, lambda: Permutation(3, size=3)) + raises(ValueError, lambda: Permutation([1, 2, 0, 3], size=3)) + + +def test_Permutation_subclassing(): + # Subclass that adds permutation application on iterables + class CustomPermutation(Permutation): + def __call__(self, *i): + try: + return super().__call__(*i) + except TypeError: + pass + + try: + perm_obj = i[0] + return [self._array_form[j] for j in perm_obj] + except TypeError: + raise TypeError('unrecognized argument') + + def __eq__(self, other): + if isinstance(other, Permutation): + return self._hashable_content() == other._hashable_content() + else: + return super().__eq__(other) + + def __hash__(self): + return super().__hash__() + + p = CustomPermutation([1, 2, 3, 0]) + q = Permutation([1, 2, 3, 0]) + + assert p == q + raises(TypeError, lambda: q([1, 2])) + assert [2, 3] == p([1, 2]) + + assert type(p * q) == CustomPermutation + assert type(q * p) == Permutation # True because q.__mul__(p) is called! + + # Run all tests for the Permutation class also on the subclass + def wrapped_test_Permutation(): + # Monkeypatch the class definition in the globals + globals()['__Perm'] = globals()['Permutation'] + globals()['Permutation'] = CustomPermutation + test_Permutation() + globals()['Permutation'] = globals()['__Perm'] # Restore + del globals()['__Perm'] + + wrapped_test_Permutation() + + +def test_josephus(): + assert Permutation.josephus(4, 6, 1) == Permutation([3, 1, 0, 2, 5, 4]) + assert Permutation.josephus(1, 5, 1).is_Identity + + +def test_ranking(): + assert Permutation.unrank_lex(5, 10).rank() == 10 + p = Permutation.unrank_lex(15, 225) + assert p.rank() == 225 + p1 = p.next_lex() + assert p1.rank() == 226 + assert Permutation.unrank_lex(15, 225).rank() == 225 + assert Permutation.unrank_lex(10, 0).is_Identity + p = Permutation.unrank_lex(4, 23) + assert p.rank() == 23 + assert p.array_form == [3, 2, 1, 0] + assert p.next_lex() is None + + p = Permutation([1, 5, 2, 0, 3, 6, 4]) + q = Permutation([[1, 2, 3, 5, 6], [0, 4]]) + a = [Permutation.unrank_trotterjohnson(4, i).array_form for i in range(5)] + assert a == [[0, 1, 2, 3], [0, 1, 3, 2], [0, 3, 1, 2], [3, 0, 1, + 2], [3, 0, 2, 1] ] + assert [Permutation(pa).rank_trotterjohnson() for pa in a] == list(range(5)) + assert Permutation([0, 1, 2, 3]).next_trotterjohnson() == \ + Permutation([0, 1, 3, 2]) + + assert q.rank_trotterjohnson() == 2283 + assert p.rank_trotterjohnson() == 3389 + assert Permutation([1, 0]).rank_trotterjohnson() == 1 + a = Permutation(list(range(3))) + b = a + l = [] + tj = [] + for i in range(6): + l.append(a) + tj.append(b) + a = a.next_lex() + b = b.next_trotterjohnson() + assert a == b is None + assert {tuple(a) for a in l} == {tuple(a) for a in tj} + + p = Permutation([2, 5, 1, 6, 3, 0, 4]) + q = Permutation([[6], [5], [0, 1, 2, 3, 4]]) + assert p.rank() == 1964 + assert q.rank() == 870 + assert Permutation([]).rank_nonlex() == 0 + prank = p.rank_nonlex() + assert prank == 1600 + assert Permutation.unrank_nonlex(7, 1600) == p + qrank = q.rank_nonlex() + assert qrank == 41 + assert Permutation.unrank_nonlex(7, 41) == Permutation(q.array_form) + + a = [Permutation.unrank_nonlex(4, i).array_form for i in range(24)] + assert a == [ + [1, 2, 3, 0], [3, 2, 0, 1], [1, 3, 0, 2], [1, 2, 0, 3], [2, 3, 1, 0], + [2, 0, 3, 1], [3, 0, 1, 2], [2, 0, 1, 3], [1, 3, 2, 0], [3, 0, 2, 1], + [1, 0, 3, 2], [1, 0, 2, 3], [2, 1, 3, 0], [2, 3, 0, 1], [3, 1, 0, 2], + [2, 1, 0, 3], [3, 2, 1, 0], [0, 2, 3, 1], [0, 3, 1, 2], [0, 2, 1, 3], + [3, 1, 2, 0], [0, 3, 2, 1], [0, 1, 3, 2], [0, 1, 2, 3]] + + N = 10 + p1 = Permutation(a[0]) + for i in range(1, N+1): + p1 = p1*Permutation(a[i]) + p2 = Permutation.rmul_with_af(*[Permutation(h) for h in a[N::-1]]) + assert p1 == p2 + + ok = [] + p = Permutation([1, 0]) + for i in range(3): + ok.append(p.array_form) + p = p.next_nonlex() + if p is None: + ok.append(None) + break + assert ok == [[1, 0], [0, 1], None] + assert Permutation([3, 2, 0, 1]).next_nonlex() == Permutation([1, 3, 0, 2]) + assert [Permutation(pa).rank_nonlex() for pa in a] == list(range(24)) + + +def test_mul(): + a, b = [0, 2, 1, 3], [0, 1, 3, 2] + assert _af_rmul(a, b) == [0, 2, 3, 1] + assert _af_rmuln(a, b, list(range(4))) == [0, 2, 3, 1] + assert rmul(Permutation(a), Permutation(b)).array_form == [0, 2, 3, 1] + + a = Permutation([0, 2, 1, 3]) + b = (0, 1, 3, 2) + c = (3, 1, 2, 0) + assert Permutation.rmul(a, b, c) == Permutation([1, 2, 3, 0]) + assert Permutation.rmul(a, c) == Permutation([3, 2, 1, 0]) + raises(TypeError, lambda: Permutation.rmul(b, c)) + + n = 6 + m = 8 + a = [Permutation.unrank_nonlex(n, i).array_form for i in range(m)] + h = list(range(n)) + for i in range(m): + h = _af_rmul(h, a[i]) + h2 = _af_rmuln(*a[:i + 1]) + assert h == h2 + + +def test_args(): + p = Permutation([(0, 3, 1, 2), (4, 5)]) + assert p._cyclic_form is None + assert Permutation(p) == p + assert p.cyclic_form == [[0, 3, 1, 2], [4, 5]] + assert p._array_form == [3, 2, 0, 1, 5, 4] + p = Permutation((0, 3, 1, 2)) + assert p._cyclic_form is None + assert p._array_form == [0, 3, 1, 2] + assert Permutation([0]) == Permutation((0, )) + assert Permutation([[0], [1]]) == Permutation(((0, ), (1, ))) == \ + Permutation(((0, ), [1])) + assert Permutation([[1, 2]]) == Permutation([0, 2, 1]) + assert Permutation([[1], [4, 2]]) == Permutation([0, 1, 4, 3, 2]) + assert Permutation([[1], [4, 2]], size=1) == Permutation([0, 1, 4, 3, 2]) + assert Permutation( + [[1], [4, 2]], size=6) == Permutation([0, 1, 4, 3, 2, 5]) + assert Permutation([[0, 1], [0, 2]]) == Permutation(0, 1, 2) + assert Permutation([], size=3) == Permutation([0, 1, 2]) + assert Permutation(3).list(5) == [0, 1, 2, 3, 4] + assert Permutation(3).list(-1) == [] + assert Permutation(5)(1, 2).list(-1) == [0, 2, 1] + assert Permutation(5)(1, 2).list() == [0, 2, 1, 3, 4, 5] + raises(ValueError, lambda: Permutation([1, 2], [0])) + # enclosing brackets needed + raises(ValueError, lambda: Permutation([[1, 2], 0])) + # enclosing brackets needed on 0 + raises(ValueError, lambda: Permutation([1, 1, 0])) + raises(ValueError, lambda: Permutation([4, 5], size=10)) # where are 0-3? + # but this is ok because cycles imply that only those listed moved + assert Permutation(4, 5) == Permutation([0, 1, 2, 3, 5, 4]) + + +def test_Cycle(): + assert str(Cycle()) == '()' + assert Cycle(Cycle(1,2)) == Cycle(1, 2) + assert Cycle(1,2).copy() == Cycle(1,2) + assert list(Cycle(1, 3, 2)) == [0, 3, 1, 2] + assert Cycle(1, 2)(2, 3) == Cycle(1, 3, 2) + assert Cycle(1, 2)(2, 3)(4, 5) == Cycle(1, 3, 2)(4, 5) + assert Permutation(Cycle(1, 2)(2, 1, 0, 3)).cyclic_form, Cycle(0, 2, 1) + raises(ValueError, lambda: Cycle().list()) + assert Cycle(1, 2).list() == [0, 2, 1] + assert Cycle(1, 2).list(4) == [0, 2, 1, 3] + assert Cycle(3).list(2) == [0, 1] + assert Cycle(3).list(6) == [0, 1, 2, 3, 4, 5] + assert Permutation(Cycle(1, 2), size=4) == \ + Permutation([0, 2, 1, 3]) + assert str(Cycle(1, 2)(4, 5)) == '(1 2)(4 5)' + assert str(Cycle(1, 2)) == '(1 2)' + assert Cycle(Permutation(list(range(3)))) == Cycle() + assert Cycle(1, 2).list() == [0, 2, 1] + assert Cycle(1, 2).list(4) == [0, 2, 1, 3] + assert Cycle().size == 0 + raises(ValueError, lambda: Cycle((1, 2))) + raises(ValueError, lambda: Cycle(1, 2, 1)) + raises(TypeError, lambda: Cycle(1, 2)*{}) + raises(ValueError, lambda: Cycle(4)[a]) + raises(ValueError, lambda: Cycle(2, -4, 3)) + + # check round-trip + p = Permutation([[1, 2], [4, 3]], size=5) + assert Permutation(Cycle(p)) == p + + +def test_from_sequence(): + assert Permutation.from_sequence('SymPy') == Permutation(4)(0, 1, 3) + assert Permutation.from_sequence('SymPy', key=lambda x: x.lower()) == \ + Permutation(4)(0, 2)(1, 3) + + +def test_resize(): + p = Permutation(0, 1, 2) + assert p.resize(5) == Permutation(0, 1, 2, size=5) + assert p.resize(4) == Permutation(0, 1, 2, size=4) + assert p.resize(3) == p + raises(ValueError, lambda: p.resize(2)) + + p = Permutation(0, 1, 2)(3, 4)(5, 6) + assert p.resize(3) == Permutation(0, 1, 2) + raises(ValueError, lambda: p.resize(4)) + + +def test_printing_cyclic(): + p1 = Permutation([0, 2, 1]) + assert repr(p1) == 'Permutation(1, 2)' + assert str(p1) == '(1 2)' + p2 = Permutation() + assert repr(p2) == 'Permutation()' + assert str(p2) == '()' + p3 = Permutation([1, 2, 0, 3]) + assert repr(p3) == 'Permutation(3)(0, 1, 2)' + + +def test_printing_non_cyclic(): + p1 = Permutation([0, 1, 2, 3, 4, 5]) + assert srepr(p1, perm_cyclic=False) == 'Permutation([], size=6)' + assert sstr(p1, perm_cyclic=False) == 'Permutation([], size=6)' + p2 = Permutation([0, 1, 2]) + assert srepr(p2, perm_cyclic=False) == 'Permutation([0, 1, 2])' + assert sstr(p2, perm_cyclic=False) == 'Permutation([0, 1, 2])' + + p3 = Permutation([0, 2, 1]) + assert srepr(p3, perm_cyclic=False) == 'Permutation([0, 2, 1])' + assert sstr(p3, perm_cyclic=False) == 'Permutation([0, 2, 1])' + p4 = Permutation([0, 1, 3, 2, 4, 5, 6, 7]) + assert srepr(p4, perm_cyclic=False) == 'Permutation([0, 1, 3, 2], size=8)' + + +def test_deprecated_print_cyclic(): + p = Permutation(0, 1, 2) + try: + Permutation.print_cyclic = True + with warns_deprecated_sympy(): + assert sstr(p) == '(0 1 2)' + with warns_deprecated_sympy(): + assert srepr(p) == 'Permutation(0, 1, 2)' + with warns_deprecated_sympy(): + assert pretty(p) == '(0 1 2)' + with warns_deprecated_sympy(): + assert latex(p) == r'\left( 0\; 1\; 2\right)' + + Permutation.print_cyclic = False + with warns_deprecated_sympy(): + assert sstr(p) == 'Permutation([1, 2, 0])' + with warns_deprecated_sympy(): + assert srepr(p) == 'Permutation([1, 2, 0])' + with warns_deprecated_sympy(): + assert pretty(p, use_unicode=False) == '/0 1 2\\\n\\1 2 0/' + with warns_deprecated_sympy(): + assert latex(p) == \ + r'\begin{pmatrix} 0 & 1 & 2 \\ 1 & 2 & 0 \end{pmatrix}' + finally: + Permutation.print_cyclic = None + + +def test_permutation_equality(): + a = Permutation(0, 1, 2) + b = Permutation(0, 1, 2) + assert Eq(a, b) is S.true + c = Permutation(0, 2, 1) + assert Eq(a, c) is S.false + + d = Permutation(0, 1, 2, size=4) + assert unchanged(Eq, a, d) + e = Permutation(0, 2, 1, size=4) + assert unchanged(Eq, a, e) + + i = Permutation() + assert unchanged(Eq, i, 0) + assert unchanged(Eq, 0, i) + + +def test_issue_17661(): + c1 = Cycle(1,2) + c2 = Cycle(1,2) + assert c1 == c2 + assert repr(c1) == 'Cycle(1, 2)' + assert c1 == c2 + + +def test_permutation_apply(): + x = Symbol('x') + p = Permutation(0, 1, 2) + assert p.apply(0) == 1 + assert isinstance(p.apply(0), Integer) + assert p.apply(x) == AppliedPermutation(p, x) + assert AppliedPermutation(p, x).subs(x, 0) == 1 + + x = Symbol('x', integer=False) + raises(NotImplementedError, lambda: p.apply(x)) + x = Symbol('x', negative=True) + raises(NotImplementedError, lambda: p.apply(x)) + + +def test_AppliedPermutation(): + x = Symbol('x') + p = Permutation(0, 1, 2) + raises(ValueError, lambda: AppliedPermutation((0, 1, 2), x)) + assert AppliedPermutation(p, 1, evaluate=True) == 2 + assert AppliedPermutation(p, 1, evaluate=False).__class__ == \ + AppliedPermutation diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_polyhedron.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_polyhedron.py new file mode 100644 index 0000000000000000000000000000000000000000..abf469bb560eef1f378eff4740a84b80b696035f --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_polyhedron.py @@ -0,0 +1,105 @@ +from sympy.core.symbol import symbols +from sympy.sets.sets import FiniteSet +from sympy.combinatorics.polyhedron import (Polyhedron, + tetrahedron, cube as square, octahedron, dodecahedron, icosahedron, + cube_faces) +from sympy.combinatorics.permutations import Permutation +from sympy.combinatorics.perm_groups import PermutationGroup +from sympy.testing.pytest import raises + +rmul = Permutation.rmul + + +def test_polyhedron(): + raises(ValueError, lambda: Polyhedron(list('ab'), + pgroup=[Permutation([0])])) + pgroup = [Permutation([[0, 7, 2, 5], [6, 1, 4, 3]]), + Permutation([[0, 7, 1, 6], [5, 2, 4, 3]]), + Permutation([[3, 6, 0, 5], [4, 1, 7, 2]]), + Permutation([[7, 4, 5], [1, 3, 0], [2], [6]]), + Permutation([[1, 3, 2], [7, 6, 5], [4], [0]]), + Permutation([[4, 7, 6], [2, 0, 3], [1], [5]]), + Permutation([[1, 2, 0], [4, 5, 6], [3], [7]]), + Permutation([[4, 2], [0, 6], [3, 7], [1, 5]]), + Permutation([[3, 5], [7, 1], [2, 6], [0, 4]]), + Permutation([[2, 5], [1, 6], [0, 4], [3, 7]]), + Permutation([[4, 3], [7, 0], [5, 1], [6, 2]]), + Permutation([[4, 1], [0, 5], [6, 2], [7, 3]]), + Permutation([[7, 2], [3, 6], [0, 4], [1, 5]]), + Permutation([0, 1, 2, 3, 4, 5, 6, 7])] + corners = tuple(symbols('A:H')) + faces = cube_faces + cube = Polyhedron(corners, faces, pgroup) + + assert cube.edges == FiniteSet(*( + (0, 1), (6, 7), (1, 2), (5, 6), (0, 3), (2, 3), + (4, 7), (4, 5), (3, 7), (1, 5), (0, 4), (2, 6))) + + for i in range(3): # add 180 degree face rotations + cube.rotate(cube.pgroup[i]**2) + + assert cube.corners == corners + + for i in range(3, 7): # add 240 degree axial corner rotations + cube.rotate(cube.pgroup[i]**2) + + assert cube.corners == corners + cube.rotate(1) + raises(ValueError, lambda: cube.rotate(Permutation([0, 1]))) + assert cube.corners != corners + assert cube.array_form == [7, 6, 4, 5, 3, 2, 0, 1] + assert cube.cyclic_form == [[0, 7, 1, 6], [2, 4, 3, 5]] + cube.reset() + assert cube.corners == corners + + def check(h, size, rpt, target): + + assert len(h.faces) + len(h.vertices) - len(h.edges) == 2 + assert h.size == size + + got = set() + for p in h.pgroup: + # make sure it restores original + P = h.copy() + hit = P.corners + for i in range(rpt): + P.rotate(p) + if P.corners == hit: + break + else: + print('error in permutation', p.array_form) + for i in range(rpt): + P.rotate(p) + got.add(tuple(P.corners)) + c = P.corners + f = [[c[i] for i in f] for f in P.faces] + assert h.faces == Polyhedron(c, f).faces + assert len(got) == target + assert PermutationGroup([Permutation(g) for g in got]).is_group + + for h, size, rpt, target in zip( + (tetrahedron, square, octahedron, dodecahedron, icosahedron), + (4, 8, 6, 20, 12), + (3, 4, 4, 5, 5), + (12, 24, 24, 60, 60)): + check(h, size, rpt, target) + + +def test_pgroups(): + from sympy.combinatorics.polyhedron import (cube, tetrahedron_faces, + octahedron_faces, dodecahedron_faces, icosahedron_faces) + from sympy.combinatorics.polyhedron import _pgroup_calcs + (tetrahedron2, cube2, octahedron2, dodecahedron2, icosahedron2, + tetrahedron_faces2, cube_faces2, octahedron_faces2, + dodecahedron_faces2, icosahedron_faces2) = _pgroup_calcs() + + assert tetrahedron == tetrahedron2 + assert cube == cube2 + assert octahedron == octahedron2 + assert dodecahedron == dodecahedron2 + assert icosahedron == icosahedron2 + assert sorted(map(sorted, tetrahedron_faces)) == sorted(map(sorted, tetrahedron_faces2)) + assert sorted(cube_faces) == sorted(cube_faces2) + assert sorted(octahedron_faces) == sorted(octahedron_faces2) + assert sorted(dodecahedron_faces) == sorted(dodecahedron_faces2) + assert sorted(icosahedron_faces) == sorted(icosahedron_faces2) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_prufer.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_prufer.py new file mode 100644 index 0000000000000000000000000000000000000000..b077c7cf3f023a4c36d7039505e6165ab29f275a --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_prufer.py @@ -0,0 +1,74 @@ +from sympy.combinatorics.prufer import Prufer +from sympy.testing.pytest import raises + + +def test_prufer(): + # number of nodes is optional + assert Prufer([[0, 1], [0, 2], [0, 3], [0, 4]], 5).nodes == 5 + assert Prufer([[0, 1], [0, 2], [0, 3], [0, 4]]).nodes == 5 + + a = Prufer([[0, 1], [0, 2], [0, 3], [0, 4]]) + assert a.rank == 0 + assert a.nodes == 5 + assert a.prufer_repr == [0, 0, 0] + + a = Prufer([[2, 4], [1, 4], [1, 3], [0, 5], [0, 4]]) + assert a.rank == 924 + assert a.nodes == 6 + assert a.tree_repr == [[2, 4], [1, 4], [1, 3], [0, 5], [0, 4]] + assert a.prufer_repr == [4, 1, 4, 0] + + assert Prufer.edges([0, 1, 2, 3], [1, 4, 5], [1, 4, 6]) == \ + ([[0, 1], [1, 2], [1, 4], [2, 3], [4, 5], [4, 6]], 7) + assert Prufer([0]*4).size == Prufer([6]*4).size == 1296 + + # accept iterables but convert to list of lists + tree = [(0, 1), (1, 5), (0, 3), (0, 2), (2, 6), (4, 7), (2, 4)] + tree_lists = [list(t) for t in tree] + assert Prufer(tree).tree_repr == tree_lists + assert sorted(Prufer(set(tree)).tree_repr) == sorted(tree_lists) + + raises(ValueError, lambda: Prufer([[1, 2], [3, 4]])) # 0 is missing + raises(ValueError, lambda: Prufer([[2, 3], [3, 4]])) # 0, 1 are missing + assert Prufer(*Prufer.edges([1, 2], [3, 4])).prufer_repr == [1, 3] + raises(ValueError, lambda: Prufer.edges( + [1, 3], [3, 4])) # a broken tree but edges doesn't care + raises(ValueError, lambda: Prufer.edges([1, 2], [5, 6])) + raises(ValueError, lambda: Prufer([[]])) + + a = Prufer([[0, 1], [0, 2], [0, 3]]) + b = a.next() + assert b.tree_repr == [[0, 2], [0, 1], [1, 3]] + assert b.rank == 1 + + +def test_round_trip(): + def doit(t, b): + e, n = Prufer.edges(*t) + t = Prufer(e, n) + a = sorted(t.tree_repr) + b = [i - 1 for i in b] + assert t.prufer_repr == b + assert sorted(Prufer(b).tree_repr) == a + assert Prufer.unrank(t.rank, n).prufer_repr == b + + doit([[1, 2]], []) + doit([[2, 1, 3]], [1]) + doit([[1, 3, 2]], [3]) + doit([[1, 2, 3]], [2]) + doit([[2, 1, 4], [1, 3]], [1, 1]) + doit([[3, 2, 1, 4]], [2, 1]) + doit([[3, 2, 1], [2, 4]], [2, 2]) + doit([[1, 3, 2, 4]], [3, 2]) + doit([[1, 4, 2, 3]], [4, 2]) + doit([[3, 1, 4, 2]], [4, 1]) + doit([[4, 2, 1, 3]], [1, 2]) + doit([[1, 2, 4, 3]], [2, 4]) + doit([[1, 3, 4, 2]], [3, 4]) + doit([[2, 4, 1], [4, 3]], [4, 4]) + doit([[1, 2, 3, 4]], [2, 3]) + doit([[2, 3, 1], [3, 4]], [3, 3]) + doit([[1, 4, 3, 2]], [4, 3]) + doit([[2, 1, 4, 3]], [1, 4]) + doit([[2, 1, 3, 4]], [1, 3]) + doit([[6, 2, 1, 4], [1, 3, 5, 8], [3, 7]], [1, 2, 1, 3, 3, 5]) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_rewriting.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_rewriting.py new file mode 100644 index 0000000000000000000000000000000000000000..97c562bd57a2cd6318fa1dcb13c6f6278c861cca --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_rewriting.py @@ -0,0 +1,49 @@ +from sympy.combinatorics.fp_groups import FpGroup +from sympy.combinatorics.free_groups import free_group +from sympy.testing.pytest import raises + + +def test_rewriting(): + F, a, b = free_group("a, b") + G = FpGroup(F, [a*b*a**-1*b**-1]) + a, b = G.generators + R = G._rewriting_system + assert R.is_confluent + + assert G.reduce(b**-1*a) == a*b**-1 + assert G.reduce(b**3*a**4*b**-2*a) == a**5*b + assert G.equals(b**2*a**-1*b, b**4*a**-1*b**-1) + + assert R.reduce_using_automaton(b*a*a**2*b**-1) == a**3 + assert R.reduce_using_automaton(b**3*a**4*b**-2*a) == a**5*b + assert R.reduce_using_automaton(b**-1*a) == a*b**-1 + + G = FpGroup(F, [a**3, b**3, (a*b)**2]) + R = G._rewriting_system + R.make_confluent() + # R._is_confluent should be set to True after + # a successful run of make_confluent + assert R.is_confluent + # but also the system should actually be confluent + assert R._check_confluence() + assert G.reduce(b*a**-1*b**-1*a**3*b**4*a**-1*b**-15) == a**-1*b**-1 + # check for automaton reduction + assert R.reduce_using_automaton(b*a**-1*b**-1*a**3*b**4*a**-1*b**-15) == a**-1*b**-1 + + G = FpGroup(F, [a**2, b**3, (a*b)**4]) + R = G._rewriting_system + assert G.reduce(a**2*b**-2*a**2*b) == b**-1 + assert R.reduce_using_automaton(a**2*b**-2*a**2*b) == b**-1 + assert G.reduce(a**3*b**-2*a**2*b) == a**-1*b**-1 + assert R.reduce_using_automaton(a**3*b**-2*a**2*b) == a**-1*b**-1 + # Check after adding a rule + R.add_rule(a**2, b) + assert R.reduce_using_automaton(a**2*b**-2*a**2*b) == b**-1 + assert R.reduce_using_automaton(a**4*b**-2*a**2*b**3) == b + + R.set_max(15) + raises(RuntimeError, lambda: R.add_rule(a**-3, b)) + R.set_max(20) + R.add_rule(a**-3, b) + + assert R.add_rule(a, a) == set() diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_schur_number.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_schur_number.py new file mode 100644 index 0000000000000000000000000000000000000000..e6beb9b11fa993a99b71d89b8485050fc3575b8e --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_schur_number.py @@ -0,0 +1,55 @@ +from sympy.core import S, Rational +from sympy.combinatorics.schur_number import schur_partition, SchurNumber +from sympy.core.random import _randint +from sympy.testing.pytest import raises +from sympy.core.symbol import symbols + + +def _sum_free_test(subset): + """ + Checks if subset is sum-free(There are no x,y,z in the subset such that + x + y = z) + """ + for i in subset: + for j in subset: + assert (i + j in subset) is False + + +def test_schur_partition(): + raises(ValueError, lambda: schur_partition(S.Infinity)) + raises(ValueError, lambda: schur_partition(-1)) + raises(ValueError, lambda: schur_partition(0)) + assert schur_partition(2) == [[1, 2]] + + random_number_generator = _randint(1000) + for _ in range(5): + n = random_number_generator(1, 1000) + result = schur_partition(n) + t = 0 + numbers = [] + for item in result: + _sum_free_test(item) + """ + Checks if the occurrence of all numbers is exactly one + """ + t += len(item) + for l in item: + assert (l in numbers) is False + numbers.append(l) + assert n == t + + x = symbols("x") + raises(ValueError, lambda: schur_partition(x)) + +def test_schur_number(): + first_known_schur_numbers = {1: 1, 2: 4, 3: 13, 4: 44, 5: 160} + for k in first_known_schur_numbers: + assert SchurNumber(k) == first_known_schur_numbers[k] + + assert SchurNumber(S.Infinity) == S.Infinity + assert SchurNumber(0) == 0 + raises(ValueError, lambda: SchurNumber(0.5)) + + n = symbols("n") + assert SchurNumber(n).lower_bound() == 3**n/2 - Rational(1, 2) + assert SchurNumber(8).lower_bound() == 5039 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_subsets.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_subsets.py new file mode 100644 index 0000000000000000000000000000000000000000..1d50076da1c685294c2d2561dcc2a6af629eaf83 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_subsets.py @@ -0,0 +1,63 @@ +from sympy.combinatorics.subsets import Subset, ksubsets +from sympy.testing.pytest import raises + + +def test_subset(): + a = Subset(['c', 'd'], ['a', 'b', 'c', 'd']) + assert a.next_binary() == Subset(['b'], ['a', 'b', 'c', 'd']) + assert a.prev_binary() == Subset(['c'], ['a', 'b', 'c', 'd']) + assert a.next_lexicographic() == Subset(['d'], ['a', 'b', 'c', 'd']) + assert a.prev_lexicographic() == Subset(['c'], ['a', 'b', 'c', 'd']) + assert a.next_gray() == Subset(['c'], ['a', 'b', 'c', 'd']) + assert a.prev_gray() == Subset(['d'], ['a', 'b', 'c', 'd']) + assert a.rank_binary == 3 + assert a.rank_lexicographic == 14 + assert a.rank_gray == 2 + assert a.cardinality == 16 + assert a.size == 2 + assert Subset.bitlist_from_subset(a, ['a', 'b', 'c', 'd']) == '0011' + + a = Subset([2, 5, 7], [1, 2, 3, 4, 5, 6, 7]) + assert a.next_binary() == Subset([2, 5, 6], [1, 2, 3, 4, 5, 6, 7]) + assert a.prev_binary() == Subset([2, 5], [1, 2, 3, 4, 5, 6, 7]) + assert a.next_lexicographic() == Subset([2, 6], [1, 2, 3, 4, 5, 6, 7]) + assert a.prev_lexicographic() == Subset([2, 5, 6, 7], [1, 2, 3, 4, 5, 6, 7]) + assert a.next_gray() == Subset([2, 5, 6, 7], [1, 2, 3, 4, 5, 6, 7]) + assert a.prev_gray() == Subset([2, 5], [1, 2, 3, 4, 5, 6, 7]) + assert a.rank_binary == 37 + assert a.rank_lexicographic == 93 + assert a.rank_gray == 57 + assert a.cardinality == 128 + + superset = ['a', 'b', 'c', 'd'] + assert Subset.unrank_binary(4, superset).rank_binary == 4 + assert Subset.unrank_gray(10, superset).rank_gray == 10 + + superset = [1, 2, 3, 4, 5, 6, 7, 8, 9] + assert Subset.unrank_binary(33, superset).rank_binary == 33 + assert Subset.unrank_gray(25, superset).rank_gray == 25 + + a = Subset([], ['a', 'b', 'c', 'd']) + i = 1 + while a.subset != Subset(['d'], ['a', 'b', 'c', 'd']).subset: + a = a.next_lexicographic() + i = i + 1 + assert i == 16 + + i = 1 + while a.subset != Subset([], ['a', 'b', 'c', 'd']).subset: + a = a.prev_lexicographic() + i = i + 1 + assert i == 16 + + raises(ValueError, lambda: Subset(['a', 'b'], ['a'])) + raises(ValueError, lambda: Subset(['a'], ['b', 'c'])) + raises(ValueError, lambda: Subset.subset_from_bitlist(['a', 'b'], '010')) + + assert Subset(['a'], ['a', 'b']) != Subset(['b'], ['a', 'b']) + assert Subset(['a'], ['a', 'b']) != Subset(['a'], ['a', 'c']) + +def test_ksubsets(): + assert list(ksubsets([1, 2, 3], 2)) == [(1, 2), (1, 3), (2, 3)] + assert list(ksubsets([1, 2, 3, 4, 5], 2)) == [(1, 2), (1, 3), (1, 4), + (1, 5), (2, 3), (2, 4), (2, 5), (3, 4), (3, 5), (4, 5)] diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_tensor_can.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_tensor_can.py new file mode 100644 index 0000000000000000000000000000000000000000..3922419f20b92536426bfaae4b7e94df5db671b5 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_tensor_can.py @@ -0,0 +1,560 @@ +from sympy.combinatorics.permutations import Permutation, Perm +from sympy.combinatorics.tensor_can import (perm_af_direct_product, dummy_sgs, + riemann_bsgs, get_symmetric_group_sgs, canonicalize, bsgs_direct_product) +from sympy.combinatorics.testutil import canonicalize_naive, graph_certificate +from sympy.testing.pytest import skip, XFAIL + +def test_perm_af_direct_product(): + gens1 = [[1,0,2,3], [0,1,3,2]] + gens2 = [[1,0]] + assert perm_af_direct_product(gens1, gens2, 0) == [[1, 0, 2, 3, 4, 5], [0, 1, 3, 2, 4, 5], [0, 1, 2, 3, 5, 4]] + gens1 = [[1,0,2,3,5,4], [0,1,3,2,4,5]] + gens2 = [[1,0,2,3]] + assert [[1, 0, 2, 3, 4, 5, 7, 6], [0, 1, 3, 2, 4, 5, 6, 7], [0, 1, 2, 3, 5, 4, 6, 7]] + +def test_dummy_sgs(): + a = dummy_sgs([1,2], 0, 4) + assert a == [[0,2,1,3,4,5]] + a = dummy_sgs([2,3,4,5], 0, 8) + assert a == [x._array_form for x in [Perm(9)(2,3), Perm(9)(4,5), + Perm(9)(2,4)(3,5)]] + + a = dummy_sgs([2,3,4,5], 1, 8) + assert a == [x._array_form for x in [Perm(2,3)(8,9), Perm(4,5)(8,9), + Perm(9)(2,4)(3,5)]] + +def test_get_symmetric_group_sgs(): + assert get_symmetric_group_sgs(2) == ([0], [Permutation(3)(0,1)]) + assert get_symmetric_group_sgs(2, 1) == ([0], [Permutation(0,1)(2,3)]) + assert get_symmetric_group_sgs(3) == ([0,1], [Permutation(4)(0,1), Permutation(4)(1,2)]) + assert get_symmetric_group_sgs(3, 1) == ([0,1], [Permutation(0,1)(3,4), Permutation(1,2)(3,4)]) + assert get_symmetric_group_sgs(4) == ([0,1,2], [Permutation(5)(0,1), Permutation(5)(1,2), Permutation(5)(2,3)]) + assert get_symmetric_group_sgs(4, 1) == ([0,1,2], [Permutation(0,1)(4,5), Permutation(1,2)(4,5), Permutation(2,3)(4,5)]) + + +def test_canonicalize_no_slot_sym(): + # cases in which there is no slot symmetry after fixing the + # free indices; here and in the following if the symmetry of the + # metric is not specified, it is assumed to be symmetric. + # If it is not specified, tensors are commuting. + + # A_d0 * B^d0; g = [1,0, 2,3]; T_c = A^d0*B_d0; can = [0,1,2,3] + base1, gens1 = get_symmetric_group_sgs(1) + dummies = [0, 1] + g = Permutation([1,0,2,3]) + can = canonicalize(g, dummies, 0, (base1,gens1,1,0), (base1,gens1,1,0)) + assert can == [0,1,2,3] + # equivalently + can = canonicalize(g, dummies, 0, (base1, gens1, 2, None)) + assert can == [0,1,2,3] + + # with antisymmetric metric; T_c = -A^d0*B_d0; can = [0,1,3,2] + can = canonicalize(g, dummies, 1, (base1,gens1,1,0), (base1,gens1,1,0)) + assert can == [0,1,3,2] + + # A^a * B^b; ord = [a,b]; g = [0,1,2,3]; can = g + g = Permutation([0,1,2,3]) + dummies = [] + t0 = t1 = (base1, gens1, 1, 0) + can = canonicalize(g, dummies, 0, t0, t1) + assert can == [0,1,2,3] + # B^b * A^a + g = Permutation([1,0,2,3]) + can = canonicalize(g, dummies, 0, t0, t1) + assert can == [1,0,2,3] + + # A symmetric + # A^{b}_{d0}*A^{d0, a} order a,b,d0,-d0; T_c = A^{a d0}*A{b}_{d0} + # g = [1,3,2,0,4,5]; can = [0,2,1,3,4,5] + base2, gens2 = get_symmetric_group_sgs(2) + dummies = [2,3] + g = Permutation([1,3,2,0,4,5]) + can = canonicalize(g, dummies, 0, (base2, gens2, 2, 0)) + assert can == [0, 2, 1, 3, 4, 5] + # with antisymmetric metric + can = canonicalize(g, dummies, 1, (base2, gens2, 2, 0)) + assert can == [0, 2, 1, 3, 4, 5] + # A^{a}_{d0}*A^{d0, b} + g = Permutation([0,3,2,1,4,5]) + can = canonicalize(g, dummies, 1, (base2, gens2, 2, 0)) + assert can == [0, 2, 1, 3, 5, 4] + + # A, B symmetric + # A^b_d0*B^{d0,a}; g=[1,3,2,0,4,5] + # T_c = A^{b,d0}*B_{a,d0}; can = [1,2,0,3,4,5] + dummies = [2,3] + g = Permutation([1,3,2,0,4,5]) + can = canonicalize(g, dummies, 0, (base2,gens2,1,0), (base2,gens2,1,0)) + assert can == [1,2,0,3,4,5] + # same with antisymmetric metric + can = canonicalize(g, dummies, 1, (base2,gens2,1,0), (base2,gens2,1,0)) + assert can == [1,2,0,3,5,4] + + # A^{d1}_{d0}*B^d0*C_d1 ord=[d0,-d0,d1,-d1]; g = [2,1,0,3,4,5] + # T_c = A^{d0 d1}*B_d0*C_d1; can = [0,2,1,3,4,5] + base1, gens1 = get_symmetric_group_sgs(1) + base2, gens2 = get_symmetric_group_sgs(2) + g = Permutation([2,1,0,3,4,5]) + dummies = [0,1,2,3] + t0 = (base2, gens2, 1, 0) + t1 = t2 = (base1, gens1, 1, 0) + can = canonicalize(g, dummies, 0, t0, t1, t2) + assert can == [0, 2, 1, 3, 4, 5] + + # A without symmetry + # A^{d1}_{d0}*B^d0*C_d1 ord=[d0,-d0,d1,-d1]; g = [2,1,0,3,4,5] + # T_c = A^{d0 d1}*B_d1*C_d0; can = [0,2,3,1,4,5] + g = Permutation([2,1,0,3,4,5]) + dummies = [0,1,2,3] + t0 = ([], [Permutation(list(range(4)))], 1, 0) + can = canonicalize(g, dummies, 0, t0, t1, t2) + assert can == [0,2,3,1,4,5] + # A, B without symmetry + # A^{d1}_{d0}*B_{d1}^{d0}; g = [2,1,3,0,4,5] + # T_c = A^{d0 d1}*B_{d0 d1}; can = [0,2,1,3,4,5] + t0 = t1 = ([], [Permutation(list(range(4)))], 1, 0) + dummies = [0,1,2,3] + g = Permutation([2,1,3,0,4,5]) + can = canonicalize(g, dummies, 0, t0, t1) + assert can == [0, 2, 1, 3, 4, 5] + # A_{d0}^{d1}*B_{d1}^{d0}; g = [1,2,3,0,4,5] + # T_c = A^{d0 d1}*B_{d1 d0}; can = [0,2,3,1,4,5] + g = Permutation([1,2,3,0,4,5]) + can = canonicalize(g, dummies, 0, t0, t1) + assert can == [0,2,3,1,4,5] + + # A, B, C without symmetry + # A^{d1 d0}*B_{a d0}*C_{d1 b} ord=[a,b,d0,-d0,d1,-d1] + # g=[4,2,0,3,5,1,6,7] + # T_c=A^{d0 d1}*B_{a d1}*C_{d0 b}; can = [2,4,0,5,3,1,6,7] + t0 = t1 = t2 = ([], [Permutation(list(range(4)))], 1, 0) + dummies = [2,3,4,5] + g = Permutation([4,2,0,3,5,1,6,7]) + can = canonicalize(g, dummies, 0, t0, t1, t2) + assert can == [2,4,0,5,3,1,6,7] + + # A symmetric, B and C without symmetry + # A^{d1 d0}*B_{a d0}*C_{d1 b} ord=[a,b,d0,-d0,d1,-d1] + # g=[4,2,0,3,5,1,6,7] + # T_c = A^{d0 d1}*B_{a d0}*C_{d1 b}; can = [2,4,0,3,5,1,6,7] + t0 = (base2,gens2,1,0) + t1 = t2 = ([], [Permutation(list(range(4)))], 1, 0) + dummies = [2,3,4,5] + g = Permutation([4,2,0,3,5,1,6,7]) + can = canonicalize(g, dummies, 0, t0, t1, t2) + assert can == [2,4,0,3,5,1,6,7] + + # A and C symmetric, B without symmetry + # A^{d1 d0}*B_{a d0}*C_{d1 b} ord=[a,b,d0,-d0,d1,-d1] + # g=[4,2,0,3,5,1,6,7] + # T_c = A^{d0 d1}*B_{a d0}*C_{b d1}; can = [2,4,0,3,1,5,6,7] + t0 = t2 = (base2,gens2,1,0) + t1 = ([], [Permutation(list(range(4)))], 1, 0) + dummies = [2,3,4,5] + g = Permutation([4,2,0,3,5,1,6,7]) + can = canonicalize(g, dummies, 0, t0, t1, t2) + assert can == [2,4,0,3,1,5,6,7] + + # A symmetric, B without symmetry, C antisymmetric + # A^{d1 d0}*B_{a d0}*C_{d1 b} ord=[a,b,d0,-d0,d1,-d1] + # g=[4,2,0,3,5,1,6,7] + # T_c = -A^{d0 d1}*B_{a d0}*C_{b d1}; can = [2,4,0,3,1,5,7,6] + t0 = (base2,gens2, 1, 0) + t1 = ([], [Permutation(list(range(4)))], 1, 0) + base2a, gens2a = get_symmetric_group_sgs(2, 1) + t2 = (base2a, gens2a, 1, 0) + dummies = [2,3,4,5] + g = Permutation([4,2,0,3,5,1,6,7]) + can = canonicalize(g, dummies, 0, t0, t1, t2) + assert can == [2,4,0,3,1,5,7,6] + + +def test_canonicalize_no_dummies(): + base1, gens1 = get_symmetric_group_sgs(1) + base2, gens2 = get_symmetric_group_sgs(2) + base2a, gens2a = get_symmetric_group_sgs(2, 1) + + # A commuting + # A^c A^b A^a; ord = [a,b,c]; g = [2,1,0,3,4] + # T_c = A^a A^b A^c; can = list(range(5)) + g = Permutation([2,1,0,3,4]) + can = canonicalize(g, [], 0, (base1, gens1, 3, 0)) + assert can == list(range(5)) + + # A anticommuting + # A^c A^b A^a; ord = [a,b,c]; g = [2,1,0,3,4] + # T_c = -A^a A^b A^c; can = [0,1,2,4,3] + g = Permutation([2,1,0,3,4]) + can = canonicalize(g, [], 0, (base1, gens1, 3, 1)) + assert can == [0,1,2,4,3] + + # A commuting and symmetric + # A^{b,d}*A^{c,a}; ord = [a,b,c,d]; g = [1,3,2,0,4,5] + # T_c = A^{a c}*A^{b d}; can = [0,2,1,3,4,5] + g = Permutation([1,3,2,0,4,5]) + can = canonicalize(g, [], 0, (base2, gens2, 2, 0)) + assert can == [0,2,1,3,4,5] + + # A anticommuting and symmetric + # A^{b,d}*A^{c,a}; ord = [a,b,c,d]; g = [1,3,2,0,4,5] + # T_c = -A^{a c}*A^{b d}; can = [0,2,1,3,5,4] + g = Permutation([1,3,2,0,4,5]) + can = canonicalize(g, [], 0, (base2, gens2, 2, 1)) + assert can == [0,2,1,3,5,4] + # A^{c,a}*A^{b,d} ; g = [2,0,1,3,4,5] + # T_c = A^{a c}*A^{b d}; can = [0,2,1,3,4,5] + g = Permutation([2,0,1,3,4,5]) + can = canonicalize(g, [], 0, (base2, gens2, 2, 1)) + assert can == [0,2,1,3,4,5] + +def test_no_metric_symmetry(): + # no metric symmetry + # A^d1_d0 * A^d0_d1; ord = [d0,-d0,d1,-d1]; g= [2,1,0,3,4,5] + # T_c = A^d0_d1 * A^d1_d0; can = [0,3,2,1,4,5] + g = Permutation([2,1,0,3,4,5]) + can = canonicalize(g, list(range(4)), None, [[], [Permutation(list(range(4)))], 2, 0]) + assert can == [0,3,2,1,4,5] + + # A^d1_d2 * A^d0_d3 * A^d2_d1 * A^d3_d0 + # ord = [d0,-d0,d1,-d1,d2,-d2,d3,-d3] + # 0 1 2 3 4 5 6 7 + # g = [2,5,0,7,4,3,6,1,8,9] + # T_c = A^d0_d1 * A^d1_d0 * A^d2_d3 * A^d3_d2 + # can = [0,3,2,1,4,7,6,5,8,9] + g = Permutation([2,5,0,7,4,3,6,1,8,9]) + #can = canonicalize(g, list(range(8)), 0, [[], [list(range(4))], 4, 0]) + #assert can == [0, 2, 3, 1, 4, 6, 7, 5, 8, 9] + can = canonicalize(g, list(range(8)), None, [[], [Permutation(list(range(4)))], 4, 0]) + assert can == [0, 3, 2, 1, 4, 7, 6, 5, 8, 9] + + # A^d0_d2 * A^d1_d3 * A^d3_d0 * A^d2_d1 + # g = [0,5,2,7,6,1,4,3,8,9] + # T_c = A^d0_d1 * A^d1_d2 * A^d2_d3 * A^d3_d0 + # can = [0,3,2,5,4,7,6,1,8,9] + g = Permutation([0,5,2,7,6,1,4,3,8,9]) + can = canonicalize(g, list(range(8)), None, [[], [Permutation(list(range(4)))], 4, 0]) + assert can == [0,3,2,5,4,7,6,1,8,9] + + g = Permutation([12,7,10,3,14,13,4,11,6,1,2,9,0,15,8,5,16,17]) + can = canonicalize(g, list(range(16)), None, [[], [Permutation(list(range(4)))], 8, 0]) + assert can == [0,3,2,5,4,7,6,1,8,11,10,13,12,15,14,9,16,17] + +def test_canonical_free(): + # t = A^{d0 a1}*A_d0^a0 + # ord = [a0,a1,d0,-d0]; g = [2,1,3,0,4,5]; dummies = [[2,3]] + # t_c = A_d0^a0*A^{d0 a1} + # can = [3,0, 2,1, 4,5] + g = Permutation([2,1,3,0,4,5]) + dummies = [[2,3]] + can = canonicalize(g, dummies, [None], ([], [Permutation(3)], 2, 0)) + assert can == [3,0, 2,1, 4,5] + +def test_canonicalize1(): + base1, gens1 = get_symmetric_group_sgs(1) + base1a, gens1a = get_symmetric_group_sgs(1, 1) + base2, gens2 = get_symmetric_group_sgs(2) + base3, gens3 = get_symmetric_group_sgs(3) + base2a, gens2a = get_symmetric_group_sgs(2, 1) + base3a, gens3a = get_symmetric_group_sgs(3, 1) + + # A_d0*A^d0; ord = [d0,-d0]; g = [1,0,2,3] + # T_c = A^d0*A_d0; can = [0,1,2,3] + g = Permutation([1,0,2,3]) + can = canonicalize(g, [0, 1], 0, (base1, gens1, 2, 0)) + assert can == list(range(4)) + + # A commuting + # A_d0*A_d1*A_d2*A^d2*A^d1*A^d0; ord=[d0,-d0,d1,-d1,d2,-d2] + # g = [1,3,5,4,2,0,6,7] + # T_c = A^d0*A_d0*A^d1*A_d1*A^d2*A_d2; can = list(range(8)) + g = Permutation([1,3,5,4,2,0,6,7]) + can = canonicalize(g, list(range(6)), 0, (base1, gens1, 6, 0)) + assert can == list(range(8)) + + # A anticommuting + # A_d0*A_d1*A_d2*A^d2*A^d1*A^d0; ord=[d0,-d0,d1,-d1,d2,-d2] + # g = [1,3,5,4,2,0,6,7] + # T_c 0; can = 0 + g = Permutation([1,3,5,4,2,0,6,7]) + can = canonicalize(g, list(range(6)), 0, (base1, gens1, 6, 1)) + assert can == 0 + can1 = canonicalize_naive(g, list(range(6)), 0, (base1, gens1, 6, 1)) + assert can1 == 0 + + # A commuting symmetric + # A^{d0 b}*A^a_d1*A^d1_d0; ord=[a,b,d0,-d0,d1,-d1] + # g = [2,1,0,5,4,3,6,7] + # T_c = A^{a d0}*A^{b d1}*A_{d0 d1}; can = [0,2,1,4,3,5,6,7] + g = Permutation([2,1,0,5,4,3,6,7]) + can = canonicalize(g, list(range(2,6)), 0, (base2, gens2, 3, 0)) + assert can == [0,2,1,4,3,5,6,7] + + # A, B commuting symmetric + # A^{d0 b}*A^d1_d0*B^a_d1; ord=[a,b,d0,-d0,d1,-d1] + # g = [2,1,4,3,0,5,6,7] + # T_c = A^{b d0}*A_d0^d1*B^a_d1; can = [1,2,3,4,0,5,6,7] + g = Permutation([2,1,4,3,0,5,6,7]) + can = canonicalize(g, list(range(2,6)), 0, (base2,gens2,2,0), (base2,gens2,1,0)) + assert can == [1,2,3,4,0,5,6,7] + + # A commuting symmetric + # A^{d1 d0 b}*A^{a}_{d1 d0}; ord=[a,b, d0,-d0,d1,-d1] + # g = [4,2,1,0,5,3,6,7] + # T_c = A^{a d0 d1}*A^{b}_{d0 d1}; can = [0,2,4,1,3,5,6,7] + g = Permutation([4,2,1,0,5,3,6,7]) + can = canonicalize(g, list(range(2,6)), 0, (base3, gens3, 2, 0)) + assert can == [0,2,4,1,3,5,6,7] + + + # A^{d3 d0 d2}*A^a0_{d1 d2}*A^d1_d3^a1*A^{a2 a3}_d0 + # ord = [a0,a1,a2,a3,d0,-d0,d1,-d1,d2,-d2,d3,-d3] + # 0 1 2 3 4 5 6 7 8 9 10 11 + # g = [10,4,8, 0,7,9, 6,11,1, 2,3,5, 12,13] + # T_c = A^{a0 d0 d1}*A^a1_d0^d2*A^{a2 a3 d3}*A_{d1 d2 d3} + # can = [0,4,6, 1,5,8, 2,3,10, 7,9,11, 12,13] + g = Permutation([10,4,8, 0,7,9, 6,11,1, 2,3,5, 12,13]) + can = canonicalize(g, list(range(4,12)), 0, (base3, gens3, 4, 0)) + assert can == [0,4,6, 1,5,8, 2,3,10, 7,9,11, 12,13] + + # A commuting symmetric, B antisymmetric + # A^{d0 d1 d2} * A_{d2 d3 d1} * B_d0^d3 + # ord = [d0,-d0,d1,-d1,d2,-d2,d3,-d3] + # g = [0,2,4,5,7,3,1,6,8,9] + # in this esxample and in the next three, + # renaming dummy indices and using symmetry of A, + # T = A^{d0 d1 d2} * A_{d0 d1 d3} * B_d2^d3 + # can = 0 + g = Permutation([0,2,4,5,7,3,1,6,8,9]) + can = canonicalize(g, list(range(8)), 0, (base3, gens3,2,0), (base2a,gens2a,1,0)) + assert can == 0 + # A anticommuting symmetric, B anticommuting + # A^{d0 d1 d2} * A_{d2 d3 d1} * B_d0^d3 + # T_c = A^{d0 d1 d2} * A_{d0 d1}^d3 * B_{d2 d3} + # can = [0,2,4, 1,3,6, 5,7, 8,9] + can = canonicalize(g, list(range(8)), 0, (base3, gens3,2,1), (base2a,gens2a,1,0)) + assert can == [0,2,4, 1,3,6, 5,7, 8,9] + # A anticommuting symmetric, B antisymmetric commuting, antisymmetric metric + # A^{d0 d1 d2} * A_{d2 d3 d1} * B_d0^d3 + # T_c = -A^{d0 d1 d2} * A_{d0 d1}^d3 * B_{d2 d3} + # can = [0,2,4, 1,3,6, 5,7, 9,8] + can = canonicalize(g, list(range(8)), 1, (base3, gens3,2,1), (base2a,gens2a,1,0)) + assert can == [0,2,4, 1,3,6, 5,7, 9,8] + + # A anticommuting symmetric, B anticommuting anticommuting, + # no metric symmetry + # A^{d0 d1 d2} * A_{d2 d3 d1} * B_d0^d3 + # T_c = A^{d0 d1 d2} * A_{d0 d1 d3} * B_d2^d3 + # can = [0,2,4, 1,3,7, 5,6, 8,9] + can = canonicalize(g, list(range(8)), None, (base3, gens3,2,1), (base2a,gens2a,1,0)) + assert can == [0,2,4,1,3,7,5,6,8,9] + + # Gamma anticommuting + # Gamma_{mu nu} * gamma^rho * Gamma^{nu mu alpha} + # ord = [alpha, rho, mu,-mu,nu,-nu] + # g = [3,5,1,4,2,0,6,7] + # T_c = -Gamma^{mu nu} * gamma^rho * Gamma_{alpha mu nu} + # can = [2,4,1,0,3,5,7,6]] + g = Permutation([3,5,1,4,2,0,6,7]) + t0 = (base2a, gens2a, 1, None) + t1 = (base1, gens1, 1, None) + t2 = (base3a, gens3a, 1, None) + can = canonicalize(g, list(range(2, 6)), 0, t0, t1, t2) + assert can == [2,4,1,0,3,5,7,6] + + # Gamma_{mu nu} * Gamma^{gamma beta} * gamma_rho * Gamma^{nu mu alpha} + # ord = [alpha, beta, gamma, -rho, mu,-mu,nu,-nu] + # 0 1 2 3 4 5 6 7 + # g = [5,7,2,1,3,6,4,0,8,9] + # T_c = Gamma^{mu nu} * Gamma^{beta gamma} * gamma_rho * Gamma^alpha_{mu nu} # can = [4,6,1,2,3,0,5,7,8,9] + t0 = (base2a, gens2a, 2, None) + g = Permutation([5,7,2,1,3,6,4,0,8,9]) + can = canonicalize(g, list(range(4, 8)), 0, t0, t1, t2) + assert can == [4,6,1,2,3,0,5,7,8,9] + + # f^a_{b,c} antisymmetric in b,c; A_mu^a no symmetry + # f^c_{d a} * f_{c e b} * A_mu^d * A_nu^a * A^{nu e} * A^{mu b} + # ord = [mu,-mu,nu,-nu,a,-a,b,-b,c,-c,d,-d, e, -e] + # 0 1 2 3 4 5 6 7 8 9 10 11 12 13 + # g = [8,11,5, 9,13,7, 1,10, 3,4, 2,12, 0,6, 14,15] + # T_c = -f^{a b c} * f_a^{d e} * A^mu_b * A_{mu d} * A^nu_c * A_{nu e} + # can = [4,6,8, 5,10,12, 0,7, 1,11, 2,9, 3,13, 15,14] + g = Permutation([8,11,5, 9,13,7, 1,10, 3,4, 2,12, 0,6, 14,15]) + base_f, gens_f = bsgs_direct_product(base1, gens1, base2a, gens2a) + base_A, gens_A = bsgs_direct_product(base1, gens1, base1, gens1) + t0 = (base_f, gens_f, 2, 0) + t1 = (base_A, gens_A, 4, 0) + can = canonicalize(g, [list(range(4)), list(range(4, 14))], [0, 0], t0, t1) + assert can == [4,6,8, 5,10,12, 0,7, 1,11, 2,9, 3,13, 15,14] + + +def test_riemann_invariants(): + baser, gensr = riemann_bsgs + # R^{d0 d1}_{d1 d0}; ord = [d0,-d0,d1,-d1]; g = [0,2,3,1,4,5] + # T_c = -R^{d0 d1}_{d0 d1}; can = [0,2,1,3,5,4] + g = Permutation([0,2,3,1,4,5]) + can = canonicalize(g, list(range(2, 4)), 0, (baser, gensr, 1, 0)) + assert can == [0,2,1,3,5,4] + # use a non minimal BSGS + can = canonicalize(g, list(range(2, 4)), 0, ([2, 0], [Permutation([1,0,2,3,5,4]), Permutation([2,3,0,1,4,5])], 1, 0)) + assert can == [0,2,1,3,5,4] + + """ + The following tests in test_riemann_invariants and in + test_riemann_invariants1 have been checked using xperm.c from XPerm in + in [1] and with an older version contained in [2] + + [1] xperm.c part of xPerm written by J. M. Martin-Garcia + http://www.xact.es/index.html + [2] test_xperm.cc in cadabra by Kasper Peeters, http://cadabra.phi-sci.com/ + """ + # R_d11^d1_d0^d5 * R^{d6 d4 d0}_d5 * R_{d7 d2 d8 d9} * + # R_{d10 d3 d6 d4} * R^{d2 d7 d11}_d1 * R^{d8 d9 d3 d10} + # ord: contravariant d_k ->2*k, covariant d_k -> 2*k+1 + # T_c = R^{d0 d1 d2 d3} * R_{d0 d1}^{d4 d5} * R_{d2 d3}^{d6 d7} * + # R_{d4 d5}^{d8 d9} * R_{d6 d7}^{d10 d11} * R_{d8 d9 d10 d11} + g = Permutation([23,2,1,10,12,8,0,11,15,5,17,19,21,7,13,9,4,14,22,3,16,18,6,20,24,25]) + can = canonicalize(g, list(range(24)), 0, (baser, gensr, 6, 0)) + assert can == [0,2,4,6,1,3,8,10,5,7,12,14,9,11,16,18,13,15,20,22,17,19,21,23,24,25] + + # use a non minimal BSGS + can = canonicalize(g, list(range(24)), 0, ([2, 0], [Permutation([1,0,2,3,5,4]), Permutation([2,3,0,1,4,5])], 6, 0)) + assert can == [0,2,4,6,1,3,8,10,5,7,12,14,9,11,16,18,13,15,20,22,17,19,21,23,24,25] + + g = Permutation([0,2,5,7,4,6,9,11,8,10,13,15,12,14,17,19,16,18,21,23,20,22,25,27,24,26,29,31,28,30,33,35,32,34,37,39,36,38,1,3,40,41]) + can = canonicalize(g, list(range(40)), 0, (baser, gensr, 10, 0)) + assert can == [0,2,4,6,1,3,8,10,5,7,12,14,9,11,16,18,13,15,20,22,17,19,24,26,21,23,28,30,25,27,32,34,29,31,36,38,33,35,37,39,40,41] + + +@XFAIL +def test_riemann_invariants1(): + skip('takes too much time') + baser, gensr = riemann_bsgs + g = Permutation([17, 44, 11, 3, 0, 19, 23, 15, 38, 4, 25, 27, 43, 36, 22, 14, 8, 30, 41, 20, 2, 10, 12, 28, 18, 1, 29, 13, 37, 42, 33, 7, 9, 31, 24, 26, 39, 5, 34, 47, 32, 6, 21, 40, 35, 46, 45, 16, 48, 49]) + can = canonicalize(g, list(range(48)), 0, (baser, gensr, 12, 0)) + assert can == [0, 2, 4, 6, 1, 3, 8, 10, 5, 7, 12, 14, 9, 11, 16, 18, 13, 15, 20, 22, 17, 19, 24, 26, 21, 23, 28, 30, 25, 27, 32, 34, 29, 31, 36, 38, 33, 35, 40, 42, 37, 39, 44, 46, 41, 43, 45, 47, 48, 49] + + g = Permutation([0,2,4,6, 7,8,10,12, 14,16,18,20, 19,22,24,26, 5,21,28,30, 32,34,36,38, 40,42,44,46, 13,48,50,52, 15,49,54,56, 17,33,41,58, 9,23,60,62, 29,35,63,64, 3,45,66,68, 25,37,47,57, 11,31,69,70, 27,39,53,72, 1,59,73,74, 55,61,67,76, 43,65,75,78, 51,71,77,79, 80,81]) + can = canonicalize(g, list(range(80)), 0, (baser, gensr, 20, 0)) + assert can == [0,2,4,6, 1,8,10,12, 3,14,16,18, 5,20,22,24, 7,26,28,30, 9,15,32,34, 11,36,23,38, 13,40,42,44, 17,39,29,46, 19,48,43,50, 21,45,52,54, 25,56,33,58, 27,60,53,62, 31,51,64,66, 35,65,47,68, 37,70,49,72, 41,74,57,76, 55,67,59,78, 61,69,71,75, 63,79,73,77, 80,81] + + +def test_riemann_products(): + baser, gensr = riemann_bsgs + base1, gens1 = get_symmetric_group_sgs(1) + base2, gens2 = get_symmetric_group_sgs(2) + base2a, gens2a = get_symmetric_group_sgs(2, 1) + + # R^{a b d0}_d0 = 0 + g = Permutation([0,1,2,3,4,5]) + can = canonicalize(g, list(range(2,4)), 0, (baser, gensr, 1, 0)) + assert can == 0 + + # R^{d0 b a}_d0 ; ord = [a,b,d0,-d0}; g = [2,1,0,3,4,5] + # T_c = -R^{a d0 b}_d0; can = [0,2,1,3,5,4] + g = Permutation([2,1,0,3,4,5]) + can = canonicalize(g, list(range(2, 4)), 0, (baser, gensr, 1, 0)) + assert can == [0,2,1,3,5,4] + + # R^d1_d2^b_d0 * R^{d0 a}_d1^d2; ord=[a,b,d0,-d0,d1,-d1,d2,-d2] + # g = [4,7,1,3,2,0,5,6,8,9] + # T_c = -R^{a d0 d1 d2}* R^b_{d0 d1 d2} + # can = [0,2,4,6,1,3,5,7,9,8] + g = Permutation([4,7,1,3,2,0,5,6,8,9]) + can = canonicalize(g, list(range(2,8)), 0, (baser, gensr, 2, 0)) + assert can == [0,2,4,6,1,3,5,7,9,8] + can1 = canonicalize_naive(g, list(range(2,8)), 0, (baser, gensr, 2, 0)) + assert can == can1 + + # A symmetric commuting + # R^{d6 d5}_d2^d1 * R^{d4 d0 d2 d3} * A_{d6 d0} A_{d3 d1} * A_{d4 d5} + # g = [12,10,5,2, 8,0,4,6, 13,1, 7,3, 9,11,14,15] + # T_c = -R^{d0 d1 d2 d3} * R_d0^{d4 d5 d6} * A_{d1 d4}*A_{d2 d5}*A_{d3 d6} + + g = Permutation([12,10,5,2,8,0,4,6,13,1,7,3,9,11,14,15]) + can = canonicalize(g, list(range(14)), 0, ((baser,gensr,2,0)), (base2,gens2,3,0)) + assert can == [0, 2, 4, 6, 1, 8, 10, 12, 3, 9, 5, 11, 7, 13, 15, 14] + + # R^{d2 a0 a2 d0} * R^d1_d2^{a1 a3} * R^{a4 a5}_{d0 d1} + # ord = [a0,a1,a2,a3,a4,a5,d0,-d0,d1,-d1,d2,-d2] + # 0 1 2 3 4 5 6 7 8 9 10 11 + # can = [0, 6, 2, 8, 1, 3, 7, 10, 4, 5, 9, 11, 12, 13] + # T_c = R^{a0 d0 a2 d1}*R^{a1 a3}_d0^d2*R^{a4 a5}_{d1 d2} + g = Permutation([10,0,2,6,8,11,1,3,4,5,7,9,12,13]) + can = canonicalize(g, list(range(6,12)), 0, (baser, gensr, 3, 0)) + assert can == [0, 6, 2, 8, 1, 3, 7, 10, 4, 5, 9, 11, 12, 13] + #can1 = canonicalize_naive(g, list(range(6,12)), 0, (baser, gensr, 3, 0)) + #assert can == can1 + + # A^n_{i, j} antisymmetric in i,j + # A_m0^d0_a1 * A_m1^a0_d0; ord = [m0,m1,a0,a1,d0,-d0] + # g = [0,4,3,1,2,5,6,7] + # T_c = -A_{m a1}^d0 * A_m1^a0_d0 + # can = [0,3,4,1,2,5,7,6] + base, gens = bsgs_direct_product(base1, gens1, base2a, gens2a) + dummies = list(range(4, 6)) + g = Permutation([0,4,3,1,2,5,6,7]) + can = canonicalize(g, dummies, 0, (base, gens, 2, 0)) + assert can == [0, 3, 4, 1, 2, 5, 7, 6] + + + # A^n_{i, j} symmetric in i,j + # A^m0_a0^d2 * A^n0_d2^d1 * A^n1_d1^d0 * A_{m0 d0}^a1 + # ordering: first the free indices; then first n, then d + # ord=[n0,n1,a0,a1, m0,-m0,d0,-d0,d1,-d1,d2,-d2] + # 0 1 2 3 4 5 6 7 8 9 10 11] + # g = [4,2,10, 0,11,8, 1,9,6, 5,7,3, 12,13] + # if the dummy indices m_i and d_i were separated, + # one gets + # T_c = A^{n0 d0 d1} * A^n1_d0^d2 * A^m0^a0_d1 * A_m0^a1_d2 + # can = [0, 6, 8, 1, 7, 10, 4, 2, 9, 5, 3, 11, 12, 13] + # If they are not, so can is + # T_c = A^{n0 m0 d0} A^n1_m0^d1 A^{d2 a0}_d0 A_d2^a1_d1 + # can = [0, 4, 6, 1, 5, 8, 10, 2, 7, 11, 3, 9, 12, 13] + # case with single type of indices + + base, gens = bsgs_direct_product(base1, gens1, base2, gens2) + dummies = list(range(4, 12)) + g = Permutation([4,2,10, 0,11,8, 1,9,6, 5,7,3, 12,13]) + can = canonicalize(g, dummies, 0, (base, gens, 4, 0)) + assert can == [0, 4, 6, 1, 5, 8, 10, 2, 7, 11, 3, 9, 12, 13] + # case with separated indices + dummies = [list(range(4, 6)), list(range(6,12))] + sym = [0, 0] + can = canonicalize(g, dummies, sym, (base, gens, 4, 0)) + assert can == [0, 6, 8, 1, 7, 10, 4, 2, 9, 5, 3, 11, 12, 13] + # case with separated indices with the second type of index + # with antisymmetric metric: there is a sign change + sym = [0, 1] + can = canonicalize(g, dummies, sym, (base, gens, 4, 0)) + assert can == [0, 6, 8, 1, 7, 10, 4, 2, 9, 5, 3, 11, 13, 12] + +def test_graph_certificate(): + # test tensor invariants constructed from random regular graphs; + # checked graph isomorphism with networkx + import random + def randomize_graph(size, g): + p = list(range(size)) + random.shuffle(p) + g1a = {} + for k, v in g1.items(): + g1a[p[k]] = [p[i] for i in v] + return g1a + + g1 = {0: [2, 3, 7], 1: [4, 5, 7], 2: [0, 4, 6], 3: [0, 6, 7], 4: [1, 2, 5], 5: [1, 4, 6], 6: [2, 3, 5], 7: [0, 1, 3]} + g2 = {0: [2, 3, 7], 1: [2, 4, 5], 2: [0, 1, 5], 3: [0, 6, 7], 4: [1, 5, 6], 5: [1, 2, 4], 6: [3, 4, 7], 7: [0, 3, 6]} + + c1 = graph_certificate(g1) + c2 = graph_certificate(g2) + assert c1 != c2 + g1a = randomize_graph(8, g1) + c1a = graph_certificate(g1a) + assert c1 == c1a + + g1 = {0: [8, 1, 9, 7], 1: [0, 9, 3, 4], 2: [3, 4, 6, 7], 3: [1, 2, 5, 6], 4: [8, 1, 2, 5], 5: [9, 3, 4, 7], 6: [8, 2, 3, 7], 7: [0, 2, 5, 6], 8: [0, 9, 4, 6], 9: [8, 0, 5, 1]} + g2 = {0: [1, 2, 5, 6], 1: [0, 9, 5, 7], 2: [0, 4, 6, 7], 3: [8, 9, 6, 7], 4: [8, 2, 6, 7], 5: [0, 9, 8, 1], 6: [0, 2, 3, 4], 7: [1, 2, 3, 4], 8: [9, 3, 4, 5], 9: [8, 1, 3, 5]} + c1 = graph_certificate(g1) + c2 = graph_certificate(g2) + assert c1 != c2 + g1a = randomize_graph(10, g1) + c1a = graph_certificate(g1a) + assert c1 == c1a diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_testutil.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_testutil.py new file mode 100644 index 0000000000000000000000000000000000000000..736e7a4ff86967e41dca71cf12de6c387a82d26d --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_testutil.py @@ -0,0 +1,55 @@ +from sympy.combinatorics.named_groups import SymmetricGroup, AlternatingGroup,\ + CyclicGroup +from sympy.combinatorics.testutil import _verify_bsgs, _cmp_perm_lists,\ + _naive_list_centralizer, _verify_centralizer,\ + _verify_normal_closure +from sympy.combinatorics.permutations import Permutation +from sympy.combinatorics.perm_groups import PermutationGroup +from sympy.core.random import shuffle + + +def test_cmp_perm_lists(): + S = SymmetricGroup(4) + els = list(S.generate_dimino()) + other = els.copy() + shuffle(other) + assert _cmp_perm_lists(els, other) is True + + +def test_naive_list_centralizer(): + # verified by GAP + S = SymmetricGroup(3) + A = AlternatingGroup(3) + assert _naive_list_centralizer(S, S) == [Permutation([0, 1, 2])] + assert PermutationGroup(_naive_list_centralizer(S, A)).is_subgroup(A) + + +def test_verify_bsgs(): + S = SymmetricGroup(5) + S.schreier_sims() + base = S.base + strong_gens = S.strong_gens + assert _verify_bsgs(S, base, strong_gens) is True + assert _verify_bsgs(S, base[:-1], strong_gens) is False + assert _verify_bsgs(S, base, S.generators) is False + + +def test_verify_centralizer(): + # verified by GAP + S = SymmetricGroup(3) + A = AlternatingGroup(3) + triv = PermutationGroup([Permutation([0, 1, 2])]) + assert _verify_centralizer(S, S, centr=triv) + assert _verify_centralizer(S, A, centr=A) + + +def test_verify_normal_closure(): + # verified by GAP + S = SymmetricGroup(3) + A = AlternatingGroup(3) + assert _verify_normal_closure(S, A, closure=A) + S = SymmetricGroup(5) + A = AlternatingGroup(5) + C = CyclicGroup(5) + assert _verify_normal_closure(S, A, closure=A) + assert _verify_normal_closure(S, C, closure=A) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_util.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_util.py new file mode 100644 index 0000000000000000000000000000000000000000..bca183e81f354e398aee9ae809fe79b20c7f2468 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/combinatorics/tests/test_util.py @@ -0,0 +1,120 @@ +from sympy.combinatorics.named_groups import SymmetricGroup, DihedralGroup,\ + AlternatingGroup +from sympy.combinatorics.permutations import Permutation +from sympy.combinatorics.util import _check_cycles_alt_sym, _strip,\ + _distribute_gens_by_base, _strong_gens_from_distr,\ + _orbits_transversals_from_bsgs, _handle_precomputed_bsgs, _base_ordering,\ + _remove_gens +from sympy.combinatorics.testutil import _verify_bsgs + + +def test_check_cycles_alt_sym(): + perm1 = Permutation([[0, 1, 2, 3, 4, 5, 6], [7], [8], [9]]) + perm2 = Permutation([[0, 1, 2, 3, 4, 5], [6, 7, 8, 9]]) + perm3 = Permutation([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]) + assert _check_cycles_alt_sym(perm1) is True + assert _check_cycles_alt_sym(perm2) is False + assert _check_cycles_alt_sym(perm3) is False + + +def test_strip(): + D = DihedralGroup(5) + D.schreier_sims() + member = Permutation([4, 0, 1, 2, 3]) + not_member1 = Permutation([0, 1, 4, 3, 2]) + not_member2 = Permutation([3, 1, 4, 2, 0]) + identity = Permutation([0, 1, 2, 3, 4]) + res1 = _strip(member, D.base, D.basic_orbits, D.basic_transversals) + res2 = _strip(not_member1, D.base, D.basic_orbits, D.basic_transversals) + res3 = _strip(not_member2, D.base, D.basic_orbits, D.basic_transversals) + assert res1[0] == identity + assert res1[1] == len(D.base) + 1 + assert res2[0] == not_member1 + assert res2[1] == len(D.base) + 1 + assert res3[0] != identity + assert res3[1] == 2 + + +def test_distribute_gens_by_base(): + base = [0, 1, 2] + gens = [Permutation([0, 1, 2, 3]), Permutation([0, 1, 3, 2]), + Permutation([0, 2, 3, 1]), Permutation([3, 2, 1, 0])] + assert _distribute_gens_by_base(base, gens) == [gens, + [Permutation([0, 1, 2, 3]), + Permutation([0, 1, 3, 2]), + Permutation([0, 2, 3, 1])], + [Permutation([0, 1, 2, 3]), + Permutation([0, 1, 3, 2])]] + + +def test_strong_gens_from_distr(): + strong_gens_distr = [[Permutation([0, 2, 1]), Permutation([1, 2, 0]), + Permutation([1, 0, 2])], [Permutation([0, 2, 1])]] + assert _strong_gens_from_distr(strong_gens_distr) == \ + [Permutation([0, 2, 1]), + Permutation([1, 2, 0]), + Permutation([1, 0, 2])] + + +def test_orbits_transversals_from_bsgs(): + S = SymmetricGroup(4) + S.schreier_sims() + base = S.base + strong_gens = S.strong_gens + strong_gens_distr = _distribute_gens_by_base(base, strong_gens) + result = _orbits_transversals_from_bsgs(base, strong_gens_distr) + orbits = result[0] + transversals = result[1] + base_len = len(base) + for i in range(base_len): + for el in orbits[i]: + assert transversals[i][el](base[i]) == el + for j in range(i): + assert transversals[i][el](base[j]) == base[j] + order = 1 + for i in range(base_len): + order *= len(orbits[i]) + assert S.order() == order + + +def test_handle_precomputed_bsgs(): + A = AlternatingGroup(5) + A.schreier_sims() + base = A.base + strong_gens = A.strong_gens + result = _handle_precomputed_bsgs(base, strong_gens) + strong_gens_distr = _distribute_gens_by_base(base, strong_gens) + assert strong_gens_distr == result[2] + transversals = result[0] + orbits = result[1] + base_len = len(base) + for i in range(base_len): + for el in orbits[i]: + assert transversals[i][el](base[i]) == el + for j in range(i): + assert transversals[i][el](base[j]) == base[j] + order = 1 + for i in range(base_len): + order *= len(orbits[i]) + assert A.order() == order + + +def test_base_ordering(): + base = [2, 4, 5] + degree = 7 + assert _base_ordering(base, degree) == [3, 4, 0, 5, 1, 2, 6] + + +def test_remove_gens(): + S = SymmetricGroup(10) + base, strong_gens = S.schreier_sims_incremental() + new_gens = _remove_gens(base, strong_gens) + assert _verify_bsgs(S, base, new_gens) is True + A = AlternatingGroup(7) + base, strong_gens = A.schreier_sims_incremental() + new_gens = _remove_gens(base, strong_gens) + assert _verify_bsgs(A, base, new_gens) is True + D = DihedralGroup(2) + base, strong_gens = D.schreier_sims_incremental() + new_gens = _remove_gens(base, strong_gens) + assert _verify_bsgs(D, base, new_gens) is True diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c7767c3b6a94f298064b01245269e1fd204747d6 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/__pycache__/delta.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/__pycache__/delta.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f60c71b644fbdc02d8b857e4ff261775159d25a7 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/__pycache__/delta.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/__pycache__/expr_with_intlimits.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/__pycache__/expr_with_intlimits.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d508c13143dee1e9a956cbfef307539b1963f5d4 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/__pycache__/expr_with_intlimits.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/__pycache__/expr_with_limits.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/__pycache__/expr_with_limits.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2f7d937bfffb273ab7f05743e806c5a8c0498827 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/__pycache__/expr_with_limits.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/__pycache__/gosper.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/__pycache__/gosper.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..93bf5c2896bee3bfaa624ba7ea7d690b5b6f4cdf Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/__pycache__/gosper.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/__pycache__/guess.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/__pycache__/guess.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7fd703602c2f70905d9571bd0201921ddb716de9 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/__pycache__/guess.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/__pycache__/products.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/__pycache__/products.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..04b080a561bd2e933c250c1a4c2e6211efd8c447 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/__pycache__/products.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/__pycache__/summations.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/__pycache__/summations.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..560d0120ee242676b01e759067c36b682734afaa Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/__pycache__/summations.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d3201aa6397ed0f7bbd3a9a932a9c78a3393ef05 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/__pycache__/test_delta.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/__pycache__/test_delta.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7e369ebedd9232d4b70700c754edb92f8d56e81e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/__pycache__/test_delta.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/__pycache__/test_gosper.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/__pycache__/test_gosper.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7774698aa92741205a71b83ea9c711a1267ee281 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/__pycache__/test_gosper.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/__pycache__/test_guess.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/__pycache__/test_guess.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dc65bad112ce6377cc72c9d488db24e95e06e9c7 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/__pycache__/test_guess.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/__pycache__/test_products.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/__pycache__/test_products.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c7d81fd2d60e29cbd237cccbcbda8785fddd7e97 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/__pycache__/test_products.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/test_delta.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/test_delta.py new file mode 100644 index 0000000000000000000000000000000000000000..9dc6e88d16346acc7dc775446d7de3f3696d0e03 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/test_delta.py @@ -0,0 +1,499 @@ +from sympy.concrete import Sum +from sympy.concrete.delta import deltaproduct as dp, deltasummation as ds, _extract_delta +from sympy.core import Eq, S, symbols, oo +from sympy.functions import KroneckerDelta as KD, Piecewise, piecewise_fold +from sympy.logic import And +from sympy.testing.pytest import raises + +i, j, k, l, m = symbols("i j k l m", integer=True, finite=True) +x, y = symbols("x y", commutative=False) + + +def test_deltaproduct_trivial(): + assert dp(x, (j, 1, 0)) == 1 + assert dp(x, (j, 1, 3)) == x**3 + assert dp(x + y, (j, 1, 3)) == (x + y)**3 + assert dp(x*y, (j, 1, 3)) == (x*y)**3 + assert dp(KD(i, j), (k, 1, 3)) == KD(i, j) + assert dp(x*KD(i, j), (k, 1, 3)) == x**3*KD(i, j) + assert dp(x*y*KD(i, j), (k, 1, 3)) == (x*y)**3*KD(i, j) + + +def test_deltaproduct_basic(): + assert dp(KD(i, j), (j, 1, 3)) == 0 + assert dp(KD(i, j), (j, 1, 1)) == KD(i, 1) + assert dp(KD(i, j), (j, 2, 2)) == KD(i, 2) + assert dp(KD(i, j), (j, 3, 3)) == KD(i, 3) + assert dp(KD(i, j), (j, 1, k)) == KD(i, 1)*KD(k, 1) + KD(k, 0) + assert dp(KD(i, j), (j, k, 3)) == KD(i, 3)*KD(k, 3) + KD(k, 4) + assert dp(KD(i, j), (j, k, l)) == KD(i, l)*KD(k, l) + KD(k, l + 1) + + +def test_deltaproduct_mul_x_kd(): + assert dp(x*KD(i, j), (j, 1, 3)) == 0 + assert dp(x*KD(i, j), (j, 1, 1)) == x*KD(i, 1) + assert dp(x*KD(i, j), (j, 2, 2)) == x*KD(i, 2) + assert dp(x*KD(i, j), (j, 3, 3)) == x*KD(i, 3) + assert dp(x*KD(i, j), (j, 1, k)) == x*KD(i, 1)*KD(k, 1) + KD(k, 0) + assert dp(x*KD(i, j), (j, k, 3)) == x*KD(i, 3)*KD(k, 3) + KD(k, 4) + assert dp(x*KD(i, j), (j, k, l)) == x*KD(i, l)*KD(k, l) + KD(k, l + 1) + + +def test_deltaproduct_mul_add_x_y_kd(): + assert dp((x + y)*KD(i, j), (j, 1, 3)) == 0 + assert dp((x + y)*KD(i, j), (j, 1, 1)) == (x + y)*KD(i, 1) + assert dp((x + y)*KD(i, j), (j, 2, 2)) == (x + y)*KD(i, 2) + assert dp((x + y)*KD(i, j), (j, 3, 3)) == (x + y)*KD(i, 3) + assert dp((x + y)*KD(i, j), (j, 1, k)) == \ + (x + y)*KD(i, 1)*KD(k, 1) + KD(k, 0) + assert dp((x + y)*KD(i, j), (j, k, 3)) == \ + (x + y)*KD(i, 3)*KD(k, 3) + KD(k, 4) + assert dp((x + y)*KD(i, j), (j, k, l)) == \ + (x + y)*KD(i, l)*KD(k, l) + KD(k, l + 1) + + +def test_deltaproduct_add_kd_kd(): + assert dp(KD(i, k) + KD(j, k), (k, 1, 3)) == 0 + assert dp(KD(i, k) + KD(j, k), (k, 1, 1)) == KD(i, 1) + KD(j, 1) + assert dp(KD(i, k) + KD(j, k), (k, 2, 2)) == KD(i, 2) + KD(j, 2) + assert dp(KD(i, k) + KD(j, k), (k, 3, 3)) == KD(i, 3) + KD(j, 3) + assert dp(KD(i, k) + KD(j, k), (k, 1, l)) == KD(l, 0) + \ + KD(i, 1)*KD(l, 1) + KD(j, 1)*KD(l, 1) + \ + KD(i, 1)*KD(j, 2)*KD(l, 2) + KD(j, 1)*KD(i, 2)*KD(l, 2) + assert dp(KD(i, k) + KD(j, k), (k, l, 3)) == KD(l, 4) + \ + KD(i, 3)*KD(l, 3) + KD(j, 3)*KD(l, 3) + \ + KD(i, 2)*KD(j, 3)*KD(l, 2) + KD(i, 3)*KD(j, 2)*KD(l, 2) + assert dp(KD(i, k) + KD(j, k), (k, l, m)) == KD(l, m + 1) + \ + KD(i, m)*KD(l, m) + KD(j, m)*KD(l, m) + \ + KD(i, m)*KD(j, m - 1)*KD(l, m - 1) + KD(i, m - 1)*KD(j, m)*KD(l, m - 1) + + +def test_deltaproduct_mul_x_add_kd_kd(): + assert dp(x*(KD(i, k) + KD(j, k)), (k, 1, 3)) == 0 + assert dp(x*(KD(i, k) + KD(j, k)), (k, 1, 1)) == x*(KD(i, 1) + KD(j, 1)) + assert dp(x*(KD(i, k) + KD(j, k)), (k, 2, 2)) == x*(KD(i, 2) + KD(j, 2)) + assert dp(x*(KD(i, k) + KD(j, k)), (k, 3, 3)) == x*(KD(i, 3) + KD(j, 3)) + assert dp(x*(KD(i, k) + KD(j, k)), (k, 1, l)) == KD(l, 0) + \ + x*KD(i, 1)*KD(l, 1) + x*KD(j, 1)*KD(l, 1) + \ + x**2*KD(i, 1)*KD(j, 2)*KD(l, 2) + x**2*KD(j, 1)*KD(i, 2)*KD(l, 2) + assert dp(x*(KD(i, k) + KD(j, k)), (k, l, 3)) == KD(l, 4) + \ + x*KD(i, 3)*KD(l, 3) + x*KD(j, 3)*KD(l, 3) + \ + x**2*KD(i, 2)*KD(j, 3)*KD(l, 2) + x**2*KD(i, 3)*KD(j, 2)*KD(l, 2) + assert dp(x*(KD(i, k) + KD(j, k)), (k, l, m)) == KD(l, m + 1) + \ + x*KD(i, m)*KD(l, m) + x*KD(j, m)*KD(l, m) + \ + x**2*KD(i, m - 1)*KD(j, m)*KD(l, m - 1) + \ + x**2*KD(i, m)*KD(j, m - 1)*KD(l, m - 1) + + +def test_deltaproduct_mul_add_x_y_add_kd_kd(): + assert dp((x + y)*(KD(i, k) + KD(j, k)), (k, 1, 3)) == 0 + assert dp((x + y)*(KD(i, k) + KD(j, k)), (k, 1, 1)) == \ + (x + y)*(KD(i, 1) + KD(j, 1)) + assert dp((x + y)*(KD(i, k) + KD(j, k)), (k, 2, 2)) == \ + (x + y)*(KD(i, 2) + KD(j, 2)) + assert dp((x + y)*(KD(i, k) + KD(j, k)), (k, 3, 3)) == \ + (x + y)*(KD(i, 3) + KD(j, 3)) + assert dp((x + y)*(KD(i, k) + KD(j, k)), (k, 1, l)) == KD(l, 0) + \ + (x + y)*KD(i, 1)*KD(l, 1) + (x + y)*KD(j, 1)*KD(l, 1) + \ + (x + y)**2*KD(i, 1)*KD(j, 2)*KD(l, 2) + \ + (x + y)**2*KD(j, 1)*KD(i, 2)*KD(l, 2) + assert dp((x + y)*(KD(i, k) + KD(j, k)), (k, l, 3)) == KD(l, 4) + \ + (x + y)*KD(i, 3)*KD(l, 3) + (x + y)*KD(j, 3)*KD(l, 3) + \ + (x + y)**2*KD(i, 2)*KD(j, 3)*KD(l, 2) + \ + (x + y)**2*KD(i, 3)*KD(j, 2)*KD(l, 2) + assert dp((x + y)*(KD(i, k) + KD(j, k)), (k, l, m)) == KD(l, m + 1) + \ + (x + y)*KD(i, m)*KD(l, m) + (x + y)*KD(j, m)*KD(l, m) + \ + (x + y)**2*KD(i, m - 1)*KD(j, m)*KD(l, m - 1) + \ + (x + y)**2*KD(i, m)*KD(j, m - 1)*KD(l, m - 1) + + +def test_deltaproduct_add_mul_x_y_mul_x_kd(): + assert dp(x*y + x*KD(i, j), (j, 1, 3)) == (x*y)**3 + \ + x*(x*y)**2*KD(i, 1) + (x*y)*x*(x*y)*KD(i, 2) + (x*y)**2*x*KD(i, 3) + assert dp(x*y + x*KD(i, j), (j, 1, 1)) == x*y + x*KD(i, 1) + assert dp(x*y + x*KD(i, j), (j, 2, 2)) == x*y + x*KD(i, 2) + assert dp(x*y + x*KD(i, j), (j, 3, 3)) == x*y + x*KD(i, 3) + assert dp(x*y + x*KD(i, j), (j, 1, k)) == \ + (x*y)**k + Piecewise( + ((x*y)**(i - 1)*x*(x*y)**(k - i), And(1 <= i, i <= k)), + (0, True) + ) + assert dp(x*y + x*KD(i, j), (j, k, 3)) == \ + (x*y)**(-k + 4) + Piecewise( + ((x*y)**(i - k)*x*(x*y)**(3 - i), And(k <= i, i <= 3)), + (0, True) + ) + assert dp(x*y + x*KD(i, j), (j, k, l)) == \ + (x*y)**(-k + l + 1) + Piecewise( + ((x*y)**(i - k)*x*(x*y)**(l - i), And(k <= i, i <= l)), + (0, True) + ) + + +def test_deltaproduct_mul_x_add_y_kd(): + assert dp(x*(y + KD(i, j)), (j, 1, 3)) == (x*y)**3 + \ + x*(x*y)**2*KD(i, 1) + (x*y)*x*(x*y)*KD(i, 2) + (x*y)**2*x*KD(i, 3) + assert dp(x*(y + KD(i, j)), (j, 1, 1)) == x*(y + KD(i, 1)) + assert dp(x*(y + KD(i, j)), (j, 2, 2)) == x*(y + KD(i, 2)) + assert dp(x*(y + KD(i, j)), (j, 3, 3)) == x*(y + KD(i, 3)) + assert dp(x*(y + KD(i, j)), (j, 1, k)) == \ + (x*y)**k + Piecewise( + ((x*y)**(i - 1)*x*(x*y)**(k - i), And(1 <= i, i <= k)), + (0, True) + ).expand() + assert dp(x*(y + KD(i, j)), (j, k, 3)) == \ + ((x*y)**(-k + 4) + Piecewise( + ((x*y)**(i - k)*x*(x*y)**(3 - i), And(k <= i, i <= 3)), + (0, True) + )).expand() + assert dp(x*(y + KD(i, j)), (j, k, l)) == \ + ((x*y)**(-k + l + 1) + Piecewise( + ((x*y)**(i - k)*x*(x*y)**(l - i), And(k <= i, i <= l)), + (0, True) + )).expand() + + +def test_deltaproduct_mul_x_add_y_twokd(): + assert dp(x*(y + 2*KD(i, j)), (j, 1, 3)) == (x*y)**3 + \ + 2*x*(x*y)**2*KD(i, 1) + 2*x*y*x*x*y*KD(i, 2) + 2*(x*y)**2*x*KD(i, 3) + assert dp(x*(y + 2*KD(i, j)), (j, 1, 1)) == x*(y + 2*KD(i, 1)) + assert dp(x*(y + 2*KD(i, j)), (j, 2, 2)) == x*(y + 2*KD(i, 2)) + assert dp(x*(y + 2*KD(i, j)), (j, 3, 3)) == x*(y + 2*KD(i, 3)) + assert dp(x*(y + 2*KD(i, j)), (j, 1, k)) == \ + (x*y)**k + Piecewise( + (2*(x*y)**(i - 1)*x*(x*y)**(k - i), And(1 <= i, i <= k)), + (0, True) + ).expand() + assert dp(x*(y + 2*KD(i, j)), (j, k, 3)) == \ + ((x*y)**(-k + 4) + Piecewise( + (2*(x*y)**(i - k)*x*(x*y)**(3 - i), And(k <= i, i <= 3)), + (0, True) + )).expand() + assert dp(x*(y + 2*KD(i, j)), (j, k, l)) == \ + ((x*y)**(-k + l + 1) + Piecewise( + (2*(x*y)**(i - k)*x*(x*y)**(l - i), And(k <= i, i <= l)), + (0, True) + )).expand() + + +def test_deltaproduct_mul_add_x_y_add_y_kd(): + assert dp((x + y)*(y + KD(i, j)), (j, 1, 3)) == ((x + y)*y)**3 + \ + (x + y)*((x + y)*y)**2*KD(i, 1) + \ + (x + y)*y*(x + y)**2*y*KD(i, 2) + \ + ((x + y)*y)**2*(x + y)*KD(i, 3) + assert dp((x + y)*(y + KD(i, j)), (j, 1, 1)) == (x + y)*(y + KD(i, 1)) + assert dp((x + y)*(y + KD(i, j)), (j, 2, 2)) == (x + y)*(y + KD(i, 2)) + assert dp((x + y)*(y + KD(i, j)), (j, 3, 3)) == (x + y)*(y + KD(i, 3)) + assert dp((x + y)*(y + KD(i, j)), (j, 1, k)) == \ + ((x + y)*y)**k + Piecewise( + (((x + y)*y)**(-1)*((x + y)*y)**i*(x + y)*((x + y)*y + )**k*((x + y)*y)**(-i), (i >= 1) & (i <= k)), (0, True)) + assert dp((x + y)*(y + KD(i, j)), (j, k, 3)) == ( + (x + y)*y)**4*((x + y)*y)**(-k) + Piecewise((((x + y)*y)**i*( + (x + y)*y)**(-k)*(x + y)*((x + y)*y)**3*((x + y)*y)**(-i), + (i >= k) & (i <= 3)), (0, True)) + assert dp((x + y)*(y + KD(i, j)), (j, k, l)) == \ + (x + y)*y*((x + y)*y)**l*((x + y)*y)**(-k) + Piecewise( + (((x + y)*y)**i*((x + y)*y)**(-k)*(x + y)*((x + y)*y + )**l*((x + y)*y)**(-i), (i >= k) & (i <= l)), (0, True)) + + +def test_deltaproduct_mul_add_x_kd_add_y_kd(): + assert dp((x + KD(i, k))*(y + KD(i, j)), (j, 1, 3)) == \ + KD(i, 1)*(KD(i, k) + x)*((KD(i, k) + x)*y)**2 + \ + KD(i, 2)*(KD(i, k) + x)*y*(KD(i, k) + x)**2*y + \ + KD(i, 3)*((KD(i, k) + x)*y)**2*(KD(i, k) + x) + \ + ((KD(i, k) + x)*y)**3 + assert dp((x + KD(i, k))*(y + KD(i, j)), (j, 1, 1)) == \ + (x + KD(i, k))*(y + KD(i, 1)) + assert dp((x + KD(i, k))*(y + KD(i, j)), (j, 2, 2)) == \ + (x + KD(i, k))*(y + KD(i, 2)) + assert dp((x + KD(i, k))*(y + KD(i, j)), (j, 3, 3)) == \ + (x + KD(i, k))*(y + KD(i, 3)) + assert dp((x + KD(i, k))*(y + KD(i, j)), (j, 1, k)) == \ + ((KD(i, k) + x)*y)**k + Piecewise( + (((KD(i, k) + x)*y)**(-1)*((KD(i, k) + x)*y)**i*(KD(i, k) + x + )*((KD(i, k) + x)*y)**k*((KD(i, k) + x)*y)**(-i), (i >= 1 + ) & (i <= k)), (0, True)) + assert dp((x + KD(i, k))*(y + KD(i, j)), (j, k, 3)) == ( + (KD(i, k) + x)*y)**4*((KD(i, k) + x)*y)**(-k) + Piecewise( + (((KD(i, k) + x)*y)**i*((KD(i, k) + x)*y)**(-k)*(KD(i, k) + + x)*((KD(i, k) + x)*y)**3*((KD(i, k) + x)*y)**(-i), + (i >= k) & (i <= 3)), (0, True)) + assert dp((x + KD(i, k))*(y + KD(i, j)), (j, k, l)) == ( + KD(i, k) + x)*y*((KD(i, k) + x)*y)**l*((KD(i, k) + x)*y + )**(-k) + Piecewise((((KD(i, k) + x)*y)**i*((KD(i, k) + x + )*y)**(-k)*(KD(i, k) + x)*((KD(i, k) + x)*y)**l*((KD(i, k) + x + )*y)**(-i), (i >= k) & (i <= l)), (0, True)) + + +def test_deltasummation_trivial(): + assert ds(x, (j, 1, 0)) == 0 + assert ds(x, (j, 1, 3)) == 3*x + assert ds(x + y, (j, 1, 3)) == 3*(x + y) + assert ds(x*y, (j, 1, 3)) == 3*x*y + assert ds(KD(i, j), (k, 1, 3)) == 3*KD(i, j) + assert ds(x*KD(i, j), (k, 1, 3)) == 3*x*KD(i, j) + assert ds(x*y*KD(i, j), (k, 1, 3)) == 3*x*y*KD(i, j) + + +def test_deltasummation_basic_numerical(): + n = symbols('n', integer=True, nonzero=True) + assert ds(KD(n, 0), (n, 1, 3)) == 0 + + # return unevaluated, until it gets implemented + assert ds(KD(i**2, j**2), (j, -oo, oo)) == \ + Sum(KD(i**2, j**2), (j, -oo, oo)) + + assert Piecewise((KD(i, k), And(1 <= i, i <= 3)), (0, True)) == \ + ds(KD(i, j)*KD(j, k), (j, 1, 3)) == \ + ds(KD(j, k)*KD(i, j), (j, 1, 3)) + + assert ds(KD(i, k), (k, -oo, oo)) == 1 + assert ds(KD(i, k), (k, 0, oo)) == Piecewise((1, S.Zero <= i), (0, True)) + assert ds(KD(i, k), (k, 1, 3)) == \ + Piecewise((1, And(1 <= i, i <= 3)), (0, True)) + assert ds(k*KD(i, j)*KD(j, k), (k, -oo, oo)) == j*KD(i, j) + assert ds(j*KD(i, j), (j, -oo, oo)) == i + assert ds(i*KD(i, j), (i, -oo, oo)) == j + assert ds(x, (i, 1, 3)) == 3*x + assert ds((i + j)*KD(i, j), (j, -oo, oo)) == 2*i + + +def test_deltasummation_basic_symbolic(): + assert ds(KD(i, j), (j, 1, 3)) == \ + Piecewise((1, And(1 <= i, i <= 3)), (0, True)) + assert ds(KD(i, j), (j, 1, 1)) == Piecewise((1, Eq(i, 1)), (0, True)) + assert ds(KD(i, j), (j, 2, 2)) == Piecewise((1, Eq(i, 2)), (0, True)) + assert ds(KD(i, j), (j, 3, 3)) == Piecewise((1, Eq(i, 3)), (0, True)) + assert ds(KD(i, j), (j, 1, k)) == \ + Piecewise((1, And(1 <= i, i <= k)), (0, True)) + assert ds(KD(i, j), (j, k, 3)) == \ + Piecewise((1, And(k <= i, i <= 3)), (0, True)) + assert ds(KD(i, j), (j, k, l)) == \ + Piecewise((1, And(k <= i, i <= l)), (0, True)) + + +def test_deltasummation_mul_x_kd(): + assert ds(x*KD(i, j), (j, 1, 3)) == \ + Piecewise((x, And(1 <= i, i <= 3)), (0, True)) + assert ds(x*KD(i, j), (j, 1, 1)) == Piecewise((x, Eq(i, 1)), (0, True)) + assert ds(x*KD(i, j), (j, 2, 2)) == Piecewise((x, Eq(i, 2)), (0, True)) + assert ds(x*KD(i, j), (j, 3, 3)) == Piecewise((x, Eq(i, 3)), (0, True)) + assert ds(x*KD(i, j), (j, 1, k)) == \ + Piecewise((x, And(1 <= i, i <= k)), (0, True)) + assert ds(x*KD(i, j), (j, k, 3)) == \ + Piecewise((x, And(k <= i, i <= 3)), (0, True)) + assert ds(x*KD(i, j), (j, k, l)) == \ + Piecewise((x, And(k <= i, i <= l)), (0, True)) + + +def test_deltasummation_mul_add_x_y_kd(): + assert ds((x + y)*KD(i, j), (j, 1, 3)) == \ + Piecewise((x + y, And(1 <= i, i <= 3)), (0, True)) + assert ds((x + y)*KD(i, j), (j, 1, 1)) == \ + Piecewise((x + y, Eq(i, 1)), (0, True)) + assert ds((x + y)*KD(i, j), (j, 2, 2)) == \ + Piecewise((x + y, Eq(i, 2)), (0, True)) + assert ds((x + y)*KD(i, j), (j, 3, 3)) == \ + Piecewise((x + y, Eq(i, 3)), (0, True)) + assert ds((x + y)*KD(i, j), (j, 1, k)) == \ + Piecewise((x + y, And(1 <= i, i <= k)), (0, True)) + assert ds((x + y)*KD(i, j), (j, k, 3)) == \ + Piecewise((x + y, And(k <= i, i <= 3)), (0, True)) + assert ds((x + y)*KD(i, j), (j, k, l)) == \ + Piecewise((x + y, And(k <= i, i <= l)), (0, True)) + + +def test_deltasummation_add_kd_kd(): + assert ds(KD(i, k) + KD(j, k), (k, 1, 3)) == piecewise_fold( + Piecewise((1, And(1 <= i, i <= 3)), (0, True)) + + Piecewise((1, And(1 <= j, j <= 3)), (0, True))) + assert ds(KD(i, k) + KD(j, k), (k, 1, 1)) == piecewise_fold( + Piecewise((1, Eq(i, 1)), (0, True)) + + Piecewise((1, Eq(j, 1)), (0, True))) + assert ds(KD(i, k) + KD(j, k), (k, 2, 2)) == piecewise_fold( + Piecewise((1, Eq(i, 2)), (0, True)) + + Piecewise((1, Eq(j, 2)), (0, True))) + assert ds(KD(i, k) + KD(j, k), (k, 3, 3)) == piecewise_fold( + Piecewise((1, Eq(i, 3)), (0, True)) + + Piecewise((1, Eq(j, 3)), (0, True))) + assert ds(KD(i, k) + KD(j, k), (k, 1, l)) == piecewise_fold( + Piecewise((1, And(1 <= i, i <= l)), (0, True)) + + Piecewise((1, And(1 <= j, j <= l)), (0, True))) + assert ds(KD(i, k) + KD(j, k), (k, l, 3)) == piecewise_fold( + Piecewise((1, And(l <= i, i <= 3)), (0, True)) + + Piecewise((1, And(l <= j, j <= 3)), (0, True))) + assert ds(KD(i, k) + KD(j, k), (k, l, m)) == piecewise_fold( + Piecewise((1, And(l <= i, i <= m)), (0, True)) + + Piecewise((1, And(l <= j, j <= m)), (0, True))) + + +def test_deltasummation_add_mul_x_kd_kd(): + assert ds(x*KD(i, k) + KD(j, k), (k, 1, 3)) == piecewise_fold( + Piecewise((x, And(1 <= i, i <= 3)), (0, True)) + + Piecewise((1, And(1 <= j, j <= 3)), (0, True))) + assert ds(x*KD(i, k) + KD(j, k), (k, 1, 1)) == piecewise_fold( + Piecewise((x, Eq(i, 1)), (0, True)) + + Piecewise((1, Eq(j, 1)), (0, True))) + assert ds(x*KD(i, k) + KD(j, k), (k, 2, 2)) == piecewise_fold( + Piecewise((x, Eq(i, 2)), (0, True)) + + Piecewise((1, Eq(j, 2)), (0, True))) + assert ds(x*KD(i, k) + KD(j, k), (k, 3, 3)) == piecewise_fold( + Piecewise((x, Eq(i, 3)), (0, True)) + + Piecewise((1, Eq(j, 3)), (0, True))) + assert ds(x*KD(i, k) + KD(j, k), (k, 1, l)) == piecewise_fold( + Piecewise((x, And(1 <= i, i <= l)), (0, True)) + + Piecewise((1, And(1 <= j, j <= l)), (0, True))) + assert ds(x*KD(i, k) + KD(j, k), (k, l, 3)) == piecewise_fold( + Piecewise((x, And(l <= i, i <= 3)), (0, True)) + + Piecewise((1, And(l <= j, j <= 3)), (0, True))) + assert ds(x*KD(i, k) + KD(j, k), (k, l, m)) == piecewise_fold( + Piecewise((x, And(l <= i, i <= m)), (0, True)) + + Piecewise((1, And(l <= j, j <= m)), (0, True))) + + +def test_deltasummation_mul_x_add_kd_kd(): + assert ds(x*(KD(i, k) + KD(j, k)), (k, 1, 3)) == piecewise_fold( + Piecewise((x, And(1 <= i, i <= 3)), (0, True)) + + Piecewise((x, And(1 <= j, j <= 3)), (0, True))) + assert ds(x*(KD(i, k) + KD(j, k)), (k, 1, 1)) == piecewise_fold( + Piecewise((x, Eq(i, 1)), (0, True)) + + Piecewise((x, Eq(j, 1)), (0, True))) + assert ds(x*(KD(i, k) + KD(j, k)), (k, 2, 2)) == piecewise_fold( + Piecewise((x, Eq(i, 2)), (0, True)) + + Piecewise((x, Eq(j, 2)), (0, True))) + assert ds(x*(KD(i, k) + KD(j, k)), (k, 3, 3)) == piecewise_fold( + Piecewise((x, Eq(i, 3)), (0, True)) + + Piecewise((x, Eq(j, 3)), (0, True))) + assert ds(x*(KD(i, k) + KD(j, k)), (k, 1, l)) == piecewise_fold( + Piecewise((x, And(1 <= i, i <= l)), (0, True)) + + Piecewise((x, And(1 <= j, j <= l)), (0, True))) + assert ds(x*(KD(i, k) + KD(j, k)), (k, l, 3)) == piecewise_fold( + Piecewise((x, And(l <= i, i <= 3)), (0, True)) + + Piecewise((x, And(l <= j, j <= 3)), (0, True))) + assert ds(x*(KD(i, k) + KD(j, k)), (k, l, m)) == piecewise_fold( + Piecewise((x, And(l <= i, i <= m)), (0, True)) + + Piecewise((x, And(l <= j, j <= m)), (0, True))) + + +def test_deltasummation_mul_add_x_y_add_kd_kd(): + assert ds((x + y)*(KD(i, k) + KD(j, k)), (k, 1, 3)) == piecewise_fold( + Piecewise((x + y, And(1 <= i, i <= 3)), (0, True)) + + Piecewise((x + y, And(1 <= j, j <= 3)), (0, True))) + assert ds((x + y)*(KD(i, k) + KD(j, k)), (k, 1, 1)) == piecewise_fold( + Piecewise((x + y, Eq(i, 1)), (0, True)) + + Piecewise((x + y, Eq(j, 1)), (0, True))) + assert ds((x + y)*(KD(i, k) + KD(j, k)), (k, 2, 2)) == piecewise_fold( + Piecewise((x + y, Eq(i, 2)), (0, True)) + + Piecewise((x + y, Eq(j, 2)), (0, True))) + assert ds((x + y)*(KD(i, k) + KD(j, k)), (k, 3, 3)) == piecewise_fold( + Piecewise((x + y, Eq(i, 3)), (0, True)) + + Piecewise((x + y, Eq(j, 3)), (0, True))) + assert ds((x + y)*(KD(i, k) + KD(j, k)), (k, 1, l)) == piecewise_fold( + Piecewise((x + y, And(1 <= i, i <= l)), (0, True)) + + Piecewise((x + y, And(1 <= j, j <= l)), (0, True))) + assert ds((x + y)*(KD(i, k) + KD(j, k)), (k, l, 3)) == piecewise_fold( + Piecewise((x + y, And(l <= i, i <= 3)), (0, True)) + + Piecewise((x + y, And(l <= j, j <= 3)), (0, True))) + assert ds((x + y)*(KD(i, k) + KD(j, k)), (k, l, m)) == piecewise_fold( + Piecewise((x + y, And(l <= i, i <= m)), (0, True)) + + Piecewise((x + y, And(l <= j, j <= m)), (0, True))) + + +def test_deltasummation_add_mul_x_y_mul_x_kd(): + assert ds(x*y + x*KD(i, j), (j, 1, 3)) == \ + Piecewise((3*x*y + x, And(1 <= i, i <= 3)), (3*x*y, True)) + assert ds(x*y + x*KD(i, j), (j, 1, 1)) == \ + Piecewise((x*y + x, Eq(i, 1)), (x*y, True)) + assert ds(x*y + x*KD(i, j), (j, 2, 2)) == \ + Piecewise((x*y + x, Eq(i, 2)), (x*y, True)) + assert ds(x*y + x*KD(i, j), (j, 3, 3)) == \ + Piecewise((x*y + x, Eq(i, 3)), (x*y, True)) + assert ds(x*y + x*KD(i, j), (j, 1, k)) == \ + Piecewise((k*x*y + x, And(1 <= i, i <= k)), (k*x*y, True)) + assert ds(x*y + x*KD(i, j), (j, k, 3)) == \ + Piecewise(((4 - k)*x*y + x, And(k <= i, i <= 3)), ((4 - k)*x*y, True)) + assert ds(x*y + x*KD(i, j), (j, k, l)) == Piecewise( + ((l - k + 1)*x*y + x, And(k <= i, i <= l)), ((l - k + 1)*x*y, True)) + + +def test_deltasummation_mul_x_add_y_kd(): + assert ds(x*(y + KD(i, j)), (j, 1, 3)) == \ + Piecewise((3*x*y + x, And(1 <= i, i <= 3)), (3*x*y, True)) + assert ds(x*(y + KD(i, j)), (j, 1, 1)) == \ + Piecewise((x*y + x, Eq(i, 1)), (x*y, True)) + assert ds(x*(y + KD(i, j)), (j, 2, 2)) == \ + Piecewise((x*y + x, Eq(i, 2)), (x*y, True)) + assert ds(x*(y + KD(i, j)), (j, 3, 3)) == \ + Piecewise((x*y + x, Eq(i, 3)), (x*y, True)) + assert ds(x*(y + KD(i, j)), (j, 1, k)) == \ + Piecewise((k*x*y + x, And(1 <= i, i <= k)), (k*x*y, True)) + assert ds(x*(y + KD(i, j)), (j, k, 3)) == \ + Piecewise(((4 - k)*x*y + x, And(k <= i, i <= 3)), ((4 - k)*x*y, True)) + assert ds(x*(y + KD(i, j)), (j, k, l)) == Piecewise( + ((l - k + 1)*x*y + x, And(k <= i, i <= l)), ((l - k + 1)*x*y, True)) + + +def test_deltasummation_mul_x_add_y_twokd(): + assert ds(x*(y + 2*KD(i, j)), (j, 1, 3)) == \ + Piecewise((3*x*y + 2*x, And(1 <= i, i <= 3)), (3*x*y, True)) + assert ds(x*(y + 2*KD(i, j)), (j, 1, 1)) == \ + Piecewise((x*y + 2*x, Eq(i, 1)), (x*y, True)) + assert ds(x*(y + 2*KD(i, j)), (j, 2, 2)) == \ + Piecewise((x*y + 2*x, Eq(i, 2)), (x*y, True)) + assert ds(x*(y + 2*KD(i, j)), (j, 3, 3)) == \ + Piecewise((x*y + 2*x, Eq(i, 3)), (x*y, True)) + assert ds(x*(y + 2*KD(i, j)), (j, 1, k)) == \ + Piecewise((k*x*y + 2*x, And(1 <= i, i <= k)), (k*x*y, True)) + assert ds(x*(y + 2*KD(i, j)), (j, k, 3)) == Piecewise( + ((4 - k)*x*y + 2*x, And(k <= i, i <= 3)), ((4 - k)*x*y, True)) + assert ds(x*(y + 2*KD(i, j)), (j, k, l)) == Piecewise( + ((l - k + 1)*x*y + 2*x, And(k <= i, i <= l)), ((l - k + 1)*x*y, True)) + + +def test_deltasummation_mul_add_x_y_add_y_kd(): + assert ds((x + y)*(y + KD(i, j)), (j, 1, 3)) == Piecewise( + (3*(x + y)*y + x + y, And(1 <= i, i <= 3)), (3*(x + y)*y, True)) + assert ds((x + y)*(y + KD(i, j)), (j, 1, 1)) == \ + Piecewise(((x + y)*y + x + y, Eq(i, 1)), ((x + y)*y, True)) + assert ds((x + y)*(y + KD(i, j)), (j, 2, 2)) == \ + Piecewise(((x + y)*y + x + y, Eq(i, 2)), ((x + y)*y, True)) + assert ds((x + y)*(y + KD(i, j)), (j, 3, 3)) == \ + Piecewise(((x + y)*y + x + y, Eq(i, 3)), ((x + y)*y, True)) + assert ds((x + y)*(y + KD(i, j)), (j, 1, k)) == Piecewise( + (k*(x + y)*y + x + y, And(1 <= i, i <= k)), (k*(x + y)*y, True)) + assert ds((x + y)*(y + KD(i, j)), (j, k, 3)) == Piecewise( + ((4 - k)*(x + y)*y + x + y, And(k <= i, i <= 3)), + ((4 - k)*(x + y)*y, True)) + assert ds((x + y)*(y + KD(i, j)), (j, k, l)) == Piecewise( + ((l - k + 1)*(x + y)*y + x + y, And(k <= i, i <= l)), + ((l - k + 1)*(x + y)*y, True)) + + +def test_deltasummation_mul_add_x_kd_add_y_kd(): + assert ds((x + KD(i, k))*(y + KD(i, j)), (j, 1, 3)) == piecewise_fold( + Piecewise((KD(i, k) + x, And(1 <= i, i <= 3)), (0, True)) + + 3*(KD(i, k) + x)*y) + assert ds((x + KD(i, k))*(y + KD(i, j)), (j, 1, 1)) == piecewise_fold( + Piecewise((KD(i, k) + x, Eq(i, 1)), (0, True)) + + (KD(i, k) + x)*y) + assert ds((x + KD(i, k))*(y + KD(i, j)), (j, 2, 2)) == piecewise_fold( + Piecewise((KD(i, k) + x, Eq(i, 2)), (0, True)) + + (KD(i, k) + x)*y) + assert ds((x + KD(i, k))*(y + KD(i, j)), (j, 3, 3)) == piecewise_fold( + Piecewise((KD(i, k) + x, Eq(i, 3)), (0, True)) + + (KD(i, k) + x)*y) + assert ds((x + KD(i, k))*(y + KD(i, j)), (j, 1, k)) == piecewise_fold( + Piecewise((KD(i, k) + x, And(1 <= i, i <= k)), (0, True)) + + k*(KD(i, k) + x)*y) + assert ds((x + KD(i, k))*(y + KD(i, j)), (j, k, 3)) == piecewise_fold( + Piecewise((KD(i, k) + x, And(k <= i, i <= 3)), (0, True)) + + (4 - k)*(KD(i, k) + x)*y) + assert ds((x + KD(i, k))*(y + KD(i, j)), (j, k, l)) == piecewise_fold( + Piecewise((KD(i, k) + x, And(k <= i, i <= l)), (0, True)) + + (l - k + 1)*(KD(i, k) + x)*y) + + +def test_extract_delta(): + raises(ValueError, lambda: _extract_delta(KD(i, j) + KD(k, l), i)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/test_gosper.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/test_gosper.py new file mode 100644 index 0000000000000000000000000000000000000000..77b642a9b7cd55f96840a8e20e517206b6a6f8f0 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/test_gosper.py @@ -0,0 +1,204 @@ +"""Tests for Gosper's algorithm for hypergeometric summation. """ + +from sympy.core.numbers import (Rational, pi) +from sympy.core.singleton import S +from sympy.core.symbol import Symbol +from sympy.functions.combinatorial.factorials import (binomial, factorial) +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.special.gamma_functions import gamma +from sympy.polys.polytools import Poly +from sympy.simplify.simplify import simplify +from sympy.concrete.gosper import gosper_normal, gosper_sum, gosper_term +from sympy.abc import a, b, j, k, m, n, r, x + + +def test_gosper_normal(): + eq = 4*n + 5, 2*(4*n + 1)*(2*n + 3), n + assert gosper_normal(*eq) == \ + (Poly(Rational(1, 4), n), Poly(n + Rational(3, 2)), Poly(n + Rational(1, 4))) + assert gosper_normal(*eq, polys=False) == \ + (Rational(1, 4), n + Rational(3, 2), n + Rational(1, 4)) + + +def test_gosper_term(): + assert gosper_term((4*k + 1)*factorial( + k)/factorial(2*k + 1), k) == (-k - S.Half)/(k + Rational(1, 4)) + + +def test_gosper_sum(): + assert gosper_sum(1, (k, 0, n)) == 1 + n + assert gosper_sum(k, (k, 0, n)) == n*(1 + n)/2 + assert gosper_sum(k**2, (k, 0, n)) == n*(1 + n)*(1 + 2*n)/6 + assert gosper_sum(k**3, (k, 0, n)) == n**2*(1 + n)**2/4 + + assert gosper_sum(2**k, (k, 0, n)) == 2*2**n - 1 + + assert gosper_sum(factorial(k), (k, 0, n)) is None + assert gosper_sum(binomial(n, k), (k, 0, n)) is None + + assert gosper_sum(factorial(k)/k**2, (k, 0, n)) is None + assert gosper_sum((k - 3)*factorial(k), (k, 0, n)) is None + + assert gosper_sum(k*factorial(k), k) == factorial(k) + assert gosper_sum( + k*factorial(k), (k, 0, n)) == n*factorial(n) + factorial(n) - 1 + + assert gosper_sum((-1)**k*binomial(n, k), (k, 0, n)) == 0 + assert gosper_sum(( + -1)**k*binomial(n, k), (k, 0, m)) == -(-1)**m*(m - n)*binomial(n, m)/n + + assert gosper_sum((4*k + 1)*factorial(k)/factorial(2*k + 1), (k, 0, n)) == \ + (2*factorial(2*n + 1) - factorial(n))/factorial(2*n + 1) + + # issue 6033: + assert gosper_sum( + n*(n + a + b)*a**n*b**n/(factorial(n + a)*factorial(n + b)), \ + (n, 0, m)).simplify() == -exp(m*log(a) + m*log(b))*gamma(a + 1) \ + *gamma(b + 1)/(gamma(a)*gamma(b)*gamma(a + m + 1)*gamma(b + m + 1)) \ + + 1/(gamma(a)*gamma(b)) + + +def test_gosper_sum_indefinite(): + assert gosper_sum(k, k) == k*(k - 1)/2 + assert gosper_sum(k**2, k) == k*(k - 1)*(2*k - 1)/6 + + assert gosper_sum(1/(k*(k + 1)), k) == -1/k + assert gosper_sum(-(27*k**4 + 158*k**3 + 430*k**2 + 678*k + 445)*gamma(2*k + + 4)/(3*(3*k + 7)*gamma(3*k + 6)), k) == \ + (3*k + 5)*(k**2 + 2*k + 5)*gamma(2*k + 4)/gamma(3*k + 6) + + +def test_gosper_sum_parametric(): + assert gosper_sum(binomial(S.Half, m - j + 1)*binomial(S.Half, m + j), (j, 1, n)) == \ + n*(1 + m - n)*(-1 + 2*m + 2*n)*binomial(S.Half, 1 + m - n)* \ + binomial(S.Half, m + n)/(m*(1 + 2*m)) + + +def test_gosper_sum_algebraic(): + assert gosper_sum( + n**2 + sqrt(2), (n, 0, m)) == (m + 1)*(2*m**2 + m + 6*sqrt(2))/6 + + +def test_gosper_sum_iterated(): + f1 = binomial(2*k, k)/4**k + f2 = (1 + 2*n)*binomial(2*n, n)/4**n + f3 = (1 + 2*n)*(3 + 2*n)*binomial(2*n, n)/(3*4**n) + f4 = (1 + 2*n)*(3 + 2*n)*(5 + 2*n)*binomial(2*n, n)/(15*4**n) + f5 = (1 + 2*n)*(3 + 2*n)*(5 + 2*n)*(7 + 2*n)*binomial(2*n, n)/(105*4**n) + + assert gosper_sum(f1, (k, 0, n)) == f2 + assert gosper_sum(f2, (n, 0, n)) == f3 + assert gosper_sum(f3, (n, 0, n)) == f4 + assert gosper_sum(f4, (n, 0, n)) == f5 + +# the AeqB tests test expressions given in +# www.math.upenn.edu/~wilf/AeqB.pdf + + +def test_gosper_sum_AeqB_part1(): + f1a = n**4 + f1b = n**3*2**n + f1c = 1/(n**2 + sqrt(5)*n - 1) + f1d = n**4*4**n/binomial(2*n, n) + f1e = factorial(3*n)/(factorial(n)*factorial(n + 1)*factorial(n + 2)*27**n) + f1f = binomial(2*n, n)**2/((n + 1)*4**(2*n)) + f1g = (4*n - 1)*binomial(2*n, n)**2/((2*n - 1)**2*4**(2*n)) + f1h = n*factorial(n - S.Half)**2/factorial(n + 1)**2 + + g1a = m*(m + 1)*(2*m + 1)*(3*m**2 + 3*m - 1)/30 + g1b = 26 + 2**(m + 1)*(m**3 - 3*m**2 + 9*m - 13) + g1c = (m + 1)*(m*(m**2 - 7*m + 3)*sqrt(5) - ( + 3*m**3 - 7*m**2 + 19*m - 6))/(2*m**3*sqrt(5) + m**4 + 5*m**2 - 1)/6 + g1d = Rational(-2, 231) + 2*4**m*(m + 1)*(63*m**4 + 112*m**3 + 18*m**2 - + 22*m + 3)/(693*binomial(2*m, m)) + g1e = Rational(-9, 2) + (81*m**2 + 261*m + 200)*factorial( + 3*m + 2)/(40*27**m*factorial(m)*factorial(m + 1)*factorial(m + 2)) + g1f = (2*m + 1)**2*binomial(2*m, m)**2/(4**(2*m)*(m + 1)) + g1g = -binomial(2*m, m)**2/4**(2*m) + g1h = 4*pi -(2*m + 1)**2*(3*m + 4)*factorial(m - S.Half)**2/factorial(m + 1)**2 + + g = gosper_sum(f1a, (n, 0, m)) + assert g is not None and simplify(g - g1a) == 0 + g = gosper_sum(f1b, (n, 0, m)) + assert g is not None and simplify(g - g1b) == 0 + g = gosper_sum(f1c, (n, 0, m)) + assert g is not None and simplify(g - g1c) == 0 + g = gosper_sum(f1d, (n, 0, m)) + assert g is not None and simplify(g - g1d) == 0 + g = gosper_sum(f1e, (n, 0, m)) + assert g is not None and simplify(g - g1e) == 0 + g = gosper_sum(f1f, (n, 0, m)) + assert g is not None and simplify(g - g1f) == 0 + g = gosper_sum(f1g, (n, 0, m)) + assert g is not None and simplify(g - g1g) == 0 + g = gosper_sum(f1h, (n, 0, m)) + # need to call rewrite(gamma) here because we have terms involving + # factorial(1/2) + assert g is not None and simplify(g - g1h).rewrite(gamma) == 0 + + +def test_gosper_sum_AeqB_part2(): + f2a = n**2*a**n + f2b = (n - r/2)*binomial(r, n) + f2c = factorial(n - 1)**2/(factorial(n - x)*factorial(n + x)) + + g2a = -a*(a + 1)/(a - 1)**3 + a**( + m + 1)*(a**2*m**2 - 2*a*m**2 + m**2 - 2*a*m + 2*m + a + 1)/(a - 1)**3 + g2b = (m - r)*binomial(r, m)/2 + ff = factorial(1 - x)*factorial(1 + x) + g2c = 1/ff*( + 1 - 1/x**2) + factorial(m)**2/(x**2*factorial(m - x)*factorial(m + x)) + + g = gosper_sum(f2a, (n, 0, m)) + assert g is not None and simplify(g - g2a) == 0 + g = gosper_sum(f2b, (n, 0, m)) + assert g is not None and simplify(g - g2b) == 0 + g = gosper_sum(f2c, (n, 1, m)) + assert g is not None and simplify(g - g2c) == 0 + + +def test_gosper_nan(): + a = Symbol('a', positive=True) + b = Symbol('b', positive=True) + n = Symbol('n', integer=True) + m = Symbol('m', integer=True) + f2d = n*(n + a + b)*a**n*b**n/(factorial(n + a)*factorial(n + b)) + g2d = 1/(factorial(a - 1)*factorial( + b - 1)) - a**(m + 1)*b**(m + 1)/(factorial(a + m)*factorial(b + m)) + g = gosper_sum(f2d, (n, 0, m)) + assert simplify(g - g2d) == 0 + + +def test_gosper_sum_AeqB_part3(): + f3a = 1/n**4 + f3b = (6*n + 3)/(4*n**4 + 8*n**3 + 8*n**2 + 4*n + 3) + f3c = 2**n*(n**2 - 2*n - 1)/(n**2*(n + 1)**2) + f3d = n**2*4**n/((n + 1)*(n + 2)) + f3e = 2**n/(n + 1) + f3f = 4*(n - 1)*(n**2 - 2*n - 1)/(n**2*(n + 1)**2*(n - 2)**2*(n - 3)**2) + f3g = (n**4 - 14*n**2 - 24*n - 9)*2**n/(n**2*(n + 1)**2*(n + 2)**2* + (n + 3)**2) + + # g3a -> no closed form + g3b = m*(m + 2)/(2*m**2 + 4*m + 3) + g3c = 2**m/m**2 - 2 + g3d = Rational(2, 3) + 4**(m + 1)*(m - 1)/(m + 2)/3 + # g3e -> no closed form + g3f = -(Rational(-1, 16) + 1/((m - 2)**2*(m + 1)**2)) # the AeqB key is wrong + g3g = Rational(-2, 9) + 2**(m + 1)/((m + 1)**2*(m + 3)**2) + + g = gosper_sum(f3a, (n, 1, m)) + assert g is None + g = gosper_sum(f3b, (n, 1, m)) + assert g is not None and simplify(g - g3b) == 0 + g = gosper_sum(f3c, (n, 1, m - 1)) + assert g is not None and simplify(g - g3c) == 0 + g = gosper_sum(f3d, (n, 1, m)) + assert g is not None and simplify(g - g3d) == 0 + g = gosper_sum(f3e, (n, 0, m - 1)) + assert g is None + g = gosper_sum(f3f, (n, 4, m)) + assert g is not None and simplify(g - g3f) == 0 + g = gosper_sum(f3g, (n, 1, m)) + assert g is not None and simplify(g - g3g) == 0 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/test_guess.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/test_guess.py new file mode 100644 index 0000000000000000000000000000000000000000..5ac5d02b89ad62a70a29bd450b71b284b6aea76d --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/test_guess.py @@ -0,0 +1,82 @@ +from sympy.concrete.guess import ( + find_simple_recurrence_vector, + find_simple_recurrence, + rationalize, + guess_generating_function_rational, + guess_generating_function, + guess + ) +from sympy.concrete.products import Product +from sympy.core.function import Function +from sympy.core.numbers import Rational +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.core.sympify import sympify +from sympy.functions.combinatorial.factorials import (RisingFactorial, factorial) +from sympy.functions.combinatorial.numbers import fibonacci +from sympy.functions.elementary.exponential import exp + + +def test_find_simple_recurrence_vector(): + assert find_simple_recurrence_vector( + [fibonacci(k) for k in range(12)]) == [1, -1, -1] + + +def test_find_simple_recurrence(): + a = Function('a') + n = Symbol('n') + assert find_simple_recurrence([fibonacci(k) for k in range(12)]) == ( + -a(n) - a(n + 1) + a(n + 2)) + + f = Function('a') + i = Symbol('n') + a = [1, 1, 1] + for k in range(15): a.append(5*a[-1]-3*a[-2]+8*a[-3]) + assert find_simple_recurrence(a, A=f, N=i) == ( + -8*f(i) + 3*f(i + 1) - 5*f(i + 2) + f(i + 3)) + assert find_simple_recurrence([0, 2, 15, 74, 12, 3, 0, + 1, 2, 85, 4, 5, 63]) == 0 + + +def test_rationalize(): + from mpmath import cos, pi, mpf + assert rationalize(cos(pi/3)) == S.Half + assert rationalize(mpf("0.333333333333333")) == Rational(1, 3) + assert rationalize(mpf("-0.333333333333333")) == Rational(-1, 3) + assert rationalize(pi, maxcoeff = 250) == Rational(355, 113) + + +def test_guess_generating_function_rational(): + x = Symbol('x') + assert guess_generating_function_rational([fibonacci(k) + for k in range(5, 15)]) == ((3*x + 5)/(-x**2 - x + 1)) + + +def test_guess_generating_function(): + x = Symbol('x') + assert guess_generating_function([fibonacci(k) + for k in range(5, 15)])['ogf'] == ((3*x + 5)/(-x**2 - x + 1)) + assert guess_generating_function( + [1, 2, 5, 14, 41, 124, 383, 1200, 3799, 12122, 38919])['ogf'] == ( + (1/(x**4 + 2*x**2 - 4*x + 1))**S.Half) + assert guess_generating_function(sympify( + "[3/2, 11/2, 0, -121/2, -363/2, 121, 4719/2, 11495/2, -8712, -178717/2]") + )['ogf'] == (x + Rational(3, 2))/(11*x**2 - 3*x + 1) + assert guess_generating_function([factorial(k) for k in range(12)], + types=['egf'])['egf'] == 1/(-x + 1) + assert guess_generating_function([k+1 for k in range(12)], + types=['egf']) == {'egf': (x + 1)*exp(x), 'lgdegf': (x + 2)/(x + 1)} + + +def test_guess(): + i0, i1 = symbols('i0 i1') + assert guess([1, 2, 6, 24, 120], evaluate=False) == [Product(i1 + 1, (i1, 1, i0 - 1))] + assert guess([1, 2, 6, 24, 120]) == [RisingFactorial(2, i0 - 1)] + assert guess([1, 2, 7, 42, 429, 7436, 218348, 10850216], niter=4) == [ + 2**(i0 - 1)*(Rational(27, 16))**(i0**2/2 - 3*i0/2 + + 1)*Product(RisingFactorial(Rational(5, 3), i1 - 1)*RisingFactorial(Rational(7, 3), i1 + - 1)/(RisingFactorial(Rational(3, 2), i1 - 1)*RisingFactorial(Rational(5, 2), i1 - + 1)), (i1, 1, i0 - 1))] + assert guess([1, 0, 2]) == [] + x, y = symbols('x y') + assert guess([1, 2, 6, 24, 120], variables=[x, y]) == [RisingFactorial(2, x - 1)] diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/test_products.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/test_products.py new file mode 100644 index 0000000000000000000000000000000000000000..9be053a7040014c6ed38c1279a609fcb2426258e --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/test_products.py @@ -0,0 +1,410 @@ +from sympy.concrete.products import (Product, product) +from sympy.concrete.summations import Sum +from sympy.core.function import (Derivative, Function, diff) +from sympy.core.numbers import (Rational, oo, pi) +from sympy.core.singleton import S +from sympy.core.symbol import (Dummy, Symbol, symbols) +from sympy.functions.combinatorial.factorials import (rf, factorial) +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.functions.special.tensor_functions import KroneckerDelta +from sympy.simplify.combsimp import combsimp +from sympy.simplify.simplify import simplify +from sympy.testing.pytest import raises + +a, k, n, m, x = symbols('a,k,n,m,x', integer=True) +f = Function('f') + + +def test_karr_convention(): + # Test the Karr product convention that we want to hold. + # See his paper "Summation in Finite Terms" for a detailed + # reasoning why we really want exactly this definition. + # The convention is described for sums on page 309 and + # essentially in section 1.4, definition 3. For products + # we can find in analogy: + # + # \prod_{m <= i < n} f(i) 'has the obvious meaning' for m < n + # \prod_{m <= i < n} f(i) = 0 for m = n + # \prod_{m <= i < n} f(i) = 1 / \prod_{n <= i < m} f(i) for m > n + # + # It is important to note that he defines all products with + # the upper limit being *exclusive*. + # In contrast, SymPy and the usual mathematical notation has: + # + # prod_{i = a}^b f(i) = f(a) * f(a+1) * ... * f(b-1) * f(b) + # + # with the upper limit *inclusive*. So translating between + # the two we find that: + # + # \prod_{m <= i < n} f(i) = \prod_{i = m}^{n-1} f(i) + # + # where we intentionally used two different ways to typeset the + # products and its limits. + + i = Symbol("i", integer=True) + k = Symbol("k", integer=True) + j = Symbol("j", integer=True, positive=True) + + # A simple example with a concrete factors and symbolic limits. + + # The normal product: m = k and n = k + j and therefore m < n: + m = k + n = k + j + + a = m + b = n - 1 + S1 = Product(i**2, (i, a, b)).doit() + + # The reversed product: m = k + j and n = k and therefore m > n: + m = k + j + n = k + + a = m + b = n - 1 + S2 = Product(i**2, (i, a, b)).doit() + + assert S1 * S2 == 1 + + # Test the empty product: m = k and n = k and therefore m = n: + m = k + n = k + + a = m + b = n - 1 + Sz = Product(i**2, (i, a, b)).doit() + + assert Sz == 1 + + # Another example this time with an unspecified factor and + # numeric limits. (We can not do both tests in the same example.) + f = Function("f") + + # The normal product with m < n: + m = 2 + n = 11 + + a = m + b = n - 1 + S1 = Product(f(i), (i, a, b)).doit() + + # The reversed product with m > n: + m = 11 + n = 2 + + a = m + b = n - 1 + S2 = Product(f(i), (i, a, b)).doit() + + assert simplify(S1 * S2) == 1 + + # Test the empty product with m = n: + m = 5 + n = 5 + + a = m + b = n - 1 + Sz = Product(f(i), (i, a, b)).doit() + + assert Sz == 1 + + +def test_karr_proposition_2a(): + # Test Karr, page 309, proposition 2, part a + i, u, v = symbols('i u v', integer=True) + + def test_the_product(m, n): + # g + g = i**3 + 2*i**2 - 3*i + # f = Delta g + f = simplify(g.subs(i, i+1) / g) + # The product + a = m + b = n - 1 + P = Product(f, (i, a, b)).doit() + # Test if Product_{m <= i < n} f(i) = g(n) / g(m) + assert combsimp(P / (g.subs(i, n) / g.subs(i, m))) == 1 + + # m < n + test_the_product(u, u + v) + # m = n + test_the_product(u, u) + # m > n + test_the_product(u + v, u) + + +def test_karr_proposition_2b(): + # Test Karr, page 309, proposition 2, part b + i, u, v, w = symbols('i u v w', integer=True) + + def test_the_product(l, n, m): + # Productmand + s = i**3 + # First product + a = l + b = n - 1 + S1 = Product(s, (i, a, b)).doit() + # Second product + a = l + b = m - 1 + S2 = Product(s, (i, a, b)).doit() + # Third product + a = m + b = n - 1 + S3 = Product(s, (i, a, b)).doit() + # Test if S1 = S2 * S3 as required + assert combsimp(S1 / (S2 * S3)) == 1 + + # l < m < n + test_the_product(u, u + v, u + v + w) + # l < m = n + test_the_product(u, u + v, u + v) + # l < m > n + test_the_product(u, u + v + w, v) + # l = m < n + test_the_product(u, u, u + v) + # l = m = n + test_the_product(u, u, u) + # l = m > n + test_the_product(u + v, u + v, u) + # l > m < n + test_the_product(u + v, u, u + w) + # l > m = n + test_the_product(u + v, u, u) + # l > m > n + test_the_product(u + v + w, u + v, u) + + +def test_simple_products(): + assert product(2, (k, a, n)) == 2**(n - a + 1) + assert product(k, (k, 1, n)) == factorial(n) + assert product(k**3, (k, 1, n)) == factorial(n)**3 + + assert product(k + 1, (k, 0, n - 1)) == factorial(n) + assert product(k + 1, (k, a, n - 1)) == rf(1 + a, n - a) + + assert product(cos(k), (k, 0, 5)) == cos(1)*cos(2)*cos(3)*cos(4)*cos(5) + assert product(cos(k), (k, 3, 5)) == cos(3)*cos(4)*cos(5) + assert product(cos(k), (k, 1, Rational(5, 2))) != cos(1)*cos(2) + + assert isinstance(product(k**k, (k, 1, n)), Product) + + assert Product(x**k, (k, 1, n)).variables == [k] + + raises(ValueError, lambda: Product(n)) + raises(ValueError, lambda: Product(n, k)) + raises(ValueError, lambda: Product(n, k, 1)) + raises(ValueError, lambda: Product(n, k, 1, 10)) + raises(ValueError, lambda: Product(n, (k, 1))) + + assert product(1, (n, 1, oo)) == 1 # issue 8301 + assert product(2, (n, 1, oo)) is oo + assert product(-1, (n, 1, oo)).func is Product + + +def test_multiple_products(): + assert product(x, (n, 1, k), (k, 1, m)) == x**(m**2/2 + m/2) + assert product(f(n), ( + n, 1, m), (m, 1, k)) == Product(f(n), (n, 1, m), (m, 1, k)).doit() + assert Product(f(n), (m, 1, k), (n, 1, k)).doit() == \ + Product(Product(f(n), (m, 1, k)), (n, 1, k)).doit() == \ + product(f(n), (m, 1, k), (n, 1, k)) == \ + product(product(f(n), (m, 1, k)), (n, 1, k)) == \ + Product(f(n)**k, (n, 1, k)) + assert Product( + x, (x, 1, k), (k, 1, n)).doit() == Product(factorial(k), (k, 1, n)) + + assert Product(x**k, (n, 1, k), (k, 1, m)).variables == [n, k] + + +def test_rational_products(): + assert product(1 + 1/k, (k, 1, n)) == rf(2, n)/factorial(n) + + +def test_special_products(): + # Wallis product + assert product((4*k)**2 / (4*k**2 - 1), (k, 1, n)) == \ + 4**n*factorial(n)**2/rf(S.Half, n)/rf(Rational(3, 2), n) + + # Euler's product formula for sin + assert product(1 + a/k**2, (k, 1, n)) == \ + rf(1 - sqrt(-a), n)*rf(1 + sqrt(-a), n)/factorial(n)**2 + + +def test__eval_product(): + from sympy.abc import i, n + # issue 4809 + a = Function('a') + assert product(2*a(i), (i, 1, n)) == 2**n * Product(a(i), (i, 1, n)) + # issue 4810 + assert product(2**i, (i, 1, n)) == 2**(n*(n + 1)/2) + k, m = symbols('k m', integer=True) + assert product(2**i, (i, k, m)) == 2**(-k**2/2 + k/2 + m**2/2 + m/2) + n = Symbol('n', negative=True, integer=True) + p = Symbol('p', positive=True, integer=True) + assert product(2**i, (i, n, p)) == 2**(-n**2/2 + n/2 + p**2/2 + p/2) + assert product(2**i, (i, p, n)) == 2**(n**2/2 + n/2 - p**2/2 + p/2) + + +def test_product_pow(): + # issue 4817 + assert product(2**f(k), (k, 1, n)) == 2**Sum(f(k), (k, 1, n)) + assert product(2**(2*f(k)), (k, 1, n)) == 2**Sum(2*f(k), (k, 1, n)) + + +def test_infinite_product(): + # issue 5737 + assert isinstance(Product(2**(1/factorial(n)), (n, 0, oo)), Product) + + +def test_conjugate_transpose(): + p = Product(x**k, (k, 1, 3)) + assert p.adjoint().doit() == p.doit().adjoint() + assert p.conjugate().doit() == p.doit().conjugate() + assert p.transpose().doit() == p.doit().transpose() + + A, B = symbols("A B", commutative=False) + p = Product(A*B**k, (k, 1, 3)) + assert p.adjoint().doit() == p.doit().adjoint() + assert p.conjugate().doit() == p.doit().conjugate() + assert p.transpose().doit() == p.doit().transpose() + + p = Product(B**k*A, (k, 1, 3)) + assert p.adjoint().doit() == p.doit().adjoint() + assert p.conjugate().doit() == p.doit().conjugate() + assert p.transpose().doit() == p.doit().transpose() + + +def test_simplify_prod(): + y, t, b, c, v, d = symbols('y, t, b, c, v, d', integer = True) + + _simplify = lambda e: simplify(e, doit=False) + assert _simplify(Product(x*y, (x, n, m), (y, a, k)) * \ + Product(y, (x, n, m), (y, a, k))) == \ + Product(x*y**2, (x, n, m), (y, a, k)) + assert _simplify(3 * y* Product(x, (x, n, m)) * Product(x, (x, m + 1, a))) \ + == 3 * y * Product(x, (x, n, a)) + assert _simplify(Product(x, (x, k + 1, a)) * Product(x, (x, n, k))) == \ + Product(x, (x, n, a)) + assert _simplify(Product(x, (x, k + 1, a)) * Product(x + 1, (x, n, k))) == \ + Product(x, (x, k + 1, a)) * Product(x + 1, (x, n, k)) + assert _simplify(Product(x, (t, a, b)) * Product(y, (t, a, b)) * \ + Product(x, (t, b+1, c))) == Product(x*y, (t, a, b)) * \ + Product(x, (t, b+1, c)) + assert _simplify(Product(x, (t, a, b)) * Product(x, (t, b+1, c)) * \ + Product(y, (t, a, b))) == Product(x*y, (t, a, b)) * \ + Product(x, (t, b+1, c)) + assert _simplify(Product(sin(t)**2 + cos(t)**2 + 1, (t, a, b))) == \ + Product(2, (t, a, b)) + assert _simplify(Product(sin(t)**2 + cos(t)**2 - 1, (t, a, b))) == \ + Product(0, (t, a, b)) + assert _simplify(Product(v*Product(sin(t)**2 + cos(t)**2, (t, a, b)), + (v, c, d))) == Product(v*Product(1, (t, a, b)), (v, c, d)) + + +def test_change_index(): + b, y, c, d, z = symbols('b, y, c, d, z', integer = True) + + assert Product(x, (x, a, b)).change_index(x, x + 1, y) == \ + Product(y - 1, (y, a + 1, b + 1)) + assert Product(x**2, (x, a, b)).change_index(x, x - 1) == \ + Product((x + 1)**2, (x, a - 1, b - 1)) + assert Product(x**2, (x, a, b)).change_index(x, -x, y) == \ + Product((-y)**2, (y, -b, -a)) + assert Product(x, (x, a, b)).change_index(x, -x - 1) == \ + Product(-x - 1, (x, - b - 1, -a - 1)) + assert Product(x*y, (x, a, b), (y, c, d)).change_index(x, x - 1, z) == \ + Product((z + 1)*y, (z, a - 1, b - 1), (y, c, d)) + + +def test_reorder(): + b, y, c, d, z = symbols('b, y, c, d, z', integer = True) + + assert Product(x*y, (x, a, b), (y, c, d)).reorder((0, 1)) == \ + Product(x*y, (y, c, d), (x, a, b)) + assert Product(x, (x, a, b), (x, c, d)).reorder((0, 1)) == \ + Product(x, (x, c, d), (x, a, b)) + assert Product(x*y + z, (x, a, b), (z, m, n), (y, c, d)).reorder(\ + (2, 0), (0, 1)) == Product(x*y + z, (z, m, n), (y, c, d), (x, a, b)) + assert Product(x*y*z, (x, a, b), (y, c, d), (z, m, n)).reorder(\ + (0, 1), (1, 2), (0, 2)) == \ + Product(x*y*z, (x, a, b), (z, m, n), (y, c, d)) + assert Product(x*y*z, (x, a, b), (y, c, d), (z, m, n)).reorder(\ + (x, y), (y, z), (x, z)) == \ + Product(x*y*z, (x, a, b), (z, m, n), (y, c, d)) + assert Product(x*y, (x, a, b), (y, c, d)).reorder((x, 1)) == \ + Product(x*y, (y, c, d), (x, a, b)) + assert Product(x*y, (x, a, b), (y, c, d)).reorder((y, x)) == \ + Product(x*y, (y, c, d), (x, a, b)) + + +def test_Product_is_convergent(): + assert Product(1/n**2, (n, 1, oo)).is_convergent() is S.false + assert Product(exp(1/n**2), (n, 1, oo)).is_convergent() is S.true + assert Product(1/n, (n, 1, oo)).is_convergent() is S.false + assert Product(1 + 1/n, (n, 1, oo)).is_convergent() is S.false + assert Product(1 + 1/n**2, (n, 1, oo)).is_convergent() is S.true + + +def test_reverse_order(): + x, y, a, b, c, d= symbols('x, y, a, b, c, d', integer = True) + + assert Product(x, (x, 0, 3)).reverse_order(0) == Product(1/x, (x, 4, -1)) + assert Product(x*y, (x, 1, 5), (y, 0, 6)).reverse_order(0, 1) == \ + Product(x*y, (x, 6, 0), (y, 7, -1)) + assert Product(x, (x, 1, 2)).reverse_order(0) == Product(1/x, (x, 3, 0)) + assert Product(x, (x, 1, 3)).reverse_order(0) == Product(1/x, (x, 4, 0)) + assert Product(x, (x, 1, a)).reverse_order(0) == Product(1/x, (x, a + 1, 0)) + assert Product(x, (x, a, 5)).reverse_order(0) == Product(1/x, (x, 6, a - 1)) + assert Product(x, (x, a + 1, a + 5)).reverse_order(0) == \ + Product(1/x, (x, a + 6, a)) + assert Product(x, (x, a + 1, a + 2)).reverse_order(0) == \ + Product(1/x, (x, a + 3, a)) + assert Product(x, (x, a + 1, a + 1)).reverse_order(0) == \ + Product(1/x, (x, a + 2, a)) + assert Product(x, (x, a, b)).reverse_order(0) == Product(1/x, (x, b + 1, a - 1)) + assert Product(x, (x, a, b)).reverse_order(x) == Product(1/x, (x, b + 1, a - 1)) + assert Product(x*y, (x, a, b), (y, 2, 5)).reverse_order(x, 1) == \ + Product(x*y, (x, b + 1, a - 1), (y, 6, 1)) + assert Product(x*y, (x, a, b), (y, 2, 5)).reverse_order(y, x) == \ + Product(x*y, (x, b + 1, a - 1), (y, 6, 1)) + + +def test_issue_9983(): + n = Symbol('n', integer=True, positive=True) + p = Product(1 + 1/n**Rational(2, 3), (n, 1, oo)) + assert p.is_convergent() is S.false + assert product(1 + 1/n**Rational(2, 3), (n, 1, oo)) == p.doit() + + +def test_issue_13546(): + n = Symbol('n') + k = Symbol('k') + p = Product(n + 1 / 2**k, (k, 0, n-1)).doit() + assert p.subs(n, 2).doit() == Rational(15, 2) + + +def test_issue_14036(): + a, n = symbols('a n') + assert product(1 - a**2 / (n*pi)**2, [n, 1, oo]) != 0 + + +def test_rewrite_Sum(): + assert Product(1 - S.Half**2/k**2, (k, 1, oo)).rewrite(Sum) == \ + exp(Sum(log(1 - 1/(4*k**2)), (k, 1, oo))) + + +def test_KroneckerDelta_Product(): + y = Symbol('y') + assert Product(x*KroneckerDelta(x, y), (x, 0, 1)).doit() == 0 + + +def test_issue_20848(): + _i = Dummy('i') + t, y, z = symbols('t y z') + assert diff(Product(x, (y, 1, z)), x).as_dummy() == Sum(Product(x, (y, 1, _i - 1))*Product(x, (y, _i + 1, z)), (_i, 1, z)).as_dummy() + assert diff(Product(x, (y, 1, z)), x).doit() == x**(z - 1)*z + assert diff(Product(x, (y, x, z)), x) == Derivative(Product(x, (y, x, z)), x) + assert diff(Product(t, (x, 1, z)), x) == S(0) + assert Product(sin(n*x), (n, -1, 1)).diff(x).doit() == S(0) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/test_sums_products.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/test_sums_products.py new file mode 100644 index 0000000000000000000000000000000000000000..b190afe0bd403819d3525453879d7d5d39e20a56 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/concrete/tests/test_sums_products.py @@ -0,0 +1,1676 @@ +from math import prod + +from sympy.concrete.expr_with_intlimits import ReorderError +from sympy.concrete.products import (Product, product) +from sympy.concrete.summations import (Sum, summation, telescopic, + eval_sum_residue, _dummy_with_inherited_properties_concrete) +from sympy.core.function import (Derivative, Function) +from sympy.core import (Catalan, EulerGamma) +from sympy.core.facts import InconsistentAssumptions +from sympy.core.mod import Mod +from sympy.core.numbers import (E, I, Rational, nan, oo, pi) +from sympy.core.relational import Eq, Ne +from sympy.core.numbers import Float +from sympy.core.singleton import S +from sympy.core.symbol import (Dummy, Symbol, symbols) +from sympy.core.sympify import sympify +from sympy.functions.combinatorial.factorials import (rf, binomial, factorial) +from sympy.functions.combinatorial.numbers import harmonic +from sympy.functions.elementary.complexes import Abs, re +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.hyperbolic import (sinh, tanh) +from sympy.functions.elementary.integers import floor +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.piecewise import Piecewise +from sympy.functions.elementary.trigonometric import (cos, sin, atan) +from sympy.functions.special.gamma_functions import (gamma, lowergamma) +from sympy.functions.special.tensor_functions import KroneckerDelta +from sympy.functions.special.zeta_functions import zeta +from sympy.integrals.integrals import Integral +from sympy.logic.boolalg import And, Or +from sympy.matrices.expressions.matexpr import MatrixSymbol +from sympy.matrices.expressions.special import Identity +from sympy.matrices import (Matrix, SparseMatrix, + ImmutableDenseMatrix, ImmutableSparseMatrix, diag) +from sympy.sets.contains import Contains +from sympy.sets.fancysets import Range +from sympy.sets.sets import Interval +from sympy.simplify.combsimp import combsimp +from sympy.simplify.simplify import simplify +from sympy.tensor.indexed import (Idx, Indexed, IndexedBase) +from sympy.testing.pytest import XFAIL, raises, slow +from sympy.abc import a, b, c, d, k, m, x, y, z + +n = Symbol('n', integer=True) +f, g = symbols('f g', cls=Function) + +def test_karr_convention(): + # Test the Karr summation convention that we want to hold. + # See his paper "Summation in Finite Terms" for a detailed + # reasoning why we really want exactly this definition. + # The convention is described on page 309 and essentially + # in section 1.4, definition 3: + # + # \sum_{m <= i < n} f(i) 'has the obvious meaning' for m < n + # \sum_{m <= i < n} f(i) = 0 for m = n + # \sum_{m <= i < n} f(i) = - \sum_{n <= i < m} f(i) for m > n + # + # It is important to note that he defines all sums with + # the upper limit being *exclusive*. + # In contrast, SymPy and the usual mathematical notation has: + # + # sum_{i = a}^b f(i) = f(a) + f(a+1) + ... + f(b-1) + f(b) + # + # with the upper limit *inclusive*. So translating between + # the two we find that: + # + # \sum_{m <= i < n} f(i) = \sum_{i = m}^{n-1} f(i) + # + # where we intentionally used two different ways to typeset the + # sum and its limits. + + i = Symbol("i", integer=True) + k = Symbol("k", integer=True) + j = Symbol("j", integer=True) + + # A simple example with a concrete summand and symbolic limits. + + # The normal sum: m = k and n = k + j and therefore m < n: + m = k + n = k + j + + a = m + b = n - 1 + S1 = Sum(i**2, (i, a, b)).doit() + + # The reversed sum: m = k + j and n = k and therefore m > n: + m = k + j + n = k + + a = m + b = n - 1 + S2 = Sum(i**2, (i, a, b)).doit() + + assert simplify(S1 + S2) == 0 + + # Test the empty sum: m = k and n = k and therefore m = n: + m = k + n = k + + a = m + b = n - 1 + Sz = Sum(i**2, (i, a, b)).doit() + + assert Sz == 0 + + # Another example this time with an unspecified summand and + # numeric limits. (We can not do both tests in the same example.) + + # The normal sum with m < n: + m = 2 + n = 11 + + a = m + b = n - 1 + S1 = Sum(f(i), (i, a, b)).doit() + + # The reversed sum with m > n: + m = 11 + n = 2 + + a = m + b = n - 1 + S2 = Sum(f(i), (i, a, b)).doit() + + assert simplify(S1 + S2) == 0 + + # Test the empty sum with m = n: + m = 5 + n = 5 + + a = m + b = n - 1 + Sz = Sum(f(i), (i, a, b)).doit() + + assert Sz == 0 + + e = Piecewise((exp(-i), Mod(i, 2) > 0), (0, True)) + s = Sum(e, (i, 0, 11)) + assert s.n(3) == s.doit().n(3) + + # issue #27893 + n = Symbol('n', integer=True) + assert Sum(1/(x**2 + 1), (x, oo, 0)).doit(deep=False) == Rational(-1, 2) + pi / (2 * tanh(pi)) + assert Sum(c**x/factorial(x), (x, oo, 0)).doit(deep=False).simplify() == exp(c) - 1 # exponential series + assert Sum((-1)**x/x, (x, oo,0)).doit() == -log(2) # alternating harmnic series + assert Sum((1/2)**x,(x, oo, -1)).doit() == S(2) # geometric series + assert Sum(1/x, (x, oo, 0)).doit() == oo # harmonic series, divergent + assert Sum((-1)**x/(2*x+1), (x, oo, -1)).doit() == pi/4 # leibniz series + assert Sum((((-1)**x) * c**(2*x+1)) / factorial(2*x+1), (x, oo, -1)).doit() == sin(c) # sinusoidal series + assert Sum((((-1)**x) * c**(2*x+1)) / (2*x+1), (x, 0, oo)).doit() \ + == Piecewise((atan(c), Ne(c**2, -1) & (Abs(c**2) <= 1)), \ + (Sum((-1)**x*c**(2*x + 1)/(2*x + 1), (x, 0, oo)), True)) # arctangent series + assert Sum(binomial(n, x) * c**x, (x, 0, oo)).doit() \ + == Piecewise(((c + 1)**n, \ + ((n <= -1) & (Abs(c) < 1)) \ + | ((n > 0) & (Abs(c) <= 1)) \ + | ((n <= 0) & (n > -1) & Ne(c, -1) & (Abs(c) <= 1))), \ + (Sum(c**x*binomial(n, x), (x, 0, oo)), True)) # binomial series + assert Sum(1/x**n, (x, oo, 0)).doit() \ + == Piecewise((zeta(n), n > 1), (Sum(x**(-n), (x, oo, 0)), True)) # Euler's zeta function + +def test_karr_proposition_2a(): + # Test Karr, page 309, proposition 2, part a + i = Symbol("i", integer=True) + u = Symbol("u", integer=True) + v = Symbol("v", integer=True) + + def test_the_sum(m, n): + # g + g = i**3 + 2*i**2 - 3*i + # f = Delta g + f = simplify(g.subs(i, i+1) - g) + # The sum + a = m + b = n - 1 + S = Sum(f, (i, a, b)).doit() + # Test if Sum_{m <= i < n} f(i) = g(n) - g(m) + assert simplify(S - (g.subs(i, n) - g.subs(i, m))) == 0 + + # m < n + test_the_sum(u, u+v) + # m = n + test_the_sum(u, u ) + # m > n + test_the_sum(u+v, u ) + + +def test_karr_proposition_2b(): + # Test Karr, page 309, proposition 2, part b + i = Symbol("i", integer=True) + u = Symbol("u", integer=True) + v = Symbol("v", integer=True) + w = Symbol("w", integer=True) + + def test_the_sum(l, n, m): + # Summand + s = i**3 + # First sum + a = l + b = n - 1 + S1 = Sum(s, (i, a, b)).doit() + # Second sum + a = l + b = m - 1 + S2 = Sum(s, (i, a, b)).doit() + # Third sum + a = m + b = n - 1 + S3 = Sum(s, (i, a, b)).doit() + # Test if S1 = S2 + S3 as required + assert S1 - (S2 + S3) == 0 + + # l < m < n + test_the_sum(u, u+v, u+v+w) + # l < m = n + test_the_sum(u, u+v, u+v ) + # l < m > n + test_the_sum(u, u+v+w, v ) + # l = m < n + test_the_sum(u, u, u+v ) + # l = m = n + test_the_sum(u, u, u ) + # l = m > n + test_the_sum(u+v, u+v, u ) + # l > m < n + test_the_sum(u+v, u, u+w ) + # l > m = n + test_the_sum(u+v, u, u ) + # l > m > n + test_the_sum(u+v+w, u+v, u ) + + +def test_arithmetic_sums(): + assert summation(1, (n, a, b)) == b - a + 1 + assert Sum(S.NaN, (n, a, b)) is S.NaN + assert Sum(x, (n, a, a)).doit() == x + assert Sum(x, (x, a, a)).doit() == a + assert Sum(x, (n, 1, a)).doit() == a*x + assert Sum(x, (x, Range(1, 11))).doit() == 55 + assert Sum(x, (x, Range(1, 11, 2))).doit() == 25 + assert Sum(x, (x, Range(1, 10, 2))) == Sum(x, (x, Range(9, 0, -2))) + lo, hi = 1, 2 + s1 = Sum(n, (n, lo, hi)) + s2 = Sum(n, (n, hi, lo)) + assert s1 != s2 + assert s1.doit() == 3 and s2.doit() == 0 + lo, hi = x, x + 1 + s1 = Sum(n, (n, lo, hi)) + s2 = Sum(n, (n, hi, lo)) + assert s1 != s2 + assert s1.doit() == 2*x + 1 and s2.doit() == 0 + assert Sum(Integral(x, (x, 1, y)) + x, (x, 1, 2)).doit() == \ + y**2 + 2 + assert summation(1, (n, 1, 10)) == 10 + assert summation(2*n, (n, 0, 10**10)) == 100000000010000000000 + assert summation(4*n*m, (n, a, 1), (m, 1, d)).expand() == \ + 2*d + 2*d**2 + a*d + a*d**2 - d*a**2 - a**2*d**2 + assert summation(cos(n), (n, -2, 1)) == cos(-2) + cos(-1) + cos(0) + cos(1) + assert summation(cos(n), (n, x, x + 2)) == cos(x) + cos(x + 1) + cos(x + 2) + assert isinstance(summation(cos(n), (n, x, x + S.Half)), Sum) + assert summation(k, (k, 0, oo)) is oo + assert summation(k, (k, Range(1, 11))) == 55 + + +def test_polynomial_sums(): + assert summation(n**2, (n, 3, 8)) == 199 + assert summation(n, (n, a, b)) == \ + ((a + b)*(b - a + 1)/2).expand() + assert summation(n**2, (n, 1, b)) == \ + ((2*b**3 + 3*b**2 + b)/6).expand() + assert summation(n**3, (n, 1, b)) == \ + ((b**4 + 2*b**3 + b**2)/4).expand() + assert summation(n**6, (n, 1, b)) == \ + ((6*b**7 + 21*b**6 + 21*b**5 - 7*b**3 + b)/42).expand() + + +def test_geometric_sums(): + assert summation(pi**n, (n, 0, b)) == (1 - pi**(b + 1)) / (1 - pi) + assert summation(2 * 3**n, (n, 0, b)) == 3**(b + 1) - 1 + assert summation(S.Half**n, (n, 1, oo)) == 1 + assert summation(2**n, (n, 0, b)) == 2**(b + 1) - 1 + assert summation(2**n, (n, 1, oo)) is oo + assert summation(2**(-n), (n, 1, oo)) == 1 + assert summation(3**(-n), (n, 4, oo)) == Rational(1, 54) + assert summation(2**(-4*n + 3), (n, 1, oo)) == Rational(8, 15) + assert summation(2**(n + 1), (n, 1, b)).expand() == 4*(2**b - 1) + + # issue 6664: + assert summation(x**n, (n, 0, oo)) == \ + Piecewise((1/(-x + 1), Abs(x) < 1), (Sum(x**n, (n, 0, oo)), True)) + + assert summation(-2**n, (n, 0, oo)) is -oo + assert summation(I**n, (n, 0, oo)) == Sum(I**n, (n, 0, oo)) + + # issue 6802: + assert summation((-1)**(2*x + 2), (x, 0, n)) == n + 1 + assert summation((-2)**(2*x + 2), (x, 0, n)) == 4*4**(n + 1)/S(3) - Rational(4, 3) + assert summation((-1)**x, (x, 0, n)) == -(-1)**(n + 1)/S(2) + S.Half + assert summation(y**x, (x, a, b)) == \ + Piecewise((-a + b + 1, Eq(y, 1)), ((y**a - y**(b + 1))/(-y + 1), True)) + assert summation((-2)**(y*x + 2), (x, 0, n)) == \ + 4*Piecewise((n + 1, Eq((-2)**y, 1)), + ((-(-2)**(y*(n + 1)) + 1)/(-(-2)**y + 1), True)) + + # issue 8251: + assert summation((1/(n + 1)**2)*n**2, (n, 0, oo)) is oo + + #issue 9908: + assert Sum(1/(n**3 - 1), (n, -oo, -2)).doit() == summation(1/(n**3 - 1), (n, -oo, -2)) + + #issue 11642: + result = Sum(0.5**n, (n, 1, oo)).doit() + assert result == 1.0 + assert result.is_Float + + result = Sum(0.25**n, (n, 1, oo)).doit() + assert result == 1/3. + assert result.is_Float + + result = Sum(0.99999**n, (n, 1, oo)).doit() + assert result == 99999.0 + assert result.is_Float + + result = Sum(S.Half**n, (n, 1, oo)).doit() + assert result == 1 + assert not result.is_Float + + result = Sum(Rational(3, 5)**n, (n, 1, oo)).doit() + assert result == Rational(3, 2) + assert not result.is_Float + + assert Sum(1.0**n, (n, 1, oo)).doit() is oo + assert Sum(2.43**n, (n, 1, oo)).doit() is oo + + # Issue 13979 + i, k, q = symbols('i k q', integer=True) + result = summation( + exp(-2*I*pi*k*i/n) * exp(2*I*pi*q*i/n) / n, (i, 0, n - 1) + ) + assert result.simplify() == Piecewise( + (1, Eq(exp(-2*I*pi*(k - q)/n), 1)), (0, True) + ) + + #Issue 23491 + assert Sum(1/(n**2 + 1), (n, 1, oo)).doit() == S(-1)/2 + pi/(2*tanh(pi)) + +def test_harmonic_sums(): + assert summation(1/k, (k, 0, n)) == Sum(1/k, (k, 0, n)) + assert summation(1/k, (k, 1, n)) == harmonic(n) + assert summation(n/k, (k, 1, n)) == n*harmonic(n) + assert summation(1/k, (k, 5, n)) == harmonic(n) - harmonic(4) + + +def test_composite_sums(): + f = S.Half*(7 - 6*n + Rational(1, 7)*n**3) + s = summation(f, (n, a, b)) + assert not isinstance(s, Sum) + A = 0 + for i in range(-3, 5): + A += f.subs(n, i) + B = s.subs(a, -3).subs(b, 4) + assert A == B + + +def test_hypergeometric_sums(): + assert summation( + binomial(2*k, k)/4**k, (k, 0, n)) == (1 + 2*n)*binomial(2*n, n)/4**n + assert summation(binomial(2*k, k)/5**k, (k, -oo, oo)) == sqrt(5) + + +def test_other_sums(): + f = m**2 + m*exp(m) + g = 3*exp(Rational(3, 2))/2 + exp(S.Half)/2 - exp(Rational(-1, 2))/2 - 3*exp(Rational(-3, 2))/2 + 5 + + assert summation(f, (m, Rational(-3, 2), Rational(3, 2))) == g + assert summation(f, (m, -1.5, 1.5)).evalf().epsilon_eq(g.evalf(), 1e-10) + +fac = factorial + + +def NS(e, n=15, **options): + return str(sympify(e).evalf(n, **options)) + + +def test_evalf_fast_series(): + # Euler transformed series for sqrt(1+x) + assert NS(Sum( + fac(2*n + 1)/fac(n)**2/2**(3*n + 1), (n, 0, oo)), 100) == NS(sqrt(2), 100) + + # Some series for exp(1) + estr = NS(E, 100) + assert NS(Sum(1/fac(n), (n, 0, oo)), 100) == estr + assert NS(1/Sum((1 - 2*n)/fac(2*n), (n, 0, oo)), 100) == estr + assert NS(Sum((2*n + 1)/fac(2*n), (n, 0, oo)), 100) == estr + assert NS(Sum((4*n + 3)/2**(2*n + 1)/fac(2*n + 1), (n, 0, oo))**2, 100) == estr + + pistr = NS(pi, 100) + # Ramanujan series for pi + assert NS(9801/sqrt(8)/Sum(fac( + 4*n)*(1103 + 26390*n)/fac(n)**4/396**(4*n), (n, 0, oo)), 100) == pistr + assert NS(1/Sum( + binomial(2*n, n)**3 * (42*n + 5)/2**(12*n + 4), (n, 0, oo)), 100) == pistr + # Machin's formula for pi + assert NS(16*Sum((-1)**n/(2*n + 1)/5**(2*n + 1), (n, 0, oo)) - + 4*Sum((-1)**n/(2*n + 1)/239**(2*n + 1), (n, 0, oo)), 100) == pistr + + # Apery's constant + astr = NS(zeta(3), 100) + P = 126392*n**5 + 412708*n**4 + 531578*n**3 + 336367*n**2 + 104000* \ + n + 12463 + assert NS(Sum((-1)**n * P / 24 * (fac(2*n + 1)*fac(2*n)*fac( + n))**3 / fac(3*n + 2) / fac(4*n + 3)**3, (n, 0, oo)), 100) == astr + assert NS(Sum((-1)**n * (205*n**2 + 250*n + 77)/64 * fac(n)**10 / + fac(2*n + 1)**5, (n, 0, oo)), 100) == astr + + +def test_evalf_fast_series_issue_4021(): + # Catalan's constant + assert NS(Sum((-1)**(n - 1)*2**(8*n)*(40*n**2 - 24*n + 3)*fac(2*n)**3* + fac(n)**2/n**3/(2*n - 1)/fac(4*n)**2, (n, 1, oo))/64, 100) == \ + NS(Catalan, 100) + astr = NS(zeta(3), 100) + assert NS(5*Sum( + (-1)**(n - 1)*fac(n)**2 / n**3 / fac(2*n), (n, 1, oo))/2, 100) == astr + assert NS(Sum((-1)**(n - 1)*(56*n**2 - 32*n + 5) / (2*n - 1)**2 * fac(n - 1) + **3 / fac(3*n), (n, 1, oo))/4, 100) == astr + + +def test_evalf_slow_series(): + assert NS(Sum((-1)**n / n, (n, 1, oo)), 15) == NS(-log(2), 15) + assert NS(Sum((-1)**n / n, (n, 1, oo)), 50) == NS(-log(2), 50) + assert NS(Sum(1/n**2, (n, 1, oo)), 15) == NS(pi**2/6, 15) + assert NS(Sum(1/n**2, (n, 1, oo)), 100) == NS(pi**2/6, 100) + assert NS(Sum(1/n**2, (n, 1, oo)), 500) == NS(pi**2/6, 500) + assert NS(Sum((-1)**n / (2*n + 1)**3, (n, 0, oo)), 15) == NS(pi**3/32, 15) + assert NS(Sum((-1)**n / (2*n + 1)**3, (n, 0, oo)), 50) == NS(pi**3/32, 50) + + +def test_evalf_oo_to_oo(): + # There used to be an error in certain cases + # Does not evaluate, but at least do not throw an error + # Evaluates symbolically to 0, which is not correct + assert Sum(1/(n**2+1), (n, -oo, oo)).evalf() == Sum(1/(n**2+1), (n, -oo, oo)) + # This evaluates if from 1 to oo and symbolically + assert Sum(1/(factorial(abs(n))), (n, -oo, -1)).evalf() == Sum(1/(factorial(abs(n))), (n, -oo, -1)) + + +def test_euler_maclaurin(): + # Exact polynomial sums with E-M + def check_exact(f, a, b, m, n): + A = Sum(f, (k, a, b)) + s, e = A.euler_maclaurin(m, n) + assert (e == 0) and (s.expand() == A.doit()) + check_exact(k**4, a, b, 0, 2) + check_exact(k**4 + 2*k, a, b, 1, 2) + check_exact(k**4 + k**2, a, b, 1, 5) + check_exact(k**5, 2, 6, 1, 2) + check_exact(k**5, 2, 6, 1, 3) + assert Sum(x-1, (x, 0, 2)).euler_maclaurin(m=30, n=30, eps=2**-15) == (0, 0) + # Not exact + assert Sum(k**6, (k, a, b)).euler_maclaurin(0, 2)[1] != 0 + # Numerical test + for mi, ni in [(2, 4), (2, 20), (10, 20), (18, 20)]: + A = Sum(1/k**3, (k, 1, oo)) + s, e = A.euler_maclaurin(mi, ni) + assert abs((s - zeta(3)).evalf()) < e.evalf() + + raises(ValueError, lambda: Sum(1, (x, 0, 1), (k, 0, 1)).euler_maclaurin()) + + +@slow +def test_evalf_euler_maclaurin(): + assert NS(Sum(1/k**k, (k, 1, oo)), 15) == '1.29128599706266' + assert NS(Sum(1/k**k, (k, 1, oo)), + 50) == '1.2912859970626635404072825905956005414986193682745' + assert NS(Sum(1/k - log(1 + 1/k), (k, 1, oo)), 15) == NS(EulerGamma, 15) + assert NS(Sum(1/k - log(1 + 1/k), (k, 1, oo)), 50) == NS(EulerGamma, 50) + assert NS(Sum(log(k)/k**2, (k, 1, oo)), 15) == '0.937548254315844' + assert NS(Sum(log(k)/k**2, (k, 1, oo)), + 50) == '0.93754825431584375370257409456786497789786028861483' + assert NS(Sum(1/k, (k, 1000000, 2000000)), 15) == '0.693147930560008' + assert NS(Sum(1/k, (k, 1000000, 2000000)), + 50) == '0.69314793056000780941723211364567656807940638436025' + + +def test_evalf_symbolic(): + # issue 6328 + expr = Sum(f(x), (x, 1, 3)) + Sum(g(x), (x, 1, 3)) + assert expr.evalf() == expr + + +def test_evalf_issue_3273(): + assert Sum(0, (k, 1, oo)).evalf() == 0 + + +def test_simple_products(): + assert Product(S.NaN, (x, 1, 3)) is S.NaN + assert product(S.NaN, (x, 1, 3)) is S.NaN + assert Product(x, (n, a, a)).doit() == x + assert Product(x, (x, a, a)).doit() == a + assert Product(x, (y, 1, a)).doit() == x**a + + lo, hi = 1, 2 + s1 = Product(n, (n, lo, hi)) + s2 = Product(n, (n, hi, lo)) + assert s1 != s2 + # This IS correct according to Karr product convention + assert s1.doit() == 2 + assert s2.doit() == 1 + + lo, hi = x, x + 1 + s1 = Product(n, (n, lo, hi)) + s2 = Product(n, (n, hi, lo)) + s3 = 1 / Product(n, (n, hi + 1, lo - 1)) + assert s1 != s2 + # This IS correct according to Karr product convention + assert s1.doit() == x*(x + 1) + assert s2.doit() == 1 + assert s3.doit() == x*(x + 1) + + assert Product(Integral(2*x, (x, 1, y)) + 2*x, (x, 1, 2)).doit() == \ + (y**2 + 1)*(y**2 + 3) + assert product(2, (n, a, b)) == 2**(b - a + 1) + assert product(n, (n, 1, b)) == factorial(b) + assert product(n**3, (n, 1, b)) == factorial(b)**3 + assert product(3**(2 + n), (n, a, b)) \ + == 3**(2*(1 - a + b) + b/2 + (b**2)/2 + a/2 - (a**2)/2) + assert product(cos(n), (n, 3, 5)) == cos(3)*cos(4)*cos(5) + assert product(cos(n), (n, x, x + 2)) == cos(x)*cos(x + 1)*cos(x + 2) + assert isinstance(product(cos(n), (n, x, x + S.Half)), Product) + # If Product managed to evaluate this one, it most likely got it wrong! + assert isinstance(Product(n**n, (n, 1, b)), Product) + + +def test_rational_products(): + assert combsimp(product(1 + 1/n, (n, a, b))) == (1 + b)/a + assert combsimp(product(n + 1, (n, a, b))) == gamma(2 + b)/gamma(1 + a) + assert combsimp(product((n + 1)/(n - 1), (n, a, b))) == b*(1 + b)/(a*(a - 1)) + assert combsimp(product(n/(n + 1)/(n + 2), (n, a, b))) == \ + a*gamma(a + 2)/(b + 1)/gamma(b + 3) + assert combsimp(product(n*(n + 1)/(n - 1)/(n - 2), (n, a, b))) == \ + b**2*(b - 1)*(1 + b)/(a - 1)**2/(a*(a - 2)) + + +def test_wallis_product(): + # Wallis product, given in two different forms to ensure that Product + # can factor simple rational expressions + A = Product(4*n**2 / (4*n**2 - 1), (n, 1, b)) + B = Product((2*n)*(2*n)/(2*n - 1)/(2*n + 1), (n, 1, b)) + R = pi*gamma(b + 1)**2/(2*gamma(b + S.Half)*gamma(b + Rational(3, 2))) + assert simplify(A.doit()) == R + assert simplify(B.doit()) == R + # This one should eventually also be doable (Euler's product formula for sin) + # assert Product(1+x/n**2, (n, 1, b)) == ... + + +def test_telescopic_sums(): + #checks also input 2 of comment 1 issue 4127 + assert Sum(1/k - 1/(k + 1), (k, 1, n)).doit() == 1 - 1/(1 + n) + assert Sum( + f(k) - f(k + 2), (k, m, n)).doit() == -f(1 + n) - f(2 + n) + f(m) + f(1 + m) + assert Sum(cos(k) - cos(k + 3), (k, 1, n)).doit() == -cos(1 + n) - \ + cos(2 + n) - cos(3 + n) + cos(1) + cos(2) + cos(3) + + # dummy variable shouldn't matter + assert telescopic(1/m, -m/(1 + m), (m, n - 1, n)) == \ + telescopic(1/k, -k/(1 + k), (k, n - 1, n)) + + assert Sum(1/x/(x - 1), (x, a, b)).doit() == 1/(a - 1) - 1/b + eq = 1/((5*n + 2)*(5*(n + 1) + 2)) + assert Sum(eq, (n, 0, oo)).doit() == S(1)/10 + nz = symbols('nz', nonzero=True) + v = Sum(eq.subs(5, nz), (n, 0, oo)).doit() + assert v.subs(nz, 5).simplify() == S(1)/10 + # check that apart is being used in non-symbolic case + s = Sum(eq, (n, 0, k)).doit() + v = Sum(eq, (n, 0, 10**100)).doit() + assert v == s.subs(k, 10**100) + + +def test_sum_reconstruct(): + s = Sum(n**2, (n, -1, 1)) + assert s == Sum(*s.args) + raises(ValueError, lambda: Sum(x, x)) + raises(ValueError, lambda: Sum(x, (x, 1))) + + +def test_limit_subs(): + for F in (Sum, Product, Integral): + assert F(a*exp(a), (a, -2, 2)) == F(a*exp(a), (a, -b, b)).subs(b, 2) + assert F(a, (a, F(b, (b, 1, 2)), 4)).subs(F(b, (b, 1, 2)), c) == \ + F(a, (a, c, 4)) + assert F(x, (x, 1, x + y)).subs(x, 1) == F(x, (x, 1, y + 1)) + + +def test_function_subs(): + S = Sum(x*f(y),(x,0,oo),(y,0,oo)) + assert S.subs(f(y),y) == Sum(x*y,(x,0,oo),(y,0,oo)) + assert S.subs(f(x),x) == S + raises(ValueError, lambda: S.subs(f(y),x+y) ) + S = Sum(x*log(y),(x,0,oo),(y,0,oo)) + assert S.subs(log(y),y) == S + S = Sum(x*f(y),(x,0,oo),(y,0,oo)) + assert S.subs(f(y),y) == Sum(x*y,(x,0,oo),(y,0,oo)) + + +def test_equality(): + # if this fails remove special handling below + raises(ValueError, lambda: Sum(x, x)) + r = symbols('x', real=True) + for F in (Sum, Product, Integral): + try: + assert F(x, x) != F(y, y) + assert F(x, (x, 1, 2)) != F(x, x) + assert F(x, (x, x)) != F(x, x) # or else they print the same + assert F(1, x) != F(1, y) + except ValueError: + pass + assert F(a, (x, 1, 2)) != F(a, (x, 1, 3)) # diff limit + assert F(a, (x, 1, x)) != F(a, (y, 1, y)) + assert F(a, (x, 1, 2)) != F(b, (x, 1, 2)) # diff expression + assert F(x, (x, 1, 2)) != F(r, (r, 1, 2)) # diff assumptions + assert F(1, (x, 1, x)) != F(1, (y, 1, x)) # only dummy is diff + assert F(1, (x, 1, x)).dummy_eq(F(1, (y, 1, x))) + + # issue 5265 + assert Sum(x, (x, 1, x)).subs(x, a) == Sum(x, (x, 1, a)) + + +def test_Sum_doit(): + assert Sum(n*Integral(a**2), (n, 0, 2)).doit() == a**3 + assert Sum(n*Integral(a**2), (n, 0, 2)).doit(deep=False) == \ + 3*Integral(a**2) + assert summation(n*Integral(a**2), (n, 0, 2)) == 3*Integral(a**2) + + # test nested sum evaluation + s = Sum( Sum( Sum(2,(z,1,n+1)), (y,x+1,n)), (x,1,n)) + assert 0 == (s.doit() - n*(n+1)*(n-1)).factor() + + # Integer assumes finite + assert Sum(KroneckerDelta(x, y), (x, -oo, oo)).doit() == Piecewise((1, And(-oo < y, y < oo)), (0, True)) + assert Sum(KroneckerDelta(m, n), (m, -oo, oo)).doit() == 1 + assert Sum(m*KroneckerDelta(x, y), (x, -oo, oo)).doit() == Piecewise((m, And(-oo < y, y < oo)), (0, True)) + assert Sum(x*KroneckerDelta(m, n), (m, -oo, oo)).doit() == x + assert Sum(Sum(KroneckerDelta(m, n), (m, 1, 3)), (n, 1, 3)).doit() == 3 + assert Sum(Sum(KroneckerDelta(k, m), (m, 1, 3)), (n, 1, 3)).doit() == \ + 3 * Piecewise((1, And(1 <= k, k <= 3)), (0, True)) + assert Sum(f(n) * Sum(KroneckerDelta(m, n), (m, 0, oo)), (n, 1, 3)).doit() == \ + f(1) + f(2) + f(3) + assert Sum(f(n) * Sum(KroneckerDelta(m, n), (m, 0, oo)), (n, 1, oo)).doit() == \ + Sum(f(n), (n, 1, oo)) + + # issue 2597 + nmax = symbols('N', integer=True, positive=True) + pw = Piecewise((1, And(1 <= n, n <= nmax)), (0, True)) + assert Sum(pw, (n, 1, nmax)).doit() == Sum(Piecewise((1, nmax >= n), + (0, True)), (n, 1, nmax)) + + q, s = symbols('q, s') + assert summation(1/n**(2*s), (n, 1, oo)) == Piecewise((zeta(2*s), 2*re(s) > 1), + (Sum(n**(-2*s), (n, 1, oo)), True)) + assert summation(1/(n+1)**s, (n, 0, oo)) == Piecewise((zeta(s), re(s) > 1), + (Sum((n + 1)**(-s), (n, 0, oo)), True)) + assert summation(1/(n+q)**s, (n, 0, oo)) == Piecewise( + (zeta(s, q), And(~Contains(-q, S.Naturals0), re(s) > 1)), + (Sum((n + q)**(-s), (n, 0, oo)), True)) + assert summation(1/(n+q)**s, (n, q, oo)) == Piecewise( + (zeta(s, 2*q), And(~Contains(-2*q, S.Naturals0), re(s) > 1)), + (Sum((n + q)**(-s), (n, q, oo)), True)) + assert summation(1/n**2, (n, 1, oo)) == zeta(2) + assert summation(1/n**s, (n, 0, oo)) == Sum(n**(-s), (n, 0, oo)) + assert summation(1/(n+1)**(2+I), (n, 0, oo)) == zeta(2+I) + t = symbols('t', real=True, positive=True) + assert summation(1/(n+I)**(t+1), (n, 0, oo)) == zeta(t+1, I) + + +def test_Product_doit(): + assert Product(n*Integral(a**2), (n, 1, 3)).doit() == 2 * a**9 / 9 + assert Product(n*Integral(a**2), (n, 1, 3)).doit(deep=False) == \ + 6*Integral(a**2)**3 + assert product(n*Integral(a**2), (n, 1, 3)) == 6*Integral(a**2)**3 + + +def test_Sum_interface(): + assert isinstance(Sum(0, (n, 0, 2)), Sum) + assert Sum(nan, (n, 0, 2)) is nan + assert Sum(nan, (n, 0, oo)) is nan + assert Sum(0, (n, 0, 2)).doit() == 0 + assert isinstance(Sum(0, (n, 0, oo)), Sum) + assert Sum(0, (n, 0, oo)).doit() == 0 + raises(ValueError, lambda: Sum(1)) + raises(ValueError, lambda: summation(1)) + + +def test_diff(): + assert Sum(x, (x, 1, 2)).diff(x) == 0 + assert Sum(x*y, (x, 1, 2)).diff(x) == 0 + assert Sum(x*y, (y, 1, 2)).diff(x) == Sum(y, (y, 1, 2)) + e = Sum(x*y, (x, 1, a)) + assert e.diff(a) == Derivative(e, a) + assert Sum(x*y, (x, 1, 3), (a, 2, 5)).diff(y).doit() == \ + Sum(x*y, (x, 1, 3), (a, 2, 5)).doit().diff(y) == 24 + assert Sum(x, (x, 1, 2)).diff(y) == 0 + + +def test_hypersum(): + assert simplify(summation(x**n/fac(n), (n, 1, oo))) == -1 + exp(x) + assert summation((-1)**n * x**(2*n) / fac(2*n), (n, 0, oo)) == cos(x) + assert simplify(summation((-1)**n*x**(2*n + 1) / + factorial(2*n + 1), (n, 3, oo))) == -x + sin(x) + x**3/6 - x**5/120 + + assert summation(1/(n + 2)**3, (n, 1, oo)) == Rational(-9, 8) + zeta(3) + assert summation(1/n**4, (n, 1, oo)) == pi**4/90 + + s = summation(x**n*n, (n, -oo, 0)) + assert s.is_Piecewise + assert s.args[0].args[0] == -1/(x*(1 - 1/x)**2) + assert s.args[0].args[1] == (abs(1/x) < 1) + + m = Symbol('n', integer=True, positive=True) + assert summation(binomial(m, k), (k, 0, m)) == 2**m + + +def test_issue_4170(): + assert summation(1/factorial(k), (k, 0, oo)) == E + + +def test_is_commutative(): + from sympy.physics.secondquant import NO, F, Fd + m = Symbol('m', commutative=False) + for f in (Sum, Product, Integral): + assert f(z, (z, 1, 1)).is_commutative is True + assert f(z*y, (z, 1, 6)).is_commutative is True + assert f(m*x, (x, 1, 2)).is_commutative is False + + assert f(NO(Fd(x)*F(y))*z, (z, 1, 2)).is_commutative is False + + +def test_is_zero(): + for func in [Sum, Product]: + assert func(0, (x, 1, 1)).is_zero is True + assert func(x, (x, 1, 1)).is_zero is None + + assert Sum(0, (x, 1, 0)).is_zero is True + assert Product(0, (x, 1, 0)).is_zero is False + + +def test_is_number(): + # is number should not rely on evaluation or assumptions, + # it should be equivalent to `not foo.free_symbols` + assert Sum(1, (x, 1, 1)).is_number is True + assert Sum(1, (x, 1, x)).is_number is False + assert Sum(0, (x, y, z)).is_number is False + assert Sum(x, (y, 1, 2)).is_number is False + assert Sum(x, (y, 1, 1)).is_number is False + assert Sum(x, (x, 1, 2)).is_number is True + assert Sum(x*y, (x, 1, 2), (y, 1, 3)).is_number is True + + assert Product(2, (x, 1, 1)).is_number is True + assert Product(2, (x, 1, y)).is_number is False + assert Product(0, (x, y, z)).is_number is False + assert Product(1, (x, y, z)).is_number is False + assert Product(x, (y, 1, x)).is_number is False + assert Product(x, (y, 1, 2)).is_number is False + assert Product(x, (y, 1, 1)).is_number is False + assert Product(x, (x, 1, 2)).is_number is True + + +def test_free_symbols(): + for func in [Sum, Product]: + assert func(1, (x, 1, 2)).free_symbols == set() + assert func(0, (x, 1, y)).free_symbols == {y} + assert func(2, (x, 1, y)).free_symbols == {y} + assert func(x, (x, 1, 2)).free_symbols == set() + assert func(x, (x, 1, y)).free_symbols == {y} + assert func(x, (y, 1, y)).free_symbols == {x, y} + assert func(x, (y, 1, 2)).free_symbols == {x} + assert func(x, (y, 1, 1)).free_symbols == {x} + assert func(x, (y, 1, z)).free_symbols == {x, z} + assert func(x, (x, 1, y), (y, 1, 2)).free_symbols == set() + assert func(x, (x, 1, y), (y, 1, z)).free_symbols == {z} + assert func(x, (x, 1, y), (y, 1, y)).free_symbols == {y} + assert func(x, (y, 1, y), (y, 1, z)).free_symbols == {x, z} + assert Sum(1, (x, 1, y)).free_symbols == {y} + # free_symbols answers whether the object *as written* has free symbols, + # not whether the evaluated expression has free symbols + assert Product(1, (x, 1, y)).free_symbols == {y} + # don't count free symbols that are not independent of integration + # variable(s) + assert func(f(x), (f(x), 1, 2)).free_symbols == set() + assert func(f(x), (f(x), 1, x)).free_symbols == {x} + assert func(f(x), (f(x), 1, y)).free_symbols == {y} + assert func(f(x), (z, 1, y)).free_symbols == {x, y} + + +def test_conjugate_transpose(): + A, B = symbols("A B", commutative=False) + p = Sum(A*B**n, (n, 1, 3)) + assert p.adjoint().doit() == p.doit().adjoint() + assert p.conjugate().doit() == p.doit().conjugate() + assert p.transpose().doit() == p.doit().transpose() + + p = Sum(B**n*A, (n, 1, 3)) + assert p.adjoint().doit() == p.doit().adjoint() + assert p.conjugate().doit() == p.doit().conjugate() + assert p.transpose().doit() == p.doit().transpose() + + +def test_noncommutativity_honoured(): + A, B = symbols("A B", commutative=False) + M = symbols('M', integer=True, positive=True) + p = Sum(A*B**n, (n, 1, M)) + assert p.doit() == A*Piecewise((M, Eq(B, 1)), + ((B - B**(M + 1))*(1 - B)**(-1), True)) + + p = Sum(B**n*A, (n, 1, M)) + assert p.doit() == Piecewise((M, Eq(B, 1)), + ((B - B**(M + 1))*(1 - B)**(-1), True))*A + + p = Sum(B**n*A*B**n, (n, 1, M)) + assert p.doit() == p + + +def test_issue_4171(): + assert summation(factorial(2*k + 1)/factorial(2*k), (k, 0, oo)) is oo + assert summation(2*k + 1, (k, 0, oo)) is oo + + +def test_issue_6273(): + assert Sum(x, (x, 1, n)).n(2, subs={n: 1}) == Float(1, 2) + + +def test_issue_6274(): + assert Sum(x, (x, 1, 0)).doit() == 0 + assert NS(Sum(x, (x, 1, 0))) == '0' + assert Sum(n, (n, 10, 5)).doit() == -30 + assert NS(Sum(n, (n, 10, 5))) == '-30.0000000000000' + + +def test_simplify_sum(): + y, t, v = symbols('y, t, v') + + _simplify = lambda e: simplify(e, doit=False) + assert _simplify(Sum(x*y, (x, n, m), (y, a, k)) + \ + Sum(y, (x, n, m), (y, a, k))) == Sum(y * (x + 1), (x, n, m), (y, a, k)) + assert _simplify(Sum(x, (x, n, m)) + Sum(x, (x, m + 1, a))) == \ + Sum(x, (x, n, a)) + assert _simplify(Sum(x, (x, k + 1, a)) + Sum(x, (x, n, k))) == \ + Sum(x, (x, n, a)) + assert _simplify(Sum(x, (x, k + 1, a)) + Sum(x + 1, (x, n, k))) == \ + Sum(x, (x, n, a)) + Sum(1, (x, n, k)) + assert _simplify(Sum(x, (x, 0, 3)) * 3 + 3 * Sum(x, (x, 4, 6)) + \ + 4 * Sum(z, (z, 0, 1))) == 4*Sum(z, (z, 0, 1)) + 3*Sum(x, (x, 0, 6)) + assert _simplify(3*Sum(x**2, (x, a, b)) + Sum(x, (x, a, b))) == \ + Sum(x*(3*x + 1), (x, a, b)) + assert _simplify(Sum(x**3, (x, n, k)) * 3 + 3 * Sum(x, (x, n, k)) + \ + 4 * y * Sum(z, (z, n, k))) + 1 == \ + 4*y*Sum(z, (z, n, k)) + 3*Sum(x**3 + x, (x, n, k)) + 1 + assert _simplify(Sum(x, (x, a, b)) + 1 + Sum(x, (x, b + 1, c))) == \ + 1 + Sum(x, (x, a, c)) + assert _simplify(Sum(x, (t, a, b)) + Sum(y, (t, a, b)) + \ + Sum(x, (t, b+1, c))) == x * Sum(1, (t, a, c)) + y * Sum(1, (t, a, b)) + assert _simplify(Sum(x, (t, a, b)) + Sum(x, (t, b+1, c)) + \ + Sum(y, (t, a, b))) == x * Sum(1, (t, a, c)) + y * Sum(1, (t, a, b)) + assert _simplify(Sum(x, (t, a, b)) + 2 * Sum(x, (t, b+1, c))) == \ + _simplify(Sum(x, (t, a, b)) + Sum(x, (t, b+1, c)) + Sum(x, (t, b+1, c))) + assert _simplify(Sum(x, (x, a, b))*Sum(x**2, (x, a, b))) == \ + Sum(x, (x, a, b)) * Sum(x**2, (x, a, b)) + assert _simplify(Sum(x, (t, a, b)) + Sum(y, (t, a, b)) + Sum(z, (t, a, b))) \ + == (x + y + z) * Sum(1, (t, a, b)) # issue 8596 + assert _simplify(Sum(x, (t, a, b)) + Sum(y, (t, a, b)) + Sum(z, (t, a, b)) + \ + Sum(v, (t, a, b))) == (x + y + z + v) * Sum(1, (t, a, b)) # issue 8596 + assert _simplify(Sum(x * y, (x, a, b)) / (3 * y)) == \ + (Sum(x, (x, a, b)) / 3) + assert _simplify(Sum(f(x) * y * z, (x, a, b)) / (y * z)) \ + == Sum(f(x), (x, a, b)) + assert _simplify(Sum(c * x, (x, a, b)) - c * Sum(x, (x, a, b))) == 0 + assert _simplify(c * (Sum(x, (x, a, b)) + y)) == c * (y + Sum(x, (x, a, b))) + assert _simplify(c * (Sum(x, (x, a, b)) + y * Sum(x, (x, a, b)))) == \ + c * (y + 1) * Sum(x, (x, a, b)) + assert _simplify(Sum(Sum(c * x, (x, a, b)), (y, a, b))) == \ + c * Sum(x, (x, a, b), (y, a, b)) + assert _simplify(Sum((3 + y) * Sum(c * x, (x, a, b)), (y, a, b))) == \ + c * Sum((3 + y), (y, a, b)) * Sum(x, (x, a, b)) + assert _simplify(Sum((3 + t) * Sum(c * t, (x, a, b)), (y, a, b))) == \ + c*t*(t + 3)*Sum(1, (x, a, b))*Sum(1, (y, a, b)) + assert _simplify(Sum(Sum(d * t, (x, a, b - 1)) + \ + Sum(d * t, (x, b, c)), (t, a, b))) == \ + d * Sum(1, (x, a, c)) * Sum(t, (t, a, b)) + assert _simplify(Sum(sin(t)**2 + cos(t)**2 + 1, (t, a, b))) == \ + 2 * Sum(1, (t, a, b)) + + +def test_change_index(): + b, v, w = symbols('b, v, w', integer = True) + + assert Sum(x, (x, a, b)).change_index(x, x + 1, y) == \ + Sum(y - 1, (y, a + 1, b + 1)) + assert Sum(x**2, (x, a, b)).change_index( x, x - 1) == \ + Sum((x+1)**2, (x, a - 1, b - 1)) + assert Sum(x**2, (x, a, b)).change_index( x, -x, y) == \ + Sum((-y)**2, (y, -b, -a)) + assert Sum(x, (x, a, b)).change_index( x, -x - 1) == \ + Sum(-x - 1, (x, -b - 1, -a - 1)) + assert Sum(x*y, (x, a, b), (y, c, d)).change_index( x, x - 1, z) == \ + Sum((z + 1)*y, (z, a - 1, b - 1), (y, c, d)) + assert Sum(x, (x, a, b)).change_index( x, x + v) == \ + Sum(-v + x, (x, a + v, b + v)) + assert Sum(x, (x, a, b)).change_index( x, -x - v) == \ + Sum(-v - x, (x, -b - v, -a - v)) + assert Sum(x, (x, a, b)).change_index(x, w*x, v) == \ + Sum(v/w, (v, b*w, a*w)) + raises(ValueError, lambda: Sum(x, (x, a, b)).change_index(x, 2*x)) + + +def test_reorder(): + b, y, c, d, z = symbols('b, y, c, d, z', integer = True) + + assert Sum(x*y, (x, a, b), (y, c, d)).reorder((0, 1)) == \ + Sum(x*y, (y, c, d), (x, a, b)) + assert Sum(x, (x, a, b), (x, c, d)).reorder((0, 1)) == \ + Sum(x, (x, c, d), (x, a, b)) + assert Sum(x*y + z, (x, a, b), (z, m, n), (y, c, d)).reorder(\ + (2, 0), (0, 1)) == Sum(x*y + z, (z, m, n), (y, c, d), (x, a, b)) + assert Sum(x*y*z, (x, a, b), (y, c, d), (z, m, n)).reorder(\ + (0, 1), (1, 2), (0, 2)) == Sum(x*y*z, (x, a, b), (z, m, n), (y, c, d)) + assert Sum(x*y*z, (x, a, b), (y, c, d), (z, m, n)).reorder(\ + (x, y), (y, z), (x, z)) == Sum(x*y*z, (x, a, b), (z, m, n), (y, c, d)) + assert Sum(x*y, (x, a, b), (y, c, d)).reorder((x, 1)) == \ + Sum(x*y, (y, c, d), (x, a, b)) + assert Sum(x*y, (x, a, b), (y, c, d)).reorder((y, x)) == \ + Sum(x*y, (y, c, d), (x, a, b)) + + +def test_reverse_order(): + assert Sum(x, (x, 0, 3)).reverse_order(0) == Sum(-x, (x, 4, -1)) + assert Sum(x*y, (x, 1, 5), (y, 0, 6)).reverse_order(0, 1) == \ + Sum(x*y, (x, 6, 0), (y, 7, -1)) + assert Sum(x, (x, 1, 2)).reverse_order(0) == Sum(-x, (x, 3, 0)) + assert Sum(x, (x, 1, 3)).reverse_order(0) == Sum(-x, (x, 4, 0)) + assert Sum(x, (x, 1, a)).reverse_order(0) == Sum(-x, (x, a + 1, 0)) + assert Sum(x, (x, a, 5)).reverse_order(0) == Sum(-x, (x, 6, a - 1)) + assert Sum(x, (x, a + 1, a + 5)).reverse_order(0) == \ + Sum(-x, (x, a + 6, a)) + assert Sum(x, (x, a + 1, a + 2)).reverse_order(0) == \ + Sum(-x, (x, a + 3, a)) + assert Sum(x, (x, a + 1, a + 1)).reverse_order(0) == \ + Sum(-x, (x, a + 2, a)) + assert Sum(x, (x, a, b)).reverse_order(0) == Sum(-x, (x, b + 1, a - 1)) + assert Sum(x, (x, a, b)).reverse_order(x) == Sum(-x, (x, b + 1, a - 1)) + assert Sum(x*y, (x, a, b), (y, 2, 5)).reverse_order(x, 1) == \ + Sum(x*y, (x, b + 1, a - 1), (y, 6, 1)) + assert Sum(x*y, (x, a, b), (y, 2, 5)).reverse_order(y, x) == \ + Sum(x*y, (x, b + 1, a - 1), (y, 6, 1)) + + +def test_issue_7097(): + assert sum(x**n/n for n in range(1, 401)) == summation(x**n/n, (n, 1, 400)) + + +def test_factor_expand_subs(): + # test factoring + assert Sum(4 * x, (x, 1, y)).factor() == 4 * Sum(x, (x, 1, y)) + assert Sum(x * a, (x, 1, y)).factor() == a * Sum(x, (x, 1, y)) + assert Sum(4 * x * a, (x, 1, y)).factor() == 4 * a * Sum(x, (x, 1, y)) + assert Sum(4 * x * y, (x, 1, y)).factor() == 4 * y * Sum(x, (x, 1, y)) + + # test expand + _x = Symbol('x', zero=False) + assert Sum(x+1,(x,1,y)).expand() == Sum(x,(x,1,y)) + Sum(1,(x,1,y)) + assert Sum(x+a*x**2,(x,1,y)).expand() == Sum(x,(x,1,y)) + Sum(a*x**2,(x,1,y)) + assert Sum(_x**(n + 1)*(n + 1), (n, -1, oo)).expand() \ + == Sum(n*_x*_x**n + _x*_x**n, (n, -1, oo)) + assert Sum(x**(n + 1)*(n + 1), (n, -1, oo)).expand(power_exp=False) \ + == Sum(n*x**(n + 1) + x**(n + 1), (n, -1, oo)) + assert Sum(x**(n + 1)*(n + 1), (n, -1, oo)).expand(force=True) \ + == Sum(x*x**n, (n, -1, oo)) + Sum(n*x*x**n, (n, -1, oo)) + assert Sum(a*n+a*n**2,(n,0,4)).expand() \ + == Sum(a*n,(n,0,4)) + Sum(a*n**2,(n,0,4)) + assert Sum(_x**a*_x**n,(x,0,3)) \ + == Sum(_x**(a+n),(x,0,3)).expand(power_exp=True) + _a, _n = symbols('a n', positive=True) + assert Sum(x**(_a+_n),(x,0,3)).expand(power_exp=True) \ + == Sum(x**_a*x**_n, (x, 0, 3)) + assert Sum(x**(_a-_n),(x,0,3)).expand(power_exp=True) \ + == Sum(x**(_a-_n),(x,0,3)).expand(power_exp=False) + + # test subs + assert Sum(1/(1+a*x**2),(x,0,3)).subs([(a,3)]) == Sum(1/(1+3*x**2),(x,0,3)) + assert Sum(x*y,(x,0,y),(y,0,x)).subs([(x,3)]) == Sum(x*y,(x,0,y),(y,0,3)) + assert Sum(x,(x,1,10)).subs([(x,y-2)]) == Sum(x,(x,1,10)) + assert Sum(1/x,(x,1,10)).subs([(x,(3+n)**3)]) == Sum(1/x,(x,1,10)) + assert Sum(1/x,(x,1,10)).subs([(x,3*x-2)]) == Sum(1/x,(x,1,10)) + + +def test_distribution_over_equality(): + assert Product(Eq(x*2, f(x)), (x, 1, 3)).doit() == Eq(48, f(1)*f(2)*f(3)) + assert Sum(Eq(f(x), x**2), (x, 0, y)) == \ + Eq(Sum(f(x), (x, 0, y)), Sum(x**2, (x, 0, y))) + + +def test_issue_2787(): + n, k = symbols('n k', positive=True, integer=True) + p = symbols('p', positive=True) + binomial_dist = binomial(n, k)*p**k*(1 - p)**(n - k) + s = Sum(binomial_dist*k, (k, 0, n)) + res = s.doit().simplify() + ans = Piecewise( + (n*p, x), + (Sum(k*p**k*binomial(n, k)*(1 - p)**(n - k), (k, 0, n)), + True)).subs(x, (Eq(n, 1) | (n > 1)) & (p/Abs(p - 1) <= 1)) + ans2 = Piecewise( + (n*p, x), + (factorial(n)*Sum(p**k*(1 - p)**(-k + n)/ + (factorial(-k + n)*factorial(k - 1)), (k, 0, n)), + True)).subs(x, (Eq(n, 1) | (n > 1)) & (p/Abs(p - 1) <= 1)) + assert res in [ans, ans2] # XXX system dependent + # Issue #17165: make sure that another simplify does not complicate + # the result by much. Why didn't first simplify replace + # Eq(n, 1) | (n > 1) with True? + assert res.simplify().count_ops() <= res.count_ops() + 2 + + +def test_issue_4668(): + assert summation(1/n, (n, 2, oo)) is oo + + +def test_matrix_sum(): + A = Matrix([[0, 1], [n, 0]]) + + result = Sum(A, (n, 0, 3)).doit() + assert result == Matrix([[0, 4], [6, 0]]) + assert result.__class__ == ImmutableDenseMatrix + + A = SparseMatrix([[0, 1], [n, 0]]) + + result = Sum(A, (n, 0, 3)).doit() + assert result.__class__ == ImmutableSparseMatrix + + +def test_failing_matrix_sum(): + n = Symbol('n') + # TODO Implement matrix geometric series summation. + A = Matrix([[0, 1, 0], [-1, 0, 0], [0, 0, 0]]) + assert Sum(A ** n, (n, 1, 4)).doit() == \ + Matrix([[0, 0, 0], [0, 0, 0], [0, 0, 0]]) + # issue sympy/sympy#16989 + assert summation(A**n, (n, 1, 1)) == A + + +def test_indexed_idx_sum(): + i = symbols('i', cls=Idx) + r = Indexed('r', i) + assert Sum(r, (i, 0, 3)).doit() == sum(r.xreplace({i: j}) for j in range(4)) + assert Product(r, (i, 0, 3)).doit() == prod([r.xreplace({i: j}) for j in range(4)]) + + j = symbols('j', integer=True) + assert Sum(r, (i, j, j+2)).doit() == sum(r.xreplace({i: j+k}) for k in range(3)) + assert Product(r, (i, j, j+2)).doit() == prod([r.xreplace({i: j+k}) for k in range(3)]) + + k = Idx('k', range=(1, 3)) + A = IndexedBase('A') + assert Sum(A[k], k).doit() == sum(A[Idx(j, (1, 3))] for j in range(1, 4)) + assert Product(A[k], k).doit() == prod([A[Idx(j, (1, 3))] for j in range(1, 4)]) + + raises(ValueError, lambda: Sum(A[k], (k, 1, 4))) + raises(ValueError, lambda: Sum(A[k], (k, 0, 3))) + raises(ValueError, lambda: Sum(A[k], (k, 2, oo))) + + raises(ValueError, lambda: Product(A[k], (k, 1, 4))) + raises(ValueError, lambda: Product(A[k], (k, 0, 3))) + raises(ValueError, lambda: Product(A[k], (k, 2, oo))) + + +@slow +def test_is_convergent(): + # divergence tests -- + assert Sum(n/(2*n + 1), (n, 1, oo)).is_convergent() is S.false + assert Sum(factorial(n)/5**n, (n, 1, oo)).is_convergent() is S.false + assert Sum(3**(-2*n - 1)*n**n, (n, 1, oo)).is_convergent() is S.false + assert Sum((-1)**n*n, (n, 3, oo)).is_convergent() is S.false + assert Sum((-1)**n, (n, 1, oo)).is_convergent() is S.false + assert Sum(log(1/n), (n, 2, oo)).is_convergent() is S.false + assert Sum(sin(n), (n, 1, oo)).is_convergent() is S.false + + # Raabe's test -- + assert Sum(Product((3*m),(m,1,n))/Product((3*m+4),(m,1,n)),(n,1,oo)).is_convergent() is S.true + + # root test -- + assert Sum((-12)**n/n, (n, 1, oo)).is_convergent() is S.false + + # integral test -- + + # p-series test -- + assert Sum(1/(n**2 + 1), (n, 1, oo)).is_convergent() is S.true + assert Sum(1/n**Rational(6, 5), (n, 1, oo)).is_convergent() is S.true + assert Sum(2/(n*sqrt(n - 1)), (n, 2, oo)).is_convergent() is S.true + assert Sum(1/(sqrt(n)*sqrt(n)), (n, 2, oo)).is_convergent() is S.false + assert Sum(factorial(n) / factorial(n+2), (n, 1, oo)).is_convergent() is S.true + assert Sum(rf(5,n)/rf(7,n),(n,1,oo)).is_convergent() is S.true + assert Sum((rf(1, n)*rf(2, n))/(rf(3, n)*factorial(n)),(n,1,oo)).is_convergent() is S.false + + # comparison test -- + assert Sum(1/(n + log(n)), (n, 1, oo)).is_convergent() is S.false + assert Sum(1/(n**2*log(n)), (n, 2, oo)).is_convergent() is S.true + assert Sum(1/(n*log(n)), (n, 2, oo)).is_convergent() is S.false + assert Sum(2/(n*log(n)*log(log(n))**2), (n, 5, oo)).is_convergent() is S.true + assert Sum(2/(n*log(n)**2), (n, 2, oo)).is_convergent() is S.true + assert Sum((n - 1)/(n**2*log(n)**3), (n, 2, oo)).is_convergent() is S.true + assert Sum(1/(n*log(n)*log(log(n))), (n, 5, oo)).is_convergent() is S.false + assert Sum((n - 1)/(n*log(n)**3), (n, 3, oo)).is_convergent() is S.false + assert Sum(2/(n**2*log(n)), (n, 2, oo)).is_convergent() is S.true + assert Sum(1/(n*sqrt(log(n))*log(log(n))), (n, 100, oo)).is_convergent() is S.false + assert Sum(log(log(n))/(n*log(n)**2), (n, 100, oo)).is_convergent() is S.true + assert Sum(log(n)/n**2, (n, 5, oo)).is_convergent() is S.true + + # alternating series tests -- + assert Sum((-1)**(n - 1)/(n**2 - 1), (n, 3, oo)).is_convergent() is S.true + + # with -negativeInfinite Limits + assert Sum(1/(n**2 + 1), (n, -oo, 1)).is_convergent() is S.true + assert Sum(1/(n - 1), (n, -oo, -1)).is_convergent() is S.false + assert Sum(1/(n**2 - 1), (n, -oo, -5)).is_convergent() is S.true + assert Sum(1/(n**2 - 1), (n, -oo, 2)).is_convergent() is S.true + assert Sum(1/(n**2 - 1), (n, -oo, oo)).is_convergent() is S.true + + # piecewise functions + f = Piecewise((n**(-2), n <= 1), (n**2, n > 1)) + assert Sum(f, (n, 1, oo)).is_convergent() is S.false + assert Sum(f, (n, -oo, oo)).is_convergent() is S.false + assert Sum(f, (n, 1, 100)).is_convergent() is S.true + #assert Sum(f, (n, -oo, 1)).is_convergent() is S.true + + # integral test + + assert Sum(log(n)/n**3, (n, 1, oo)).is_convergent() is S.true + assert Sum(-log(n)/n**3, (n, 1, oo)).is_convergent() is S.true + # the following function has maxima located at (x, y) = + # (1.2, 0.43), (3.0, -0.25) and (6.8, 0.050) + eq = (x - 2)*(x**2 - 6*x + 4)*exp(-x) + assert Sum(eq, (x, 1, oo)).is_convergent() is S.true + assert Sum(eq, (x, 1, 2)).is_convergent() is S.true + assert Sum(1/(x**3), (x, 1, oo)).is_convergent() is S.true + assert Sum(1/(x**S.Half), (x, 1, oo)).is_convergent() is S.false + + # issue 19545 + assert Sum(1/n - 3/(3*n +2), (n, 1, oo)).is_convergent() is S.true + + # issue 19836 + assert Sum(4/(n + 2) - 5/(n + 1) + 1/n,(n, 7, oo)).is_convergent() is S.true + + +def test_is_absolutely_convergent(): + assert Sum((-1)**n, (n, 1, oo)).is_absolutely_convergent() is S.false + assert Sum((-1)**n/n**2, (n, 1, oo)).is_absolutely_convergent() is S.true + + +@XFAIL +def test_convergent_failing(): + # dirichlet tests + assert Sum(sin(n)/n, (n, 1, oo)).is_convergent() is S.true + assert Sum(sin(2*n)/n, (n, 1, oo)).is_convergent() is S.true + + +def test_issue_6966(): + i, k, m = symbols('i k m', integer=True) + z_i, q_i = symbols('z_i q_i') + a_k = Sum(-q_i*z_i/k,(i,1,m)) + b_k = a_k.diff(z_i) + assert isinstance(b_k, Sum) + assert b_k == Sum(-q_i/k,(i,1,m)) + + +def test_issue_10156(): + cx = Sum(2*y**2*x, (x, 1,3)) + e = 2*y*Sum(2*cx*x**2, (x, 1, 9)) + assert e.factor() == \ + 8*y**3*Sum(x, (x, 1, 3))*Sum(x**2, (x, 1, 9)) + + +def test_issue_10973(): + assert Sum((-n + (n**3 + 1)**(S(1)/3))/log(n), (n, 1, oo)).is_convergent() is S.true + + +def test_issue_14103(): + assert Sum(sin(n)**2 + cos(n)**2 - 1, (n, 1, oo)).is_convergent() is S.true + assert Sum(sin(pi*n), (n, 1, oo)).is_convergent() is S.true + + +def test_issue_14129(): + x = Symbol('x', zero=False) + assert Sum( k*x**k, (k, 0, n-1)).doit() == \ + Piecewise((n**2/2 - n/2, Eq(x, 1)), ((n*x*x**n - + n*x**n - x*x**n + x)/(x - 1)**2, True)) + assert Sum( x**k, (k, 0, n-1)).doit() == \ + Piecewise((n, Eq(x, 1)), ((-x**n + 1)/(-x + 1), True)) + assert Sum( k*(x/y+x)**k, (k, 0, n-1)).doit() == \ + Piecewise((n*(n - 1)/2, Eq(x, y/(y + 1))), + (x*(y + 1)*(n*x*y*(x + x/y)**(n - 1) + + n*x*(x + x/y)**(n - 1) - n*y*(x + x/y)**(n - 1) - + x*y*(x + x/y)**(n - 1) - x*(x + x/y)**(n - 1) + y)/ + (x*y + x - y)**2, True)) + + +def test_issue_14112(): + assert Sum((-1)**n/sqrt(n), (n, 1, oo)).is_absolutely_convergent() is S.false + assert Sum((-1)**(2*n)/n, (n, 1, oo)).is_convergent() is S.false + assert Sum((-2)**n + (-3)**n, (n, 1, oo)).is_convergent() is S.false + + +def test_issue_14219(): + A = diag(0, 2, -3) + res = diag(1, 15, -20) + assert Sum(A**n, (n, 0, 3)).doit() == res + + +def test_sin_times_absolutely_convergent(): + assert Sum(sin(n) / n**3, (n, 1, oo)).is_convergent() is S.true + assert Sum(sin(n) * log(n) / n**3, (n, 1, oo)).is_convergent() is S.true + + +def test_issue_14111(): + assert Sum(1/log(log(n)), (n, 22, oo)).is_convergent() is S.false + + +def test_issue_14484(): + assert Sum(sin(n)/log(log(n)), (n, 22, oo)).is_convergent() is S.false + + +def test_issue_14640(): + i, n = symbols("i n", integer=True) + a, b, c = symbols("a b c", zero=False) + + assert Sum(a**-i/(a - b), (i, 0, n)).doit() == Sum( + 1/(a*a**i - a**i*b), (i, 0, n)).doit() == Piecewise( + (n + 1, Eq(1/a, 1)), + ((-a**(-n - 1) + 1)/(1 - 1/a), True))/(a - b) + + assert Sum((b*a**i - c*a**i)**-2, (i, 0, n)).doit() == Piecewise( + (n + 1, Eq(a**(-2), 1)), + ((-a**(-2*n - 2) + 1)/(1 - 1/a**2), True))/(b - c)**2 + + s = Sum(i*(a**(n - i) - b**(n - i))/(a - b), (i, 0, n)).doit() + assert not s.has(Sum) + assert s.subs({a: 2, b: 3, n: 5}) == 122 + + +def test_issue_15943(): + s = Sum(binomial(n, k)*factorial(n - k), (k, 0, n)).doit().rewrite(gamma) + assert s == -E*(n + 1)*gamma(n + 1)*lowergamma(n + 1, 1)/gamma(n + 2 + ) + E*gamma(n + 1) + assert s.simplify() == E*(factorial(n) - lowergamma(n + 1, 1)) + + +def test_Sum_dummy_eq(): + assert not Sum(x, (x, a, b)).dummy_eq(1) + assert not Sum(x, (x, a, b)).dummy_eq(Sum(x, (x, a, b), (a, 1, 2))) + assert not Sum(x, (x, a, b)).dummy_eq(Sum(x, (x, a, c))) + assert Sum(x, (x, a, b)).dummy_eq(Sum(x, (x, a, b))) + d = Dummy() + assert Sum(x, (x, a, d)).dummy_eq(Sum(x, (x, a, c)), c) + assert not Sum(x, (x, a, d)).dummy_eq(Sum(x, (x, a, c))) + assert Sum(x, (x, a, c)).dummy_eq(Sum(y, (y, a, c))) + assert Sum(x, (x, a, d)).dummy_eq(Sum(y, (y, a, c)), c) + assert not Sum(x, (x, a, d)).dummy_eq(Sum(y, (y, a, c))) + + +def test_issue_15852(): + assert summation(x**y*y, (y, -oo, oo)).doit() == Sum(x**y*y, (y, -oo, oo)) + + +def test_exceptions(): + S = Sum(x, (x, a, b)) + raises(ValueError, lambda: S.change_index(x, x**2, y)) + S = Sum(x, (x, a, b), (x, 1, 4)) + raises(ValueError, lambda: S.index(x)) + S = Sum(x, (x, a, b), (y, 1, 4)) + raises(ValueError, lambda: S.reorder([x])) + S = Sum(x, (x, y, b), (y, 1, 4)) + raises(ReorderError, lambda: S.reorder_limit(0, 1)) + S = Sum(x*y, (x, a, b), (y, 1, 4)) + raises(NotImplementedError, lambda: S.is_convergent()) + + +def test_sumproducts_assumptions(): + M = Symbol('M', integer=True, positive=True) + + m = Symbol('m', integer=True) + for func in [Sum, Product]: + assert func(m, (m, -M, M)).is_positive is None + assert func(m, (m, -M, M)).is_nonpositive is None + assert func(m, (m, -M, M)).is_negative is None + assert func(m, (m, -M, M)).is_nonnegative is None + assert func(m, (m, -M, M)).is_finite is True + + m = Symbol('m', integer=True, nonnegative=True) + for func in [Sum, Product]: + assert func(m, (m, 0, M)).is_positive is None + assert func(m, (m, 0, M)).is_nonpositive is None + assert func(m, (m, 0, M)).is_negative is False + assert func(m, (m, 0, M)).is_nonnegative is True + assert func(m, (m, 0, M)).is_finite is True + + m = Symbol('m', integer=True, positive=True) + for func in [Sum, Product]: + assert func(m, (m, 1, M)).is_positive is True + assert func(m, (m, 1, M)).is_nonpositive is False + assert func(m, (m, 1, M)).is_negative is False + assert func(m, (m, 1, M)).is_nonnegative is True + assert func(m, (m, 1, M)).is_finite is True + + m = Symbol('m', integer=True, negative=True) + assert Sum(m, (m, -M, -1)).is_positive is False + assert Sum(m, (m, -M, -1)).is_nonpositive is True + assert Sum(m, (m, -M, -1)).is_negative is True + assert Sum(m, (m, -M, -1)).is_nonnegative is False + assert Sum(m, (m, -M, -1)).is_finite is True + assert Product(m, (m, -M, -1)).is_positive is None + assert Product(m, (m, -M, -1)).is_nonpositive is None + assert Product(m, (m, -M, -1)).is_negative is None + assert Product(m, (m, -M, -1)).is_nonnegative is None + assert Product(m, (m, -M, -1)).is_finite is True + + m = Symbol('m', integer=True, nonpositive=True) + assert Sum(m, (m, -M, 0)).is_positive is False + assert Sum(m, (m, -M, 0)).is_nonpositive is True + assert Sum(m, (m, -M, 0)).is_negative is None + assert Sum(m, (m, -M, 0)).is_nonnegative is None + assert Sum(m, (m, -M, 0)).is_finite is True + assert Product(m, (m, -M, 0)).is_positive is None + assert Product(m, (m, -M, 0)).is_nonpositive is None + assert Product(m, (m, -M, 0)).is_negative is None + assert Product(m, (m, -M, 0)).is_nonnegative is None + assert Product(m, (m, -M, 0)).is_finite is True + + m = Symbol('m', integer=True) + assert Sum(2, (m, 0, oo)).is_positive is None + assert Sum(2, (m, 0, oo)).is_nonpositive is None + assert Sum(2, (m, 0, oo)).is_negative is None + assert Sum(2, (m, 0, oo)).is_nonnegative is None + assert Sum(2, (m, 0, oo)).is_finite is None + + assert Product(2, (m, 0, oo)).is_positive is None + assert Product(2, (m, 0, oo)).is_nonpositive is None + assert Product(2, (m, 0, oo)).is_negative is False + assert Product(2, (m, 0, oo)).is_nonnegative is None + assert Product(2, (m, 0, oo)).is_finite is None + + assert Product(0, (x, M, M-1)).is_positive is True + assert Product(0, (x, M, M-1)).is_finite is True + + +def test_expand_with_assumptions(): + M = Symbol('M', integer=True, positive=True) + x = Symbol('x', positive=True) + m = Symbol('m', nonnegative=True) + assert log(Product(x**m, (m, 0, M))).expand() == Sum(m*log(x), (m, 0, M)) + assert log(Product(exp(x**m), (m, 0, M))).expand() == Sum(x**m, (m, 0, M)) + assert log(Product(x**m, (m, 0, M))).rewrite(Sum).expand() == Sum(m*log(x), (m, 0, M)) + assert log(Product(exp(x**m), (m, 0, M))).rewrite(Sum).expand() == Sum(x**m, (m, 0, M)) + + n = Symbol('n', nonnegative=True) + i, j = symbols('i,j', positive=True, integer=True) + x, y = symbols('x,y', positive=True) + assert log(Product(x**i*y**j, (i, 1, n), (j, 1, m))).expand() \ + == Sum(i*log(x) + j*log(y), (i, 1, n), (j, 1, m)) + + m = Symbol('m', nonnegative=True, integer=True) + s = Sum(x**m, (m, 0, M)) + s_as_product = s.rewrite(Product) + assert s_as_product.has(Product) + assert s_as_product == log(Product(exp(x**m), (m, 0, M))) + assert s_as_product.expand() == s + s5 = s.subs(M, 5) + s5_as_product = s5.rewrite(Product) + assert s5_as_product.has(Product) + assert s5_as_product.doit().expand() == s5.doit() + + +def test_has_finite_limits(): + x = Symbol('x') + assert Sum(1, (x, 1, 9)).has_finite_limits is True + assert Sum(1, (x, 1, oo)).has_finite_limits is False + M = Symbol('M') + assert Sum(1, (x, 1, M)).has_finite_limits is None + M = Symbol('M', positive=True) + assert Sum(1, (x, 1, M)).has_finite_limits is True + x = Symbol('x', positive=True) + M = Symbol('M') + assert Sum(1, (x, 1, M)).has_finite_limits is True + + assert Sum(1, (x, 1, M), (y, -oo, oo)).has_finite_limits is False + +def test_has_reversed_limits(): + assert Sum(1, (x, 1, 1)).has_reversed_limits is False + assert Sum(1, (x, 1, 9)).has_reversed_limits is False + assert Sum(1, (x, 1, -9)).has_reversed_limits is True + assert Sum(1, (x, 1, 0)).has_reversed_limits is True + assert Sum(1, (x, 1, oo)).has_reversed_limits is False + M = Symbol('M') + assert Sum(1, (x, 1, M)).has_reversed_limits is None + M = Symbol('M', positive=True, integer=True) + assert Sum(1, (x, 1, M)).has_reversed_limits is False + assert Sum(1, (x, 1, M), (y, -oo, oo)).has_reversed_limits is False + M = Symbol('M', negative=True) + assert Sum(1, (x, 1, M)).has_reversed_limits is True + + assert Sum(1, (x, 1, M), (y, -oo, oo)).has_reversed_limits is True + assert Sum(1, (x, oo, oo)).has_reversed_limits is None + + +def test_has_empty_sequence(): + assert Sum(1, (x, 1, 1)).has_empty_sequence is False + assert Sum(1, (x, 1, 9)).has_empty_sequence is False + assert Sum(1, (x, 1, -9)).has_empty_sequence is False + assert Sum(1, (x, 1, 0)).has_empty_sequence is True + assert Sum(1, (x, y, y - 1)).has_empty_sequence is True + assert Sum(1, (x, 3, 2), (y, -oo, oo)).has_empty_sequence is True + assert Sum(1, (y, -oo, oo), (x, 3, 2)).has_empty_sequence is True + assert Sum(1, (x, oo, oo)).has_empty_sequence is False + + +def test_empty_sequence(): + assert Product(x*y, (x, -oo, oo), (y, 1, 0)).doit() == 1 + assert Product(x*y, (y, 1, 0), (x, -oo, oo)).doit() == 1 + assert Sum(x, (x, -oo, oo), (y, 1, 0)).doit() == 0 + assert Sum(x, (y, 1, 0), (x, -oo, oo)).doit() == 0 + + +def test_issue_8016(): + k = Symbol('k', integer=True) + n, m = symbols('n, m', integer=True, positive=True) + s = Sum(binomial(m, k)*binomial(m, n - k)*(-1)**k, (k, 0, n)) + assert s.doit().simplify() == \ + cos(pi*n/2)*gamma(m + 1)/gamma(n/2 + 1)/gamma(m - n/2 + 1) + + +def test_issue_14313(): + assert Sum(S.Half**floor(n/2), (n, 1, oo)).is_convergent() + + +def test_issue_14563(): + # The assertion was failing due to no assumptions methods in Sums and Product + assert 1 % Sum(1, (x, 0, 1)) == 1 + + +def test_issue_16735(): + assert Sum(5**n/gamma(n+1), (n, 1, oo)).is_convergent() is S.true + + +def test_issue_14871(): + assert Sum((Rational(1, 10))**n*rf(0, n)/factorial(n), (n, 0, oo)).rewrite(factorial).doit() == 1 + + +def test_issue_17165(): + n = symbols("n", integer=True) + x = symbols('x') + s = (x*Sum(x**n, (n, -1, oo))) + ssimp = s.doit().simplify() + + assert ssimp == Piecewise((-1/(x - 1), (x > -1) & (x < 1)), + (x*Sum(x**n, (n, -1, oo)), True)), ssimp + assert ssimp.simplify() == ssimp + + +def test_issue_19379(): + assert Sum(factorial(n)/factorial(n + 2), (n, 1, oo)).is_convergent() is S.true + + +def test_issue_20777(): + assert Sum(exp(x*sin(n/m)), (n, 1, m)).doit() == Sum(exp(x*sin(n/m)), (n, 1, m)) + + +def test__dummy_with_inherited_properties_concrete(): + x = Symbol('x') + + from sympy.core.containers import Tuple + d = _dummy_with_inherited_properties_concrete(Tuple(x, 0, 5)) + assert d.is_real + assert d.is_integer + assert d.is_nonnegative + assert d.is_extended_nonnegative + + d = _dummy_with_inherited_properties_concrete(Tuple(x, 1, 9)) + assert d.is_real + assert d.is_integer + assert d.is_positive + assert d.is_odd is None + + d = _dummy_with_inherited_properties_concrete(Tuple(x, -5, 5)) + assert d.is_real + assert d.is_integer + assert d.is_positive is None + assert d.is_extended_nonnegative is None + assert d.is_odd is None + + d = _dummy_with_inherited_properties_concrete(Tuple(x, -1.5, 1.5)) + assert d.is_real + assert d.is_integer is None + assert d.is_positive is None + assert d.is_extended_nonnegative is None + + N = Symbol('N', integer=True, positive=True) + d = _dummy_with_inherited_properties_concrete(Tuple(x, 2, N)) + assert d.is_real + assert d.is_positive + assert d.is_integer + + # Return None if no assumptions are added + N = Symbol('N', integer=True, positive=True) + d = _dummy_with_inherited_properties_concrete(Tuple(N, 2, 4)) + assert d is None + + x = Symbol('x', negative=True) + raises(InconsistentAssumptions, + lambda: _dummy_with_inherited_properties_concrete(Tuple(x, 1, 5))) + + +def test_matrixsymbol_summation_numerical_limits(): + A = MatrixSymbol('A', 3, 3) + n = Symbol('n', integer=True) + + assert Sum(A**n, (n, 0, 2)).doit() == Identity(3) + A + A**2 + assert Sum(A, (n, 0, 2)).doit() == 3*A + assert Sum(n*A, (n, 0, 2)).doit() == 3*A + + B = Matrix([[0, n, 0], [-1, 0, 0], [0, 0, 2]]) + ans = Matrix([[0, 6, 0], [-4, 0, 0], [0, 0, 8]]) + 4*A + assert Sum(A+B, (n, 0, 3)).doit() == ans + ans = A*Matrix([[0, 6, 0], [-4, 0, 0], [0, 0, 8]]) + assert Sum(A*B, (n, 0, 3)).doit() == ans + + ans = (A**2*Matrix([[-2, 0, 0], [0,-2, 0], [0, 0, 4]]) + + A**3*Matrix([[0, -9, 0], [3, 0, 0], [0, 0, 8]]) + + A*Matrix([[0, 1, 0], [-1, 0, 0], [0, 0, 2]])) + assert Sum(A**n*B**n, (n, 1, 3)).doit() == ans + + +def test_issue_21651(): + i = Symbol('i') + a = Sum(floor(2*2**(-i)), (i, S.One, 2)) + assert a.doit() == S.One + + +@XFAIL +def test_matrixsymbol_summation_symbolic_limits(): + N = Symbol('N', integer=True, positive=True) + + A = MatrixSymbol('A', 3, 3) + n = Symbol('n', integer=True) + assert Sum(A, (n, 0, N)).doit() == (N+1)*A + assert Sum(n*A, (n, 0, N)).doit() == (N**2/2+N/2)*A + + +def test_summation_by_residues(): + x = Symbol('x') + + # Examples from Nakhle H. Asmar, Loukas Grafakos, + # Complex Analysis with Applications + assert eval_sum_residue(1 / (x**2 + 1), (x, -oo, oo)) == pi/tanh(pi) + assert eval_sum_residue(1 / x**6, (x, S(1), oo)) == pi**6/945 + assert eval_sum_residue(1 / (x**2 + 9), (x, -oo, oo)) == pi/(3*tanh(3*pi)) + assert eval_sum_residue(1 / (x**2 + 1)**2, (x, -oo, oo)).cancel() == \ + (-pi**2*tanh(pi)**2 + pi*tanh(pi) + pi**2)/(2*tanh(pi)**2) + assert eval_sum_residue(x**2 / (x**2 + 1)**2, (x, -oo, oo)).cancel() == \ + (-pi**2 + pi*tanh(pi) + pi**2*tanh(pi)**2)/(2*tanh(pi)**2) + assert eval_sum_residue(1 / (4*x**2 - 1), (x, -oo, oo)) == 0 + assert eval_sum_residue(x**2 / (x**2 - S(1)/4)**2, (x, -oo, oo)) == pi**2/2 + assert eval_sum_residue(1 / (4*x**2 - 1)**2, (x, -oo, oo)) == pi**2/8 + assert eval_sum_residue(1 / ((x - S(1)/2)**2 + 1), (x, -oo, oo)) == pi*tanh(pi) + assert eval_sum_residue(1 / x**2, (x, S(1), oo)) == pi**2/6 + assert eval_sum_residue(1 / x**4, (x, S(1), oo)) == pi**4/90 + assert eval_sum_residue(1 / x**2 / (x**2 + 4), (x, S(1), oo)) == \ + -pi*(-pi/12 - 1/(16*pi) + 1/(8*tanh(2*pi)))/2 + + # Some examples made from 1 / (x**2 + 1) + assert eval_sum_residue(1 / (x**2 + 1), (x, S(0), oo)) == \ + S(1)/2 + pi/(2*tanh(pi)) + assert eval_sum_residue(1 / (x**2 + 1), (x, S(1), oo)) == \ + -S(1)/2 + pi/(2*tanh(pi)) + assert eval_sum_residue(1 / (x**2 + 1), (x, S(-1), oo)) == \ + 1 + pi/(2*tanh(pi)) + assert eval_sum_residue((-1)**x / (x**2 + 1), (x, -oo, oo)) == \ + pi/sinh(pi) + assert eval_sum_residue((-1)**x / (x**2 + 1), (x, S(0), oo)) == \ + pi/(2*sinh(pi)) + S(1)/2 + assert eval_sum_residue((-1)**x / (x**2 + 1), (x, S(1), oo)) == \ + -S(1)/2 + pi/(2*sinh(pi)) + assert eval_sum_residue((-1)**x / (x**2 + 1), (x, S(-1), oo)) == \ + pi/(2*sinh(pi)) + + # Some examples made from shifting of 1 / (x**2 + 1) + assert eval_sum_residue(1 / (x**2 + 2*x + 2), (x, S(-1), oo)) == S(1)/2 + pi/(2*tanh(pi)) + assert eval_sum_residue(1 / (x**2 + 4*x + 5), (x, S(-2), oo)) == S(1)/2 + pi/(2*tanh(pi)) + assert eval_sum_residue(1 / (x**2 - 2*x + 2), (x, S(1), oo)) == S(1)/2 + pi/(2*tanh(pi)) + assert eval_sum_residue(1 / (x**2 - 4*x + 5), (x, S(2), oo)) == S(1)/2 + pi/(2*tanh(pi)) + assert eval_sum_residue((-1)**x * -1 / (x**2 + 2*x + 2), (x, S(-1), oo)) == S(1)/2 + pi/(2*sinh(pi)) + assert eval_sum_residue((-1)**x * -1 / (x**2 -2*x + 2), (x, S(1), oo)) == S(1)/2 + pi/(2*sinh(pi)) + + # Some examples made from 1 / x**2 + assert eval_sum_residue(1 / x**2, (x, S(2), oo)) == -1 + pi**2/6 + assert eval_sum_residue(1 / x**2, (x, S(3), oo)) == -S(5)/4 + pi**2/6 + assert eval_sum_residue((-1)**x / x**2, (x, S(1), oo)) == -pi**2/12 + assert eval_sum_residue((-1)**x / x**2, (x, S(2), oo)) == 1 - pi**2/12 + + +@slow +def test_summation_by_residues_failing(): + x = Symbol('x') + + # Failing because of the bug in residue computation + assert eval_sum_residue(x**2 / (x**4 + 1), (x, S(1), oo)) + assert eval_sum_residue(1 / ((x - 1)*(x - 2) + 1), (x, -oo, oo)) != 0 + + +def test_process_limits(): + from sympy.concrete.expr_with_limits import _process_limits + + # these should be (x, Range(3)) not Range(3) + raises(ValueError, lambda: _process_limits( + Range(3), discrete=True)) + raises(ValueError, lambda: _process_limits( + Range(3), discrete=False)) + # these should be (x, union) not union + # (but then we would get a TypeError because we don't + # handle non-contiguous sets: see below use of `union`) + union = Or(x < 1, x > 3).as_set() + raises(ValueError, lambda: _process_limits( + union, discrete=True)) + raises(ValueError, lambda: _process_limits( + union, discrete=False)) + + # error not triggered if not needed + assert _process_limits((x, 1, 2)) == ([(x, 1, 2)], 1) + + # this equivalence is used to detect Reals in _process_limits + assert isinstance(S.Reals, Interval) + + C = Integral # continuous limits + assert C(x, x >= 5) == C(x, (x, 5, oo)) + assert C(x, x < 3) == C(x, (x, -oo, 3)) + ans = C(x, (x, 0, 3)) + assert C(x, And(x >= 0, x < 3)) == ans + assert C(x, (x, Interval.Ropen(0, 3))) == ans + raises(TypeError, lambda: C(x, (x, Range(3)))) + + # discrete limits + for D in (Sum, Product): + r, ans = Range(3, 10, 2), D(2*x + 3, (x, 0, 3)) + assert D(x, (x, r)) == ans + assert D(x, (x, r.reversed)) == ans + r, ans = Range(3, oo, 2), D(2*x + 3, (x, 0, oo)) + assert D(x, (x, r)) == ans + assert D(x, (x, r.reversed)) == ans + r, ans = Range(-oo, 5, 2), D(3 - 2*x, (x, 0, oo)) + assert D(x, (x, r)) == ans + assert D(x, (x, r.reversed)) == ans + raises(TypeError, lambda: D(x, x > 0)) + raises(ValueError, lambda: D(x, Interval(1, 3))) + raises(NotImplementedError, lambda: D(x, (x, union))) + + +def test_pr_22677(): + b = Symbol('b', integer=True, positive=True) + assert Sum(1/x**2,(x, 0, b)).doit() == Sum(x**(-2), (x, 0, b)) + assert Sum(1/(x - b)**2,(x, 0, b-1)).doit() == Sum( + (-b + x)**(-2), (x, 0, b - 1)) + + +def test_issue_23952(): + p, q = symbols("p q", real=True, nonnegative=True) + k1, k2 = symbols("k1 k2", integer=True, nonnegative=True) + n = Symbol("n", integer=True, positive=True) + expr = Sum(abs(k1 - k2)*p**k1 *(1 - q)**(n - k2), + (k1, 0, n), (k2, 0, n)) + assert expr.subs(p,0).subs(q,1).subs(n, 3).doit() == 3 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d468b07f5455447c34f9660418a06299644ef464 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/__pycache__/diffgeom.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/__pycache__/diffgeom.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0925077cbf4e9262d73a37f4bc3aae536fb69d6e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/__pycache__/diffgeom.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/__pycache__/rn.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/__pycache__/rn.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4bd6006b44f30f024e8fe1c1e58afa5102da4ebd Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/__pycache__/rn.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..84676fe2d3beda9258f9776faddc5b264868c1c7 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/__pycache__/test_class_structure.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/__pycache__/test_class_structure.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d7f795b69da25098ddf56e459d440051474c800a Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/__pycache__/test_class_structure.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/__pycache__/test_diffgeom.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/__pycache__/test_diffgeom.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..db287c06622c7ffb3c6b1a9778a50c5f60a80abe Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/__pycache__/test_diffgeom.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/__pycache__/test_function_diffgeom_book.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/__pycache__/test_function_diffgeom_book.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c2734dc00a2bf6dda06d5b0314152c8fccedee54 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/__pycache__/test_function_diffgeom_book.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/__pycache__/test_hyperbolic_space.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/__pycache__/test_hyperbolic_space.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a8ca5172c1f19d7c45408d931a21857614273be6 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/__pycache__/test_hyperbolic_space.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/test_class_structure.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/test_class_structure.py new file mode 100644 index 0000000000000000000000000000000000000000..c649fd9fcb9acdf1f410a021966c6e0fee62cc2b --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/test_class_structure.py @@ -0,0 +1,33 @@ +from sympy.diffgeom import Manifold, Patch, CoordSystem, Point +from sympy.core.function import Function +from sympy.core.symbol import symbols +from sympy.testing.pytest import warns_deprecated_sympy + +m = Manifold('m', 2) +p = Patch('p', m) +a, b = symbols('a b') +cs = CoordSystem('cs', p, [a, b]) +x, y = symbols('x y') +f = Function('f') +s1, s2 = cs.coord_functions() +v1, v2 = cs.base_vectors() +f1, f2 = cs.base_oneforms() + +def test_point(): + point = Point(cs, [x, y]) + assert point != Point(cs, [2, y]) + #TODO assert point.subs(x, 2) == Point(cs, [2, y]) + #TODO assert point.free_symbols == set([x, y]) + +def test_subs(): + assert s1.subs(s1, s2) == s2 + assert v1.subs(v1, v2) == v2 + assert f1.subs(f1, f2) == f2 + assert (x*f(s1) + y).subs(s1, s2) == x*f(s2) + y + assert (f(s1)*v1).subs(v1, v2) == f(s1)*v2 + assert (y*f(s1)*f1).subs(f1, f2) == y*f(s1)*f2 + +def test_deprecated(): + with warns_deprecated_sympy(): + cs_wname = CoordSystem('cs', p, ['a', 'b']) + assert cs_wname == cs_wname.func(*cs_wname.args) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/test_diffgeom.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/test_diffgeom.py new file mode 100644 index 0000000000000000000000000000000000000000..7c3c9265785896b8f4ffa3a2b41816ca90579758 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/test_diffgeom.py @@ -0,0 +1,342 @@ +from sympy.core import Lambda, Symbol, symbols +from sympy.diffgeom.rn import R2, R2_p, R2_r, R3_r, R3_c, R3_s, R2_origin +from sympy.diffgeom import (Manifold, Patch, CoordSystem, Commutator, Differential, TensorProduct, + WedgeProduct, BaseCovarDerivativeOp, CovarDerivativeOp, LieDerivative, + covariant_order, contravariant_order, twoform_to_matrix, metric_to_Christoffel_1st, + metric_to_Christoffel_2nd, metric_to_Riemann_components, + metric_to_Ricci_components, intcurve_diffequ, intcurve_series) +from sympy.simplify import trigsimp, simplify +from sympy.functions import sqrt, atan2, sin +from sympy.matrices import Matrix +from sympy.testing.pytest import raises, nocache_fail +from sympy.testing.pytest import warns_deprecated_sympy + +TP = TensorProduct + + +def test_coordsys_transform(): + # test inverse transforms + p, q, r, s = symbols('p q r s') + rel = {('first', 'second'): [(p, q), (q, -p)]} + R2_pq = CoordSystem('first', R2_origin, [p, q], rel) + R2_rs = CoordSystem('second', R2_origin, [r, s], rel) + r, s = R2_rs.symbols + assert R2_rs.transform(R2_pq) == Matrix([[-s], [r]]) + + # inverse transform impossible case + a, b = symbols('a b', positive=True) + rel = {('first', 'second'): [(a,), (-a,)]} + R2_a = CoordSystem('first', R2_origin, [a], rel) + R2_b = CoordSystem('second', R2_origin, [b], rel) + # This transformation is uninvertible because there is no positive a, b satisfying a = -b + with raises(NotImplementedError): + R2_b.transform(R2_a) + + # inverse transform ambiguous case + c, d = symbols('c d') + rel = {('first', 'second'): [(c,), (c**2,)]} + R2_c = CoordSystem('first', R2_origin, [c], rel) + R2_d = CoordSystem('second', R2_origin, [d], rel) + # The transform method should throw if it finds multiple inverses for a coordinate transformation. + with raises(ValueError): + R2_d.transform(R2_c) + + # test indirect transformation + a, b, c, d, e, f = symbols('a, b, c, d, e, f') + rel = {('C1', 'C2'): [(a, b), (2*a, 3*b)], + ('C2', 'C3'): [(c, d), (3*c, 2*d)]} + C1 = CoordSystem('C1', R2_origin, (a, b), rel) + C2 = CoordSystem('C2', R2_origin, (c, d), rel) + C3 = CoordSystem('C3', R2_origin, (e, f), rel) + a, b = C1.symbols + c, d = C2.symbols + e, f = C3.symbols + assert C2.transform(C1) == Matrix([c/2, d/3]) + assert C1.transform(C3) == Matrix([6*a, 6*b]) + assert C3.transform(C1) == Matrix([e/6, f/6]) + assert C3.transform(C2) == Matrix([e/3, f/2]) + + a, b, c, d, e, f = symbols('a, b, c, d, e, f') + rel = {('C1', 'C2'): [(a, b), (2*a, 3*b + 1)], + ('C3', 'C2'): [(e, f), (-e - 2, 2*f)]} + C1 = CoordSystem('C1', R2_origin, (a, b), rel) + C2 = CoordSystem('C2', R2_origin, (c, d), rel) + C3 = CoordSystem('C3', R2_origin, (e, f), rel) + a, b = C1.symbols + c, d = C2.symbols + e, f = C3.symbols + assert C2.transform(C1) == Matrix([c/2, (d - 1)/3]) + assert C1.transform(C3) == Matrix([-2*a - 2, (3*b + 1)/2]) + assert C3.transform(C1) == Matrix([-e/2 - 1, (2*f - 1)/3]) + assert C3.transform(C2) == Matrix([-e - 2, 2*f]) + + # old signature uses Lambda + a, b, c, d, e, f = symbols('a, b, c, d, e, f') + rel = {('C1', 'C2'): Lambda((a, b), (2*a, 3*b + 1)), + ('C3', 'C2'): Lambda((e, f), (-e - 2, 2*f))} + C1 = CoordSystem('C1', R2_origin, (a, b), rel) + C2 = CoordSystem('C2', R2_origin, (c, d), rel) + C3 = CoordSystem('C3', R2_origin, (e, f), rel) + a, b = C1.symbols + c, d = C2.symbols + e, f = C3.symbols + assert C2.transform(C1) == Matrix([c/2, (d - 1)/3]) + assert C1.transform(C3) == Matrix([-2*a - 2, (3*b + 1)/2]) + assert C3.transform(C1) == Matrix([-e/2 - 1, (2*f - 1)/3]) + assert C3.transform(C2) == Matrix([-e - 2, 2*f]) + + +def test_R2(): + x0, y0, r0, theta0 = symbols('x0, y0, r0, theta0', real=True) + point_r = R2_r.point([x0, y0]) + point_p = R2_p.point([r0, theta0]) + + # r**2 = x**2 + y**2 + assert (R2.r**2 - R2.x**2 - R2.y**2).rcall(point_r) == 0 + assert trigsimp( (R2.r**2 - R2.x**2 - R2.y**2).rcall(point_p) ) == 0 + assert trigsimp(R2.e_r(R2.x**2 + R2.y**2).rcall(point_p).doit()) == 2*r0 + + # polar->rect->polar == Id + a, b = symbols('a b', positive=True) + m = Matrix([[a], [b]]) + + #TODO assert m == R2_r.transform(R2_p, R2_p.transform(R2_r, [a, b])).applyfunc(simplify) + assert m == R2_p.transform(R2_r, R2_r.transform(R2_p, m)).applyfunc(simplify) + + # deprecated method + with warns_deprecated_sympy(): + assert m == R2_p.coord_tuple_transform_to( + R2_r, R2_r.coord_tuple_transform_to(R2_p, m)).applyfunc(simplify) + + +def test_R3(): + a, b, c = symbols('a b c', positive=True) + m = Matrix([[a], [b], [c]]) + + assert m == R3_c.transform(R3_r, R3_r.transform(R3_c, m)).applyfunc(simplify) + #TODO assert m == R3_r.transform(R3_c, R3_c.transform(R3_r, m)).applyfunc(simplify) + assert m == R3_s.transform( + R3_r, R3_r.transform(R3_s, m)).applyfunc(simplify) + #TODO assert m == R3_r.transform(R3_s, R3_s.transform(R3_r, m)).applyfunc(simplify) + assert m == R3_s.transform( + R3_c, R3_c.transform(R3_s, m)).applyfunc(simplify) + #TODO assert m == R3_c.transform(R3_s, R3_s.transform(R3_c, m)).applyfunc(simplify) + + with warns_deprecated_sympy(): + assert m == R3_c.coord_tuple_transform_to( + R3_r, R3_r.coord_tuple_transform_to(R3_c, m)).applyfunc(simplify) + #TODO assert m == R3_r.coord_tuple_transform_to(R3_c, R3_c.coord_tuple_transform_to(R3_r, m)).applyfunc(simplify) + assert m == R3_s.coord_tuple_transform_to( + R3_r, R3_r.coord_tuple_transform_to(R3_s, m)).applyfunc(simplify) + #TODO assert m == R3_r.coord_tuple_transform_to(R3_s, R3_s.coord_tuple_transform_to(R3_r, m)).applyfunc(simplify) + assert m == R3_s.coord_tuple_transform_to( + R3_c, R3_c.coord_tuple_transform_to(R3_s, m)).applyfunc(simplify) + #TODO assert m == R3_c.coord_tuple_transform_to(R3_s, R3_s.coord_tuple_transform_to(R3_c, m)).applyfunc(simplify) + + +def test_CoordinateSymbol(): + x, y = R2_r.symbols + r, theta = R2_p.symbols + assert y.rewrite(R2_p) == r*sin(theta) + + +def test_point(): + x, y = symbols('x, y') + p = R2_r.point([x, y]) + assert p.free_symbols == {x, y} + assert p.coords(R2_r) == p.coords() == Matrix([x, y]) + assert p.coords(R2_p) == Matrix([sqrt(x**2 + y**2), atan2(y, x)]) + + +def test_commutator(): + assert Commutator(R2.e_x, R2.e_y) == 0 + assert Commutator(R2.x*R2.e_x, R2.x*R2.e_x) == 0 + assert Commutator(R2.x*R2.e_x, R2.x*R2.e_y) == R2.x*R2.e_y + c = Commutator(R2.e_x, R2.e_r) + assert c(R2.x) == R2.y*(R2.x**2 + R2.y**2)**(-1)*sin(R2.theta) + + +def test_differential(): + xdy = R2.x*R2.dy + dxdy = Differential(xdy) + assert xdy.rcall(None) == xdy + assert dxdy(R2.e_x, R2.e_y) == 1 + assert dxdy(R2.e_x, R2.x*R2.e_y) == R2.x + assert Differential(dxdy) == 0 + + +def test_products(): + assert TensorProduct( + R2.dx, R2.dy)(R2.e_x, R2.e_y) == R2.dx(R2.e_x)*R2.dy(R2.e_y) == 1 + assert TensorProduct(R2.dx, R2.dy)(None, R2.e_y) == R2.dx + assert TensorProduct(R2.dx, R2.dy)(R2.e_x, None) == R2.dy + assert TensorProduct(R2.dx, R2.dy)(R2.e_x) == R2.dy + assert TensorProduct(R2.x, R2.dx) == R2.x*R2.dx + assert TensorProduct( + R2.e_x, R2.e_y)(R2.x, R2.y) == R2.e_x(R2.x) * R2.e_y(R2.y) == 1 + assert TensorProduct(R2.e_x, R2.e_y)(None, R2.y) == R2.e_x + assert TensorProduct(R2.e_x, R2.e_y)(R2.x, None) == R2.e_y + assert TensorProduct(R2.e_x, R2.e_y)(R2.x) == R2.e_y + assert TensorProduct(R2.x, R2.e_x) == R2.x * R2.e_x + assert TensorProduct( + R2.dx, R2.e_y)(R2.e_x, R2.y) == R2.dx(R2.e_x) * R2.e_y(R2.y) == 1 + assert TensorProduct(R2.dx, R2.e_y)(None, R2.y) == R2.dx + assert TensorProduct(R2.dx, R2.e_y)(R2.e_x, None) == R2.e_y + assert TensorProduct(R2.dx, R2.e_y)(R2.e_x) == R2.e_y + assert TensorProduct(R2.x, R2.e_x) == R2.x * R2.e_x + assert TensorProduct( + R2.e_x, R2.dy)(R2.x, R2.e_y) == R2.e_x(R2.x) * R2.dy(R2.e_y) == 1 + assert TensorProduct(R2.e_x, R2.dy)(None, R2.e_y) == R2.e_x + assert TensorProduct(R2.e_x, R2.dy)(R2.x, None) == R2.dy + assert TensorProduct(R2.e_x, R2.dy)(R2.x) == R2.dy + assert TensorProduct(R2.e_y,R2.e_x)(R2.x**2 + R2.y**2,R2.x**2 + R2.y**2) == 4*R2.x*R2.y + + assert WedgeProduct(R2.dx, R2.dy)(R2.e_x, R2.e_y) == 1 + assert WedgeProduct(R2.e_x, R2.e_y)(R2.x, R2.y) == 1 + + +def test_lie_derivative(): + assert LieDerivative(R2.e_x, R2.y) == R2.e_x(R2.y) == 0 + assert LieDerivative(R2.e_x, R2.x) == R2.e_x(R2.x) == 1 + assert LieDerivative(R2.e_x, R2.e_x) == Commutator(R2.e_x, R2.e_x) == 0 + assert LieDerivative(R2.e_x, R2.e_r) == Commutator(R2.e_x, R2.e_r) + assert LieDerivative(R2.e_x + R2.e_y, R2.x) == 1 + assert LieDerivative( + R2.e_x, TensorProduct(R2.dx, R2.dy))(R2.e_x, R2.e_y) == 0 + + +@nocache_fail +def test_covar_deriv(): + ch = metric_to_Christoffel_2nd(TP(R2.dx, R2.dx) + TP(R2.dy, R2.dy)) + cvd = BaseCovarDerivativeOp(R2_r, 0, ch) + assert cvd(R2.x) == 1 + # This line fails if the cache is disabled: + assert cvd(R2.x*R2.e_x) == R2.e_x + cvd = CovarDerivativeOp(R2.x*R2.e_x, ch) + assert cvd(R2.x) == R2.x + assert cvd(R2.x*R2.e_x) == R2.x*R2.e_x + + +def test_intcurve_diffequ(): + t = symbols('t') + start_point = R2_r.point([1, 0]) + vector_field = -R2.y*R2.e_x + R2.x*R2.e_y + equations, init_cond = intcurve_diffequ(vector_field, t, start_point) + assert str(equations) == '[f_1(t) + Derivative(f_0(t), t), -f_0(t) + Derivative(f_1(t), t)]' + assert str(init_cond) == '[f_0(0) - 1, f_1(0)]' + equations, init_cond = intcurve_diffequ(vector_field, t, start_point, R2_p) + assert str( + equations) == '[Derivative(f_0(t), t), Derivative(f_1(t), t) - 1]' + assert str(init_cond) == '[f_0(0) - 1, f_1(0)]' + + +def test_helpers_and_coordinate_dependent(): + one_form = R2.dr + R2.dx + two_form = Differential(R2.x*R2.dr + R2.r*R2.dx) + three_form = Differential( + R2.y*two_form) + Differential(R2.x*Differential(R2.r*R2.dr)) + metric = TensorProduct(R2.dx, R2.dx) + TensorProduct(R2.dy, R2.dy) + metric_ambig = TensorProduct(R2.dx, R2.dx) + TensorProduct(R2.dr, R2.dr) + misform_a = TensorProduct(R2.dr, R2.dr) + R2.dr + misform_b = R2.dr**4 + misform_c = R2.dx*R2.dy + twoform_not_sym = TensorProduct(R2.dx, R2.dx) + TensorProduct(R2.dx, R2.dy) + twoform_not_TP = WedgeProduct(R2.dx, R2.dy) + + one_vector = R2.e_x + R2.e_y + two_vector = TensorProduct(R2.e_x, R2.e_y) + three_vector = TensorProduct(R2.e_x, R2.e_y, R2.e_x) + two_wp = WedgeProduct(R2.e_x,R2.e_y) + + assert covariant_order(one_form) == 1 + assert covariant_order(two_form) == 2 + assert covariant_order(three_form) == 3 + assert covariant_order(two_form + metric) == 2 + assert covariant_order(two_form + metric_ambig) == 2 + assert covariant_order(two_form + twoform_not_sym) == 2 + assert covariant_order(two_form + twoform_not_TP) == 2 + + assert contravariant_order(one_vector) == 1 + assert contravariant_order(two_vector) == 2 + assert contravariant_order(three_vector) == 3 + assert contravariant_order(two_vector + two_wp) == 2 + + raises(ValueError, lambda: covariant_order(misform_a)) + raises(ValueError, lambda: covariant_order(misform_b)) + raises(ValueError, lambda: covariant_order(misform_c)) + + assert twoform_to_matrix(metric) == Matrix([[1, 0], [0, 1]]) + assert twoform_to_matrix(twoform_not_sym) == Matrix([[1, 0], [1, 0]]) + assert twoform_to_matrix(twoform_not_TP) == Matrix([[0, -1], [1, 0]]) + + raises(ValueError, lambda: twoform_to_matrix(one_form)) + raises(ValueError, lambda: twoform_to_matrix(three_form)) + raises(ValueError, lambda: twoform_to_matrix(metric_ambig)) + + raises(ValueError, lambda: metric_to_Christoffel_1st(twoform_not_sym)) + raises(ValueError, lambda: metric_to_Christoffel_2nd(twoform_not_sym)) + raises(ValueError, lambda: metric_to_Riemann_components(twoform_not_sym)) + raises(ValueError, lambda: metric_to_Ricci_components(twoform_not_sym)) + + +def test_correct_arguments(): + raises(ValueError, lambda: R2.e_x(R2.e_x)) + raises(ValueError, lambda: R2.e_x(R2.dx)) + + raises(ValueError, lambda: Commutator(R2.e_x, R2.x)) + raises(ValueError, lambda: Commutator(R2.dx, R2.e_x)) + + raises(ValueError, lambda: Differential(Differential(R2.e_x))) + + raises(ValueError, lambda: R2.dx(R2.x)) + + raises(ValueError, lambda: LieDerivative(R2.dx, R2.dx)) + raises(ValueError, lambda: LieDerivative(R2.x, R2.dx)) + + raises(ValueError, lambda: CovarDerivativeOp(R2.dx, [])) + raises(ValueError, lambda: CovarDerivativeOp(R2.x, [])) + + a = Symbol('a') + raises(ValueError, lambda: intcurve_series(R2.dx, a, R2_r.point([1, 2]))) + raises(ValueError, lambda: intcurve_series(R2.x, a, R2_r.point([1, 2]))) + + raises(ValueError, lambda: intcurve_diffequ(R2.dx, a, R2_r.point([1, 2]))) + raises(ValueError, lambda: intcurve_diffequ(R2.x, a, R2_r.point([1, 2]))) + + raises(ValueError, lambda: contravariant_order(R2.e_x + R2.dx)) + raises(ValueError, lambda: covariant_order(R2.e_x + R2.dx)) + + raises(ValueError, lambda: contravariant_order(R2.e_x*R2.e_y)) + raises(ValueError, lambda: covariant_order(R2.dx*R2.dy)) + +def test_simplify(): + x, y = R2_r.coord_functions() + dx, dy = R2_r.base_oneforms() + ex, ey = R2_r.base_vectors() + assert simplify(x) == x + assert simplify(x*y) == x*y + assert simplify(dx*dy) == dx*dy + assert simplify(ex*ey) == ex*ey + assert ((1-x)*dx)/(1-x)**2 == dx/(1-x) + + +def test_issue_17917(): + X = R2.x*R2.e_x - R2.y*R2.e_y + Y = (R2.x**2 + R2.y**2)*R2.e_x - R2.x*R2.y*R2.e_y + assert LieDerivative(X, Y).expand() == ( + R2.x**2*R2.e_x - 3*R2.y**2*R2.e_x - R2.x*R2.y*R2.e_y) + +def test_deprecations(): + m = Manifold('M', 2) + p = Patch('P', m) + with warns_deprecated_sympy(): + CoordSystem('Car2d', p, names=['x', 'y']) + + with warns_deprecated_sympy(): + c = CoordSystem('Car2d', p, ['x', 'y']) + + with warns_deprecated_sympy(): + list(m.patches) + + with warns_deprecated_sympy(): + list(c.transforms) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/test_function_diffgeom_book.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/test_function_diffgeom_book.py new file mode 100644 index 0000000000000000000000000000000000000000..44d9623bc34ab73c7d575d9d9fd5b6d84f8e4a94 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/test_function_diffgeom_book.py @@ -0,0 +1,145 @@ +from sympy.diffgeom.rn import R2, R2_p, R2_r, R3_r +from sympy.diffgeom import intcurve_series, Differential, WedgeProduct +from sympy.core import symbols, Function, Derivative +from sympy.simplify import trigsimp, simplify +from sympy.functions import sqrt, atan2, sin, cos +from sympy.matrices import Matrix + +# Most of the functionality is covered in the +# test_functional_diffgeom_ch* tests which are based on the +# example from the paper of Sussman and Wisdom. +# If they do not cover something, additional tests are added in other test +# functions. + +# From "Functional Differential Geometry" as of 2011 +# by Sussman and Wisdom. + + +def test_functional_diffgeom_ch2(): + x0, y0, r0, theta0 = symbols('x0, y0, r0, theta0', real=True) + x, y = symbols('x, y', real=True) + f = Function('f') + + assert (R2_p.point_to_coords(R2_r.point([x0, y0])) == + Matrix([sqrt(x0**2 + y0**2), atan2(y0, x0)])) + assert (R2_r.point_to_coords(R2_p.point([r0, theta0])) == + Matrix([r0*cos(theta0), r0*sin(theta0)])) + + assert R2_p.jacobian(R2_r, [r0, theta0]) == Matrix( + [[cos(theta0), -r0*sin(theta0)], [sin(theta0), r0*cos(theta0)]]) + + field = f(R2.x, R2.y) + p1_in_rect = R2_r.point([x0, y0]) + p1_in_polar = R2_p.point([sqrt(x0**2 + y0**2), atan2(y0, x0)]) + assert field.rcall(p1_in_rect) == f(x0, y0) + assert field.rcall(p1_in_polar) == f(x0, y0) + + p_r = R2_r.point([x0, y0]) + p_p = R2_p.point([r0, theta0]) + assert R2.x(p_r) == x0 + assert R2.x(p_p) == r0*cos(theta0) + assert R2.r(p_p) == r0 + assert R2.r(p_r) == sqrt(x0**2 + y0**2) + assert R2.theta(p_r) == atan2(y0, x0) + + h = R2.x*R2.r**2 + R2.y**3 + assert h.rcall(p_r) == x0*(x0**2 + y0**2) + y0**3 + assert h.rcall(p_p) == r0**3*sin(theta0)**3 + r0**3*cos(theta0) + + +def test_functional_diffgeom_ch3(): + x0, y0 = symbols('x0, y0', real=True) + x, y, t = symbols('x, y, t', real=True) + f = Function('f') + b1 = Function('b1') + b2 = Function('b2') + p_r = R2_r.point([x0, y0]) + + s_field = f(R2.x, R2.y) + v_field = b1(R2.x)*R2.e_x + b2(R2.y)*R2.e_y + assert v_field.rcall(s_field).rcall(p_r).doit() == b1( + x0)*Derivative(f(x0, y0), x0) + b2(y0)*Derivative(f(x0, y0), y0) + + assert R2.e_x(R2.r**2).rcall(p_r) == 2*x0 + v = R2.e_x + 2*R2.e_y + s = R2.r**2 + 3*R2.x + assert v.rcall(s).rcall(p_r).doit() == 2*x0 + 4*y0 + 3 + + circ = -R2.y*R2.e_x + R2.x*R2.e_y + series = intcurve_series(circ, t, R2_r.point([1, 0]), coeffs=True) + series_x, series_y = zip(*series) + assert all( + term == cos(t).taylor_term(i, t) for i, term in enumerate(series_x)) + assert all( + term == sin(t).taylor_term(i, t) for i, term in enumerate(series_y)) + + +def test_functional_diffgeom_ch4(): + x0, y0, theta0 = symbols('x0, y0, theta0', real=True) + x, y, r, theta = symbols('x, y, r, theta', real=True) + r0 = symbols('r0', positive=True) + f = Function('f') + b1 = Function('b1') + b2 = Function('b2') + p_r = R2_r.point([x0, y0]) + p_p = R2_p.point([r0, theta0]) + + f_field = b1(R2.x, R2.y)*R2.dx + b2(R2.x, R2.y)*R2.dy + assert f_field.rcall(R2.e_x).rcall(p_r) == b1(x0, y0) + assert f_field.rcall(R2.e_y).rcall(p_r) == b2(x0, y0) + + s_field_r = f(R2.x, R2.y) + df = Differential(s_field_r) + assert df(R2.e_x).rcall(p_r).doit() == Derivative(f(x0, y0), x0) + assert df(R2.e_y).rcall(p_r).doit() == Derivative(f(x0, y0), y0) + + s_field_p = f(R2.r, R2.theta) + df = Differential(s_field_p) + assert trigsimp(df(R2.e_x).rcall(p_p).doit()) == ( + cos(theta0)*Derivative(f(r0, theta0), r0) - + sin(theta0)*Derivative(f(r0, theta0), theta0)/r0) + assert trigsimp(df(R2.e_y).rcall(p_p).doit()) == ( + sin(theta0)*Derivative(f(r0, theta0), r0) + + cos(theta0)*Derivative(f(r0, theta0), theta0)/r0) + + assert R2.dx(R2.e_x).rcall(p_r) == 1 + assert R2.dx(R2.e_x) == 1 + assert R2.dx(R2.e_y).rcall(p_r) == 0 + assert R2.dx(R2.e_y) == 0 + + circ = -R2.y*R2.e_x + R2.x*R2.e_y + assert R2.dx(circ).rcall(p_r).doit() == -y0 + assert R2.dy(circ).rcall(p_r) == x0 + assert R2.dr(circ).rcall(p_r) == 0 + assert simplify(R2.dtheta(circ).rcall(p_r)) == 1 + + assert (circ - R2.e_theta).rcall(s_field_r).rcall(p_r) == 0 + + +def test_functional_diffgeom_ch6(): + u0, u1, u2, v0, v1, v2, w0, w1, w2 = symbols('u0:3, v0:3, w0:3', real=True) + + u = u0*R2.e_x + u1*R2.e_y + v = v0*R2.e_x + v1*R2.e_y + wp = WedgeProduct(R2.dx, R2.dy) + assert wp(u, v) == u0*v1 - u1*v0 + + u = u0*R3_r.e_x + u1*R3_r.e_y + u2*R3_r.e_z + v = v0*R3_r.e_x + v1*R3_r.e_y + v2*R3_r.e_z + w = w0*R3_r.e_x + w1*R3_r.e_y + w2*R3_r.e_z + wp = WedgeProduct(R3_r.dx, R3_r.dy, R3_r.dz) + assert wp( + u, v, w) == Matrix(3, 3, [u0, u1, u2, v0, v1, v2, w0, w1, w2]).det() + + a, b, c = symbols('a, b, c', cls=Function) + a_f = a(R3_r.x, R3_r.y, R3_r.z) + b_f = b(R3_r.x, R3_r.y, R3_r.z) + c_f = c(R3_r.x, R3_r.y, R3_r.z) + theta = a_f*R3_r.dx + b_f*R3_r.dy + c_f*R3_r.dz + dtheta = Differential(theta) + da = Differential(a_f) + db = Differential(b_f) + dc = Differential(c_f) + expr = dtheta - WedgeProduct( + da, R3_r.dx) - WedgeProduct(db, R3_r.dy) - WedgeProduct(dc, R3_r.dz) + assert expr.rcall(R3_r.e_x, R3_r.e_y) == 0 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/test_hyperbolic_space.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/test_hyperbolic_space.py new file mode 100644 index 0000000000000000000000000000000000000000..48ddc7f8065f2b69bcd8eca4726a21c5901514ec --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/diffgeom/tests/test_hyperbolic_space.py @@ -0,0 +1,91 @@ +r''' +unit test describing the hyperbolic half-plane with the Poincare metric. This +is a basic model of hyperbolic geometry on the (positive) half-space + +{(x,y) \in R^2 | y > 0} + +with the Riemannian metric + +ds^2 = (dx^2 + dy^2)/y^2 + +It has constant negative scalar curvature = -2 + +https://en.wikipedia.org/wiki/Poincare_half-plane_model +''' +from sympy.matrices.dense import diag +from sympy.diffgeom import (twoform_to_matrix, + metric_to_Christoffel_1st, metric_to_Christoffel_2nd, + metric_to_Riemann_components, metric_to_Ricci_components) +import sympy.diffgeom.rn +from sympy.tensor.array import ImmutableDenseNDimArray + + +def test_H2(): + TP = sympy.diffgeom.TensorProduct + R2 = sympy.diffgeom.rn.R2 + y = R2.y + dy = R2.dy + dx = R2.dx + g = (TP(dx, dx) + TP(dy, dy))*y**(-2) + automat = twoform_to_matrix(g) + mat = diag(y**(-2), y**(-2)) + assert mat == automat + + gamma1 = metric_to_Christoffel_1st(g) + assert gamma1[0, 0, 0] == 0 + assert gamma1[0, 0, 1] == -y**(-3) + assert gamma1[0, 1, 0] == -y**(-3) + assert gamma1[0, 1, 1] == 0 + + assert gamma1[1, 1, 1] == -y**(-3) + assert gamma1[1, 1, 0] == 0 + assert gamma1[1, 0, 1] == 0 + assert gamma1[1, 0, 0] == y**(-3) + + gamma2 = metric_to_Christoffel_2nd(g) + assert gamma2[0, 0, 0] == 0 + assert gamma2[0, 0, 1] == -y**(-1) + assert gamma2[0, 1, 0] == -y**(-1) + assert gamma2[0, 1, 1] == 0 + + assert gamma2[1, 1, 1] == -y**(-1) + assert gamma2[1, 1, 0] == 0 + assert gamma2[1, 0, 1] == 0 + assert gamma2[1, 0, 0] == y**(-1) + + Rm = metric_to_Riemann_components(g) + assert Rm[0, 0, 0, 0] == 0 + assert Rm[0, 0, 0, 1] == 0 + assert Rm[0, 0, 1, 0] == 0 + assert Rm[0, 0, 1, 1] == 0 + + assert Rm[0, 1, 0, 0] == 0 + assert Rm[0, 1, 0, 1] == -y**(-2) + assert Rm[0, 1, 1, 0] == y**(-2) + assert Rm[0, 1, 1, 1] == 0 + + assert Rm[1, 0, 0, 0] == 0 + assert Rm[1, 0, 0, 1] == y**(-2) + assert Rm[1, 0, 1, 0] == -y**(-2) + assert Rm[1, 0, 1, 1] == 0 + + assert Rm[1, 1, 0, 0] == 0 + assert Rm[1, 1, 0, 1] == 0 + assert Rm[1, 1, 1, 0] == 0 + assert Rm[1, 1, 1, 1] == 0 + + Ric = metric_to_Ricci_components(g) + assert Ric[0, 0] == -y**(-2) + assert Ric[0, 1] == 0 + assert Ric[1, 0] == 0 + assert Ric[0, 0] == -y**(-2) + + assert Ric == ImmutableDenseNDimArray([-y**(-2), 0, 0, -y**(-2)], (2, 2)) + + ## scalar curvature is -2 + #TODO - it would be nice to have index contraction built-in + R = (Ric[0, 0] + Ric[1, 1])*y**2 + assert R == -2 + + ## Gauss curvature is -1 + assert R/2 == -1 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..52d21ed375791b25b1c9e42c2af4f2a1da10ba98 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..584b3c8d46b5c7600d85efc7db46d7aa190397f8 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/__init__.py @@ -0,0 +1 @@ +# Stub __init__.py for sympy.functions.combinatorial diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..419099b34043055c9b87b32bbfb123e677507576 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/__pycache__/factorials.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/__pycache__/factorials.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..766a0adc86953236c551327505eb6930695268a7 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/__pycache__/factorials.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/factorials.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/factorials.py new file mode 100644 index 0000000000000000000000000000000000000000..0c6d2f09524debca29d3040b28a019127a244b33 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/factorials.py @@ -0,0 +1,1133 @@ +from __future__ import annotations +from functools import reduce + +from sympy.core import S, sympify, Dummy, Mod +from sympy.core.cache import cacheit +from sympy.core.function import DefinedFunction, ArgumentIndexError, PoleError +from sympy.core.logic import fuzzy_and +from sympy.core.numbers import Integer, pi, I +from sympy.core.relational import Eq +from sympy.external.gmpy import gmpy as _gmpy +from sympy.ntheory import sieve +from sympy.ntheory.residue_ntheory import binomial_mod +from sympy.polys.polytools import Poly + +from math import factorial as _factorial, prod, sqrt as _sqrt + +class CombinatorialFunction(DefinedFunction): + """Base class for combinatorial functions. """ + + def _eval_simplify(self, **kwargs): + from sympy.simplify.combsimp import combsimp + # combinatorial function with non-integer arguments is + # automatically passed to gammasimp + expr = combsimp(self) + measure = kwargs['measure'] + if measure(expr) <= kwargs['ratio']*measure(self): + return expr + return self + + +############################################################################### +######################## FACTORIAL and MULTI-FACTORIAL ######################## +############################################################################### + + +class factorial(CombinatorialFunction): + r"""Implementation of factorial function over nonnegative integers. + By convention (consistent with the gamma function and the binomial + coefficients), factorial of a negative integer is complex infinity. + + The factorial is very important in combinatorics where it gives + the number of ways in which `n` objects can be permuted. It also + arises in calculus, probability, number theory, etc. + + There is strict relation of factorial with gamma function. In + fact `n! = gamma(n+1)` for nonnegative integers. Rewrite of this + kind is very useful in case of combinatorial simplification. + + Computation of the factorial is done using two algorithms. For + small arguments a precomputed look up table is used. However for bigger + input algorithm Prime-Swing is used. It is the fastest algorithm + known and computes `n!` via prime factorization of special class + of numbers, called here the 'Swing Numbers'. + + Examples + ======== + + >>> from sympy import Symbol, factorial, S + >>> n = Symbol('n', integer=True) + + >>> factorial(0) + 1 + + >>> factorial(7) + 5040 + + >>> factorial(-2) + zoo + + >>> factorial(n) + factorial(n) + + >>> factorial(2*n) + factorial(2*n) + + >>> factorial(S(1)/2) + factorial(1/2) + + See Also + ======== + + factorial2, RisingFactorial, FallingFactorial + """ + + def fdiff(self, argindex=1): + from sympy.functions.special.gamma_functions import (gamma, polygamma) + if argindex == 1: + return gamma(self.args[0] + 1)*polygamma(0, self.args[0] + 1) + else: + raise ArgumentIndexError(self, argindex) + + _small_swing = [ + 1, 1, 1, 3, 3, 15, 5, 35, 35, 315, 63, 693, 231, 3003, 429, 6435, 6435, 109395, + 12155, 230945, 46189, 969969, 88179, 2028117, 676039, 16900975, 1300075, + 35102025, 5014575, 145422675, 9694845, 300540195, 300540195 + ] + + _small_factorials: list[int] = [] + + @classmethod + def _swing(cls, n): + if n < 33: + return cls._small_swing[n] + else: + N, primes = int(_sqrt(n)), [] + + for prime in sieve.primerange(3, N + 1): + p, q = 1, n + + while True: + q //= prime + + if q > 0: + if q & 1 == 1: + p *= prime + else: + break + + if p > 1: + primes.append(p) + + for prime in sieve.primerange(N + 1, n//3 + 1): + if (n // prime) & 1 == 1: + primes.append(prime) + + L_product = prod(sieve.primerange(n//2 + 1, n + 1)) + R_product = prod(primes) + + return L_product*R_product + + @classmethod + def _recursive(cls, n): + if n < 2: + return 1 + else: + return (cls._recursive(n//2)**2)*cls._swing(n) + + @classmethod + def eval(cls, n): + n = sympify(n) + + if n.is_Number: + if n.is_zero: + return S.One + elif n is S.Infinity: + return S.Infinity + elif n.is_Integer: + if n.is_negative: + return S.ComplexInfinity + else: + n = n.p + + if n < 20: + if not cls._small_factorials: + result = 1 + for i in range(1, 20): + result *= i + cls._small_factorials.append(result) + result = cls._small_factorials[n-1] + + # GMPY factorial is faster, use it when available + # + # XXX: There is a sympy.external.gmpy.factorial function + # which provides gmpy.fac if available or the flint version + # if flint is used. It could be used here to avoid the + # conditional logic but it needs to be checked whether the + # pure Python fallback used there is as fast as the + # fallback used here (perhaps the fallback here should be + # moved to sympy.external.ntheory). + elif _gmpy is not None: + result = _gmpy.fac(n) + + else: + bits = bin(n).count('1') + result = cls._recursive(n)*2**(n - bits) + + return Integer(result) + + def _facmod(self, n, q): + res, N = 1, int(_sqrt(n)) + + # Exponent of prime p in n! is e_p(n) = [n/p] + [n/p**2] + ... + # for p > sqrt(n), e_p(n) < sqrt(n), the primes with [n/p] = m, + # occur consecutively and are grouped together in pw[m] for + # simultaneous exponentiation at a later stage + pw = [1]*N + + m = 2 # to initialize the if condition below + for prime in sieve.primerange(2, n + 1): + if m > 1: + m, y = 0, n // prime + while y: + m += y + y //= prime + if m < N: + pw[m] = pw[m]*prime % q + else: + res = res*pow(prime, m, q) % q + + for ex, bs in enumerate(pw): + if ex == 0 or bs == 1: + continue + if bs == 0: + return 0 + res = res*pow(bs, ex, q) % q + + return res + + def _eval_Mod(self, q): + n = self.args[0] + if n.is_integer and n.is_nonnegative and q.is_integer: + aq = abs(q) + d = aq - n + if d.is_nonpositive: + return S.Zero + else: + isprime = aq.is_prime + if d == 1: + # Apply Wilson's theorem (if a natural number n > 1 + # is a prime number, then (n-1)! = -1 mod n) and + # its inverse (if n > 4 is a composite number, then + # (n-1)! = 0 mod n) + if isprime: + return -1 % q + elif isprime is False and (aq - 6).is_nonnegative: + return S.Zero + elif n.is_Integer and q.is_Integer: + n, d, aq = map(int, (n, d, aq)) + if isprime and (d - 1 < n): + fc = self._facmod(d - 1, aq) + fc = pow(fc, aq - 2, aq) + if d%2: + fc = -fc + else: + fc = self._facmod(n, aq) + + return fc % q + + def _eval_rewrite_as_gamma(self, n, piecewise=True, **kwargs): + from sympy.functions.special.gamma_functions import gamma + return gamma(n + 1) + + def _eval_rewrite_as_Product(self, n, **kwargs): + from sympy.concrete.products import Product + if n.is_nonnegative and n.is_integer: + i = Dummy('i', integer=True) + return Product(i, (i, 1, n)) + + def _eval_is_integer(self): + if self.args[0].is_integer and self.args[0].is_nonnegative: + return True + + def _eval_is_positive(self): + if self.args[0].is_integer and self.args[0].is_nonnegative: + return True + + def _eval_is_even(self): + x = self.args[0] + if x.is_integer and x.is_nonnegative: + return (x - 2).is_nonnegative + + def _eval_is_composite(self): + x = self.args[0] + if x.is_integer and x.is_nonnegative: + return (x - 3).is_nonnegative + + def _eval_is_real(self): + x = self.args[0] + if x.is_nonnegative or x.is_noninteger: + return True + + def _eval_as_leading_term(self, x, logx, cdir): + arg = self.args[0].as_leading_term(x) + arg0 = arg.subs(x, 0) + if arg0.is_zero: + return S.One + elif not arg0.is_infinite: + return self.func(arg) + raise PoleError("Cannot expand %s around 0" % (self)) + +class MultiFactorial(CombinatorialFunction): + pass + + +class subfactorial(CombinatorialFunction): + r"""The subfactorial counts the derangements of $n$ items and is + defined for non-negative integers as: + + .. math:: !n = \begin{cases} 1 & n = 0 \\ 0 & n = 1 \\ + (n-1)(!(n-1) + !(n-2)) & n > 1 \end{cases} + + It can also be written as ``int(round(n!/exp(1)))`` but the + recursive definition with caching is implemented for this function. + + An interesting analytic expression is the following [2]_ + + .. math:: !x = \Gamma(x + 1, -1)/e + + which is valid for non-negative integers `x`. The above formula + is not very useful in case of non-integers. `\Gamma(x + 1, -1)` is + single-valued only for integral arguments `x`, elsewhere on the positive + real axis it has an infinite number of branches none of which are real. + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Subfactorial + .. [2] https://mathworld.wolfram.com/Subfactorial.html + + Examples + ======== + + >>> from sympy import subfactorial + >>> from sympy.abc import n + >>> subfactorial(n + 1) + subfactorial(n + 1) + >>> subfactorial(5) + 44 + + See Also + ======== + + factorial, uppergamma, + sympy.utilities.iterables.generate_derangements + """ + + @classmethod + @cacheit + def _eval(self, n): + if not n: + return S.One + elif n == 1: + return S.Zero + else: + z1, z2 = 1, 0 + for i in range(2, n + 1): + z1, z2 = z2, (i - 1)*(z2 + z1) + return z2 + + @classmethod + def eval(cls, arg): + if arg.is_Number: + if arg.is_Integer and arg.is_nonnegative: + return cls._eval(arg) + elif arg is S.NaN: + return S.NaN + elif arg is S.Infinity: + return S.Infinity + + def _eval_is_even(self): + if self.args[0].is_odd and self.args[0].is_nonnegative: + return True + + def _eval_is_integer(self): + if self.args[0].is_integer and self.args[0].is_nonnegative: + return True + + def _eval_rewrite_as_factorial(self, arg, **kwargs): + from sympy.concrete.summations import summation + i = Dummy('i') + f = S.NegativeOne**i / factorial(i) + return factorial(arg) * summation(f, (i, 0, arg)) + + def _eval_rewrite_as_gamma(self, arg, piecewise=True, **kwargs): + from sympy.functions.elementary.exponential import exp + from sympy.functions.special.gamma_functions import (gamma, lowergamma) + return (S.NegativeOne**(arg + 1)*exp(-I*pi*arg)*lowergamma(arg + 1, -1) + + gamma(arg + 1))*exp(-1) + + def _eval_rewrite_as_uppergamma(self, arg, **kwargs): + from sympy.functions.special.gamma_functions import uppergamma + return uppergamma(arg + 1, -1)/S.Exp1 + + def _eval_is_nonnegative(self): + if self.args[0].is_integer and self.args[0].is_nonnegative: + return True + + def _eval_is_odd(self): + if self.args[0].is_even and self.args[0].is_nonnegative: + return True + + +class factorial2(CombinatorialFunction): + r"""The double factorial `n!!`, not to be confused with `(n!)!` + + The double factorial is defined for nonnegative integers and for odd + negative integers as: + + .. math:: n!! = \begin{cases} 1 & n = 0 \\ + n(n-2)(n-4) \cdots 1 & n\ \text{positive odd} \\ + n(n-2)(n-4) \cdots 2 & n\ \text{positive even} \\ + (n+2)!!/(n+2) & n\ \text{negative odd} \end{cases} + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Double_factorial + + Examples + ======== + + >>> from sympy import factorial2, var + >>> n = var('n') + >>> n + n + >>> factorial2(n + 1) + factorial2(n + 1) + >>> factorial2(5) + 15 + >>> factorial2(-1) + 1 + >>> factorial2(-5) + 1/3 + + See Also + ======== + + factorial, RisingFactorial, FallingFactorial + """ + + @classmethod + def eval(cls, arg): + # TODO: extend this to complex numbers? + + if arg.is_Number: + if not arg.is_Integer: + raise ValueError("argument must be nonnegative integer " + "or negative odd integer") + + # This implementation is faster than the recursive one + # It also avoids "maximum recursion depth exceeded" runtime error + if arg.is_nonnegative: + if arg.is_even: + k = arg / 2 + return 2**k * factorial(k) + return factorial(arg) / factorial2(arg - 1) + + + if arg.is_odd: + return arg*(S.NegativeOne)**((1 - arg)/2) / factorial2(-arg) + raise ValueError("argument must be nonnegative integer " + "or negative odd integer") + + + def _eval_is_even(self): + # Double factorial is even for every positive even input + n = self.args[0] + if n.is_integer: + if n.is_odd: + return False + if n.is_even: + if n.is_positive: + return True + if n.is_zero: + return False + + def _eval_is_integer(self): + # Double factorial is an integer for every nonnegative input, and for + # -1 and -3 + n = self.args[0] + if n.is_integer: + if (n + 1).is_nonnegative: + return True + if n.is_odd: + return (n + 3).is_nonnegative + + def _eval_is_odd(self): + # Double factorial is odd for every odd input not smaller than -3, and + # for 0 + n = self.args[0] + if n.is_odd: + return (n + 3).is_nonnegative + if n.is_even: + if n.is_positive: + return False + if n.is_zero: + return True + + def _eval_is_positive(self): + # Double factorial is positive for every nonnegative input, and for + # every odd negative input which is of the form -1-4k for an + # nonnegative integer k + n = self.args[0] + if n.is_integer: + if (n + 1).is_nonnegative: + return True + if n.is_odd: + return ((n + 1) / 2).is_even + + def _eval_rewrite_as_gamma(self, n, piecewise=True, **kwargs): + from sympy.functions.elementary.miscellaneous import sqrt + from sympy.functions.elementary.piecewise import Piecewise + from sympy.functions.special.gamma_functions import gamma + return 2**(n/2)*gamma(n/2 + 1) * Piecewise((1, Eq(Mod(n, 2), 0)), + (sqrt(2/pi), Eq(Mod(n, 2), 1))) + + +############################################################################### +######################## RISING and FALLING FACTORIALS ######################## +############################################################################### + + +class RisingFactorial(CombinatorialFunction): + r""" + Rising factorial (also called Pochhammer symbol [1]_) is a double valued + function arising in concrete mathematics, hypergeometric functions + and series expansions. It is defined by: + + .. math:: \texttt{rf(y, k)} = (x)^k = x \cdot (x+1) \cdots (x+k-1) + + where `x` can be arbitrary expression and `k` is an integer. For + more information check "Concrete mathematics" by Graham, pp. 66 + or visit https://mathworld.wolfram.com/RisingFactorial.html page. + + When `x` is a `~.Poly` instance of degree $\ge 1$ with a single variable, + `(x)^k = x(y) \cdot x(y+1) \cdots x(y+k-1)`, where `y` is the + variable of `x`. This is as described in [2]_. + + Examples + ======== + + >>> from sympy import rf, Poly + >>> from sympy.abc import x + >>> rf(x, 0) + 1 + >>> rf(1, 5) + 120 + >>> rf(x, 5) == x*(1 + x)*(2 + x)*(3 + x)*(4 + x) + True + >>> rf(Poly(x**3, x), 2) + Poly(x**6 + 3*x**5 + 3*x**4 + x**3, x, domain='ZZ') + + Rewriting is complicated unless the relationship between + the arguments is known, but rising factorial can + be rewritten in terms of gamma, factorial, binomial, + and falling factorial. + + >>> from sympy import Symbol, factorial, ff, binomial, gamma + >>> n = Symbol('n', integer=True, positive=True) + >>> R = rf(n, n + 2) + >>> for i in (rf, ff, factorial, binomial, gamma): + ... R.rewrite(i) + ... + RisingFactorial(n, n + 2) + FallingFactorial(2*n + 1, n + 2) + factorial(2*n + 1)/factorial(n - 1) + binomial(2*n + 1, n + 2)*factorial(n + 2) + gamma(2*n + 2)/gamma(n) + + See Also + ======== + + factorial, factorial2, FallingFactorial + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Pochhammer_symbol + .. [2] Peter Paule, "Greatest Factorial Factorization and Symbolic + Summation", Journal of Symbolic Computation, vol. 20, pp. 235-268, + 1995. + + """ + + @classmethod + def eval(cls, x, k): + x = sympify(x) + k = sympify(k) + + if x is S.NaN or k is S.NaN: + return S.NaN + elif x is S.One: + return factorial(k) + elif k.is_Integer: + if k.is_zero: + return S.One + else: + if k.is_positive: + if x is S.Infinity: + return S.Infinity + elif x is S.NegativeInfinity: + if k.is_odd: + return S.NegativeInfinity + else: + return S.Infinity + else: + if isinstance(x, Poly): + gens = x.gens + if len(gens)!= 1: + raise ValueError("rf only defined for " + "polynomials on one generator") + else: + return reduce(lambda r, i: + r*(x.shift(i)), + range(int(k)), 1) + else: + return reduce(lambda r, i: r*(x + i), + range(int(k)), 1) + + else: + if x is S.Infinity: + return S.Infinity + elif x is S.NegativeInfinity: + return S.Infinity + else: + if isinstance(x, Poly): + gens = x.gens + if len(gens)!= 1: + raise ValueError("rf only defined for " + "polynomials on one generator") + else: + return 1/reduce(lambda r, i: + r*(x.shift(-i)), + range(1, abs(int(k)) + 1), 1) + else: + return 1/reduce(lambda r, i: + r*(x - i), + range(1, abs(int(k)) + 1), 1) + + if k.is_integer == False: + if x.is_integer and x.is_negative: + return S.Zero + + def _eval_rewrite_as_gamma(self, x, k, piecewise=True, **kwargs): + from sympy.functions.elementary.piecewise import Piecewise + from sympy.functions.special.gamma_functions import gamma + if not piecewise: + if (x <= 0) == True: + return S.NegativeOne**k*gamma(1 - x) / gamma(-k - x + 1) + return gamma(x + k) / gamma(x) + return Piecewise( + (gamma(x + k) / gamma(x), x > 0), + (S.NegativeOne**k*gamma(1 - x) / gamma(-k - x + 1), True)) + + def _eval_rewrite_as_FallingFactorial(self, x, k, **kwargs): + return FallingFactorial(x + k - 1, k) + + def _eval_rewrite_as_factorial(self, x, k, **kwargs): + from sympy.functions.elementary.piecewise import Piecewise + if x.is_integer and k.is_integer: + return Piecewise( + (factorial(k + x - 1)/factorial(x - 1), x > 0), + (S.NegativeOne**k*factorial(-x)/factorial(-k - x), True)) + + def _eval_rewrite_as_binomial(self, x, k, **kwargs): + if k.is_integer: + return factorial(k) * binomial(x + k - 1, k) + + def _eval_rewrite_as_tractable(self, x, k, limitvar=None, **kwargs): + from sympy.functions.special.gamma_functions import gamma + if limitvar: + k_lim = k.subs(limitvar, S.Infinity) + if k_lim is S.Infinity: + return (gamma(x + k).rewrite('tractable', deep=True) / gamma(x)) + elif k_lim is S.NegativeInfinity: + return (S.NegativeOne**k*gamma(1 - x) / gamma(-k - x + 1).rewrite('tractable', deep=True)) + return self.rewrite(gamma).rewrite('tractable', deep=True) + + def _eval_is_integer(self): + return fuzzy_and((self.args[0].is_integer, self.args[1].is_integer, + self.args[1].is_nonnegative)) + + +class FallingFactorial(CombinatorialFunction): + r""" + Falling factorial (related to rising factorial) is a double valued + function arising in concrete mathematics, hypergeometric functions + and series expansions. It is defined by + + .. math:: \texttt{ff(x, k)} = (x)_k = x \cdot (x-1) \cdots (x-k+1) + + where `x` can be arbitrary expression and `k` is an integer. For + more information check "Concrete mathematics" by Graham, pp. 66 + or [1]_. + + When `x` is a `~.Poly` instance of degree $\ge 1$ with single variable, + `(x)_k = x(y) \cdot x(y-1) \cdots x(y-k+1)`, where `y` is the + variable of `x`. This is as described in + + >>> from sympy import ff, Poly, Symbol + >>> from sympy.abc import x + >>> n = Symbol('n', integer=True) + + >>> ff(x, 0) + 1 + >>> ff(5, 5) + 120 + >>> ff(x, 5) == x*(x - 1)*(x - 2)*(x - 3)*(x - 4) + True + >>> ff(Poly(x**2, x), 2) + Poly(x**4 - 2*x**3 + x**2, x, domain='ZZ') + >>> ff(n, n) + factorial(n) + + Rewriting is complicated unless the relationship between + the arguments is known, but falling factorial can + be rewritten in terms of gamma, factorial and binomial + and rising factorial. + + >>> from sympy import factorial, rf, gamma, binomial, Symbol + >>> n = Symbol('n', integer=True, positive=True) + >>> F = ff(n, n - 2) + >>> for i in (rf, ff, factorial, binomial, gamma): + ... F.rewrite(i) + ... + RisingFactorial(3, n - 2) + FallingFactorial(n, n - 2) + factorial(n)/2 + binomial(n, n - 2)*factorial(n - 2) + gamma(n + 1)/2 + + See Also + ======== + + factorial, factorial2, RisingFactorial + + References + ========== + + .. [1] https://mathworld.wolfram.com/FallingFactorial.html + .. [2] Peter Paule, "Greatest Factorial Factorization and Symbolic + Summation", Journal of Symbolic Computation, vol. 20, pp. 235-268, + 1995. + + """ + + @classmethod + def eval(cls, x, k): + x = sympify(x) + k = sympify(k) + + if x is S.NaN or k is S.NaN: + return S.NaN + elif k.is_integer and x == k: + return factorial(x) + elif k.is_Integer: + if k.is_zero: + return S.One + else: + if k.is_positive: + if x is S.Infinity: + return S.Infinity + elif x is S.NegativeInfinity: + if k.is_odd: + return S.NegativeInfinity + else: + return S.Infinity + else: + if isinstance(x, Poly): + gens = x.gens + if len(gens)!= 1: + raise ValueError("ff only defined for " + "polynomials on one generator") + else: + return reduce(lambda r, i: + r*(x.shift(-i)), + range(int(k)), 1) + else: + return reduce(lambda r, i: r*(x - i), + range(int(k)), 1) + else: + if x is S.Infinity: + return S.Infinity + elif x is S.NegativeInfinity: + return S.Infinity + else: + if isinstance(x, Poly): + gens = x.gens + if len(gens)!= 1: + raise ValueError("rf only defined for " + "polynomials on one generator") + else: + return 1/reduce(lambda r, i: + r*(x.shift(i)), + range(1, abs(int(k)) + 1), 1) + else: + return 1/reduce(lambda r, i: r*(x + i), + range(1, abs(int(k)) + 1), 1) + + def _eval_rewrite_as_gamma(self, x, k, piecewise=True, **kwargs): + from sympy.functions.elementary.piecewise import Piecewise + from sympy.functions.special.gamma_functions import gamma + if not piecewise: + if (x < 0) == True: + return S.NegativeOne**k*gamma(k - x) / gamma(-x) + return gamma(x + 1) / gamma(x - k + 1) + return Piecewise( + (gamma(x + 1) / gamma(x - k + 1), x >= 0), + (S.NegativeOne**k*gamma(k - x) / gamma(-x), True)) + + def _eval_rewrite_as_RisingFactorial(self, x, k, **kwargs): + return rf(x - k + 1, k) + + def _eval_rewrite_as_binomial(self, x, k, **kwargs): + if k.is_integer: + return factorial(k) * binomial(x, k) + + def _eval_rewrite_as_factorial(self, x, k, **kwargs): + from sympy.functions.elementary.piecewise import Piecewise + if x.is_integer and k.is_integer: + return Piecewise( + (factorial(x)/factorial(-k + x), x >= 0), + (S.NegativeOne**k*factorial(k - x - 1)/factorial(-x - 1), True)) + + def _eval_rewrite_as_tractable(self, x, k, limitvar=None, **kwargs): + from sympy.functions.special.gamma_functions import gamma + if limitvar: + k_lim = k.subs(limitvar, S.Infinity) + if k_lim is S.Infinity: + return (S.NegativeOne**k*gamma(k - x).rewrite('tractable', deep=True) / gamma(-x)) + elif k_lim is S.NegativeInfinity: + return (gamma(x + 1) / gamma(x - k + 1).rewrite('tractable', deep=True)) + return self.rewrite(gamma).rewrite('tractable', deep=True) + + def _eval_is_integer(self): + return fuzzy_and((self.args[0].is_integer, self.args[1].is_integer, + self.args[1].is_nonnegative)) + + +rf = RisingFactorial +ff = FallingFactorial + +############################################################################### +########################### BINOMIAL COEFFICIENTS ############################# +############################################################################### + + +class binomial(CombinatorialFunction): + r"""Implementation of the binomial coefficient. It can be defined + in two ways depending on its desired interpretation: + + .. math:: \binom{n}{k} = \frac{n!}{k!(n-k)!}\ \text{or}\ + \binom{n}{k} = \frac{(n)_k}{k!} + + First, in a strict combinatorial sense it defines the + number of ways we can choose `k` elements from a set of + `n` elements. In this case both arguments are nonnegative + integers and binomial is computed using an efficient + algorithm based on prime factorization. + + The other definition is generalization for arbitrary `n`, + however `k` must also be nonnegative. This case is very + useful when evaluating summations. + + For the sake of convenience, for negative integer `k` this function + will return zero no matter the other argument. + + To expand the binomial when `n` is a symbol, use either + ``expand_func()`` or ``expand(func=True)``. The former will keep + the polynomial in factored form while the latter will expand the + polynomial itself. See examples for details. + + Examples + ======== + + >>> from sympy import Symbol, Rational, binomial, expand_func + >>> n = Symbol('n', integer=True, positive=True) + + >>> binomial(15, 8) + 6435 + + >>> binomial(n, -1) + 0 + + Rows of Pascal's triangle can be generated with the binomial function: + + >>> for N in range(8): + ... print([binomial(N, i) for i in range(N + 1)]) + ... + [1] + [1, 1] + [1, 2, 1] + [1, 3, 3, 1] + [1, 4, 6, 4, 1] + [1, 5, 10, 10, 5, 1] + [1, 6, 15, 20, 15, 6, 1] + [1, 7, 21, 35, 35, 21, 7, 1] + + As can a given diagonal, e.g. the 4th diagonal: + + >>> N = -4 + >>> [binomial(N, i) for i in range(1 - N)] + [1, -4, 10, -20, 35] + + >>> binomial(Rational(5, 4), 3) + -5/128 + >>> binomial(Rational(-5, 4), 3) + -195/128 + + >>> binomial(n, 3) + binomial(n, 3) + + >>> binomial(n, 3).expand(func=True) + n**3/6 - n**2/2 + n/3 + + >>> expand_func(binomial(n, 3)) + n*(n - 2)*(n - 1)/6 + + In many cases, we can also compute binomial coefficients modulo a + prime p quickly using Lucas' Theorem [2]_, though we need to include + `evaluate=False` to postpone evaluation: + + >>> from sympy import Mod + >>> Mod(binomial(156675, 4433, evaluate=False), 10**5 + 3) + 28625 + + Using a generalisation of Lucas's Theorem given by Granville [3]_, + we can extend this to arbitrary n: + + >>> Mod(binomial(10**18, 10**12, evaluate=False), (10**5 + 3)**2) + 3744312326 + + References + ========== + + .. [1] https://www.johndcook.com/blog/binomial_coefficients/ + .. [2] https://en.wikipedia.org/wiki/Lucas%27s_theorem + .. [3] Binomial coefficients modulo prime powers, Andrew Granville, + Available: https://web.archive.org/web/20170202003812/http://www.dms.umontreal.ca/~andrew/PDF/BinCoeff.pdf + """ + + def fdiff(self, argindex=1): + from sympy.functions.special.gamma_functions import polygamma + if argindex == 1: + # https://functions.wolfram.com/GammaBetaErf/Binomial/20/01/01/ + n, k = self.args + return binomial(n, k)*(polygamma(0, n + 1) - \ + polygamma(0, n - k + 1)) + elif argindex == 2: + # https://functions.wolfram.com/GammaBetaErf/Binomial/20/01/02/ + n, k = self.args + return binomial(n, k)*(polygamma(0, n - k + 1) - \ + polygamma(0, k + 1)) + else: + raise ArgumentIndexError(self, argindex) + + @classmethod + def _eval(self, n, k): + # n.is_Number and k.is_Integer and k != 1 and n != k + + if k.is_Integer: + if n.is_Integer and n >= 0: + n, k = int(n), int(k) + + if k > n: + return S.Zero + elif k > n // 2: + k = n - k + + # XXX: This conditional logic should be moved to + # sympy.external.gmpy and the pure Python version of bincoef + # should be moved to sympy.external.ntheory. + if _gmpy is not None: + return Integer(_gmpy.bincoef(n, k)) + + d, result = n - k, 1 + for i in range(1, k + 1): + d += 1 + result = result * d // i + return Integer(result) + else: + d, result = n - k, 1 + for i in range(1, k + 1): + d += 1 + result *= d + return result / _factorial(k) + + @classmethod + def eval(cls, n, k): + n, k = map(sympify, (n, k)) + d = n - k + n_nonneg, n_isint = n.is_nonnegative, n.is_integer + if k.is_zero or ((n_nonneg or n_isint is False) + and d.is_zero): + return S.One + if (k - 1).is_zero or ((n_nonneg or n_isint is False) + and (d - 1).is_zero): + return n + if k.is_integer: + if k.is_negative or (n_nonneg and n_isint and d.is_negative): + return S.Zero + elif n.is_number: + res = cls._eval(n, k) + return res.expand(basic=True) if res else res + elif n_nonneg is False and n_isint: + # a special case when binomial evaluates to complex infinity + return S.ComplexInfinity + elif k.is_number: + from sympy.functions.special.gamma_functions import gamma + return gamma(n + 1)/(gamma(k + 1)*gamma(n - k + 1)) + + def _eval_Mod(self, q): + n, k = self.args + + if any(x.is_integer is False for x in (n, k, q)): + raise ValueError("Integers expected for binomial Mod") + + if all(x.is_Integer for x in (n, k, q)): + n, k = map(int, (n, k)) + aq, res = abs(q), 1 + + # handle negative integers k or n + if k < 0: + return S.Zero + if n < 0: + n = -n + k - 1 + res = -1 if k%2 else 1 + + # non negative integers k and n + if k > n: + return S.Zero + + isprime = aq.is_prime + aq = int(aq) + if isprime: + if aq < n: + # use Lucas Theorem + N, K = n, k + while N or K: + res = res*binomial(N % aq, K % aq) % aq + N, K = N // aq, K // aq + + else: + # use Factorial Modulo + d = n - k + if k > d: + k, d = d, k + kf = 1 + for i in range(2, k + 1): + kf = kf*i % aq + df = kf + for i in range(k + 1, d + 1): + df = df*i % aq + res *= df + for i in range(d + 1, n + 1): + res = res*i % aq + + res *= pow(kf*df % aq, aq - 2, aq) + res %= aq + + elif _sqrt(q) < k and q != 1: + res = binomial_mod(n, k, q) + + else: + # Binomial Factorization is performed by calculating the + # exponents of primes <= n in `n! /(k! (n - k)!)`, + # for non-negative integers n and k. As the exponent of + # prime in n! is e_p(n) = [n/p] + [n/p**2] + ... + # the exponent of prime in binomial(n, k) would be + # e_p(n) - e_p(k) - e_p(n - k) + M = int(_sqrt(n)) + for prime in sieve.primerange(2, n + 1): + if prime > n - k: + res = res*prime % aq + elif prime > n // 2: + continue + elif prime > M: + if n % prime < k % prime: + res = res*prime % aq + else: + N, K = n, k + exp = a = 0 + + while N > 0: + a = int((N % prime) < (K % prime + a)) + N, K = N // prime, K // prime + exp += a + + if exp > 0: + res *= pow(prime, exp, aq) + res %= aq + + return S(res % q) + + def _eval_expand_func(self, **hints): + """ + Function to expand binomial(n, k) when m is positive integer + Also, + n is self.args[0] and k is self.args[1] while using binomial(n, k) + """ + n = self.args[0] + if n.is_Number: + return binomial(*self.args) + + k = self.args[1] + if (n-k).is_Integer: + k = n - k + + if k.is_Integer: + if k.is_zero: + return S.One + elif k.is_negative: + return S.Zero + else: + n, result = self.args[0], 1 + for i in range(1, k + 1): + result *= n - k + i + return result / _factorial(k) + else: + return binomial(*self.args) + + def _eval_rewrite_as_factorial(self, n, k, **kwargs): + return factorial(n)/(factorial(k)*factorial(n - k)) + + def _eval_rewrite_as_gamma(self, n, k, piecewise=True, **kwargs): + from sympy.functions.special.gamma_functions import gamma + return gamma(n + 1)/(gamma(k + 1)*gamma(n - k + 1)) + + def _eval_rewrite_as_tractable(self, n, k, limitvar=None, **kwargs): + return self._eval_rewrite_as_gamma(n, k).rewrite('tractable') + + def _eval_rewrite_as_FallingFactorial(self, n, k, **kwargs): + if k.is_integer: + return ff(n, k) / factorial(k) + + def _eval_is_integer(self): + n, k = self.args + if n.is_integer and k.is_integer: + return True + elif k.is_integer is False: + return False + + def _eval_is_nonnegative(self): + n, k = self.args + if n.is_integer and k.is_integer: + if n.is_nonnegative or k.is_negative or k.is_even: + return True + elif k.is_even is False: + return False + + def _eval_as_leading_term(self, x, logx, cdir): + from sympy.functions.special.gamma_functions import gamma + return self.rewrite(gamma)._eval_as_leading_term(x, logx=logx, cdir=cdir) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/numbers.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/numbers.py new file mode 100644 index 0000000000000000000000000000000000000000..c0dfc518d4a6784712341edaa5731145469a8d1e --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/numbers.py @@ -0,0 +1,3196 @@ +""" +This module implements some special functions that commonly appear in +combinatorial contexts (e.g. in power series); in particular, +sequences of rational numbers such as Bernoulli and Fibonacci numbers. + +Factorials, binomial coefficients and related functions are located in +the separate 'factorials' module. +""" +from __future__ import annotations +from math import prod +from collections import defaultdict +from typing import Callable + +from sympy.core import S, Symbol, Add, Dummy +from sympy.core.cache import cacheit +from sympy.core.containers import Dict +from sympy.core.expr import Expr +from sympy.core.function import ArgumentIndexError, DefinedFunction, expand_mul +from sympy.core.logic import fuzzy_not +from sympy.core.mul import Mul +from sympy.core.numbers import E, I, pi, oo, Rational, Integer +from sympy.core.relational import Eq, is_le, is_gt, is_lt +from sympy.external.gmpy import SYMPY_INTS, remove, lcm, legendre, jacobi, kronecker +from sympy.functions.combinatorial.factorials import (binomial, + factorial, subfactorial) +from sympy.functions.elementary.exponential import log +from sympy.functions.elementary.piecewise import Piecewise +from sympy.ntheory.factor_ import (factorint, _divisor_sigma, is_carmichael, + find_carmichael_numbers_in_range, find_first_n_carmichaels) +from sympy.ntheory.generate import _primepi +from sympy.ntheory.partitions_ import _partition, _partition_rec +from sympy.ntheory.primetest import isprime, is_square +from sympy.polys.appellseqs import bernoulli_poly, euler_poly, genocchi_poly +from sympy.polys.polytools import cancel +from sympy.utilities.enumerative import MultisetPartitionTraverser +from sympy.utilities.exceptions import sympy_deprecation_warning +from sympy.utilities.iterables import multiset, multiset_derangements, iterable +from sympy.utilities.memoization import recurrence_memo +from sympy.utilities.misc import as_int + +from mpmath import mp, workprec +from mpmath.libmp import ifib as _ifib + + +def _product(a, b): + return prod(range(a, b + 1)) + + +# Dummy symbol used for computing polynomial sequences +_sym = Symbol('x') + + +#----------------------------------------------------------------------------# +# # +# Carmichael numbers # +# # +#----------------------------------------------------------------------------# + +class carmichael(DefinedFunction): + r""" + Carmichael Numbers: + + Certain cryptographic algorithms make use of big prime numbers. + However, checking whether a big number is prime is not so easy. + Randomized prime number checking tests exist that offer a high degree of + confidence of accurate determination at low cost, such as the Fermat test. + + Let 'a' be a random number between $2$ and $n - 1$, where $n$ is the + number whose primality we are testing. Then, $n$ is probably prime if it + satisfies the modular arithmetic congruence relation: + + .. math :: a^{n-1} = 1 \pmod{n} + + (where mod refers to the modulo operation) + + If a number passes the Fermat test several times, then it is prime with a + high probability. + + Unfortunately, certain composite numbers (non-primes) still pass the Fermat + test with every number smaller than themselves. + These numbers are called Carmichael numbers. + + A Carmichael number will pass a Fermat primality test to every base $b$ + relatively prime to the number, even though it is not actually prime. + This makes tests based on Fermat's Little Theorem less effective than + strong probable prime tests such as the Baillie-PSW primality test and + the Miller-Rabin primality test. + + Examples + ======== + + >>> from sympy.ntheory.factor_ import find_first_n_carmichaels, find_carmichael_numbers_in_range + >>> find_first_n_carmichaels(5) + [561, 1105, 1729, 2465, 2821] + >>> find_carmichael_numbers_in_range(0, 562) + [561] + >>> find_carmichael_numbers_in_range(0,1000) + [561] + >>> find_carmichael_numbers_in_range(0,2000) + [561, 1105, 1729] + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Carmichael_number + .. [2] https://en.wikipedia.org/wiki/Fermat_primality_test + .. [3] https://www.jstor.org/stable/23248683?seq=1#metadata_info_tab_contents + """ + + @staticmethod + def is_perfect_square(n): + sympy_deprecation_warning( + """ +is_perfect_square is just a wrapper around sympy.ntheory.primetest.is_square +so use that directly instead. + """, + deprecated_since_version="1.11", + active_deprecations_target='deprecated-carmichael-static-methods', + ) + return is_square(n) + + @staticmethod + def divides(p, n): + sympy_deprecation_warning( + """ + divides can be replaced by directly testing n % p == 0. + """, + deprecated_since_version="1.11", + active_deprecations_target='deprecated-carmichael-static-methods', + ) + return n % p == 0 + + @staticmethod + def is_prime(n): + sympy_deprecation_warning( + """ +is_prime is just a wrapper around sympy.ntheory.primetest.isprime so use that +directly instead. + """, + deprecated_since_version="1.11", + active_deprecations_target='deprecated-carmichael-static-methods', + ) + return isprime(n) + + @staticmethod + def is_carmichael(n): + sympy_deprecation_warning( + """ +is_carmichael is just a wrapper around sympy.ntheory.factor_.is_carmichael so use that +directly instead. + """, + deprecated_since_version="1.13", + active_deprecations_target='deprecated-ntheory-symbolic-functions', + ) + return is_carmichael(n) + + @staticmethod + def find_carmichael_numbers_in_range(x, y): + sympy_deprecation_warning( + """ +find_carmichael_numbers_in_range is just a wrapper around sympy.ntheory.factor_.find_carmichael_numbers_in_range so use that +directly instead. + """, + deprecated_since_version="1.13", + active_deprecations_target='deprecated-ntheory-symbolic-functions', + ) + return find_carmichael_numbers_in_range(x, y) + + @staticmethod + def find_first_n_carmichaels(n): + sympy_deprecation_warning( + """ +find_first_n_carmichaels is just a wrapper around sympy.ntheory.factor_.find_first_n_carmichaels so use that +directly instead. + """, + deprecated_since_version="1.13", + active_deprecations_target='deprecated-ntheory-symbolic-functions', + ) + return find_first_n_carmichaels(n) + + +#----------------------------------------------------------------------------# +# # +# Fibonacci numbers # +# # +#----------------------------------------------------------------------------# + + +class fibonacci(DefinedFunction): + r""" + Fibonacci numbers / Fibonacci polynomials + + The Fibonacci numbers are the integer sequence defined by the + initial terms `F_0 = 0`, `F_1 = 1` and the two-term recurrence + relation `F_n = F_{n-1} + F_{n-2}`. This definition + extended to arbitrary real and complex arguments using + the formula + + .. math :: F_z = \frac{\phi^z - \cos(\pi z) \phi^{-z}}{\sqrt 5} + + The Fibonacci polynomials are defined by `F_1(x) = 1`, + `F_2(x) = x`, and `F_n(x) = x*F_{n-1}(x) + F_{n-2}(x)` for `n > 2`. + For all positive integers `n`, `F_n(1) = F_n`. + + * ``fibonacci(n)`` gives the `n^{th}` Fibonacci number, `F_n` + * ``fibonacci(n, x)`` gives the `n^{th}` Fibonacci polynomial in `x`, `F_n(x)` + + Examples + ======== + + >>> from sympy import fibonacci, Symbol + + >>> [fibonacci(x) for x in range(11)] + [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55] + >>> fibonacci(5, Symbol('t')) + t**4 + 3*t**2 + 1 + + See Also + ======== + + bell, bernoulli, catalan, euler, harmonic, lucas, genocchi, partition, tribonacci + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Fibonacci_number + .. [2] https://mathworld.wolfram.com/FibonacciNumber.html + + """ + + @staticmethod + def _fib(n): + return _ifib(n) + + @staticmethod + @recurrence_memo([None, S.One, _sym]) + def _fibpoly(n, prev): + return (prev[-2] + _sym*prev[-1]).expand() + + @classmethod + def eval(cls, n, sym=None): + if n is S.Infinity: + return S.Infinity + + if n.is_Integer: + if sym is None: + n = int(n) + if n < 0: + return S.NegativeOne**(n + 1) * fibonacci(-n) + else: + return Integer(cls._fib(n)) + else: + if n < 1: + raise ValueError("Fibonacci polynomials are defined " + "only for positive integer indices.") + return cls._fibpoly(n).subs(_sym, sym) + + def _eval_rewrite_as_tractable(self, n, **kwargs): + from sympy.functions import sqrt, cos + return (S.GoldenRatio**n - cos(S.Pi*n)/S.GoldenRatio**n)/sqrt(5) + + def _eval_rewrite_as_sqrt(self, n, **kwargs): + from sympy.functions.elementary.miscellaneous import sqrt + return 2**(-n)*sqrt(5)*((1 + sqrt(5))**n - (-sqrt(5) + 1)**n) / 5 + + def _eval_rewrite_as_GoldenRatio(self,n, **kwargs): + return (S.GoldenRatio**n - 1/(-S.GoldenRatio)**n)/(2*S.GoldenRatio-1) + + +#----------------------------------------------------------------------------# +# # +# Lucas numbers # +# # +#----------------------------------------------------------------------------# + + +class lucas(DefinedFunction): + """ + Lucas numbers + + Lucas numbers satisfy a recurrence relation similar to that of + the Fibonacci sequence, in which each term is the sum of the + preceding two. They are generated by choosing the initial + values `L_0 = 2` and `L_1 = 1`. + + * ``lucas(n)`` gives the `n^{th}` Lucas number + + Examples + ======== + + >>> from sympy import lucas + + >>> [lucas(x) for x in range(11)] + [2, 1, 3, 4, 7, 11, 18, 29, 47, 76, 123] + + See Also + ======== + + bell, bernoulli, catalan, euler, fibonacci, harmonic, genocchi, partition, tribonacci + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Lucas_number + .. [2] https://mathworld.wolfram.com/LucasNumber.html + + """ + + @classmethod + def eval(cls, n): + if n is S.Infinity: + return S.Infinity + + if n.is_Integer: + return fibonacci(n + 1) + fibonacci(n - 1) + + def _eval_rewrite_as_sqrt(self, n, **kwargs): + from sympy.functions.elementary.miscellaneous import sqrt + return 2**(-n)*((1 + sqrt(5))**n + (-sqrt(5) + 1)**n) + + +#----------------------------------------------------------------------------# +# # +# Tribonacci numbers # +# # +#----------------------------------------------------------------------------# + + +class tribonacci(DefinedFunction): + r""" + Tribonacci numbers / Tribonacci polynomials + + The Tribonacci numbers are the integer sequence defined by the + initial terms `T_0 = 0`, `T_1 = 1`, `T_2 = 1` and the three-term + recurrence relation `T_n = T_{n-1} + T_{n-2} + T_{n-3}`. + + The Tribonacci polynomials are defined by `T_0(x) = 0`, `T_1(x) = 1`, + `T_2(x) = x^2`, and `T_n(x) = x^2 T_{n-1}(x) + x T_{n-2}(x) + T_{n-3}(x)` + for `n > 2`. For all positive integers `n`, `T_n(1) = T_n`. + + * ``tribonacci(n)`` gives the `n^{th}` Tribonacci number, `T_n` + * ``tribonacci(n, x)`` gives the `n^{th}` Tribonacci polynomial in `x`, `T_n(x)` + + Examples + ======== + + >>> from sympy import tribonacci, Symbol + + >>> [tribonacci(x) for x in range(11)] + [0, 1, 1, 2, 4, 7, 13, 24, 44, 81, 149] + >>> tribonacci(5, Symbol('t')) + t**8 + 3*t**5 + 3*t**2 + + See Also + ======== + + bell, bernoulli, catalan, euler, fibonacci, harmonic, lucas, genocchi, partition + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Generalizations_of_Fibonacci_numbers#Tribonacci_numbers + .. [2] https://mathworld.wolfram.com/TribonacciNumber.html + .. [3] https://oeis.org/A000073 + + """ + + @staticmethod + @recurrence_memo([S.Zero, S.One, S.One]) + def _trib(n, prev): + return (prev[-3] + prev[-2] + prev[-1]) + + @staticmethod + @recurrence_memo([S.Zero, S.One, _sym**2]) + def _tribpoly(n, prev): + return (prev[-3] + _sym*prev[-2] + _sym**2*prev[-1]).expand() + + @classmethod + def eval(cls, n, sym=None): + if n is S.Infinity: + return S.Infinity + + if n.is_Integer: + n = int(n) + if n < 0: + raise ValueError("Tribonacci polynomials are defined " + "only for non-negative integer indices.") + if sym is None: + return Integer(cls._trib(n)) + else: + return cls._tribpoly(n).subs(_sym, sym) + + def _eval_rewrite_as_sqrt(self, n, **kwargs): + from sympy.functions.elementary.miscellaneous import cbrt, sqrt + w = (-1 + S.ImaginaryUnit * sqrt(3)) / 2 + a = (1 + cbrt(19 + 3*sqrt(33)) + cbrt(19 - 3*sqrt(33))) / 3 + b = (1 + w*cbrt(19 + 3*sqrt(33)) + w**2*cbrt(19 - 3*sqrt(33))) / 3 + c = (1 + w**2*cbrt(19 + 3*sqrt(33)) + w*cbrt(19 - 3*sqrt(33))) / 3 + Tn = (a**(n + 1)/((a - b)*(a - c)) + + b**(n + 1)/((b - a)*(b - c)) + + c**(n + 1)/((c - a)*(c - b))) + return Tn + + def _eval_rewrite_as_TribonacciConstant(self, n, **kwargs): + from sympy.functions.elementary.integers import floor + from sympy.functions.elementary.miscellaneous import cbrt, sqrt + b = cbrt(586 + 102*sqrt(33)) + Tn = 3 * b * S.TribonacciConstant**n / (b**2 - 2*b + 4) + return floor(Tn + S.Half) + + +#----------------------------------------------------------------------------# +# # +# Bernoulli numbers # +# # +#----------------------------------------------------------------------------# + + +class bernoulli(DefinedFunction): + r""" + Bernoulli numbers / Bernoulli polynomials / Bernoulli function + + The Bernoulli numbers are a sequence of rational numbers + defined by `B_0 = 1` and the recursive relation (`n > 0`): + + .. math :: n+1 = \sum_{k=0}^n \binom{n+1}{k} B_k + + They are also commonly defined by their exponential generating + function, which is `\frac{x}{1 - e^{-x}}`. For odd indices > 1, + the Bernoulli numbers are zero. + + The Bernoulli polynomials satisfy the analogous formula: + + .. math :: B_n(x) = \sum_{k=0}^n (-1)^k \binom{n}{k} B_k x^{n-k} + + Bernoulli numbers and Bernoulli polynomials are related as + `B_n(1) = B_n`. + + The generalized Bernoulli function `\operatorname{B}(s, a)` + is defined for any complex `s` and `a`, except where `a` is a + nonpositive integer and `s` is not a nonnegative integer. It is + an entire function of `s` for fixed `a`, related to the Hurwitz + zeta function by + + .. math:: \operatorname{B}(s, a) = \begin{cases} + -s \zeta(1-s, a) & s \ne 0 \\ 1 & s = 0 \end{cases} + + When `s` is a nonnegative integer this function reduces to the + Bernoulli polynomials: `\operatorname{B}(n, x) = B_n(x)`. When + `a` is omitted it is assumed to be 1, yielding the (ordinary) + Bernoulli function which interpolates the Bernoulli numbers and is + related to the Riemann zeta function. + + We compute Bernoulli numbers using Ramanujan's formula: + + .. math :: B_n = \frac{A(n) - S(n)}{\binom{n+3}{n}} + + where: + + .. math :: A(n) = \begin{cases} \frac{n+3}{3} & + n \equiv 0\ \text{or}\ 2 \pmod{6} \\ + -\frac{n+3}{6} & n \equiv 4 \pmod{6} \end{cases} + + and: + + .. math :: S(n) = \sum_{k=1}^{[n/6]} \binom{n+3}{n-6k} B_{n-6k} + + This formula is similar to the sum given in the definition, but + cuts `\frac{2}{3}` of the terms. For Bernoulli polynomials, we use + Appell sequences. + + For `n` a nonnegative integer and `s`, `a`, `x` arbitrary complex numbers, + + * ``bernoulli(n)`` gives the nth Bernoulli number, `B_n` + * ``bernoulli(s)`` gives the Bernoulli function `\operatorname{B}(s)` + * ``bernoulli(n, x)`` gives the nth Bernoulli polynomial in `x`, `B_n(x)` + * ``bernoulli(s, a)`` gives the generalized Bernoulli function + `\operatorname{B}(s, a)` + + .. versionchanged:: 1.12 + ``bernoulli(1)`` gives `+\frac{1}{2}` instead of `-\frac{1}{2}`. + This choice of value confers several theoretical advantages [5]_, + including the extension to complex parameters described above + which this function now implements. The previous behavior, defined + only for nonnegative integers `n`, can be obtained with + ``(-1)**n*bernoulli(n)``. + + Examples + ======== + + >>> from sympy import bernoulli + >>> from sympy.abc import x + >>> [bernoulli(n) for n in range(11)] + [1, 1/2, 1/6, 0, -1/30, 0, 1/42, 0, -1/30, 0, 5/66] + >>> bernoulli(1000001) + 0 + >>> bernoulli(3, x) + x**3 - 3*x**2/2 + x/2 + + See Also + ======== + + andre, bell, catalan, euler, fibonacci, harmonic, lucas, genocchi, + partition, tribonacci, sympy.polys.appellseqs.bernoulli_poly + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Bernoulli_number + .. [2] https://en.wikipedia.org/wiki/Bernoulli_polynomial + .. [3] https://mathworld.wolfram.com/BernoulliNumber.html + .. [4] https://mathworld.wolfram.com/BernoulliPolynomial.html + .. [5] Peter Luschny, "The Bernoulli Manifesto", + https://luschny.de/math/zeta/The-Bernoulli-Manifesto.html + .. [6] Peter Luschny, "An introduction to the Bernoulli function", + https://arxiv.org/abs/2009.06743 + + """ + + args: tuple[Integer] + + # Calculates B_n for positive even n + @staticmethod + def _calc_bernoulli(n): + s = 0 + a = int(binomial(n + 3, n - 6)) + for j in range(1, n//6 + 1): + s += a * bernoulli(n - 6*j) + # Avoid computing each binomial coefficient from scratch + a *= _product(n - 6 - 6*j + 1, n - 6*j) + a //= _product(6*j + 4, 6*j + 9) + if n % 6 == 4: + s = -Rational(n + 3, 6) - s + else: + s = Rational(n + 3, 3) - s + return s / binomial(n + 3, n) + + # We implement a specialized memoization scheme to handle each + # case modulo 6 separately + _cache = {0: S.One, 1: Rational(1, 2), 2: Rational(1, 6), 4: Rational(-1, 30)} + _highest = {0: 0, 1: 1, 2: 2, 4: 4} + + @classmethod + def eval(cls, n, x=None): + if x is S.One: + return cls(n) + elif n.is_zero: + return S.One + elif n.is_integer is False or n.is_nonnegative is False: + if x is not None and x.is_Integer and x.is_nonpositive: + return S.NaN + return + # Bernoulli numbers + elif x is None: + if n is S.One: + return S.Half + elif n.is_odd and (n-1).is_positive: + return S.Zero + elif n.is_Number: + n = int(n) + # Use mpmath for enormous Bernoulli numbers + if n > 500: + p, q = mp.bernfrac(n) + return Rational(int(p), int(q)) + case = n % 6 + highest_cached = cls._highest[case] + if n <= highest_cached: + return cls._cache[n] + # To avoid excessive recursion when, say, bernoulli(1000) is + # requested, calculate and cache the entire sequence ... B_988, + # B_994, B_1000 in increasing order + for i in range(highest_cached + 6, n + 6, 6): + b = cls._calc_bernoulli(i) + cls._cache[i] = b + cls._highest[case] = i + return b + # Bernoulli polynomials + elif n.is_Number: + return bernoulli_poly(n, x) + + def _eval_rewrite_as_zeta(self, n, x=1, **kwargs): + from sympy.functions.special.zeta_functions import zeta + return Piecewise((1, Eq(n, 0)), (-n * zeta(1-n, x), True)) + + def _eval_evalf(self, prec): + if not all(x.is_number for x in self.args): + return + n = self.args[0]._to_mpmath(prec) + x = (self.args[1] if len(self.args) > 1 else S.One)._to_mpmath(prec) + with workprec(prec): + if n == 0: + res = mp.mpf(1) + elif n == 1: + res = x - mp.mpf(0.5) + elif mp.isint(n) and n >= 0: + res = mp.bernoulli(n) if x == 1 else mp.bernpoly(n, x) + else: + res = -n * mp.zeta(1-n, x) + return Expr._from_mpmath(res, prec) + + +#----------------------------------------------------------------------------# +# # +# Bell numbers # +# # +#----------------------------------------------------------------------------# + + +class bell(DefinedFunction): + r""" + Bell numbers / Bell polynomials + + The Bell numbers satisfy `B_0 = 1` and + + .. math:: B_n = \sum_{k=0}^{n-1} \binom{n-1}{k} B_k. + + They are also given by: + + .. math:: B_n = \frac{1}{e} \sum_{k=0}^{\infty} \frac{k^n}{k!}. + + The Bell polynomials are given by `B_0(x) = 1` and + + .. math:: B_n(x) = x \sum_{k=1}^{n-1} \binom{n-1}{k-1} B_{k-1}(x). + + The second kind of Bell polynomials (are sometimes called "partial" Bell + polynomials or incomplete Bell polynomials) are defined as + + .. math:: B_{n,k}(x_1, x_2,\dotsc x_{n-k+1}) = + \sum_{j_1+j_2+j_2+\dotsb=k \atop j_1+2j_2+3j_2+\dotsb=n} + \frac{n!}{j_1!j_2!\dotsb j_{n-k+1}!} + \left(\frac{x_1}{1!} \right)^{j_1} + \left(\frac{x_2}{2!} \right)^{j_2} \dotsb + \left(\frac{x_{n-k+1}}{(n-k+1)!} \right) ^{j_{n-k+1}}. + + * ``bell(n)`` gives the `n^{th}` Bell number, `B_n`. + * ``bell(n, x)`` gives the `n^{th}` Bell polynomial, `B_n(x)`. + * ``bell(n, k, (x1, x2, ...))`` gives Bell polynomials of the second kind, + `B_{n,k}(x_1, x_2, \dotsc, x_{n-k+1})`. + + Notes + ===== + + Not to be confused with Bernoulli numbers and Bernoulli polynomials, + which use the same notation. + + Examples + ======== + + >>> from sympy import bell, Symbol, symbols + + >>> [bell(n) for n in range(11)] + [1, 1, 2, 5, 15, 52, 203, 877, 4140, 21147, 115975] + >>> bell(30) + 846749014511809332450147 + >>> bell(4, Symbol('t')) + t**4 + 6*t**3 + 7*t**2 + t + >>> bell(6, 2, symbols('x:6')[1:]) + 6*x1*x5 + 15*x2*x4 + 10*x3**2 + + See Also + ======== + + bernoulli, catalan, euler, fibonacci, harmonic, lucas, genocchi, partition, tribonacci + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Bell_number + .. [2] https://mathworld.wolfram.com/BellNumber.html + .. [3] https://mathworld.wolfram.com/BellPolynomial.html + + """ + + @staticmethod + @recurrence_memo([1, 1]) + def _bell(n, prev): + s = 1 + a = 1 + for k in range(1, n): + a = a * (n - k) // k + s += a * prev[k] + return s + + @staticmethod + @recurrence_memo([S.One, _sym]) + def _bell_poly(n, prev): + s = 1 + a = 1 + for k in range(2, n + 1): + a = a * (n - k + 1) // (k - 1) + s += a * prev[k - 1] + return expand_mul(_sym * s) + + @staticmethod + def _bell_incomplete_poly(n, k, symbols): + r""" + The second kind of Bell polynomials (incomplete Bell polynomials). + + Calculated by recurrence formula: + + .. math:: B_{n,k}(x_1, x_2, \dotsc, x_{n-k+1}) = + \sum_{m=1}^{n-k+1} + \x_m \binom{n-1}{m-1} B_{n-m,k-1}(x_1, x_2, \dotsc, x_{n-m-k}) + + where + `B_{0,0} = 1;` + `B_{n,0} = 0; for n \ge 1` + `B_{0,k} = 0; for k \ge 1` + + """ + if (n == 0) and (k == 0): + return S.One + elif (n == 0) or (k == 0): + return S.Zero + s = S.Zero + a = S.One + for m in range(1, n - k + 2): + s += a * bell._bell_incomplete_poly( + n - m, k - 1, symbols) * symbols[m - 1] + a = a * (n - m) / m + return expand_mul(s) + + @classmethod + def eval(cls, n, k_sym=None, symbols=None): + if n is S.Infinity: + if k_sym is None: + return S.Infinity + else: + raise ValueError("Bell polynomial is not defined") + + if n.is_negative or n.is_integer is False: + raise ValueError("a non-negative integer expected") + + if n.is_Integer and n.is_nonnegative: + if k_sym is None: + return Integer(cls._bell(int(n))) + elif symbols is None: + return cls._bell_poly(int(n)).subs(_sym, k_sym) + else: + r = cls._bell_incomplete_poly(int(n), int(k_sym), symbols) + return r + + def _eval_rewrite_as_Sum(self, n, k_sym=None, symbols=None, **kwargs): + from sympy.concrete.summations import Sum + if (k_sym is not None) or (symbols is not None): + return self + + # Dobinski's formula + if not n.is_nonnegative: + return self + k = Dummy('k', integer=True, nonnegative=True) + return 1 / E * Sum(k**n / factorial(k), (k, 0, S.Infinity)) + + +#----------------------------------------------------------------------------# +# # +# Harmonic numbers # +# # +#----------------------------------------------------------------------------# + + +class harmonic(DefinedFunction): + r""" + Harmonic numbers + + The nth harmonic number is given by `\operatorname{H}_{n} = + 1 + \frac{1}{2} + \frac{1}{3} + \ldots + \frac{1}{n}`. + + More generally: + + .. math:: \operatorname{H}_{n,m} = \sum_{k=1}^{n} \frac{1}{k^m} + + As `n \rightarrow \infty`, `\operatorname{H}_{n,m} \rightarrow \zeta(m)`, + the Riemann zeta function. + + * ``harmonic(n)`` gives the nth harmonic number, `\operatorname{H}_n` + + * ``harmonic(n, m)`` gives the nth generalized harmonic number + of order `m`, `\operatorname{H}_{n,m}`, where + ``harmonic(n) == harmonic(n, 1)`` + + This function can be extended to complex `n` and `m` where `n` is not a + negative integer or `m` is a nonpositive integer as + + .. math:: \operatorname{H}_{n,m} = \begin{cases} \zeta(m) - \zeta(m, n+1) + & m \ne 1 \\ \psi(n+1) + \gamma & m = 1 \end{cases} + + Examples + ======== + + >>> from sympy import harmonic, oo + + >>> [harmonic(n) for n in range(6)] + [0, 1, 3/2, 11/6, 25/12, 137/60] + >>> [harmonic(n, 2) for n in range(6)] + [0, 1, 5/4, 49/36, 205/144, 5269/3600] + >>> harmonic(oo, 2) + pi**2/6 + + >>> from sympy import Symbol, Sum + >>> n = Symbol("n") + + >>> harmonic(n).rewrite(Sum) + Sum(1/_k, (_k, 1, n)) + + We can evaluate harmonic numbers for all integral and positive + rational arguments: + + >>> from sympy import S, expand_func, simplify + >>> harmonic(8) + 761/280 + >>> harmonic(11) + 83711/27720 + + >>> H = harmonic(1/S(3)) + >>> H + harmonic(1/3) + >>> He = expand_func(H) + >>> He + -log(6) - sqrt(3)*pi/6 + 2*Sum(log(sin(_k*pi/3))*cos(2*_k*pi/3), (_k, 1, 1)) + + 3*Sum(1/(3*_k + 1), (_k, 0, 0)) + >>> He.doit() + -log(6) - sqrt(3)*pi/6 - log(sqrt(3)/2) + 3 + >>> H = harmonic(25/S(7)) + >>> He = simplify(expand_func(H).doit()) + >>> He + log(sin(2*pi/7)**(2*cos(16*pi/7))/(14*sin(pi/7)**(2*cos(pi/7))*cos(pi/14)**(2*sin(pi/14)))) + pi*tan(pi/14)/2 + 30247/9900 + >>> He.n(40) + 1.983697455232980674869851942390639915940 + >>> harmonic(25/S(7)).n(40) + 1.983697455232980674869851942390639915940 + + We can rewrite harmonic numbers in terms of polygamma functions: + + >>> from sympy import digamma, polygamma + >>> m = Symbol("m", integer=True, positive=True) + + >>> harmonic(n).rewrite(digamma) + polygamma(0, n + 1) + EulerGamma + + >>> harmonic(n).rewrite(polygamma) + polygamma(0, n + 1) + EulerGamma + + >>> harmonic(n,3).rewrite(polygamma) + polygamma(2, n + 1)/2 + zeta(3) + + >>> simplify(harmonic(n,m).rewrite(polygamma)) + Piecewise((polygamma(0, n + 1) + EulerGamma, Eq(m, 1)), + (-(-1)**m*polygamma(m - 1, n + 1)/factorial(m - 1) + zeta(m), True)) + + Integer offsets in the argument can be pulled out: + + >>> from sympy import expand_func + + >>> expand_func(harmonic(n+4)) + harmonic(n) + 1/(n + 4) + 1/(n + 3) + 1/(n + 2) + 1/(n + 1) + + >>> expand_func(harmonic(n-4)) + harmonic(n) - 1/(n - 1) - 1/(n - 2) - 1/(n - 3) - 1/n + + Some limits can be computed as well: + + >>> from sympy import limit, oo + + >>> limit(harmonic(n), n, oo) + oo + + >>> limit(harmonic(n, 2), n, oo) + pi**2/6 + + >>> limit(harmonic(n, 3), n, oo) + zeta(3) + + For `m > 1`, `H_{n,m}` tends to `\zeta(m)` in the limit of infinite `n`: + + >>> m = Symbol("m", positive=True) + >>> limit(harmonic(n, m+1), n, oo) + zeta(m + 1) + + See Also + ======== + + bell, bernoulli, catalan, euler, fibonacci, lucas, genocchi, partition, tribonacci + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Harmonic_number + .. [2] https://functions.wolfram.com/GammaBetaErf/HarmonicNumber/ + .. [3] https://functions.wolfram.com/GammaBetaErf/HarmonicNumber2/ + + """ + + # This prevents redundant recalculations and speeds up harmonic number computations. + harmonic_cache: dict[Integer, Callable[[int], Rational]] = {} + + @classmethod + def eval(cls, n, m=None): + from sympy.functions.special.zeta_functions import zeta + if m is S.One: + return cls(n) + if m is None: + m = S.One + if n.is_zero: + return S.Zero + elif m.is_zero: + return n + elif n is S.Infinity: + if m.is_negative: + return S.NaN + elif is_le(m, S.One): + return S.Infinity + elif is_gt(m, S.One): + return zeta(m) + elif m.is_Integer and m.is_nonpositive: + return (bernoulli(1-m, n+1) - bernoulli(1-m)) / (1-m) + elif n.is_Integer: + if n.is_negative and (m.is_integer is False or m.is_nonpositive is False): + return S.ComplexInfinity if m is S.One else S.NaN + if n.is_nonnegative: + if m.is_Integer: + if m not in cls.harmonic_cache: + @recurrence_memo([0]) + def f(n, prev): + return prev[-1] + S.One / n**m + cls.harmonic_cache[m] = f + return cls.harmonic_cache[m](int(n)) + return Add(*(k**(-m) for k in range(1, int(n) + 1))) + + def _eval_rewrite_as_polygamma(self, n, m=S.One, **kwargs): + from sympy.functions.special.gamma_functions import gamma, polygamma + if m.is_integer and m.is_positive: + return Piecewise((polygamma(0, n+1) + S.EulerGamma, Eq(m, 1)), + (S.NegativeOne**m * (polygamma(m-1, 1) - polygamma(m-1, n+1)) / + gamma(m), True)) + + def _eval_rewrite_as_digamma(self, n, m=1, **kwargs): + from sympy.functions.special.gamma_functions import polygamma + return self.rewrite(polygamma) + + def _eval_rewrite_as_trigamma(self, n, m=1, **kwargs): + from sympy.functions.special.gamma_functions import polygamma + return self.rewrite(polygamma) + + def _eval_rewrite_as_Sum(self, n, m=None, **kwargs): + from sympy.concrete.summations import Sum + k = Dummy("k", integer=True) + if m is None: + m = S.One + return Sum(k**(-m), (k, 1, n)) + + def _eval_rewrite_as_zeta(self, n, m=S.One, **kwargs): + from sympy.functions.special.zeta_functions import zeta + from sympy.functions.special.gamma_functions import digamma + return Piecewise((digamma(n + 1) + S.EulerGamma, Eq(m, 1)), + (zeta(m) - zeta(m, n+1), True)) + + def _eval_expand_func(self, **hints): + from sympy.concrete.summations import Sum + n = self.args[0] + m = self.args[1] if len(self.args) == 2 else 1 + + if m == S.One: + if n.is_Add: + off = n.args[0] + nnew = n - off + if off.is_Integer and off.is_positive: + result = [S.One/(nnew + i) for i in range(off, 0, -1)] + [harmonic(nnew)] + return Add(*result) + elif off.is_Integer and off.is_negative: + result = [-S.One/(nnew + i) for i in range(0, off, -1)] + [harmonic(nnew)] + return Add(*result) + + if n.is_Rational: + # Expansions for harmonic numbers at general rational arguments (u + p/q) + # Split n as u + p/q with p < q + p, q = n.as_numer_denom() + u = p // q + p = p - u * q + if u.is_nonnegative and p.is_positive and q.is_positive and p < q: + from sympy.functions.elementary.exponential import log + from sympy.functions.elementary.integers import floor + from sympy.functions.elementary.trigonometric import sin, cos, cot + k = Dummy("k") + t1 = q * Sum(1 / (q * k + p), (k, 0, u)) + t2 = 2 * Sum(cos((2 * pi * p * k) / S(q)) * + log(sin((pi * k) / S(q))), + (k, 1, floor((q - 1) / S(2)))) + t3 = (pi / 2) * cot((pi * p) / q) + log(2 * q) + return t1 + t2 - t3 + + return self + + def _eval_rewrite_as_tractable(self, n, m=1, limitvar=None, **kwargs): + from sympy.functions.special.zeta_functions import zeta + from sympy.functions.special.gamma_functions import polygamma + pg = self.rewrite(polygamma) + if not isinstance(pg, harmonic): + return pg.rewrite("tractable", deep=True) + arg = m - S.One + if arg.is_nonzero: + return (zeta(m) - zeta(m, n+1)).rewrite("tractable", deep=True) + + def _eval_evalf(self, prec): + if not all(x.is_number for x in self.args): + return + n = self.args[0]._to_mpmath(prec) + m = (self.args[1] if len(self.args) > 1 else S.One)._to_mpmath(prec) + if mp.isint(n) and n < 0: + return S.NaN + with workprec(prec): + if m == 1: + res = mp.harmonic(n) + else: + res = mp.zeta(m) - mp.zeta(m, n+1) + return Expr._from_mpmath(res, prec) + + def fdiff(self, argindex=1): + from sympy.functions.special.zeta_functions import zeta + if len(self.args) == 2: + n, m = self.args + else: + n, m = self.args + (1,) + if argindex == 1: + return m * zeta(m+1, n+1) + else: + raise ArgumentIndexError + + +#----------------------------------------------------------------------------# +# # +# Euler numbers # +# # +#----------------------------------------------------------------------------# + + +class euler(DefinedFunction): + r""" + Euler numbers / Euler polynomials / Euler function + + The Euler numbers are given by: + + .. math:: E_{2n} = I \sum_{k=1}^{2n+1} \sum_{j=0}^k \binom{k}{j} + \frac{(-1)^j (k-2j)^{2n+1}}{2^k I^k k} + + .. math:: E_{2n+1} = 0 + + Euler numbers and Euler polynomials are related by + + .. math:: E_n = 2^n E_n\left(\frac{1}{2}\right). + + We compute symbolic Euler polynomials using Appell sequences, + but numerical evaluation of the Euler polynomial is computed + more efficiently (and more accurately) using the mpmath library. + + The Euler polynomials are special cases of the generalized Euler function, + related to the Genocchi function as + + .. math:: \operatorname{E}(s, a) = -\frac{\operatorname{G}(s+1, a)}{s+1} + + with the limit of `\psi\left(\frac{a+1}{2}\right) - \psi\left(\frac{a}{2}\right)` + being taken when `s = -1`. The (ordinary) Euler function interpolating + the Euler numbers is then obtained as + `\operatorname{E}(s) = 2^s \operatorname{E}\left(s, \frac{1}{2}\right)`. + + * ``euler(n)`` gives the nth Euler number `E_n`. + * ``euler(s)`` gives the Euler function `\operatorname{E}(s)`. + * ``euler(n, x)`` gives the nth Euler polynomial `E_n(x)`. + * ``euler(s, a)`` gives the generalized Euler function `\operatorname{E}(s, a)`. + + Examples + ======== + + >>> from sympy import euler, Symbol, S + >>> [euler(n) for n in range(10)] + [1, 0, -1, 0, 5, 0, -61, 0, 1385, 0] + >>> [2**n*euler(n,1) for n in range(10)] + [1, 1, 0, -2, 0, 16, 0, -272, 0, 7936] + >>> n = Symbol("n") + >>> euler(n + 2*n) + euler(3*n) + + >>> x = Symbol("x") + >>> euler(n, x) + euler(n, x) + + >>> euler(0, x) + 1 + >>> euler(1, x) + x - 1/2 + >>> euler(2, x) + x**2 - x + >>> euler(3, x) + x**3 - 3*x**2/2 + 1/4 + >>> euler(4, x) + x**4 - 2*x**3 + x + + >>> euler(12, S.Half) + 2702765/4096 + >>> euler(12) + 2702765 + + See Also + ======== + + andre, bell, bernoulli, catalan, fibonacci, harmonic, lucas, genocchi, + partition, tribonacci, sympy.polys.appellseqs.euler_poly + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Euler_numbers + .. [2] https://mathworld.wolfram.com/EulerNumber.html + .. [3] https://en.wikipedia.org/wiki/Alternating_permutation + .. [4] https://mathworld.wolfram.com/AlternatingPermutation.html + + """ + + @classmethod + def eval(cls, n, x=None): + if n.is_zero: + return S.One + elif n is S.NegativeOne: + if x is None: + return S.Pi/2 + from sympy.functions.special.gamma_functions import digamma + return digamma((x+1)/2) - digamma(x/2) + elif n.is_integer is False or n.is_nonnegative is False: + return + # Euler numbers + elif x is None: + if n.is_odd and n.is_positive: + return S.Zero + elif n.is_Number: + from mpmath import mp + n = n._to_mpmath(mp.prec) + res = mp.eulernum(n, exact=True) + return Integer(res) + # Euler polynomials + elif n.is_Number: + from sympy.core.evalf import pure_complex + n = int(n) + reim = pure_complex(x, or_real=True) + if reim and all(a.is_Float or a.is_Integer for a in reim) \ + and any(a.is_Float for a in reim): + from mpmath import mp + prec = min([a._prec for a in reim if a.is_Float]) + with workprec(prec): + res = mp.eulerpoly(n, x) + return Expr._from_mpmath(res, prec) + return euler_poly(n, x) + + def _eval_rewrite_as_Sum(self, n, x=None, **kwargs): + from sympy.concrete.summations import Sum + if x is None and n.is_even: + k = Dummy("k", integer=True) + j = Dummy("j", integer=True) + n = n / 2 + Em = (S.ImaginaryUnit * Sum(Sum(binomial(k, j) * (S.NegativeOne**j * + (k - 2*j)**(2*n + 1)) / + (2**k*S.ImaginaryUnit**k * k), (j, 0, k)), (k, 1, 2*n + 1))) + return Em + if x: + k = Dummy("k", integer=True) + return Sum(binomial(n, k)*euler(k)/2**k*(x - S.Half)**(n - k), (k, 0, n)) + + def _eval_rewrite_as_genocchi(self, n, x=None, **kwargs): + if x is None: + return Piecewise((S.Pi/2, Eq(n, -1)), + (-2**n * genocchi(n+1, S.Half) / (n+1), True)) + from sympy.functions.special.gamma_functions import digamma + return Piecewise((digamma((x+1)/2) - digamma(x/2), Eq(n, -1)), + (-genocchi(n+1, x) / (n+1), True)) + + def _eval_evalf(self, prec): + if not all(i.is_number for i in self.args): + return + from mpmath import mp + m, x = (self.args[0], None) if len(self.args) == 1 else self.args + m = m._to_mpmath(prec) + if x is not None: + x = x._to_mpmath(prec) + with workprec(prec): + if mp.isint(m) and m >= 0: + res = mp.eulernum(m) if x is None else mp.eulerpoly(m, x) + else: + if m == -1: + res = mp.pi if x is None else mp.digamma((x+1)/2) - mp.digamma(x/2) + else: + y = 0.5 if x is None else x + res = 2 * (mp.zeta(-m, y) - 2**(m+1) * mp.zeta(-m, (y+1)/2)) + if x is None: + res *= 2**m + return Expr._from_mpmath(res, prec) + + +#----------------------------------------------------------------------------# +# # +# Catalan numbers # +# # +#----------------------------------------------------------------------------# + + +class catalan(DefinedFunction): + r""" + Catalan numbers + + The `n^{th}` catalan number is given by: + + .. math :: C_n = \frac{1}{n+1} \binom{2n}{n} + + * ``catalan(n)`` gives the `n^{th}` Catalan number, `C_n` + + Examples + ======== + + >>> from sympy import (Symbol, binomial, gamma, hyper, + ... catalan, diff, combsimp, Rational, I) + + >>> [catalan(i) for i in range(1,10)] + [1, 2, 5, 14, 42, 132, 429, 1430, 4862] + + >>> n = Symbol("n", integer=True) + + >>> catalan(n) + catalan(n) + + Catalan numbers can be transformed into several other, identical + expressions involving other mathematical functions + + >>> catalan(n).rewrite(binomial) + binomial(2*n, n)/(n + 1) + + >>> catalan(n).rewrite(gamma) + 4**n*gamma(n + 1/2)/(sqrt(pi)*gamma(n + 2)) + + >>> catalan(n).rewrite(hyper) + hyper((-n, 1 - n), (2,), 1) + + For some non-integer values of n we can get closed form + expressions by rewriting in terms of gamma functions: + + >>> catalan(Rational(1, 2)).rewrite(gamma) + 8/(3*pi) + + We can differentiate the Catalan numbers C(n) interpreted as a + continuous real function in n: + + >>> diff(catalan(n), n) + (polygamma(0, n + 1/2) - polygamma(0, n + 2) + log(4))*catalan(n) + + As a more advanced example consider the following ratio + between consecutive numbers: + + >>> combsimp((catalan(n + 1)/catalan(n)).rewrite(binomial)) + 2*(2*n + 1)/(n + 2) + + The Catalan numbers can be generalized to complex numbers: + + >>> catalan(I).rewrite(gamma) + 4**I*gamma(1/2 + I)/(sqrt(pi)*gamma(2 + I)) + + and evaluated with arbitrary precision: + + >>> catalan(I).evalf(20) + 0.39764993382373624267 - 0.020884341620842555705*I + + See Also + ======== + + andre, bell, bernoulli, euler, fibonacci, harmonic, lucas, genocchi, + partition, tribonacci, sympy.functions.combinatorial.factorials.binomial + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Catalan_number + .. [2] https://mathworld.wolfram.com/CatalanNumber.html + .. [3] https://functions.wolfram.com/GammaBetaErf/CatalanNumber/ + .. [4] http://geometer.org/mathcircles/catalan.pdf + + """ + + @classmethod + def eval(cls, n): + from sympy.functions.special.gamma_functions import gamma + if (n.is_Integer and n.is_nonnegative) or \ + (n.is_noninteger and n.is_negative): + return 4**n*gamma(n + S.Half)/(gamma(S.Half)*gamma(n + 2)) + + if (n.is_integer and n.is_negative): + if (n + 1).is_negative: + return S.Zero + if (n + 1).is_zero: + return Rational(-1, 2) + + def fdiff(self, argindex=1): + from sympy.functions.elementary.exponential import log + from sympy.functions.special.gamma_functions import polygamma + n = self.args[0] + return catalan(n)*(polygamma(0, n + S.Half) - polygamma(0, n + 2) + log(4)) + + def _eval_rewrite_as_binomial(self, n, **kwargs): + return binomial(2*n, n)/(n + 1) + + def _eval_rewrite_as_factorial(self, n, **kwargs): + return factorial(2*n) / (factorial(n+1) * factorial(n)) + + def _eval_rewrite_as_gamma(self, n, piecewise=True, **kwargs): + from sympy.functions.special.gamma_functions import gamma + # The gamma function allows to generalize Catalan numbers to complex n + return 4**n*gamma(n + S.Half)/(gamma(S.Half)*gamma(n + 2)) + + def _eval_rewrite_as_hyper(self, n, **kwargs): + from sympy.functions.special.hyper import hyper + return hyper([1 - n, -n], [2], 1) + + def _eval_rewrite_as_Product(self, n, **kwargs): + from sympy.concrete.products import Product + if not (n.is_integer and n.is_nonnegative): + return self + k = Dummy('k', integer=True, positive=True) + return Product((n + k) / k, (k, 2, n)) + + def _eval_is_integer(self): + if self.args[0].is_integer and self.args[0].is_nonnegative: + return True + + def _eval_is_positive(self): + if self.args[0].is_nonnegative: + return True + + def _eval_is_composite(self): + if self.args[0].is_integer and (self.args[0] - 3).is_positive: + return True + + def _eval_evalf(self, prec): + from sympy.functions.special.gamma_functions import gamma + if self.args[0].is_number: + return self.rewrite(gamma)._eval_evalf(prec) + + +#----------------------------------------------------------------------------# +# # +# Genocchi numbers # +# # +#----------------------------------------------------------------------------# + + +class genocchi(DefinedFunction): + r""" + Genocchi numbers / Genocchi polynomials / Genocchi function + + The Genocchi numbers are a sequence of integers `G_n` that satisfy the + relation: + + .. math:: \frac{-2t}{1 + e^{-t}} = \sum_{n=0}^\infty \frac{G_n t^n}{n!} + + They are related to the Bernoulli numbers by + + .. math:: G_n = 2 (1 - 2^n) B_n + + and generalize like the Bernoulli numbers to the Genocchi polynomials and + function as + + .. math:: \operatorname{G}(s, a) = 2 \left(\operatorname{B}(s, a) - + 2^s \operatorname{B}\left(s, \frac{a+1}{2}\right)\right) + + .. versionchanged:: 1.12 + ``genocchi(1)`` gives `-1` instead of `1`. + + Examples + ======== + + >>> from sympy import genocchi, Symbol + >>> [genocchi(n) for n in range(9)] + [0, -1, -1, 0, 1, 0, -3, 0, 17] + >>> n = Symbol('n', integer=True, positive=True) + >>> genocchi(2*n + 1) + 0 + >>> x = Symbol('x') + >>> genocchi(4, x) + -4*x**3 + 6*x**2 - 1 + + See Also + ======== + + bell, bernoulli, catalan, euler, fibonacci, harmonic, lucas, partition, tribonacci + sympy.polys.appellseqs.genocchi_poly + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Genocchi_number + .. [2] https://mathworld.wolfram.com/GenocchiNumber.html + .. [3] Peter Luschny, "An introduction to the Bernoulli function", + https://arxiv.org/abs/2009.06743 + + """ + + @classmethod + def eval(cls, n, x=None): + if x is S.One: + return cls(n) + elif n.is_integer is False or n.is_nonnegative is False: + return + # Genocchi numbers + elif x is None: + if n.is_odd and (n-1).is_positive: + return S.Zero + elif n.is_Number: + return 2 * (1-S(2)**n) * bernoulli(n) + # Genocchi polynomials + elif n.is_Number: + return genocchi_poly(n, x) + + def _eval_rewrite_as_bernoulli(self, n, x=1, **kwargs): + if x == 1 and n.is_integer and n.is_nonnegative: + return 2 * (1-S(2)**n) * bernoulli(n) + return 2 * (bernoulli(n, x) - 2**n * bernoulli(n, (x+1) / 2)) + + def _eval_rewrite_as_dirichlet_eta(self, n, x=1, **kwargs): + from sympy.functions.special.zeta_functions import dirichlet_eta + return -2*n * dirichlet_eta(1-n, x) + + def _eval_is_integer(self): + if len(self.args) > 1 and self.args[1] != 1: + return + n = self.args[0] + if n.is_integer and n.is_nonnegative: + return True + + def _eval_is_negative(self): + if len(self.args) > 1 and self.args[1] != 1: + return + n = self.args[0] + if n.is_integer and n.is_nonnegative: + if n.is_odd: + return fuzzy_not((n-1).is_positive) + return (n/2).is_odd + + def _eval_is_positive(self): + if len(self.args) > 1 and self.args[1] != 1: + return + n = self.args[0] + if n.is_integer and n.is_nonnegative: + if n.is_zero or n.is_odd: + return False + return (n/2).is_even + + def _eval_is_even(self): + if len(self.args) > 1 and self.args[1] != 1: + return + n = self.args[0] + if n.is_integer and n.is_nonnegative: + if n.is_even: + return n.is_zero + return (n-1).is_positive + + def _eval_is_odd(self): + if len(self.args) > 1 and self.args[1] != 1: + return + n = self.args[0] + if n.is_integer and n.is_nonnegative: + if n.is_even: + return fuzzy_not(n.is_zero) + return fuzzy_not((n-1).is_positive) + + def _eval_is_prime(self): + if len(self.args) > 1 and self.args[1] != 1: + return + n = self.args[0] + # only G_6 = -3 and G_8 = 17 are prime, + # but SymPy does not consider negatives as prime + # so only n=8 is tested + return (n-8).is_zero + + def _eval_evalf(self, prec): + if all(i.is_number for i in self.args): + return self.rewrite(bernoulli)._eval_evalf(prec) + + +#----------------------------------------------------------------------------# +# # +# Andre numbers # +# # +#----------------------------------------------------------------------------# + + +class andre(DefinedFunction): + r""" + Andre numbers / Andre function + + The Andre number `\mathcal{A}_n` is Luschny's name for half the number of + *alternating permutations* on `n` elements, where a permutation is alternating + if adjacent elements alternately compare "greater" and "smaller" going from + left to right. For example, `2 < 3 > 1 < 4` is an alternating permutation. + + This sequence is A000111 in the OEIS, which assigns the names *up/down numbers* + and *Euler zigzag numbers*. It satisfies a recurrence relation similar to that + for the Catalan numbers, with `\mathcal{A}_0 = 1` and + + .. math:: 2 \mathcal{A}_{n+1} = \sum_{k=0}^n \binom{n}{k} \mathcal{A}_k \mathcal{A}_{n-k} + + The Bernoulli and Euler numbers are signed transformations of the odd- and + even-indexed elements of this sequence respectively: + + .. math :: \operatorname{B}_{2k} = \frac{2k \mathcal{A}_{2k-1}}{(-4)^k - (-16)^k} + + .. math :: \operatorname{E}_{2k} = (-1)^k \mathcal{A}_{2k} + + Like the Bernoulli and Euler numbers, the Andre numbers are interpolated by the + entire Andre function: + + .. math :: \mathcal{A}(s) = (-i)^{s+1} \operatorname{Li}_{-s}(i) + + i^{s+1} \operatorname{Li}_{-s}(-i) = \\ \frac{2 \Gamma(s+1)}{(2\pi)^{s+1}} + (\zeta(s+1, 1/4) - \zeta(s+1, 3/4) \cos{\pi s}) + + Examples + ======== + + >>> from sympy import andre, euler, bernoulli + >>> [andre(n) for n in range(11)] + [1, 1, 1, 2, 5, 16, 61, 272, 1385, 7936, 50521] + >>> [(-1)**k * andre(2*k) for k in range(7)] + [1, -1, 5, -61, 1385, -50521, 2702765] + >>> [euler(2*k) for k in range(7)] + [1, -1, 5, -61, 1385, -50521, 2702765] + >>> [andre(2*k-1) * (2*k) / ((-4)**k - (-16)**k) for k in range(1, 8)] + [1/6, -1/30, 1/42, -1/30, 5/66, -691/2730, 7/6] + >>> [bernoulli(2*k) for k in range(1, 8)] + [1/6, -1/30, 1/42, -1/30, 5/66, -691/2730, 7/6] + + See Also + ======== + + bernoulli, catalan, euler, sympy.polys.appellseqs.andre_poly + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Alternating_permutation + .. [2] https://mathworld.wolfram.com/EulerZigzagNumber.html + .. [3] Peter Luschny, "An introduction to the Bernoulli function", + https://arxiv.org/abs/2009.06743 + """ + + @classmethod + def eval(cls, n): + if n is S.NaN: + return S.NaN + elif n is S.Infinity: + return S.Infinity + if n.is_zero: + return S.One + elif n == -1: + return -log(2) + elif n == -2: + return -2*S.Catalan + elif n.is_Integer: + if n.is_nonnegative and n.is_even: + return abs(euler(n)) + elif n.is_odd: + from sympy.functions.special.zeta_functions import zeta + m = -n-1 + return I**m * Rational(1-2**m, 4**m) * zeta(-n) + + def _eval_rewrite_as_zeta(self, s, **kwargs): + from sympy.functions.elementary.trigonometric import cos + from sympy.functions.special.gamma_functions import gamma + from sympy.functions.special.zeta_functions import zeta + return 2 * gamma(s+1) / (2*pi)**(s+1) * \ + (zeta(s+1, S.One/4) - cos(pi*s) * zeta(s+1, S(3)/4)) + + def _eval_rewrite_as_polylog(self, s, **kwargs): + from sympy.functions.special.zeta_functions import polylog + return (-I)**(s+1) * polylog(-s, I) + I**(s+1) * polylog(-s, -I) + + def _eval_is_integer(self): + n = self.args[0] + if n.is_integer and n.is_nonnegative: + return True + + def _eval_is_positive(self): + if self.args[0].is_nonnegative: + return True + + def _eval_evalf(self, prec): + if not self.args[0].is_number: + return + s = self.args[0]._to_mpmath(prec+12) + with workprec(prec+12): + sp, cp = mp.sinpi(s/2), mp.cospi(s/2) + res = 2*mp.dirichlet(-s, (-sp, cp, sp, -cp)) + return Expr._from_mpmath(res, prec) + + +#----------------------------------------------------------------------------# +# # +# Partition numbers # +# # +#----------------------------------------------------------------------------# + +class partition(DefinedFunction): + r""" + Partition numbers + + The Partition numbers are a sequence of integers `p_n` that represent the + number of distinct ways of representing `n` as a sum of natural numbers + (with order irrelevant). The generating function for `p_n` is given by: + + .. math:: \sum_{n=0}^\infty p_n x^n = \prod_{k=1}^\infty (1 - x^k)^{-1} + + Examples + ======== + + >>> from sympy import partition, Symbol + >>> [partition(n) for n in range(9)] + [1, 1, 2, 3, 5, 7, 11, 15, 22] + >>> n = Symbol('n', integer=True, negative=True) + >>> partition(n) + 0 + + See Also + ======== + + bell, bernoulli, catalan, euler, fibonacci, harmonic, lucas, genocchi, tribonacci + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Partition_(number_theory%29 + .. [2] https://en.wikipedia.org/wiki/Pentagonal_number_theorem + + """ + is_integer = True + is_nonnegative = True + + @classmethod + def eval(cls, n): + if n.is_integer is False: + raise TypeError("n should be an integer") + if n.is_negative is True: + return S.Zero + if n.is_zero is True or n is S.One: + return S.One + if n.is_Integer is True: + return S(_partition(as_int(n))) + + def _eval_is_positive(self): + if self.args[0].is_nonnegative is True: + return True + + def _eval_Mod(self, q): + # Ramanujan's congruences + n = self.args[0] + for p, rem in [(5, 4), (7, 5), (11, 6)]: + if q == p and n % q == rem: + return S.Zero + + +class divisor_sigma(DefinedFunction): + r""" + Calculate the divisor function `\sigma_k(n)` for positive integer n + + ``divisor_sigma(n, k)`` is equal to ``sum([x**k for x in divisors(n)])`` + + If n's prime factorization is: + + .. math :: + n = \prod_{i=1}^\omega p_i^{m_i}, + + then + + .. math :: + \sigma_k(n) = \prod_{i=1}^\omega (1+p_i^k+p_i^{2k}+\cdots + + p_i^{m_ik}). + + Examples + ======== + + >>> from sympy.functions.combinatorial.numbers import divisor_sigma + >>> divisor_sigma(18, 0) + 6 + >>> divisor_sigma(39, 1) + 56 + >>> divisor_sigma(12, 2) + 210 + >>> divisor_sigma(37) + 38 + + See Also + ======== + + sympy.ntheory.factor_.divisor_count, totient, sympy.ntheory.factor_.divisors, sympy.ntheory.factor_.factorint + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Divisor_function + + """ + is_integer = True + is_positive = True + + @classmethod + def eval(cls, n, k=S.One): + if n.is_integer is False: + raise TypeError("n should be an integer") + if n.is_positive is False: + raise ValueError("n should be a positive integer") + if k.is_integer is False: + raise TypeError("k should be an integer") + if k.is_nonnegative is False: + raise ValueError("k should be a nonnegative integer") + if n.is_prime is True: + return 1 + n**k + if n is S.One: + return S.One + if n.is_Integer is True: + if k.is_zero is True: + return Mul(*[e + 1 for e in factorint(n).values()]) + if k.is_Integer is True: + return S(_divisor_sigma(as_int(n), as_int(k))) + if k.is_zero is False: + return Mul(*[cancel((p**(k*(e + 1)) - 1) / (p**k - 1)) for p, e in factorint(n).items()]) + + +class udivisor_sigma(DefinedFunction): + r""" + Calculate the unitary divisor function `\sigma_k^*(n)` for positive integer n + + ``udivisor_sigma(n, k)`` is equal to ``sum([x**k for x in udivisors(n)])`` + + If n's prime factorization is: + + .. math :: + n = \prod_{i=1}^\omega p_i^{m_i}, + + then + + .. math :: + \sigma_k^*(n) = \prod_{i=1}^\omega (1+ p_i^{m_ik}). + + Parameters + ========== + + k : power of divisors in the sum + + for k = 0, 1: + ``udivisor_sigma(n, 0)`` is equal to ``udivisor_count(n)`` + ``udivisor_sigma(n, 1)`` is equal to ``sum(udivisors(n))`` + + Default for k is 1. + + Examples + ======== + + >>> from sympy.functions.combinatorial.numbers import udivisor_sigma + >>> udivisor_sigma(18, 0) + 4 + >>> udivisor_sigma(74, 1) + 114 + >>> udivisor_sigma(36, 3) + 47450 + >>> udivisor_sigma(111) + 152 + + See Also + ======== + + sympy.ntheory.factor_.divisor_count, totient, sympy.ntheory.factor_.divisors, + sympy.ntheory.factor_.udivisors, sympy.ntheory.factor_.udivisor_count, divisor_sigma, + sympy.ntheory.factor_.factorint + + References + ========== + + .. [1] https://mathworld.wolfram.com/UnitaryDivisorFunction.html + + """ + is_integer = True + is_positive = True + + @classmethod + def eval(cls, n, k=S.One): + if n.is_integer is False: + raise TypeError("n should be an integer") + if n.is_positive is False: + raise ValueError("n should be a positive integer") + if k.is_integer is False: + raise TypeError("k should be an integer") + if k.is_nonnegative is False: + raise ValueError("k should be a nonnegative integer") + if n.is_prime is True: + return 1 + n**k + if n.is_Integer: + return Mul(*[1+p**(k*e) for p, e in factorint(n).items()]) + + +class legendre_symbol(DefinedFunction): + r""" + Returns the Legendre symbol `(a / p)`. + + For an integer ``a`` and an odd prime ``p``, the Legendre symbol is + defined as + + .. math :: + \genfrac(){}{}{a}{p} = \begin{cases} + 0 & \text{if } p \text{ divides } a\\ + 1 & \text{if } a \text{ is a quadratic residue modulo } p\\ + -1 & \text{if } a \text{ is a quadratic nonresidue modulo } p + \end{cases} + + Examples + ======== + + >>> from sympy.functions.combinatorial.numbers import legendre_symbol + >>> [legendre_symbol(i, 7) for i in range(7)] + [0, 1, 1, -1, 1, -1, -1] + >>> sorted(set([i**2 % 7 for i in range(7)])) + [0, 1, 2, 4] + + See Also + ======== + + sympy.ntheory.residue_ntheory.is_quad_residue, jacobi_symbol + + """ + is_integer = True + is_prime = False + + @classmethod + def eval(cls, a, p): + if a.is_integer is False: + raise TypeError("a should be an integer") + if p.is_integer is False: + raise TypeError("p should be an integer") + if p.is_prime is False or p.is_odd is False: + raise ValueError("p should be an odd prime integer") + if (a % p).is_zero is True: + return S.Zero + if a is S.One: + return S.One + if a.is_Integer is True and p.is_Integer is True: + return S(legendre(as_int(a), as_int(p))) + + +class jacobi_symbol(DefinedFunction): + r""" + Returns the Jacobi symbol `(m / n)`. + + For any integer ``m`` and any positive odd integer ``n`` the Jacobi symbol + is defined as the product of the Legendre symbols corresponding to the + prime factors of ``n``: + + .. math :: + \genfrac(){}{}{m}{n} = + \genfrac(){}{}{m}{p^{1}}^{\alpha_1} + \genfrac(){}{}{m}{p^{2}}^{\alpha_2} + ... + \genfrac(){}{}{m}{p^{k}}^{\alpha_k} + \text{ where } n = + p_1^{\alpha_1} + p_2^{\alpha_2} + ... + p_k^{\alpha_k} + + Like the Legendre symbol, if the Jacobi symbol `\genfrac(){}{}{m}{n} = -1` + then ``m`` is a quadratic nonresidue modulo ``n``. + + But, unlike the Legendre symbol, if the Jacobi symbol + `\genfrac(){}{}{m}{n} = 1` then ``m`` may or may not be a quadratic residue + modulo ``n``. + + Examples + ======== + + >>> from sympy.functions.combinatorial.numbers import jacobi_symbol, legendre_symbol + >>> from sympy import S + >>> jacobi_symbol(45, 77) + -1 + >>> jacobi_symbol(60, 121) + 1 + + The relationship between the ``jacobi_symbol`` and ``legendre_symbol`` can + be demonstrated as follows: + + >>> L = legendre_symbol + >>> S(45).factors() + {3: 2, 5: 1} + >>> jacobi_symbol(7, 45) == L(7, 3)**2 * L(7, 5)**1 + True + + See Also + ======== + + sympy.ntheory.residue_ntheory.is_quad_residue, legendre_symbol + + """ + is_integer = True + is_prime = False + + @classmethod + def eval(cls, m, n): + if m.is_integer is False: + raise TypeError("m should be an integer") + if n.is_integer is False: + raise TypeError("n should be an integer") + if n.is_positive is False or n.is_odd is False: + raise ValueError("n should be an odd positive integer") + if m is S.One or n is S.One: + return S.One + if (m % n).is_zero is True: + return S.Zero + if m.is_Integer is True and n.is_Integer is True: + return S(jacobi(as_int(m), as_int(n))) + + +class kronecker_symbol(DefinedFunction): + r""" + Returns the Kronecker symbol `(a / n)`. + + Examples + ======== + + >>> from sympy.functions.combinatorial.numbers import kronecker_symbol + >>> kronecker_symbol(45, 77) + -1 + >>> kronecker_symbol(13, -120) + 1 + + See Also + ======== + + jacobi_symbol, legendre_symbol + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Kronecker_symbol + + """ + is_integer = True + is_prime = False + + @classmethod + def eval(cls, a, n): + if a.is_integer is False: + raise TypeError("a should be an integer") + if n.is_integer is False: + raise TypeError("n should be an integer") + if a is S.One or n is S.One: + return S.One + if a.is_Integer is True and n.is_Integer is True: + return S(kronecker(as_int(a), as_int(n))) + + +class mobius(DefinedFunction): + """ + Mobius function maps natural number to {-1, 0, 1} + + It is defined as follows: + 1) `1` if `n = 1`. + 2) `0` if `n` has a squared prime factor. + 3) `(-1)^k` if `n` is a square-free positive integer with `k` + number of prime factors. + + It is an important multiplicative function in number theory + and combinatorics. It has applications in mathematical series, + algebraic number theory and also physics (Fermion operator has very + concrete realization with Mobius Function model). + + Examples + ======== + + >>> from sympy.functions.combinatorial.numbers import mobius + >>> mobius(13*7) + 1 + >>> mobius(1) + 1 + >>> mobius(13*7*5) + -1 + >>> mobius(13**2) + 0 + + Even in the case of a symbol, if it clearly contains a squared prime factor, it will be zero. + + >>> from sympy import Symbol + >>> n = Symbol("n", integer=True, positive=True) + >>> mobius(4*n) + 0 + >>> mobius(n**2) + 0 + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/M%C3%B6bius_function + .. [2] Thomas Koshy "Elementary Number Theory with Applications" + .. [3] https://oeis.org/A008683 + + """ + is_integer = True + is_prime = False + + @classmethod + def eval(cls, n): + if n.is_integer is False: + raise TypeError("n should be an integer") + if n.is_positive is False: + raise ValueError("n should be a positive integer") + if n.is_prime is True: + return S.NegativeOne + if n is S.One: + return S.One + result = None + for m, e in (_.as_base_exp() for _ in Mul.make_args(n)): + if m.is_integer is True and m.is_positive is True and \ + e.is_integer is True and e.is_positive is True: + lt = is_lt(S.One, e) # 1 < e + if lt is True: + result = S.Zero + elif m.is_Integer is True: + factors = factorint(m) + if any(v > 1 for v in factors.values()): + result = S.Zero + elif lt is False: + s = S.NegativeOne if len(factors) % 2 else S.One + if result is None: + result = s + else: + result *= s + else: + return + return result + + +class primenu(DefinedFunction): + r""" + Calculate the number of distinct prime factors for a positive integer n. + + If n's prime factorization is: + + .. math :: + n = \prod_{i=1}^k p_i^{m_i}, + + then ``primenu(n)`` or `\nu(n)` is: + + .. math :: + \nu(n) = k. + + Examples + ======== + + >>> from sympy.functions.combinatorial.numbers import primenu + >>> primenu(1) + 0 + >>> primenu(30) + 3 + + See Also + ======== + + sympy.ntheory.factor_.factorint + + References + ========== + + .. [1] https://mathworld.wolfram.com/PrimeFactor.html + .. [2] https://oeis.org/A001221 + + """ + is_integer = True + is_nonnegative = True + + @classmethod + def eval(cls, n): + if n.is_integer is False: + raise TypeError("n should be an integer") + if n.is_positive is False: + raise ValueError("n should be a positive integer") + if n.is_prime is True: + return S.One + if n is S.One: + return S.Zero + if n.is_Integer is True: + return S(len(factorint(n))) + + +class primeomega(DefinedFunction): + r""" + Calculate the number of prime factors counting multiplicities for a + positive integer n. + + If n's prime factorization is: + + .. math :: + n = \prod_{i=1}^k p_i^{m_i}, + + then ``primeomega(n)`` or `\Omega(n)` is: + + .. math :: + \Omega(n) = \sum_{i=1}^k m_i. + + Examples + ======== + + >>> from sympy.functions.combinatorial.numbers import primeomega + >>> primeomega(1) + 0 + >>> primeomega(20) + 3 + + See Also + ======== + + sympy.ntheory.factor_.factorint + + References + ========== + + .. [1] https://mathworld.wolfram.com/PrimeFactor.html + .. [2] https://oeis.org/A001222 + + """ + is_integer = True + is_nonnegative = True + + @classmethod + def eval(cls, n): + if n.is_integer is False: + raise TypeError("n should be an integer") + if n.is_positive is False: + raise ValueError("n should be a positive integer") + if n.is_prime is True: + return S.One + if n is S.One: + return S.Zero + if n.is_Integer is True: + return S(sum(factorint(n).values())) + + +class totient(DefinedFunction): + r""" + Calculate the Euler totient function phi(n) + + ``totient(n)`` or `\phi(n)` is the number of positive integers `\leq` n + that are relatively prime to n. + + Examples + ======== + + >>> from sympy.functions.combinatorial.numbers import totient + >>> totient(1) + 1 + >>> totient(25) + 20 + >>> totient(45) == totient(5)*totient(9) + True + + See Also + ======== + + sympy.ntheory.factor_.divisor_count + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Euler%27s_totient_function + .. [2] https://mathworld.wolfram.com/TotientFunction.html + .. [3] https://oeis.org/A000010 + + """ + is_integer = True + is_positive = True + + @classmethod + def eval(cls, n): + if n.is_integer is False: + raise TypeError("n should be an integer") + if n.is_positive is False: + raise ValueError("n should be a positive integer") + if n is S.One: + return S.One + if n.is_prime is True: + return n - 1 + if isinstance(n, Dict): + return S(prod(p**(k-1)*(p-1) for p, k in n.items())) + if n.is_Integer is True: + return S(prod(p**(k-1)*(p-1) for p, k in factorint(n).items())) + + +class reduced_totient(DefinedFunction): + r""" + Calculate the Carmichael reduced totient function lambda(n) + + ``reduced_totient(n)`` or `\lambda(n)` is the smallest m > 0 such that + `k^m \equiv 1 \mod n` for all k relatively prime to n. + + Examples + ======== + + >>> from sympy.functions.combinatorial.numbers import reduced_totient + >>> reduced_totient(1) + 1 + >>> reduced_totient(8) + 2 + >>> reduced_totient(30) + 4 + + See Also + ======== + + totient + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Carmichael_function + .. [2] https://mathworld.wolfram.com/CarmichaelFunction.html + .. [3] https://oeis.org/A002322 + + """ + is_integer = True + is_positive = True + + @classmethod + def eval(cls, n): + if n.is_integer is False: + raise TypeError("n should be an integer") + if n.is_positive is False: + raise ValueError("n should be a positive integer") + if n is S.One: + return S.One + if n.is_prime is True: + return n - 1 + if isinstance(n, Dict): + t = 1 + if 2 in n: + t = (1 << (n[2] - 2)) if 2 < n[2] else n[2] + return S(lcm(int(t), *(int(p-1)*int(p)**int(k-1) for p, k in n.items() if p != 2))) + if n.is_Integer is True: + n, t = remove(int(n), 2) + if not t: + t = 1 + elif 2 < t: + t = 1 << (t - 2) + return S(lcm(t, *((p-1)*p**(k-1) for p, k in factorint(n).items()))) + + +class primepi(DefinedFunction): + r""" Represents the prime counting function pi(n) = the number + of prime numbers less than or equal to n. + + Examples + ======== + + >>> from sympy.functions.combinatorial.numbers import primepi + >>> from sympy import prime, prevprime, isprime + >>> primepi(25) + 9 + + So there are 9 primes less than or equal to 25. Is 25 prime? + + >>> isprime(25) + False + + It is not. So the first prime less than 25 must be the + 9th prime: + + >>> prevprime(25) == prime(9) + True + + See Also + ======== + + sympy.ntheory.primetest.isprime : Test if n is prime + sympy.ntheory.generate.primerange : Generate all primes in a given range + sympy.ntheory.generate.prime : Return the nth prime + + References + ========== + + .. [1] https://oeis.org/A000720 + + """ + is_integer = True + is_nonnegative = True + + @classmethod + def eval(cls, n): + if n is S.Infinity: + return S.Infinity + if n is S.NegativeInfinity: + return S.Zero + if n.is_real is False: + raise TypeError("n should be a real") + if is_lt(n, S(2)) is True: + return S.Zero + try: + n = int(n) + except TypeError: + return + return S(_primepi(n)) + + +####################################################################### +### +### Functions for enumerating partitions, permutations and combinations +### +####################################################################### + + +class _MultisetHistogram(tuple): + __slots__ = () + + +_N = -1 +_ITEMS = -2 +_M = slice(None, _ITEMS) + + +def _multiset_histogram(n): + """Return tuple used in permutation and combination counting. Input + is a dictionary giving items with counts as values or a sequence of + items (which need not be sorted). + + The data is stored in a class deriving from tuple so it is easily + recognized and so it can be converted easily to a list. + """ + if isinstance(n, dict): # item: count + if not all(isinstance(v, int) and v >= 0 for v in n.values()): + raise ValueError + tot = sum(n.values()) + items = sum(1 for k in n if n[k] > 0) + return _MultisetHistogram([n[k] for k in n if n[k] > 0] + [items, tot]) + else: + n = list(n) + s = set(n) + lens = len(s) + lenn = len(n) + if lens == lenn: + n = [1]*lenn + [lenn, lenn] + return _MultisetHistogram(n) + m = dict(zip(s, range(lens))) + d = dict(zip(range(lens), (0,)*lens)) + for i in n: + d[m[i]] += 1 + return _multiset_histogram(d) + + +def nP(n, k=None, replacement=False): + """Return the number of permutations of ``n`` items taken ``k`` at a time. + + Possible values for ``n``: + + integer - set of length ``n`` + + sequence - converted to a multiset internally + + multiset - {element: multiplicity} + + If ``k`` is None then the total of all permutations of length 0 + through the number of items represented by ``n`` will be returned. + + If ``replacement`` is True then a given item can appear more than once + in the ``k`` items. (For example, for 'ab' permutations of 2 would + include 'aa', 'ab', 'ba' and 'bb'.) The multiplicity of elements in + ``n`` is ignored when ``replacement`` is True but the total number + of elements is considered since no element can appear more times than + the number of elements in ``n``. + + Examples + ======== + + >>> from sympy.functions.combinatorial.numbers import nP + >>> from sympy.utilities.iterables import multiset_permutations, multiset + >>> nP(3, 2) + 6 + >>> nP('abc', 2) == nP(multiset('abc'), 2) == 6 + True + >>> nP('aab', 2) + 3 + >>> nP([1, 2, 2], 2) + 3 + >>> [nP(3, i) for i in range(4)] + [1, 3, 6, 6] + >>> nP(3) == sum(_) + True + + When ``replacement`` is True, each item can have multiplicity + equal to the length represented by ``n``: + + >>> nP('aabc', replacement=True) + 121 + >>> [len(list(multiset_permutations('aaaabbbbcccc', i))) for i in range(5)] + [1, 3, 9, 27, 81] + >>> sum(_) + 121 + + See Also + ======== + sympy.utilities.iterables.multiset_permutations + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Permutation + + """ + try: + n = as_int(n) + except ValueError: + return Integer(_nP(_multiset_histogram(n), k, replacement)) + return Integer(_nP(n, k, replacement)) + + +@cacheit +def _nP(n, k=None, replacement=False): + + if k == 0: + return 1 + if isinstance(n, SYMPY_INTS): # n different items + # assert n >= 0 + if k is None: + return sum(_nP(n, i, replacement) for i in range(n + 1)) + elif replacement: + return n**k + elif k > n: + return 0 + elif k == n: + return factorial(k) + elif k == 1: + return n + else: + # assert k >= 0 + return _product(n - k + 1, n) + elif isinstance(n, _MultisetHistogram): + if k is None: + return sum(_nP(n, i, replacement) for i in range(n[_N] + 1)) + elif replacement: + return n[_ITEMS]**k + elif k == n[_N]: + return factorial(k)/prod([factorial(i) for i in n[_M] if i > 1]) + elif k > n[_N]: + return 0 + elif k == 1: + return n[_ITEMS] + else: + # assert k >= 0 + tot = 0 + n = list(n) + for i in range(len(n[_M])): + if not n[i]: + continue + n[_N] -= 1 + if n[i] == 1: + n[i] = 0 + n[_ITEMS] -= 1 + tot += _nP(_MultisetHistogram(n), k - 1) + n[_ITEMS] += 1 + n[i] = 1 + else: + n[i] -= 1 + tot += _nP(_MultisetHistogram(n), k - 1) + n[i] += 1 + n[_N] += 1 + return tot + + +@cacheit +def _AOP_product(n): + """for n = (m1, m2, .., mk) return the coefficients of the polynomial, + prod(sum(x**i for i in range(nj + 1)) for nj in n); i.e. the coefficients + of the product of AOPs (all-one polynomials) or order given in n. The + resulting coefficient corresponding to x**r is the number of r-length + combinations of sum(n) elements with multiplicities given in n. + The coefficients are given as a default dictionary (so if a query is made + for a key that is not present, 0 will be returned). + + Examples + ======== + + >>> from sympy.functions.combinatorial.numbers import _AOP_product + >>> from sympy.abc import x + >>> n = (2, 2, 3) # e.g. aabbccc + >>> prod = ((x**2 + x + 1)*(x**2 + x + 1)*(x**3 + x**2 + x + 1)).expand() + >>> c = _AOP_product(n); dict(c) + {0: 1, 1: 3, 2: 6, 3: 8, 4: 8, 5: 6, 6: 3, 7: 1} + >>> [c[i] for i in range(8)] == [prod.coeff(x, i) for i in range(8)] + True + + The generating poly used here is the same as that listed in + https://tinyurl.com/cep849r, but in a refactored form. + + """ + + n = list(n) + ord = sum(n) + need = (ord + 2)//2 + rv = [1]*(n.pop() + 1) + rv.extend((0,) * (need - len(rv))) + rv = rv[:need] + while n: + ni = n.pop() + N = ni + 1 + was = rv[:] + for i in range(1, min(N, len(rv))): + rv[i] += rv[i - 1] + for i in range(N, need): + rv[i] += rv[i - 1] - was[i - N] + rev = list(reversed(rv)) + if ord % 2: + rv = rv + rev + else: + rv[-1:] = rev + d = defaultdict(int) + for i, r in enumerate(rv): + d[i] = r + return d + + +def nC(n, k=None, replacement=False): + """Return the number of combinations of ``n`` items taken ``k`` at a time. + + Possible values for ``n``: + + integer - set of length ``n`` + + sequence - converted to a multiset internally + + multiset - {element: multiplicity} + + If ``k`` is None then the total of all combinations of length 0 + through the number of items represented in ``n`` will be returned. + + If ``replacement`` is True then a given item can appear more than once + in the ``k`` items. (For example, for 'ab' sets of 2 would include 'aa', + 'ab', and 'bb'.) The multiplicity of elements in ``n`` is ignored when + ``replacement`` is True but the total number of elements is considered + since no element can appear more times than the number of elements in + ``n``. + + Examples + ======== + + >>> from sympy.functions.combinatorial.numbers import nC + >>> from sympy.utilities.iterables import multiset_combinations + >>> nC(3, 2) + 3 + >>> nC('abc', 2) + 3 + >>> nC('aab', 2) + 2 + + When ``replacement`` is True, each item can have multiplicity + equal to the length represented by ``n``: + + >>> nC('aabc', replacement=True) + 35 + >>> [len(list(multiset_combinations('aaaabbbbcccc', i))) for i in range(5)] + [1, 3, 6, 10, 15] + >>> sum(_) + 35 + + If there are ``k`` items with multiplicities ``m_1, m_2, ..., m_k`` + then the total of all combinations of length 0 through ``k`` is the + product, ``(m_1 + 1)*(m_2 + 1)*...*(m_k + 1)``. When the multiplicity + of each item is 1 (i.e., k unique items) then there are 2**k + combinations. For example, if there are 4 unique items, the total number + of combinations is 16: + + >>> sum(nC(4, i) for i in range(5)) + 16 + + See Also + ======== + + sympy.utilities.iterables.multiset_combinations + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Combination + .. [2] https://tinyurl.com/cep849r + + """ + + if isinstance(n, SYMPY_INTS): + if k is None: + if not replacement: + return 2**n + return sum(nC(n, i, replacement) for i in range(n + 1)) + if k < 0: + raise ValueError("k cannot be negative") + if replacement: + return binomial(n + k - 1, k) + return binomial(n, k) + if isinstance(n, _MultisetHistogram): + N = n[_N] + if k is None: + if not replacement: + return prod(m + 1 for m in n[_M]) + return sum(nC(n, i, replacement) for i in range(N + 1)) + elif replacement: + return nC(n[_ITEMS], k, replacement) + # assert k >= 0 + elif k in (1, N - 1): + return n[_ITEMS] + elif k in (0, N): + return 1 + return _AOP_product(tuple(n[_M]))[k] + else: + return nC(_multiset_histogram(n), k, replacement) + + +def _eval_stirling1(n, k): + if n == k == 0: + return S.One + if 0 in (n, k): + return S.Zero + + # some special values + if n == k: + return S.One + elif k == n - 1: + return binomial(n, 2) + elif k == n - 2: + return (3*n - 1)*binomial(n, 3)/4 + elif k == n - 3: + return binomial(n, 2)*binomial(n, 4) + + return _stirling1(n, k) + + +@cacheit +def _stirling1(n, k): + row = [0, 1]+[0]*(k-1) # for n = 1 + for i in range(2, n+1): + for j in range(min(k,i), 0, -1): + row[j] = (i-1) * row[j] + row[j-1] + return Integer(row[k]) + + +def _eval_stirling2(n, k): + if n == k == 0: + return S.One + if 0 in (n, k): + return S.Zero + + # some special values + if n == k: + return S.One + elif k == n - 1: + return binomial(n, 2) + elif k == 1: + return S.One + elif k == 2: + return Integer(2**(n - 1) - 1) + + return _stirling2(n, k) + + +@cacheit +def _stirling2(n, k): + row = [0, 1]+[0]*(k-1) # for n = 1 + for i in range(2, n+1): + for j in range(min(k,i), 0, -1): + row[j] = j * row[j] + row[j-1] + return Integer(row[k]) + + +def stirling(n, k, d=None, kind=2, signed=False): + r"""Return Stirling number $S(n, k)$ of the first or second (default) kind. + + The sum of all Stirling numbers of the second kind for $k = 1$ + through $n$ is ``bell(n)``. The recurrence relationship for these numbers + is: + + .. math :: {0 \brace 0} = 1; {n \brace 0} = {0 \brace k} = 0; + + .. math :: {{n+1} \brace k} = j {n \brace k} + {n \brace {k-1}} + + where $j$ is: + $n$ for Stirling numbers of the first kind, + $-n$ for signed Stirling numbers of the first kind, + $k$ for Stirling numbers of the second kind. + + The first kind of Stirling number counts the number of permutations of + ``n`` distinct items that have ``k`` cycles; the second kind counts the + ways in which ``n`` distinct items can be partitioned into ``k`` parts. + If ``d`` is given, the "reduced Stirling number of the second kind" is + returned: $S^{d}(n, k) = S(n - d + 1, k - d + 1)$ with $n \ge k \ge d$. + (This counts the ways to partition $n$ consecutive integers into $k$ + groups with no pairwise difference less than $d$. See example below.) + + To obtain the signed Stirling numbers of the first kind, use keyword + ``signed=True``. Using this keyword automatically sets ``kind`` to 1. + + Examples + ======== + + >>> from sympy.functions.combinatorial.numbers import stirling, bell + >>> from sympy.combinatorics import Permutation + >>> from sympy.utilities.iterables import multiset_partitions, permutations + + First kind (unsigned by default): + + >>> [stirling(6, i, kind=1) for i in range(7)] + [0, 120, 274, 225, 85, 15, 1] + >>> perms = list(permutations(range(4))) + >>> [sum(Permutation(p).cycles == i for p in perms) for i in range(5)] + [0, 6, 11, 6, 1] + >>> [stirling(4, i, kind=1) for i in range(5)] + [0, 6, 11, 6, 1] + + First kind (signed): + + >>> [stirling(4, i, signed=True) for i in range(5)] + [0, -6, 11, -6, 1] + + Second kind: + + >>> [stirling(10, i) for i in range(12)] + [0, 1, 511, 9330, 34105, 42525, 22827, 5880, 750, 45, 1, 0] + >>> sum(_) == bell(10) + True + >>> len(list(multiset_partitions(range(4), 2))) == stirling(4, 2) + True + + Reduced second kind: + + >>> from sympy import subsets, oo + >>> def delta(p): + ... if len(p) == 1: + ... return oo + ... return min(abs(i[0] - i[1]) for i in subsets(p, 2)) + >>> parts = multiset_partitions(range(5), 3) + >>> d = 2 + >>> sum(1 for p in parts if all(delta(i) >= d for i in p)) + 7 + >>> stirling(5, 3, 2) + 7 + + See Also + ======== + sympy.utilities.iterables.multiset_partitions + + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Stirling_numbers_of_the_first_kind + .. [2] https://en.wikipedia.org/wiki/Stirling_numbers_of_the_second_kind + + """ + # TODO: make this a class like bell() + + n = as_int(n) + k = as_int(k) + if n < 0: + raise ValueError('n must be nonnegative') + if k > n: + return S.Zero + if d: + # assert k >= d + # kind is ignored -- only kind=2 is supported + return _eval_stirling2(n - d + 1, k - d + 1) + elif signed: + # kind is ignored -- only kind=1 is supported + return S.NegativeOne**(n - k)*_eval_stirling1(n, k) + + if kind == 1: + return _eval_stirling1(n, k) + elif kind == 2: + return _eval_stirling2(n, k) + else: + raise ValueError('kind must be 1 or 2, not %s' % k) + + +@cacheit +def _nT(n, k): + """Return the partitions of ``n`` items into ``k`` parts. This + is used by ``nT`` for the case when ``n`` is an integer.""" + # really quick exits + if k > n or k < 0: + return 0 + if k in (1, n): + return 1 + if k == 0: + return 0 + # exits that could be done below but this is quicker + if k == 2: + return n//2 + d = n - k + if d <= 3: + return d + # quick exit + if 3*k >= n: # or, equivalently, 2*k >= d + # all the information needed in this case + # will be in the cache needed to calculate + # partition(d), so... + # update cache + tot = _partition_rec(d) + # and correct for values not needed + if d - k > 0: + tot -= sum(_partition_rec.fetch_item(slice(d - k))) + return tot + # regular exit + # nT(n, k) = Sum(nT(n - k, m), (m, 1, k)); + # calculate needed nT(i, j) values + p = [1]*d + for i in range(2, k + 1): + for m in range(i + 1, d): + p[m] += p[m - i] + d -= 1 + # if p[0] were appended to the end of p then the last + # k values of p are the nT(n, j) values for 0 < j < k in reverse + # order p[-1] = nT(n, 1), p[-2] = nT(n, 2), etc.... Instead of + # putting the 1 from p[0] there, however, it is simply added to + # the sum below which is valid for 1 < k <= n//2 + return (1 + sum(p[1 - k:])) + + +def nT(n, k=None): + """Return the number of ``k``-sized partitions of ``n`` items. + + Possible values for ``n``: + + integer - ``n`` identical items + + sequence - converted to a multiset internally + + multiset - {element: multiplicity} + + Note: the convention for ``nT`` is different than that of ``nC`` and + ``nP`` in that + here an integer indicates ``n`` *identical* items instead of a set of + length ``n``; this is in keeping with the ``partitions`` function which + treats its integer-``n`` input like a list of ``n`` 1s. One can use + ``range(n)`` for ``n`` to indicate ``n`` distinct items. + + If ``k`` is None then the total number of ways to partition the elements + represented in ``n`` will be returned. + + Examples + ======== + + >>> from sympy.functions.combinatorial.numbers import nT + + Partitions of the given multiset: + + >>> [nT('aabbc', i) for i in range(1, 7)] + [1, 8, 11, 5, 1, 0] + >>> nT('aabbc') == sum(_) + True + + >>> [nT("mississippi", i) for i in range(1, 12)] + [1, 74, 609, 1521, 1768, 1224, 579, 197, 50, 9, 1] + + Partitions when all items are identical: + + >>> [nT(5, i) for i in range(1, 6)] + [1, 2, 2, 1, 1] + >>> nT('1'*5) == sum(_) + True + + When all items are different: + + >>> [nT(range(5), i) for i in range(1, 6)] + [1, 15, 25, 10, 1] + >>> nT(range(5)) == sum(_) + True + + Partitions of an integer expressed as a sum of positive integers: + + >>> from sympy import partition + >>> partition(4) + 5 + >>> nT(4, 1) + nT(4, 2) + nT(4, 3) + nT(4, 4) + 5 + >>> nT('1'*4) + 5 + + See Also + ======== + sympy.utilities.iterables.partitions + sympy.utilities.iterables.multiset_partitions + sympy.functions.combinatorial.numbers.partition + + References + ========== + + .. [1] https://web.archive.org/web/20210507012732/https://teaching.csse.uwa.edu.au/units/CITS7209/partition.pdf + + """ + + if isinstance(n, SYMPY_INTS): + # n identical items + if k is None: + return partition(n) + if isinstance(k, SYMPY_INTS): + n = as_int(n) + k = as_int(k) + return Integer(_nT(n, k)) + if not isinstance(n, _MultisetHistogram): + try: + # if n contains hashable items there is some + # quick handling that can be done + u = len(set(n)) + if u <= 1: + return nT(len(n), k) + elif u == len(n): + n = range(u) + raise TypeError + except TypeError: + n = _multiset_histogram(n) + N = n[_N] + if k is None and N == 1: + return 1 + if k in (1, N): + return 1 + if k == 2 or N == 2 and k is None: + m, r = divmod(N, 2) + rv = sum(nC(n, i) for i in range(1, m + 1)) + if not r: + rv -= nC(n, m)//2 + if k is None: + rv += 1 # for k == 1 + return rv + if N == n[_ITEMS]: + # all distinct + if k is None: + return bell(N) + return stirling(N, k) + m = MultisetPartitionTraverser() + if k is None: + return m.count_partitions(n[_M]) + # MultisetPartitionTraverser does not have a range-limited count + # method, so need to enumerate and count + tot = 0 + for discard in m.enum_range(n[_M], k-1, k): + tot += 1 + return tot + + +#-----------------------------------------------------------------------------# +# # +# Motzkin numbers # +# # +#-----------------------------------------------------------------------------# + + +class motzkin(DefinedFunction): + """ + The nth Motzkin number is the number + of ways of drawing non-intersecting chords + between n points on a circle (not necessarily touching + every point by a chord). The Motzkin numbers are named + after Theodore Motzkin and have diverse applications + in geometry, combinatorics and number theory. + + Motzkin numbers are the integer sequence defined by the + initial terms `M_0 = 1`, `M_1 = 1` and the two-term recurrence relation + `M_n = \frac{2*n + 1}{n + 2} * M_{n-1} + \frac{3n - 3}{n + 2} * M_{n-2}`. + + + Examples + ======== + + >>> from sympy import motzkin + + >>> motzkin.is_motzkin(5) + False + >>> motzkin.find_motzkin_numbers_in_range(2,300) + [2, 4, 9, 21, 51, 127] + >>> motzkin.find_motzkin_numbers_in_range(2,900) + [2, 4, 9, 21, 51, 127, 323, 835] + >>> motzkin.find_first_n_motzkins(10) + [1, 1, 2, 4, 9, 21, 51, 127, 323, 835] + + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Motzkin_number + .. [2] https://mathworld.wolfram.com/MotzkinNumber.html + + """ + + @staticmethod + def is_motzkin(n): + try: + n = as_int(n) + except ValueError: + return False + if n > 0: + if n in (1, 2): + return True + + tn1 = 1 + tn = 2 + i = 3 + while tn < n: + a = ((2*i + 1)*tn + (3*i - 3)*tn1)/(i + 2) + i += 1 + tn1 = tn + tn = a + + if tn == n: + return True + else: + return False + + else: + return False + + @staticmethod + def find_motzkin_numbers_in_range(x, y): + if 0 <= x <= y: + motzkins = [] + if x <= 1 <= y: + motzkins.append(1) + tn1 = 1 + tn = 2 + i = 3 + while tn <= y: + if tn >= x: + motzkins.append(tn) + a = ((2*i + 1)*tn + (3*i - 3)*tn1)/(i + 2) + i += 1 + tn1 = tn + tn = int(a) + + return motzkins + + else: + raise ValueError('The provided range is not valid. This condition should satisfy x <= y') + + @staticmethod + def find_first_n_motzkins(n): + try: + n = as_int(n) + except ValueError: + raise ValueError('The provided number must be a positive integer') + if n < 0: + raise ValueError('The provided number must be a positive integer') + motzkins = [1] + if n >= 1: + motzkins.append(1) + tn1 = 1 + tn = 2 + i = 3 + while i <= n: + motzkins.append(tn) + a = ((2*i + 1)*tn + (3*i - 3)*tn1)/(i + 2) + i += 1 + tn1 = tn + tn = int(a) + + return motzkins + + @staticmethod + @recurrence_memo([S.One, S.One]) + def _motzkin(n, prev): + return ((2*n + 1)*prev[-1] + (3*n - 3)*prev[-2]) // (n + 2) + + @classmethod + def eval(cls, n): + try: + n = as_int(n) + except ValueError: + raise ValueError('The provided number must be a positive integer') + if n < 0: + raise ValueError('The provided number must be a positive integer') + return Integer(cls._motzkin(n - 1)) + + +def nD(i=None, brute=None, *, n=None, m=None): + """return the number of derangements for: ``n`` unique items, ``i`` + items (as a sequence or multiset), or multiplicities, ``m`` given + as a sequence or multiset. + + Examples + ======== + + >>> from sympy.utilities.iterables import generate_derangements as enum + >>> from sympy.functions.combinatorial.numbers import nD + + A derangement ``d`` of sequence ``s`` has all ``d[i] != s[i]``: + + >>> set([''.join(i) for i in enum('abc')]) + {'bca', 'cab'} + >>> nD('abc') + 2 + + Input as iterable or dictionary (multiset form) is accepted: + + >>> assert nD([1, 2, 2, 3, 3, 3]) == nD({1: 1, 2: 2, 3: 3}) + + By default, a brute-force enumeration and count of multiset permutations + is only done if there are fewer than 9 elements. There may be cases when + there is high multiplicity with few unique elements that will benefit + from a brute-force enumeration, too. For this reason, the `brute` + keyword (default None) is provided. When False, the brute-force + enumeration will never be used. When True, it will always be used. + + >>> nD('1111222233', brute=True) + 44 + + For convenience, one may specify ``n`` distinct items using the + ``n`` keyword: + + >>> assert nD(n=3) == nD('abc') == 2 + + Since the number of derangments depends on the multiplicity of the + elements and not the elements themselves, it may be more convenient + to give a list or multiset of multiplicities using keyword ``m``: + + >>> assert nD('abc') == nD(m=(1,1,1)) == nD(m={1:3}) == 2 + + """ + from sympy.integrals.integrals import integrate + from sympy.functions.special.polynomials import laguerre + from sympy.abc import x + def ok(x): + if not isinstance(x, SYMPY_INTS): + raise TypeError('expecting integer values') + if x < 0: + raise ValueError('value must not be negative') + return True + + if (i, n, m).count(None) != 2: + raise ValueError('enter only 1 of i, n, or m') + if i is not None: + if isinstance(i, SYMPY_INTS): + raise TypeError('items must be a list or dictionary') + if not i: + return S.Zero + if type(i) is not dict: + s = list(i) + ms = multiset(s) + elif type(i) is dict: + all(ok(_) for _ in i.values()) + ms = {k: v for k, v in i.items() if v} + s = None + if not ms: + return S.Zero + N = sum(ms.values()) + counts = multiset(ms.values()) + nkey = len(ms) + elif n is not None: + ok(n) + if not n: + return S.Zero + return subfactorial(n) + elif m is not None: + if isinstance(m, dict): + all(ok(i) and ok(j) for i, j in m.items()) + counts = {k: v for k, v in m.items() if k*v} + elif iterable(m) or isinstance(m, str): + m = list(m) + all(ok(i) for i in m) + counts = multiset([i for i in m if i]) + else: + raise TypeError('expecting iterable') + if not counts: + return S.Zero + N = sum(k*v for k, v in counts.items()) + nkey = sum(counts.values()) + s = None + big = int(max(counts)) + if big == 1: # no repetition + return subfactorial(nkey) + nval = len(counts) + if big*2 > N: + return S.Zero + if big*2 == N: + if nkey == 2 and nval == 1: + return S.One # aaabbb + if nkey - 1 == big: # one element repeated + return factorial(big) # e.g. abc part of abcddd + if N < 9 and brute is None or brute: + # for all possibilities, this was found to be faster + if s is None: + s = [] + i = 0 + for m, v in counts.items(): + for j in range(v): + s.extend([i]*m) + i += 1 + return Integer(sum(1 for i in multiset_derangements(s))) + from sympy.functions.elementary.exponential import exp + return Integer(abs(integrate(exp(-x)*Mul(*[ + laguerre(i, x)**m for i, m in counts.items()]), (x, 0, oo)))) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..08af64da0c45b9dcd3a9155635212cb7c4c704bb Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/tests/__pycache__/test_comb_factorials.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/tests/__pycache__/test_comb_factorials.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..37bda45049ed6498d8969abb57b2dee2fbff8416 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/tests/__pycache__/test_comb_factorials.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/tests/test_comb_factorials.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/tests/test_comb_factorials.py new file mode 100644 index 0000000000000000000000000000000000000000..6e3986c56736cccec0b3370007e047a1f38f06d1 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/tests/test_comb_factorials.py @@ -0,0 +1,653 @@ +from sympy.concrete.products import Product +from sympy.core.function import expand_func +from sympy.core.mod import Mod +from sympy.core.mul import Mul +from sympy.core import EulerGamma +from sympy.core.numbers import (Float, I, Rational, nan, oo, pi, zoo) +from sympy.core.relational import Eq +from sympy.core.singleton import S +from sympy.core.symbol import (Dummy, Symbol, symbols) +from sympy.functions.combinatorial.factorials import (ff, rf, binomial, factorial, factorial2) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.piecewise import Piecewise +from sympy.functions.special.gamma_functions import (gamma, polygamma) +from sympy.polys.polytools import Poly +from sympy.series.order import O +from sympy.simplify.simplify import simplify +from sympy.core.expr import unchanged +from sympy.core.function import ArgumentIndexError +from sympy.functions.combinatorial.factorials import subfactorial +from sympy.functions.special.gamma_functions import uppergamma +from sympy.testing.pytest import XFAIL, raises, slow + +#Solves and Fixes Issue #10388 - This is the updated test for the same solved issue + +def test_rf_eval_apply(): + x, y = symbols('x,y') + n, k = symbols('n k', integer=True) + m = Symbol('m', integer=True, nonnegative=True) + + assert rf(nan, y) is nan + assert rf(x, nan) is nan + + assert unchanged(rf, x, y) + + assert rf(oo, 0) == 1 + assert rf(-oo, 0) == 1 + + assert rf(oo, 6) is oo + assert rf(-oo, 7) is -oo + assert rf(-oo, 6) is oo + + assert rf(oo, -6) is oo + assert rf(-oo, -7) is oo + + assert rf(-1, pi) == 0 + assert rf(-5, 1 + I) == 0 + + assert unchanged(rf, -3, k) + assert unchanged(rf, x, Symbol('k', integer=False)) + assert rf(-3, Symbol('k', integer=False)) == 0 + assert rf(Symbol('x', negative=True, integer=True), Symbol('k', integer=False)) == 0 + + assert rf(x, 0) == 1 + assert rf(x, 1) == x + assert rf(x, 2) == x*(x + 1) + assert rf(x, 3) == x*(x + 1)*(x + 2) + assert rf(x, 5) == x*(x + 1)*(x + 2)*(x + 3)*(x + 4) + + assert rf(x, -1) == 1/(x - 1) + assert rf(x, -2) == 1/((x - 1)*(x - 2)) + assert rf(x, -3) == 1/((x - 1)*(x - 2)*(x - 3)) + + assert rf(1, 100) == factorial(100) + + assert rf(x**2 + 3*x, 2) == (x**2 + 3*x)*(x**2 + 3*x + 1) + assert isinstance(rf(x**2 + 3*x, 2), Mul) + assert rf(x**3 + x, -2) == 1/((x**3 + x - 1)*(x**3 + x - 2)) + + assert rf(Poly(x**2 + 3*x, x), 2) == Poly(x**4 + 8*x**3 + 19*x**2 + 12*x, x) + assert isinstance(rf(Poly(x**2 + 3*x, x), 2), Poly) + raises(ValueError, lambda: rf(Poly(x**2 + 3*x, x, y), 2)) + assert rf(Poly(x**3 + x, x), -2) == 1/(x**6 - 9*x**5 + 35*x**4 - 75*x**3 + 94*x**2 - 66*x + 20) + raises(ValueError, lambda: rf(Poly(x**3 + x, x, y), -2)) + + assert rf(x, m).is_integer is None + assert rf(n, k).is_integer is None + assert rf(n, m).is_integer is True + assert rf(n, k + pi).is_integer is False + assert rf(n, m + pi).is_integer is False + assert rf(pi, m).is_integer is False + + def check(x, k, o, n): + a, b = Dummy(), Dummy() + r = lambda x, k: o(a, b).rewrite(n).subs({a:x,b:k}) + for i in range(-5,5): + for j in range(-5,5): + assert o(i, j) == r(i, j), (o, n, i, j) + check(x, k, rf, ff) + check(x, k, rf, binomial) + check(n, k, rf, factorial) + check(x, y, rf, factorial) + check(x, y, rf, binomial) + + assert rf(x, k).rewrite(ff) == ff(x + k - 1, k) + assert rf(x, k).rewrite(gamma) == Piecewise( + (gamma(k + x)/gamma(x), x > 0), + ((-1)**k*gamma(1 - x)/gamma(-k - x + 1), True)) + assert rf(5, k).rewrite(gamma) == gamma(k + 5)/24 + assert rf(x, k).rewrite(binomial) == factorial(k)*binomial(x + k - 1, k) + assert rf(n, k).rewrite(factorial) == Piecewise( + (factorial(k + n - 1)/factorial(n - 1), n > 0), + ((-1)**k*factorial(-n)/factorial(-k - n), True)) + assert rf(5, k).rewrite(factorial) == factorial(k + 4)/24 + assert rf(x, y).rewrite(factorial) == rf(x, y) + assert rf(x, y).rewrite(binomial) == rf(x, y) + + import random + from mpmath import rf as mpmath_rf + for i in range(100): + x = -500 + 500 * random.random() + k = -500 + 500 * random.random() + assert (abs(mpmath_rf(x, k) - rf(x, k)) < 10**(-15)) + + +def test_ff_eval_apply(): + x, y = symbols('x,y') + n, k = symbols('n k', integer=True) + m = Symbol('m', integer=True, nonnegative=True) + + assert ff(nan, y) is nan + assert ff(x, nan) is nan + + assert unchanged(ff, x, y) + + assert ff(oo, 0) == 1 + assert ff(-oo, 0) == 1 + + assert ff(oo, 6) is oo + assert ff(-oo, 7) is -oo + assert ff(-oo, 6) is oo + + assert ff(oo, -6) is oo + assert ff(-oo, -7) is oo + + assert ff(x, 0) == 1 + assert ff(x, 1) == x + assert ff(x, 2) == x*(x - 1) + assert ff(x, 3) == x*(x - 1)*(x - 2) + assert ff(x, 5) == x*(x - 1)*(x - 2)*(x - 3)*(x - 4) + + assert ff(x, -1) == 1/(x + 1) + assert ff(x, -2) == 1/((x + 1)*(x + 2)) + assert ff(x, -3) == 1/((x + 1)*(x + 2)*(x + 3)) + + assert ff(100, 100) == factorial(100) + + assert ff(2*x**2 - 5*x, 2) == (2*x**2 - 5*x)*(2*x**2 - 5*x - 1) + assert isinstance(ff(2*x**2 - 5*x, 2), Mul) + assert ff(x**2 + 3*x, -2) == 1/((x**2 + 3*x + 1)*(x**2 + 3*x + 2)) + + assert ff(Poly(2*x**2 - 5*x, x), 2) == Poly(4*x**4 - 28*x**3 + 59*x**2 - 35*x, x) + assert isinstance(ff(Poly(2*x**2 - 5*x, x), 2), Poly) + raises(ValueError, lambda: ff(Poly(2*x**2 - 5*x, x, y), 2)) + assert ff(Poly(x**2 + 3*x, x), -2) == 1/(x**4 + 12*x**3 + 49*x**2 + 78*x + 40) + raises(ValueError, lambda: ff(Poly(x**2 + 3*x, x, y), -2)) + + + assert ff(x, m).is_integer is None + assert ff(n, k).is_integer is None + assert ff(n, m).is_integer is True + assert ff(n, k + pi).is_integer is False + assert ff(n, m + pi).is_integer is False + assert ff(pi, m).is_integer is False + + assert isinstance(ff(x, x), ff) + assert ff(n, n) == factorial(n) + + def check(x, k, o, n): + a, b = Dummy(), Dummy() + r = lambda x, k: o(a, b).rewrite(n).subs({a:x,b:k}) + for i in range(-5,5): + for j in range(-5,5): + assert o(i, j) == r(i, j), (o, n) + check(x, k, ff, rf) + check(x, k, ff, gamma) + check(n, k, ff, factorial) + check(x, k, ff, binomial) + check(x, y, ff, factorial) + check(x, y, ff, binomial) + + assert ff(x, k).rewrite(rf) == rf(x - k + 1, k) + assert ff(x, k).rewrite(gamma) == Piecewise( + (gamma(x + 1)/gamma(-k + x + 1), x >= 0), + ((-1)**k*gamma(k - x)/gamma(-x), True)) + assert ff(5, k).rewrite(gamma) == 120/gamma(6 - k) + assert ff(n, k).rewrite(factorial) == Piecewise( + (factorial(n)/factorial(-k + n), n >= 0), + ((-1)**k*factorial(k - n - 1)/factorial(-n - 1), True)) + assert ff(5, k).rewrite(factorial) == 120/factorial(5 - k) + assert ff(x, k).rewrite(binomial) == factorial(k) * binomial(x, k) + assert ff(x, y).rewrite(factorial) == ff(x, y) + assert ff(x, y).rewrite(binomial) == ff(x, y) + + import random + from mpmath import ff as mpmath_ff + for i in range(100): + x = -500 + 500 * random.random() + k = -500 + 500 * random.random() + a = mpmath_ff(x, k) + b = ff(x, k) + assert (abs(a - b) < abs(a) * 10**(-15)) + + +def test_rf_ff_eval_hiprec(): + maple = Float('6.9109401292234329956525265438452') + us = ff(18, Rational(2, 3)).evalf(32) + assert abs(us - maple)/us < 1e-31 + + maple = Float('6.8261540131125511557924466355367') + us = rf(18, Rational(2, 3)).evalf(32) + assert abs(us - maple)/us < 1e-31 + + maple = Float('34.007346127440197150854651814225') + us = rf(Float('4.4', 32), Float('2.2', 32)) + assert abs(us - maple)/us < 1e-31 + + +def test_rf_lambdify_mpmath(): + from sympy.utilities.lambdify import lambdify + x, y = symbols('x,y') + f = lambdify((x,y), rf(x, y), 'mpmath') + maple = Float('34.007346127440197') + us = f(4.4, 2.2) + assert abs(us - maple)/us < 1e-15 + + +def test_factorial(): + x = Symbol('x') + n = Symbol('n', integer=True) + k = Symbol('k', integer=True, nonnegative=True) + r = Symbol('r', integer=False) + s = Symbol('s', integer=False, negative=True) + t = Symbol('t', nonnegative=True) + u = Symbol('u', noninteger=True) + + assert factorial(-2) is zoo + assert factorial(0) == 1 + assert factorial(7) == 5040 + assert factorial(19) == 121645100408832000 + assert factorial(31) == 8222838654177922817725562880000000 + assert factorial(n).func == factorial + assert factorial(2*n).func == factorial + + assert factorial(x).is_integer is None + assert factorial(n).is_integer is None + assert factorial(k).is_integer + assert factorial(r).is_integer is None + + assert factorial(n).is_positive is None + assert factorial(k).is_positive + + assert factorial(x).is_real is None + assert factorial(n).is_real is None + assert factorial(k).is_real is True + assert factorial(r).is_real is None + assert factorial(s).is_real is True + assert factorial(t).is_real is True + assert factorial(u).is_real is True + + assert factorial(x).is_composite is None + assert factorial(n).is_composite is None + assert factorial(k).is_composite is None + assert factorial(k + 3).is_composite is True + assert factorial(r).is_composite is None + assert factorial(s).is_composite is None + assert factorial(t).is_composite is None + assert factorial(u).is_composite is None + + assert factorial(oo) is oo + + +def test_factorial_Mod(): + pr = Symbol('pr', prime=True) + p, q = 10**9 + 9, 10**9 + 33 # prime modulo + r, s = 10**7 + 5, 33333333 # composite modulo + assert Mod(factorial(pr - 1), pr) == pr - 1 + assert Mod(factorial(pr - 1), -pr) == -1 + assert Mod(factorial(r - 1, evaluate=False), r) == 0 + assert Mod(factorial(s - 1, evaluate=False), s) == 0 + assert Mod(factorial(p - 1, evaluate=False), p) == p - 1 + assert Mod(factorial(q - 1, evaluate=False), q) == q - 1 + assert Mod(factorial(p - 50, evaluate=False), p) == 854928834 + assert Mod(factorial(q - 1800, evaluate=False), q) == 905504050 + assert Mod(factorial(153, evaluate=False), r) == Mod(factorial(153), r) + assert Mod(factorial(255, evaluate=False), s) == Mod(factorial(255), s) + assert Mod(factorial(4, evaluate=False), 3) == S.Zero + assert Mod(factorial(5, evaluate=False), 6) == S.Zero + + +def test_factorial_diff(): + n = Symbol('n', integer=True) + + assert factorial(n).diff(n) == \ + gamma(1 + n)*polygamma(0, 1 + n) + assert factorial(n**2).diff(n) == \ + 2*n*gamma(1 + n**2)*polygamma(0, 1 + n**2) + raises(ArgumentIndexError, lambda: factorial(n**2).fdiff(2)) + + +def test_factorial_series(): + n = Symbol('n', integer=True) + + assert factorial(n).series(n, 0, 3) == \ + 1 - n*EulerGamma + n**2*(EulerGamma**2/2 + pi**2/12) + O(n**3) + + +def test_factorial_rewrite(): + n = Symbol('n', integer=True) + k = Symbol('k', integer=True, nonnegative=True) + + assert factorial(n).rewrite(gamma) == gamma(n + 1) + _i = Dummy('i') + assert factorial(k).rewrite(Product).dummy_eq(Product(_i, (_i, 1, k))) + assert factorial(n).rewrite(Product) == factorial(n) + + +def test_factorial2(): + n = Symbol('n', integer=True) + + assert factorial2(-1) == 1 + assert factorial2(0) == 1 + assert factorial2(7) == 105 + assert factorial2(8) == 384 + + # The following is exhaustive + tt = Symbol('tt', integer=True, nonnegative=True) + tte = Symbol('tte', even=True, nonnegative=True) + tpe = Symbol('tpe', even=True, positive=True) + tto = Symbol('tto', odd=True, nonnegative=True) + tf = Symbol('tf', integer=True, nonnegative=False) + tfe = Symbol('tfe', even=True, nonnegative=False) + tfo = Symbol('tfo', odd=True, nonnegative=False) + ft = Symbol('ft', integer=False, nonnegative=True) + ff = Symbol('ff', integer=False, nonnegative=False) + fn = Symbol('fn', integer=False) + nt = Symbol('nt', nonnegative=True) + nf = Symbol('nf', nonnegative=False) + nn = Symbol('nn') + z = Symbol('z', zero=True) + #Solves and Fixes Issue #10388 - This is the updated test for the same solved issue + raises(ValueError, lambda: factorial2(oo)) + raises(ValueError, lambda: factorial2(Rational(5, 2))) + raises(ValueError, lambda: factorial2(-4)) + assert factorial2(n).is_integer is None + assert factorial2(tt - 1).is_integer + assert factorial2(tte - 1).is_integer + assert factorial2(tpe - 3).is_integer + assert factorial2(tto - 4).is_integer + assert factorial2(tto - 2).is_integer + assert factorial2(tf).is_integer is None + assert factorial2(tfe).is_integer is None + assert factorial2(tfo).is_integer is None + assert factorial2(ft).is_integer is None + assert factorial2(ff).is_integer is None + assert factorial2(fn).is_integer is None + assert factorial2(nt).is_integer is None + assert factorial2(nf).is_integer is None + assert factorial2(nn).is_integer is None + + assert factorial2(n).is_positive is None + assert factorial2(tt - 1).is_positive is True + assert factorial2(tte - 1).is_positive is True + assert factorial2(tpe - 3).is_positive is True + assert factorial2(tpe - 1).is_positive is True + assert factorial2(tto - 2).is_positive is True + assert factorial2(tto - 1).is_positive is True + assert factorial2(tf).is_positive is None + assert factorial2(tfe).is_positive is None + assert factorial2(tfo).is_positive is None + assert factorial2(ft).is_positive is None + assert factorial2(ff).is_positive is None + assert factorial2(fn).is_positive is None + assert factorial2(nt).is_positive is None + assert factorial2(nf).is_positive is None + assert factorial2(nn).is_positive is None + + assert factorial2(tt).is_even is None + assert factorial2(tt).is_odd is None + assert factorial2(tte).is_even is None + assert factorial2(tte).is_odd is None + assert factorial2(tte + 2).is_even is True + assert factorial2(tpe).is_even is True + assert factorial2(tpe).is_odd is False + assert factorial2(tto).is_odd is True + assert factorial2(tf).is_even is None + assert factorial2(tf).is_odd is None + assert factorial2(tfe).is_even is None + assert factorial2(tfe).is_odd is None + assert factorial2(tfo).is_even is False + assert factorial2(tfo).is_odd is None + assert factorial2(z).is_even is False + assert factorial2(z).is_odd is True + + +def test_factorial2_rewrite(): + n = Symbol('n', integer=True) + assert factorial2(n).rewrite(gamma) == \ + 2**(n/2)*Piecewise((1, Eq(Mod(n, 2), 0)), (sqrt(2)/sqrt(pi), Eq(Mod(n, 2), 1)))*gamma(n/2 + 1) + assert factorial2(2*n).rewrite(gamma) == 2**n*gamma(n + 1) + assert factorial2(2*n + 1).rewrite(gamma) == \ + sqrt(2)*2**(n + S.Half)*gamma(n + Rational(3, 2))/sqrt(pi) + + +def test_binomial(): + x = Symbol('x') + n = Symbol('n', integer=True) + nz = Symbol('nz', integer=True, nonzero=True) + k = Symbol('k', integer=True) + kp = Symbol('kp', integer=True, positive=True) + kn = Symbol('kn', integer=True, negative=True) + u = Symbol('u', negative=True) + v = Symbol('v', nonnegative=True) + p = Symbol('p', positive=True) + z = Symbol('z', zero=True) + nt = Symbol('nt', integer=False) + kt = Symbol('kt', integer=False) + a = Symbol('a', integer=True, nonnegative=True) + b = Symbol('b', integer=True, nonnegative=True) + + assert binomial(0, 0) == 1 + assert binomial(1, 1) == 1 + assert binomial(10, 10) == 1 + assert binomial(n, z) == 1 + assert binomial(1, 2) == 0 + assert binomial(-1, 2) == 1 + assert binomial(1, -1) == 0 + assert binomial(-1, 1) == -1 + assert binomial(-1, -1) == 0 + assert binomial(S.Half, S.Half) == 1 + assert binomial(-10, 1) == -10 + assert binomial(-10, 7) == -11440 + assert binomial(n, -1) == 0 # holds for all integers (negative, zero, positive) + assert binomial(kp, -1) == 0 + assert binomial(nz, 0) == 1 + assert expand_func(binomial(n, 1)) == n + assert expand_func(binomial(n, 2)) == n*(n - 1)/2 + assert expand_func(binomial(n, n - 2)) == n*(n - 1)/2 + assert expand_func(binomial(n, n - 1)) == n + assert binomial(n, 3).func == binomial + assert binomial(n, 3).expand(func=True) == n**3/6 - n**2/2 + n/3 + assert expand_func(binomial(n, 3)) == n*(n - 2)*(n - 1)/6 + assert binomial(n, n).func == binomial # e.g. (-1, -1) == 0, (2, 2) == 1 + assert binomial(n, n + 1).func == binomial # e.g. (-1, 0) == 1 + assert binomial(kp, kp + 1) == 0 + assert binomial(kn, kn) == 0 # issue #14529 + assert binomial(n, u).func == binomial + assert binomial(kp, u).func == binomial + assert binomial(n, p).func == binomial + assert binomial(n, k).func == binomial + assert binomial(n, n + p).func == binomial + assert binomial(kp, kp + p).func == binomial + + assert expand_func(binomial(n, n - 3)) == n*(n - 2)*(n - 1)/6 + + assert binomial(n, k).is_integer + assert binomial(nt, k).is_integer is None + assert binomial(x, nt).is_integer is False + + assert binomial(gamma(25), 6) == 79232165267303928292058750056084441948572511312165380965440075720159859792344339983120618959044048198214221915637090855535036339620413440000 + assert binomial(1324, 47) == 906266255662694632984994480774946083064699457235920708992926525848438478406790323869952 + assert binomial(1735, 43) == 190910140420204130794758005450919715396159959034348676124678207874195064798202216379800 + assert binomial(2512, 53) == 213894469313832631145798303740098720367984955243020898718979538096223399813295457822575338958939834177325304000 + assert binomial(3383, 52) == 27922807788818096863529701501764372757272890613101645521813434902890007725667814813832027795881839396839287659777235 + assert binomial(4321, 51) == 124595639629264868916081001263541480185227731958274383287107643816863897851139048158022599533438936036467601690983780576 + + assert binomial(a, b).is_nonnegative is True + assert binomial(-1, 2, evaluate=False).is_nonnegative is True + assert binomial(10, 5, evaluate=False).is_nonnegative is True + assert binomial(10, -3, evaluate=False).is_nonnegative is True + assert binomial(-10, -3, evaluate=False).is_nonnegative is True + assert binomial(-10, 2, evaluate=False).is_nonnegative is True + assert binomial(-10, 1, evaluate=False).is_nonnegative is False + assert binomial(-10, 7, evaluate=False).is_nonnegative is False + + # issue #14625 + for _ in (pi, -pi, nt, v, a): + assert binomial(_, _) == 1 + assert binomial(_, _ - 1) == _ + assert isinstance(binomial(u, u), binomial) + assert isinstance(binomial(u, u - 1), binomial) + assert isinstance(binomial(x, x), binomial) + assert isinstance(binomial(x, x - 1), binomial) + + #issue #18802 + assert expand_func(binomial(x + 1, x)) == x + 1 + assert expand_func(binomial(x, x - 1)) == x + assert expand_func(binomial(x + 1, x - 1)) == x*(x + 1)/2 + assert expand_func(binomial(x**2 + 1, x**2)) == x**2 + 1 + + # issue #13980 and #13981 + assert binomial(-7, -5) == 0 + assert binomial(-23, -12) == 0 + assert binomial(Rational(13, 2), -10) == 0 + assert binomial(-49, -51) == 0 + + assert binomial(19, Rational(-7, 2)) == S(-68719476736)/(911337863661225*pi) + assert binomial(0, Rational(3, 2)) == S(-2)/(3*pi) + assert binomial(-3, Rational(-7, 2)) is zoo + assert binomial(kn, kt) is zoo + + assert binomial(nt, kt).func == binomial + assert binomial(nt, Rational(15, 6)) == 8*gamma(nt + 1)/(15*sqrt(pi)*gamma(nt - Rational(3, 2))) + assert binomial(Rational(20, 3), Rational(-10, 8)) == gamma(Rational(23, 3))/(gamma(Rational(-1, 4))*gamma(Rational(107, 12))) + assert binomial(Rational(19, 2), Rational(-7, 2)) == Rational(-1615, 8388608) + assert binomial(Rational(-13, 5), Rational(-7, 8)) == gamma(Rational(-8, 5))/(gamma(Rational(-29, 40))*gamma(Rational(1, 8))) + assert binomial(Rational(-19, 8), Rational(-13, 5)) == gamma(Rational(-11, 8))/(gamma(Rational(-8, 5))*gamma(Rational(49, 40))) + + # binomial for complexes + assert binomial(I, Rational(-89, 8)) == gamma(1 + I)/(gamma(Rational(-81, 8))*gamma(Rational(97, 8) + I)) + assert binomial(I, 2*I) == gamma(1 + I)/(gamma(1 - I)*gamma(1 + 2*I)) + assert binomial(-7, I) is zoo + assert binomial(Rational(-7, 6), I) == gamma(Rational(-1, 6))/(gamma(Rational(-1, 6) - I)*gamma(1 + I)) + assert binomial((1+2*I), (1+3*I)) == gamma(2 + 2*I)/(gamma(1 - I)*gamma(2 + 3*I)) + assert binomial(I, 5) == Rational(1, 3) - I/S(12) + assert binomial((2*I + 3), 7) == -13*I/S(63) + assert isinstance(binomial(I, n), binomial) + assert expand_func(binomial(3, 2, evaluate=False)) == 3 + assert expand_func(binomial(n, 0, evaluate=False)) == 1 + assert expand_func(binomial(n, -2, evaluate=False)) == 0 + assert expand_func(binomial(n, k)) == binomial(n, k) + + +def test_binomial_Mod(): + p, q = 10**5 + 3, 10**9 + 33 # prime modulo + r = 10**7 + 5 # composite modulo + + # A few tests to get coverage + # Lucas Theorem + assert Mod(binomial(156675, 4433, evaluate=False), p) == Mod(binomial(156675, 4433), p) + + # factorial Mod + assert Mod(binomial(1234, 432, evaluate=False), q) == Mod(binomial(1234, 432), q) + + # binomial factorize + assert Mod(binomial(253, 113, evaluate=False), r) == Mod(binomial(253, 113), r) + + # using Granville's generalisation of Lucas' Theorem + assert Mod(binomial(10**18, 10**12, evaluate=False), p*p) == 3744312326 + + +@slow +def test_binomial_Mod_slow(): + p, q = 10**5 + 3, 10**9 + 33 # prime modulo + r, s = 10**7 + 5, 33333333 # composite modulo + + n, k, m = symbols('n k m') + assert (binomial(n, k) % q).subs({n: s, k: p}) == Mod(binomial(s, p), q) + assert (binomial(n, k) % m).subs({n: 8, k: 5, m: 13}) == 4 + assert (binomial(9, k) % 7).subs(k, 2) == 1 + + # Lucas Theorem + assert Mod(binomial(123456, 43253, evaluate=False), p) == Mod(binomial(123456, 43253), p) + assert Mod(binomial(-178911, 237, evaluate=False), p) == Mod(-binomial(178911 + 237 - 1, 237), p) + assert Mod(binomial(-178911, 238, evaluate=False), p) == Mod(binomial(178911 + 238 - 1, 238), p) + + # factorial Mod + assert Mod(binomial(9734, 451, evaluate=False), q) == Mod(binomial(9734, 451), q) + assert Mod(binomial(-10733, 4459, evaluate=False), q) == Mod(binomial(-10733, 4459), q) + assert Mod(binomial(-15733, 4458, evaluate=False), q) == Mod(binomial(-15733, 4458), q) + assert Mod(binomial(23, -38, evaluate=False), q) is S.Zero + assert Mod(binomial(23, 38, evaluate=False), q) is S.Zero + + # binomial factorize + assert Mod(binomial(753, 119, evaluate=False), r) == Mod(binomial(753, 119), r) + assert Mod(binomial(3781, 948, evaluate=False), s) == Mod(binomial(3781, 948), s) + assert Mod(binomial(25773, 1793, evaluate=False), s) == Mod(binomial(25773, 1793), s) + assert Mod(binomial(-753, 118, evaluate=False), r) == Mod(binomial(-753, 118), r) + assert Mod(binomial(-25773, 1793, evaluate=False), s) == Mod(binomial(-25773, 1793), s) + + +def test_binomial_diff(): + n = Symbol('n', integer=True) + k = Symbol('k', integer=True) + + assert binomial(n, k).diff(n) == \ + (-polygamma(0, 1 + n - k) + polygamma(0, 1 + n))*binomial(n, k) + assert binomial(n**2, k**3).diff(n) == \ + 2*n*(-polygamma( + 0, 1 + n**2 - k**3) + polygamma(0, 1 + n**2))*binomial(n**2, k**3) + + assert binomial(n, k).diff(k) == \ + (-polygamma(0, 1 + k) + polygamma(0, 1 + n - k))*binomial(n, k) + assert binomial(n**2, k**3).diff(k) == \ + 3*k**2*(-polygamma( + 0, 1 + k**3) + polygamma(0, 1 + n**2 - k**3))*binomial(n**2, k**3) + raises(ArgumentIndexError, lambda: binomial(n, k).fdiff(3)) + + +def test_binomial_rewrite(): + n = Symbol('n', integer=True) + k = Symbol('k', integer=True) + x = Symbol('x') + + assert binomial(n, k).rewrite( + factorial) == factorial(n)/(factorial(k)*factorial(n - k)) + assert binomial( + n, k).rewrite(gamma) == gamma(n + 1)/(gamma(k + 1)*gamma(n - k + 1)) + assert binomial(n, k).rewrite(ff) == ff(n, k) / factorial(k) + assert binomial(n, x).rewrite(ff) == binomial(n, x) + + +@XFAIL +def test_factorial_simplify_fail(): + # simplify(factorial(x + 1).diff(x) - ((x + 1)*factorial(x)).diff(x))) == 0 + from sympy.abc import x + assert simplify(x*polygamma(0, x + 1) - x*polygamma(0, x + 2) + + polygamma(0, x + 1) - polygamma(0, x + 2) + 1) == 0 + + +def test_subfactorial(): + assert all(subfactorial(i) == ans for i, ans in enumerate( + [1, 0, 1, 2, 9, 44, 265, 1854, 14833, 133496])) + assert subfactorial(oo) is oo + assert subfactorial(nan) is nan + assert subfactorial(23) == 9510425471055777937262 + assert unchanged(subfactorial, 2.2) + + x = Symbol('x') + assert subfactorial(x).rewrite(uppergamma) == uppergamma(x + 1, -1)/S.Exp1 + + tt = Symbol('tt', integer=True, nonnegative=True) + tf = Symbol('tf', integer=True, nonnegative=False) + tn = Symbol('tf', integer=True) + ft = Symbol('ft', integer=False, nonnegative=True) + ff = Symbol('ff', integer=False, nonnegative=False) + fn = Symbol('ff', integer=False) + nt = Symbol('nt', nonnegative=True) + nf = Symbol('nf', nonnegative=False) + nn = Symbol('nf') + te = Symbol('te', even=True, nonnegative=True) + to = Symbol('to', odd=True, nonnegative=True) + assert subfactorial(tt).is_integer + assert subfactorial(tf).is_integer is None + assert subfactorial(tn).is_integer is None + assert subfactorial(ft).is_integer is None + assert subfactorial(ff).is_integer is None + assert subfactorial(fn).is_integer is None + assert subfactorial(nt).is_integer is None + assert subfactorial(nf).is_integer is None + assert subfactorial(nn).is_integer is None + assert subfactorial(tt).is_nonnegative + assert subfactorial(tf).is_nonnegative is None + assert subfactorial(tn).is_nonnegative is None + assert subfactorial(ft).is_nonnegative is None + assert subfactorial(ff).is_nonnegative is None + assert subfactorial(fn).is_nonnegative is None + assert subfactorial(nt).is_nonnegative is None + assert subfactorial(nf).is_nonnegative is None + assert subfactorial(nn).is_nonnegative is None + assert subfactorial(tt).is_even is None + assert subfactorial(tt).is_odd is None + assert subfactorial(te).is_odd is True + assert subfactorial(to).is_even is True diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/tests/test_comb_numbers.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/tests/test_comb_numbers.py new file mode 100644 index 0000000000000000000000000000000000000000..83a7de89ed8e4fcc433d29f41fc87b9d0d397539 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/combinatorial/tests/test_comb_numbers.py @@ -0,0 +1,1250 @@ +import string + +from sympy.concrete.products import Product +from sympy.concrete.summations import Sum +from sympy.core.function import (diff, expand_func) +from sympy.core import (EulerGamma, TribonacciConstant) +from sympy.core.numbers import (Float, I, Rational, oo, pi) +from sympy.core.singleton import S +from sympy.core.symbol import (Dummy, Symbol, symbols) +from sympy.functions.combinatorial.numbers import carmichael +from sympy.functions.elementary.complexes import (im, re) +from sympy.functions.elementary.integers import floor +from sympy.polys.polytools import cancel +from sympy.series.limits import limit, Limit +from sympy.series.order import O +from sympy.functions import ( + bernoulli, harmonic, bell, fibonacci, tribonacci, lucas, euler, catalan, + genocchi, andre, partition, divisor_sigma, udivisor_sigma, legendre_symbol, + jacobi_symbol, kronecker_symbol, mobius, + primenu, primeomega, totient, reduced_totient, primepi, + motzkin, binomial, gamma, sqrt, cbrt, hyper, log, digamma, + trigamma, polygamma, factorial, sin, cos, cot, polylog, zeta, dirichlet_eta) +from sympy.functions.combinatorial.numbers import _nT +from sympy.ntheory.factor_ import factorint + +from sympy.core.expr import unchanged +from sympy.core.numbers import GoldenRatio, Integer + +from sympy.testing.pytest import raises, nocache_fail, warns_deprecated_sympy +from sympy.abc import x + + +def test_carmichael(): + with warns_deprecated_sympy(): + assert carmichael.is_prime(2821) == False + + +def test_bernoulli(): + assert bernoulli(0) == 1 + assert bernoulli(1) == Rational(1, 2) + assert bernoulli(2) == Rational(1, 6) + assert bernoulli(3) == 0 + assert bernoulli(4) == Rational(-1, 30) + assert bernoulli(5) == 0 + assert bernoulli(6) == Rational(1, 42) + assert bernoulli(7) == 0 + assert bernoulli(8) == Rational(-1, 30) + assert bernoulli(10) == Rational(5, 66) + assert bernoulli(1000001) == 0 + + assert bernoulli(0, x) == 1 + assert bernoulli(1, x) == x - S.Half + assert bernoulli(2, x) == x**2 - x + Rational(1, 6) + assert bernoulli(3, x) == x**3 - (3*x**2)/2 + x/2 + + # Should be fast; computed with mpmath + b = bernoulli(1000) + assert b.p % 10**10 == 7950421099 + assert b.q == 342999030 + + b = bernoulli(10**6, evaluate=False).evalf() + assert str(b) == '-2.23799235765713e+4767529' + + # Issue #8527 + l = Symbol('l', integer=True) + m = Symbol('m', integer=True, nonnegative=True) + n = Symbol('n', integer=True, positive=True) + assert isinstance(bernoulli(2 * l + 1), bernoulli) + assert isinstance(bernoulli(2 * m + 1), bernoulli) + assert bernoulli(2 * n + 1) == 0 + + assert bernoulli(x, 1) == bernoulli(x) + + assert str(bernoulli(0.0, 2.3).evalf(n=10)) == '1.000000000' + assert str(bernoulli(1.0).evalf(n=10)) == '0.5000000000' + assert str(bernoulli(1.2).evalf(n=10)) == '0.4195995367' + assert str(bernoulli(1.2, 0.8).evalf(n=10)) == '0.2144830348' + assert str(bernoulli(1.2, -0.8).evalf(n=10)) == '-1.158865646 - 0.6745558744*I' + assert str(bernoulli(3.0, 1j).evalf(n=10)) == '1.5 - 0.5*I' + assert str(bernoulli(I).evalf(n=10)) == '0.9268485643 - 0.5821580598*I' + assert str(bernoulli(I, I).evalf(n=10)) == '0.1267792071 + 0.01947413152*I' + assert bernoulli(x).evalf() == bernoulli(x) + + +def test_bernoulli_rewrite(): + from sympy.functions.elementary.piecewise import Piecewise + n = Symbol('n', integer=True, nonnegative=True) + + assert bernoulli(-1).rewrite(zeta) == pi**2/6 + assert bernoulli(-2).rewrite(zeta) == 2*zeta(3) + assert not bernoulli(n, -3).rewrite(zeta).has(harmonic) + assert bernoulli(-4, x).rewrite(zeta) == 4*zeta(5, x) + assert isinstance(bernoulli(n, x).rewrite(zeta), Piecewise) + assert bernoulli(n+1, x).rewrite(zeta) == -(n+1) * zeta(-n, x) + + +def test_fibonacci(): + assert [fibonacci(n) for n in range(-3, 5)] == [2, -1, 1, 0, 1, 1, 2, 3] + assert fibonacci(100) == 354224848179261915075 + assert [lucas(n) for n in range(-3, 5)] == [-4, 3, -1, 2, 1, 3, 4, 7] + assert lucas(100) == 792070839848372253127 + + assert fibonacci(1, x) == 1 + assert fibonacci(2, x) == x + assert fibonacci(3, x) == x**2 + 1 + assert fibonacci(4, x) == x**3 + 2*x + + # issue #8800 + n = Dummy('n') + assert fibonacci(n).limit(n, S.Infinity) is S.Infinity + assert lucas(n).limit(n, S.Infinity) is S.Infinity + + assert fibonacci(n).rewrite(sqrt) == \ + 2**(-n)*sqrt(5)*((1 + sqrt(5))**n - (-sqrt(5) + 1)**n) / 5 + assert fibonacci(n).rewrite(sqrt).subs(n, 10).expand() == fibonacci(10) + assert fibonacci(n).rewrite(GoldenRatio).subs(n,10).evalf() == \ + Float(fibonacci(10)) + assert lucas(n).rewrite(sqrt) == \ + (fibonacci(n-1).rewrite(sqrt) + fibonacci(n+1).rewrite(sqrt)).simplify() + assert lucas(n).rewrite(sqrt).subs(n, 10).expand() == lucas(10) + raises(ValueError, lambda: fibonacci(-3, x)) + + +def test_tribonacci(): + assert [tribonacci(n) for n in range(8)] == [0, 1, 1, 2, 4, 7, 13, 24] + assert tribonacci(100) == 98079530178586034536500564 + + assert tribonacci(0, x) == 0 + assert tribonacci(1, x) == 1 + assert tribonacci(2, x) == x**2 + assert tribonacci(3, x) == x**4 + x + assert tribonacci(4, x) == x**6 + 2*x**3 + 1 + assert tribonacci(5, x) == x**8 + 3*x**5 + 3*x**2 + + n = Dummy('n') + assert tribonacci(n).limit(n, S.Infinity) is S.Infinity + + w = (-1 + S.ImaginaryUnit * sqrt(3)) / 2 + a = (1 + cbrt(19 + 3*sqrt(33)) + cbrt(19 - 3*sqrt(33))) / 3 + b = (1 + w*cbrt(19 + 3*sqrt(33)) + w**2*cbrt(19 - 3*sqrt(33))) / 3 + c = (1 + w**2*cbrt(19 + 3*sqrt(33)) + w*cbrt(19 - 3*sqrt(33))) / 3 + assert tribonacci(n).rewrite(sqrt) == \ + (a**(n + 1)/((a - b)*(a - c)) + + b**(n + 1)/((b - a)*(b - c)) + + c**(n + 1)/((c - a)*(c - b))) + assert tribonacci(n).rewrite(sqrt).subs(n, 4).simplify() == tribonacci(4) + assert tribonacci(n).rewrite(GoldenRatio).subs(n,10).evalf() == \ + Float(tribonacci(10)) + assert tribonacci(n).rewrite(TribonacciConstant) == floor( + 3*TribonacciConstant**n*(102*sqrt(33) + 586)**Rational(1, 3)/ + (-2*(102*sqrt(33) + 586)**Rational(1, 3) + 4 + (102*sqrt(33) + + 586)**Rational(2, 3)) + S.Half) + raises(ValueError, lambda: tribonacci(-1, x)) + + +@nocache_fail +def test_bell(): + assert [bell(n) for n in range(8)] == [1, 1, 2, 5, 15, 52, 203, 877] + + assert bell(0, x) == 1 + assert bell(1, x) == x + assert bell(2, x) == x**2 + x + assert bell(5, x) == x**5 + 10*x**4 + 25*x**3 + 15*x**2 + x + assert bell(oo) is S.Infinity + raises(ValueError, lambda: bell(oo, x)) + + raises(ValueError, lambda: bell(-1)) + raises(ValueError, lambda: bell(S.Half)) + + X = symbols('x:6') + # X = (x0, x1, .. x5) + # at the same time: X[1] = x1, X[2] = x2 for standard readablity. + # but we must supply zero-based indexed object X[1:] = (x1, .. x5) + + assert bell(6, 2, X[1:]) == 6*X[5]*X[1] + 15*X[4]*X[2] + 10*X[3]**2 + assert bell( + 6, 3, X[1:]) == 15*X[4]*X[1]**2 + 60*X[3]*X[2]*X[1] + 15*X[2]**3 + + X = (1, 10, 100, 1000, 10000) + assert bell(6, 2, X) == (6 + 15 + 10)*10000 + + X = (1, 2, 3, 3, 5) + assert bell(6, 2, X) == 6*5 + 15*3*2 + 10*3**2 + + X = (1, 2, 3, 5) + assert bell(6, 3, X) == 15*5 + 60*3*2 + 15*2**3 + + # Dobinski's formula + n = Symbol('n', integer=True, nonnegative=True) + # For large numbers, this is too slow + # For nonintegers, there are significant precision errors + for i in [0, 2, 3, 7, 13, 42, 55]: + # Running without the cache this is either very slow or goes into an + # infinite loop. + assert bell(i).evalf() == bell(n).rewrite(Sum).evalf(subs={n: i}) + + m = Symbol("m") + assert bell(m).rewrite(Sum) == bell(m) + assert bell(n, m).rewrite(Sum) == bell(n, m) + # issue 9184 + n = Dummy('n') + assert bell(n).limit(n, S.Infinity) is S.Infinity + + +def test_harmonic(): + n = Symbol("n") + m = Symbol("m") + + assert harmonic(n, 0) == n + assert harmonic(n).evalf() == harmonic(n) + assert harmonic(n, 1) == harmonic(n) + assert harmonic(1, n) == 1 + + assert harmonic(0, 1) == 0 + assert harmonic(1, 1) == 1 + assert harmonic(2, 1) == Rational(3, 2) + assert harmonic(3, 1) == Rational(11, 6) + assert harmonic(4, 1) == Rational(25, 12) + assert harmonic(0, 2) == 0 + assert harmonic(1, 2) == 1 + assert harmonic(2, 2) == Rational(5, 4) + assert harmonic(3, 2) == Rational(49, 36) + assert harmonic(4, 2) == Rational(205, 144) + assert harmonic(0, 3) == 0 + assert harmonic(1, 3) == 1 + assert harmonic(2, 3) == Rational(9, 8) + assert harmonic(3, 3) == Rational(251, 216) + assert harmonic(4, 3) == Rational(2035, 1728) + + assert harmonic(oo, -1) is S.NaN + assert harmonic(oo, 0) is oo + assert harmonic(oo, S.Half) is oo + assert harmonic(oo, 1) is oo + assert harmonic(oo, 2) == (pi**2)/6 + assert harmonic(oo, 3) == zeta(3) + assert harmonic(oo, Dummy(negative=True)) is S.NaN + ip = Dummy(integer=True, positive=True) + if (1/ip <= 1) is True: #---------------------------------+ + assert None, 'delete this if-block and the next line' #| + ip = Dummy(even=True, positive=True) #--------------------+ + assert harmonic(oo, 1/ip) is oo + assert harmonic(oo, 1 + ip) is zeta(1 + ip) + + assert harmonic(0, m) == 0 + assert harmonic(-1, -1) == 0 + assert harmonic(-1, 0) == -1 + assert harmonic(-1, 1) is S.ComplexInfinity + assert harmonic(-1, 2) is S.NaN + assert harmonic(-3, -2) == -5 + assert harmonic(-3, -3) == 9 + + +def test_harmonic_rational(): + ne = S(6) + no = S(5) + pe = S(8) + po = S(9) + qe = S(10) + qo = S(13) + + Heee = harmonic(ne + pe/qe) + Aeee = (-log(10) + 2*(Rational(-1, 4) + sqrt(5)/4)*log(sqrt(-sqrt(5)/8 + Rational(5, 8))) + + 2*(-sqrt(5)/4 - Rational(1, 4))*log(sqrt(sqrt(5)/8 + Rational(5, 8))) + + pi*sqrt(2*sqrt(5)/5 + 1)/2 + Rational(13944145, 4720968)) + + Heeo = harmonic(ne + pe/qo) + Aeeo = (-log(26) + 2*log(sin(pi*Rational(3, 13)))*cos(pi*Rational(4, 13)) + 2*log(sin(pi*Rational(2, 13)))*cos(pi*Rational(32, 13)) + + 2*log(sin(pi*Rational(5, 13)))*cos(pi*Rational(80, 13)) - 2*log(sin(pi*Rational(6, 13)))*cos(pi*Rational(5, 13)) + - 2*log(sin(pi*Rational(4, 13)))*cos(pi/13) + pi*cot(pi*Rational(5, 13))/2 - 2*log(sin(pi/13))*cos(pi*Rational(3, 13)) + + Rational(2422020029, 702257080)) + + Heoe = harmonic(ne + po/qe) + Aeoe = (-log(20) + 2*(Rational(1, 4) + sqrt(5)/4)*log(Rational(-1, 4) + sqrt(5)/4) + + 2*(Rational(-1, 4) + sqrt(5)/4)*log(sqrt(-sqrt(5)/8 + Rational(5, 8))) + + 2*(-sqrt(5)/4 - Rational(1, 4))*log(sqrt(sqrt(5)/8 + Rational(5, 8))) + + 2*(-sqrt(5)/4 + Rational(1, 4))*log(Rational(1, 4) + sqrt(5)/4) + + Rational(11818877030, 4286604231) + pi*sqrt(2*sqrt(5) + 5)/2) + + Heoo = harmonic(ne + po/qo) + Aeoo = (-log(26) + 2*log(sin(pi*Rational(3, 13)))*cos(pi*Rational(54, 13)) + 2*log(sin(pi*Rational(4, 13)))*cos(pi*Rational(6, 13)) + + 2*log(sin(pi*Rational(6, 13)))*cos(pi*Rational(108, 13)) - 2*log(sin(pi*Rational(5, 13)))*cos(pi/13) + - 2*log(sin(pi/13))*cos(pi*Rational(5, 13)) + pi*cot(pi*Rational(4, 13))/2 + - 2*log(sin(pi*Rational(2, 13)))*cos(pi*Rational(3, 13)) + Rational(11669332571, 3628714320)) + + Hoee = harmonic(no + pe/qe) + Aoee = (-log(10) + 2*(Rational(-1, 4) + sqrt(5)/4)*log(sqrt(-sqrt(5)/8 + Rational(5, 8))) + + 2*(-sqrt(5)/4 - Rational(1, 4))*log(sqrt(sqrt(5)/8 + Rational(5, 8))) + + pi*sqrt(2*sqrt(5)/5 + 1)/2 + Rational(779405, 277704)) + + Hoeo = harmonic(no + pe/qo) + Aoeo = (-log(26) + 2*log(sin(pi*Rational(3, 13)))*cos(pi*Rational(4, 13)) + 2*log(sin(pi*Rational(2, 13)))*cos(pi*Rational(32, 13)) + + 2*log(sin(pi*Rational(5, 13)))*cos(pi*Rational(80, 13)) - 2*log(sin(pi*Rational(6, 13)))*cos(pi*Rational(5, 13)) + - 2*log(sin(pi*Rational(4, 13)))*cos(pi/13) + pi*cot(pi*Rational(5, 13))/2 + - 2*log(sin(pi/13))*cos(pi*Rational(3, 13)) + Rational(53857323, 16331560)) + + Hooe = harmonic(no + po/qe) + Aooe = (-log(20) + 2*(Rational(1, 4) + sqrt(5)/4)*log(Rational(-1, 4) + sqrt(5)/4) + + 2*(Rational(-1, 4) + sqrt(5)/4)*log(sqrt(-sqrt(5)/8 + Rational(5, 8))) + + 2*(-sqrt(5)/4 - Rational(1, 4))*log(sqrt(sqrt(5)/8 + Rational(5, 8))) + + 2*(-sqrt(5)/4 + Rational(1, 4))*log(Rational(1, 4) + sqrt(5)/4) + + Rational(486853480, 186374097) + pi*sqrt(2*sqrt(5) + 5)/2) + + Hooo = harmonic(no + po/qo) + Aooo = (-log(26) + 2*log(sin(pi*Rational(3, 13)))*cos(pi*Rational(54, 13)) + 2*log(sin(pi*Rational(4, 13)))*cos(pi*Rational(6, 13)) + + 2*log(sin(pi*Rational(6, 13)))*cos(pi*Rational(108, 13)) - 2*log(sin(pi*Rational(5, 13)))*cos(pi/13) + - 2*log(sin(pi/13))*cos(pi*Rational(5, 13)) + pi*cot(pi*Rational(4, 13))/2 + - 2*log(sin(pi*Rational(2, 13)))*cos(3*pi/13) + Rational(383693479, 125128080)) + + H = [Heee, Heeo, Heoe, Heoo, Hoee, Hoeo, Hooe, Hooo] + A = [Aeee, Aeeo, Aeoe, Aeoo, Aoee, Aoeo, Aooe, Aooo] + for h, a in zip(H, A): + e = expand_func(h).doit() + assert cancel(e/a) == 1 + assert abs(h.n() - a.n()) < 1e-12 + + +def test_harmonic_evalf(): + assert str(harmonic(1.5).evalf(n=10)) == '1.280372306' + assert str(harmonic(1.5, 2).evalf(n=10)) == '1.154576311' # issue 7443 + assert str(harmonic(4.0, -3).evalf(n=10)) == '100.0000000' + assert str(harmonic(7.0, 1.0).evalf(n=10)) == '2.592857143' + assert str(harmonic(1, pi).evalf(n=10)) == '1.000000000' + assert str(harmonic(2, pi).evalf(n=10)) == '1.113314732' + assert str(harmonic(1000.0, pi).evalf(n=10)) == '1.176241563' + assert str(harmonic(I).evalf(n=10)) == '0.6718659855 + 1.076674047*I' + assert str(harmonic(I, I).evalf(n=10)) == '-0.3970915266 + 1.9629689*I' + + assert harmonic(-1.0, 1).evalf() is S.NaN + assert harmonic(-2.0, 2.0).evalf() is S.NaN + +def test_harmonic_rewrite(): + from sympy.functions.elementary.piecewise import Piecewise + n = Symbol("n") + m = Symbol("m", integer=True, positive=True) + x1 = Symbol("x1", positive=True) + x2 = Symbol("x2", negative=True) + + assert harmonic(n).rewrite(digamma) == polygamma(0, n + 1) + EulerGamma + assert harmonic(n).rewrite(trigamma) == polygamma(0, n + 1) + EulerGamma + assert harmonic(n).rewrite(polygamma) == polygamma(0, n + 1) + EulerGamma + + assert harmonic(n,3).rewrite(polygamma) == polygamma(2, n + 1)/2 - polygamma(2, 1)/2 + assert isinstance(harmonic(n,m).rewrite(polygamma), Piecewise) + + assert expand_func(harmonic(n+4)) == harmonic(n) + 1/(n + 4) + 1/(n + 3) + 1/(n + 2) + 1/(n + 1) + assert expand_func(harmonic(n-4)) == harmonic(n) - 1/(n - 1) - 1/(n - 2) - 1/(n - 3) - 1/n + + assert harmonic(n, m).rewrite("tractable") == harmonic(n, m).rewrite(polygamma) + assert harmonic(n, x1).rewrite("tractable") == harmonic(n, x1) + assert harmonic(n, x1 + 1).rewrite("tractable") == zeta(x1 + 1) - zeta(x1 + 1, n + 1) + assert harmonic(n, x2).rewrite("tractable") == zeta(x2) - zeta(x2, n + 1) + + _k = Dummy("k") + assert harmonic(n).rewrite(Sum).dummy_eq(Sum(1/_k, (_k, 1, n))) + assert harmonic(n, m).rewrite(Sum).dummy_eq(Sum(_k**(-m), (_k, 1, n))) + + +def test_harmonic_calculus(): + y = Symbol("y", positive=True) + z = Symbol("z", negative=True) + assert harmonic(x, 1).limit(x, 0) == 0 + assert harmonic(x, y).limit(x, 0) == 0 + assert harmonic(x, 1).series(x, y, 2) == \ + harmonic(y) + (x - y)*zeta(2, y + 1) + O((x - y)**2, (x, y)) + assert limit(harmonic(x, y), x, oo) == harmonic(oo, y) + assert limit(harmonic(x, y + 1), x, oo) == zeta(y + 1) + assert limit(harmonic(x, y - 1), x, oo) == harmonic(oo, y - 1) + assert limit(harmonic(x, z), x, oo) == Limit(harmonic(x, z), x, oo, dir='-') + assert limit(harmonic(x, z + 1), x, oo) == oo + assert limit(harmonic(x, z + 2), x, oo) == harmonic(oo, z + 2) + assert limit(harmonic(x, z - 1), x, oo) == Limit(harmonic(x, z - 1), x, oo, dir='-') + + +def test_euler(): + assert euler(0) == 1 + assert euler(1) == 0 + assert euler(2) == -1 + assert euler(3) == 0 + assert euler(4) == 5 + assert euler(6) == -61 + assert euler(8) == 1385 + + assert euler(20, evaluate=False) != 370371188237525 + + n = Symbol('n', integer=True) + assert euler(n) != -1 + assert euler(n).subs(n, 2) == -1 + + assert euler(-1) == S.Pi / 2 + assert euler(-1, 1) == 2*log(2) + assert euler(-2).evalf() == (2*S.Catalan).evalf() + assert euler(-3).evalf() == (S.Pi**3 / 16).evalf() + assert str(euler(2.3).evalf(n=10)) == '-1.052850274' + assert str(euler(1.2, 3.4).evalf(n=10)) == '3.575613489' + assert str(euler(I).evalf(n=10)) == '1.248446443 - 0.7675445124*I' + assert str(euler(I, I).evalf(n=10)) == '0.04812930469 + 0.01052411008*I' + + assert euler(20).evalf() == 370371188237525.0 + assert euler(20, evaluate=False).evalf() == 370371188237525.0 + + assert euler(n).rewrite(Sum) == euler(n) + n = Symbol('n', integer=True, nonnegative=True) + assert euler(2*n + 1).rewrite(Sum) == 0 + _j = Dummy('j') + _k = Dummy('k') + assert euler(2*n).rewrite(Sum).dummy_eq( + I*Sum((-1)**_j*2**(-_k)*I**(-_k)*(-2*_j + _k)**(2*n + 1)* + binomial(_k, _j)/_k, (_j, 0, _k), (_k, 1, 2*n + 1))) + + +def test_euler_odd(): + n = Symbol('n', odd=True, positive=True) + assert euler(n) == 0 + n = Symbol('n', odd=True) + assert euler(n) != 0 + + +def test_euler_polynomials(): + assert euler(0, x) == 1 + assert euler(1, x) == x - S.Half + assert euler(2, x) == x**2 - x + assert euler(3, x) == x**3 - (3*x**2)/2 + Rational(1, 4) + m = Symbol('m') + assert isinstance(euler(m, x), euler) + from sympy.core.numbers import Float + A = Float('-0.46237208575048694923364757452876131e8') # from Maple + B = euler(19, S.Pi).evalf(32) + assert abs((A - B)/A) < 1e-31 + z = Float(0.1) + Float(0.2)*I + expected = Float(-3126.54721663773 ) + Float(565.736261497056) * I + assert abs(euler(13, z) - expected) < 1e-10 + + +def test_euler_polynomial_rewrite(): + m = Symbol('m') + A = euler(m, x).rewrite('Sum') + assert A.subs({m:3, x:5}).doit() == euler(3, 5) + + +def test_catalan(): + n = Symbol('n', integer=True) + m = Symbol('m', integer=True, positive=True) + k = Symbol('k', integer=True, nonnegative=True) + p = Symbol('p', nonnegative=True) + + catalans = [1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786] + for i, c in enumerate(catalans): + assert catalan(i) == c + assert catalan(n).rewrite(factorial).subs(n, i) == c + assert catalan(n).rewrite(Product).subs(n, i).doit() == c + + assert unchanged(catalan, x) + assert catalan(2*x).rewrite(binomial) == binomial(4*x, 2*x)/(2*x + 1) + assert catalan(S.Half).rewrite(gamma) == 8/(3*pi) + assert catalan(S.Half).rewrite(factorial).rewrite(gamma) ==\ + 8 / (3 * pi) + assert catalan(3*x).rewrite(gamma) == 4**( + 3*x)*gamma(3*x + S.Half)/(sqrt(pi)*gamma(3*x + 2)) + assert catalan(x).rewrite(hyper) == hyper((-x + 1, -x), (2,), 1) + + assert catalan(n).rewrite(factorial) == factorial(2*n) / (factorial(n + 1) + * factorial(n)) + assert isinstance(catalan(n).rewrite(Product), catalan) + assert isinstance(catalan(m).rewrite(Product), Product) + + assert diff(catalan(x), x) == (polygamma( + 0, x + S.Half) - polygamma(0, x + 2) + log(4))*catalan(x) + + assert catalan(x).evalf() == catalan(x) + c = catalan(S.Half).evalf() + assert str(c) == '0.848826363156775' + c = catalan(I).evalf(3) + assert str((re(c), im(c))) == '(0.398, -0.0209)' + + # Assumptions + assert catalan(p).is_positive is True + assert catalan(k).is_integer is True + assert catalan(m+3).is_composite is True + + +def test_genocchi(): + genocchis = [0, -1, -1, 0, 1, 0, -3, 0, 17] + for n, g in enumerate(genocchis): + assert genocchi(n) == g + + m = Symbol('m', integer=True) + n = Symbol('n', integer=True, positive=True) + assert unchanged(genocchi, m) + assert genocchi(2*n + 1) == 0 + gn = 2 * (1 - 2**n) * bernoulli(n) + assert genocchi(n).rewrite(bernoulli).factor() == gn.factor() + gnx = 2 * (bernoulli(n, x) - 2**n * bernoulli(n, (x+1) / 2)) + assert genocchi(n, x).rewrite(bernoulli).factor() == gnx.factor() + assert genocchi(2 * n).is_odd + assert genocchi(2 * n).is_even is False + assert genocchi(2 * n + 1).is_even + assert genocchi(n).is_integer + assert genocchi(4 * n).is_positive + # these are the only 2 prime Genocchi numbers + assert genocchi(6, evaluate=False).is_prime == S(-3).is_prime + assert genocchi(8, evaluate=False).is_prime + assert genocchi(4 * n + 2).is_negative + assert genocchi(4 * n + 1).is_negative is False + assert genocchi(4 * n - 2).is_negative + + g0 = genocchi(0, evaluate=False) + assert g0.is_positive is False + assert g0.is_negative is False + assert g0.is_even is True + assert g0.is_odd is False + + assert genocchi(0, x) == 0 + assert genocchi(1, x) == -1 + assert genocchi(2, x) == 1 - 2*x + assert genocchi(3, x) == 3*x - 3*x**2 + assert genocchi(4, x) == -1 + 6*x**2 - 4*x**3 + y = Symbol("y") + assert genocchi(5, (x+y)**100) == -5*(x+y)**400 + 10*(x+y)**300 - 5*(x+y)**100 + + assert str(genocchi(5.0, 4.0).evalf(n=10)) == '-660.0000000' + assert str(genocchi(Rational(5, 4)).evalf(n=10)) == '-1.104286457' + assert str(genocchi(-2).evalf(n=10)) == '3.606170709' + assert str(genocchi(1.3, 3.7).evalf(n=10)) == '-1.847375373' + assert str(genocchi(I, 1.0).evalf(n=10)) == '-0.3161917278 - 1.45311955*I' + + n = Symbol('n') + assert genocchi(n, x).rewrite(dirichlet_eta) == -2*n * dirichlet_eta(1-n, x) + + +def test_andre(): + nums = [1, 1, 1, 2, 5, 16, 61, 272, 1385, 7936, 50521] + for n, a in enumerate(nums): + assert andre(n) == a + assert andre(S.Infinity) == S.Infinity + assert andre(-1) == -log(2) + assert andre(-2) == -2*S.Catalan + assert andre(-3) == 3*zeta(3)/16 + assert andre(-5) == -15*zeta(5)/256 + # In fact andre(-2*n) is related to the Dirichlet *beta* function + # at 2*n, but SymPy doesn't implement that (or general L-functions) + assert unchanged(andre, -4) + + n = Symbol('n', integer=True, nonnegative=True) + assert unchanged(andre, n) + assert andre(n).is_integer is True + assert andre(n).is_positive is True + + assert str(andre(10, evaluate=False).evalf(n=10)) == '50521.00000' + assert str(andre(-1, evaluate=False).evalf(n=10)) == '-0.6931471806' + assert str(andre(-2, evaluate=False).evalf(n=10)) == '-1.831931188' + assert str(andre(-4, evaluate=False).evalf(n=10)) == '1.977889103' + assert str(andre(I, evaluate=False).evalf(n=10)) == '2.378417833 + 0.6343322845*I' + + assert andre(x).rewrite(polylog) == \ + (-I)**(x+1) * polylog(-x, I) + I**(x+1) * polylog(-x, -I) + assert andre(x).rewrite(zeta) == \ + 2 * gamma(x+1) / (2*pi)**(x+1) * \ + (zeta(x+1, Rational(1,4)) - cos(pi*x) * zeta(x+1, Rational(3,4))) + + +@nocache_fail +def test_partition(): + partition_nums = [1, 1, 2, 3, 5, 7, 11, 15, 22] + for n, p in enumerate(partition_nums): + assert partition(n) == p + + x = Symbol('x') + y = Symbol('y', real=True) + m = Symbol('m', integer=True) + n = Symbol('n', integer=True, negative=True) + p = Symbol('p', integer=True, nonnegative=True) + assert partition(m).is_integer + assert not partition(m).is_negative + assert partition(m).is_nonnegative + assert partition(n).is_zero + assert partition(p).is_positive + assert partition(x).subs(x, 7) == 15 + assert partition(y).subs(y, 8) == 22 + raises(TypeError, lambda: partition(Rational(5, 4))) + assert partition(9, evaluate=False) % 5 == 0 + assert partition(5*m + 4) % 5 == 0 + assert partition(47, evaluate=False) % 7 == 0 + assert partition(7*m + 5) % 7 == 0 + assert partition(50, evaluate=False) % 11 == 0 + assert partition(11*m + 6) % 11 == 0 + + +def test_divisor_sigma(): + # error + m = Symbol('m', integer=False) + raises(TypeError, lambda: divisor_sigma(m)) + raises(TypeError, lambda: divisor_sigma(4.5)) + raises(TypeError, lambda: divisor_sigma(1, m)) + raises(TypeError, lambda: divisor_sigma(1, 4.5)) + m = Symbol('m', positive=False) + raises(ValueError, lambda: divisor_sigma(m)) + raises(ValueError, lambda: divisor_sigma(0)) + m = Symbol('m', negative=True) + raises(ValueError, lambda: divisor_sigma(1, m)) + raises(ValueError, lambda: divisor_sigma(1, -1)) + + # special case + p = Symbol('p', prime=True) + k = Symbol('k', integer=True) + assert divisor_sigma(p, 1) == p + 1 + assert divisor_sigma(p, k) == p**k + 1 + + # property + n = Symbol('n', integer=True, positive=True) + assert divisor_sigma(n).is_integer is True + assert divisor_sigma(n).is_positive is True + + # symbolic + k = Symbol('k', integer=True, zero=False) + assert divisor_sigma(4, k) == 2**(2*k) + 2**k + 1 + assert divisor_sigma(6, k) == (2**k + 1) * (3**k + 1) + + # Integer + assert divisor_sigma(23450) == 50592 + assert divisor_sigma(23450, 0) == 24 + assert divisor_sigma(23450, 1) == 50592 + assert divisor_sigma(23450, 2) == 730747500 + assert divisor_sigma(23450, 3) == 14666785333344 + + +def test_udivisor_sigma(): + # error + m = Symbol('m', integer=False) + raises(TypeError, lambda: udivisor_sigma(m)) + raises(TypeError, lambda: udivisor_sigma(4.5)) + raises(TypeError, lambda: udivisor_sigma(1, m)) + raises(TypeError, lambda: udivisor_sigma(1, 4.5)) + m = Symbol('m', positive=False) + raises(ValueError, lambda: udivisor_sigma(m)) + raises(ValueError, lambda: udivisor_sigma(0)) + m = Symbol('m', negative=True) + raises(ValueError, lambda: udivisor_sigma(1, m)) + raises(ValueError, lambda: udivisor_sigma(1, -1)) + + # special case + p = Symbol('p', prime=True) + k = Symbol('k', integer=True) + assert udivisor_sigma(p, 1) == p + 1 + assert udivisor_sigma(p, k) == p**k + 1 + + # property + n = Symbol('n', integer=True, positive=True) + assert udivisor_sigma(n).is_integer is True + assert udivisor_sigma(n).is_positive is True + + # Integer + A034444 = [1, 2, 2, 2, 2, 4, 2, 2, 2, 4, 2, 4, 2, 4, 4, 2, 2, 4, 2, 4, + 4, 4, 2, 4, 2, 4, 2, 4, 2, 8, 2, 2, 4, 4, 4, 4, 2, 4, 4, 4, + 2, 8, 2, 4, 4, 4, 2, 4, 2, 4, 4, 4, 2, 4, 4, 4, 4, 4, 2, 8] + for n, val in enumerate(A034444, 1): + assert udivisor_sigma(n, 0) == val + A034448 = [1, 3, 4, 5, 6, 12, 8, 9, 10, 18, 12, 20, 14, 24, 24, 17, 18, + 30, 20, 30, 32, 36, 24, 36, 26, 42, 28, 40, 30, 72, 32, 33, + 48, 54, 48, 50, 38, 60, 56, 54, 42, 96, 44, 60, 60, 72, 48] + for n, val in enumerate(A034448, 1): + assert udivisor_sigma(n, 1) == val + A034676 = [1, 5, 10, 17, 26, 50, 50, 65, 82, 130, 122, 170, 170, 250, + 260, 257, 290, 410, 362, 442, 500, 610, 530, 650, 626, 850, + 730, 850, 842, 1300, 962, 1025, 1220, 1450, 1300, 1394, 1370] + for n, val in enumerate(A034676, 1): + assert udivisor_sigma(n, 2) == val + + +def test_legendre_symbol(): + # error + m = Symbol('m', integer=False) + raises(TypeError, lambda: legendre_symbol(m, 3)) + raises(TypeError, lambda: legendre_symbol(4.5, 3)) + raises(TypeError, lambda: legendre_symbol(1, m)) + raises(TypeError, lambda: legendre_symbol(1, 4.5)) + m = Symbol('m', prime=False) + raises(ValueError, lambda: legendre_symbol(1, m)) + raises(ValueError, lambda: legendre_symbol(1, 6)) + m = Symbol('m', odd=False) + raises(ValueError, lambda: legendre_symbol(1, m)) + raises(ValueError, lambda: legendre_symbol(1, 2)) + + # special case + p = Symbol('p', prime=True) + k = Symbol('k', integer=True) + assert legendre_symbol(p*k, p) == 0 + assert legendre_symbol(1, p) == 1 + + # property + n = Symbol('n') + m = Symbol('m') + assert legendre_symbol(m, n).is_integer is True + assert legendre_symbol(m, n).is_prime is False + + # Integer + assert legendre_symbol(5, 11) == 1 + assert legendre_symbol(25, 41) == 1 + assert legendre_symbol(67, 101) == -1 + assert legendre_symbol(0, 13) == 0 + assert legendre_symbol(9, 3) == 0 + + +def test_jacobi_symbol(): + # error + m = Symbol('m', integer=False) + raises(TypeError, lambda: jacobi_symbol(m, 3)) + raises(TypeError, lambda: jacobi_symbol(4.5, 3)) + raises(TypeError, lambda: jacobi_symbol(1, m)) + raises(TypeError, lambda: jacobi_symbol(1, 4.5)) + m = Symbol('m', positive=False) + raises(ValueError, lambda: jacobi_symbol(1, m)) + raises(ValueError, lambda: jacobi_symbol(1, -6)) + m = Symbol('m', odd=False) + raises(ValueError, lambda: jacobi_symbol(1, m)) + raises(ValueError, lambda: jacobi_symbol(1, 2)) + + # special case + p = Symbol('p', integer=True) + k = Symbol('k', integer=True) + assert jacobi_symbol(p*k, p) == 0 + assert jacobi_symbol(1, p) == 1 + assert jacobi_symbol(1, 1) == 1 + assert jacobi_symbol(0, 1) == 1 + + # property + n = Symbol('n') + m = Symbol('m') + assert jacobi_symbol(m, n).is_integer is True + assert jacobi_symbol(m, n).is_prime is False + + # Integer + assert jacobi_symbol(25, 41) == 1 + assert jacobi_symbol(-23, 83) == -1 + assert jacobi_symbol(3, 9) == 0 + assert jacobi_symbol(42, 97) == -1 + assert jacobi_symbol(3, 5) == -1 + assert jacobi_symbol(7, 9) == 1 + assert jacobi_symbol(0, 3) == 0 + assert jacobi_symbol(0, 1) == 1 + assert jacobi_symbol(2, 1) == 1 + assert jacobi_symbol(1, 3) == 1 + + +def test_kronecker_symbol(): + # error + m = Symbol('m', integer=False) + raises(TypeError, lambda: kronecker_symbol(m, 3)) + raises(TypeError, lambda: kronecker_symbol(4.5, 3)) + raises(TypeError, lambda: kronecker_symbol(1, m)) + raises(TypeError, lambda: kronecker_symbol(1, 4.5)) + + # special case + p = Symbol('p', integer=True) + assert kronecker_symbol(1, p) == 1 + assert kronecker_symbol(1, 1) == 1 + assert kronecker_symbol(0, 1) == 1 + + # property + n = Symbol('n') + m = Symbol('m') + assert kronecker_symbol(m, n).is_integer is True + assert kronecker_symbol(m, n).is_prime is False + + # Integer + for n in range(3, 10, 2): + for a in range(-n, n): + val = kronecker_symbol(a, n) + assert val == jacobi_symbol(a, n) + minus = kronecker_symbol(a, -n) + if a < 0: + assert -minus == val + else: + assert minus == val + even = kronecker_symbol(a, 2 * n) + if a % 2 == 0: + assert even == 0 + elif a % 8 in [1, 7]: + assert even == val + else: + assert -even == val + assert kronecker_symbol(1, 0) == kronecker_symbol(-1, 0) == 1 + assert kronecker_symbol(0, 0) == 0 + + +def test_mobius(): + # error + m = Symbol('m', integer=False) + raises(TypeError, lambda: mobius(m)) + raises(TypeError, lambda: mobius(4.5)) + m = Symbol('m', positive=False) + raises(ValueError, lambda: mobius(m)) + raises(ValueError, lambda: mobius(-3)) + + # special case + p = Symbol('p', prime=True) + assert mobius(p) == -1 + + # property + n = Symbol('n', integer=True, positive=True) + assert mobius(n).is_integer is True + assert mobius(n).is_prime is False + + # symbolic + n = Symbol('n', integer=True, positive=True) + k = Symbol('k', integer=True, positive=True) + assert mobius(n**2) == 0 + assert mobius(4*n) == 0 + assert isinstance(mobius(n**k), mobius) + assert mobius(n**(k+1)) == 0 + assert isinstance(mobius(3**k), mobius) + assert mobius(3**(k+1)) == 0 + m = Symbol('m') + assert isinstance(mobius(4*m), mobius) + + # Integer + assert mobius(13*7) == 1 + assert mobius(1) == 1 + assert mobius(13*7*5) == -1 + assert mobius(13**2) == 0 + A008683 = [1, -1, -1, 0, -1, 1, -1, 0, 0, 1, -1, 0, -1, 1, 1, 0, -1, 0, + -1, 0, 1, 1, -1, 0, 0, 1, 0, 0, -1, -1, -1, 0, 1, 1, 1, 0, -1, + 1, 1, 0, -1, -1, -1, 0, 0, 1, -1, 0, 0, 0, 1, 0, -1, 0, 1, 0] + for n, val in enumerate(A008683, 1): + assert mobius(n) == val + + +def test_primenu(): + # error + m = Symbol('m', integer=False) + raises(TypeError, lambda: primenu(m)) + raises(TypeError, lambda: primenu(4.5)) + m = Symbol('m', positive=False) + raises(ValueError, lambda: primenu(m)) + raises(ValueError, lambda: primenu(0)) + + # special case + p = Symbol('p', prime=True) + assert primenu(p) == 1 + + # property + n = Symbol('n', integer=True, positive=True) + assert primenu(n).is_integer is True + assert primenu(n).is_nonnegative is True + + # Integer + assert primenu(7*13) == 2 + assert primenu(2*17*19) == 3 + assert primenu(2**3 * 17 * 19**2) == 3 + A001221 = [0, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 2, 1, 2, 2, 1, 1, 2, + 1, 2, 2, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 1, 2, 2, 2, 2] + for n, val in enumerate(A001221, 1): + assert primenu(n) == val + + +def test_primeomega(): + # error + m = Symbol('m', integer=False) + raises(TypeError, lambda: primeomega(m)) + raises(TypeError, lambda: primeomega(4.5)) + m = Symbol('m', positive=False) + raises(ValueError, lambda: primeomega(m)) + raises(ValueError, lambda: primeomega(0)) + + # special case + p = Symbol('p', prime=True) + assert primeomega(p) == 1 + + # property + n = Symbol('n', integer=True, positive=True) + assert primeomega(n).is_integer is True + assert primeomega(n).is_nonnegative is True + + # Integer + assert primeomega(7*13) == 2 + assert primeomega(2*17*19) == 3 + assert primeomega(2**3 * 17 * 19**2) == 6 + A001222 = [0, 1, 1, 2, 1, 2, 1, 3, 2, 2, 1, 3, 1, 2, 2, 4, 1, 3, + 1, 3, 2, 2, 1, 4, 2, 2, 3, 3, 1, 3, 1, 5, 2, 2, 2, 4] + for n, val in enumerate(A001222, 1): + assert primeomega(n) == val + + +def test_totient(): + # error + m = Symbol('m', integer=False) + raises(TypeError, lambda: totient(m)) + raises(TypeError, lambda: totient(4.5)) + m = Symbol('m', positive=False) + raises(ValueError, lambda: totient(m)) + raises(ValueError, lambda: totient(0)) + + # special case + p = Symbol('p', prime=True) + assert totient(p) == p - 1 + + # property + n = Symbol('n', integer=True, positive=True) + assert totient(n).is_integer is True + assert totient(n).is_positive is True + + # Integer + assert totient(7*13) == totient(factorint(7*13)) == (7-1)*(13-1) + assert totient(2*17*19) == totient(factorint(2*17*19)) == (17-1)*(19-1) + assert totient(2**3 * 17 * 19**2) == totient({2: 3, 17: 1, 19: 2}) == 2**2 * (17-1) * 19*(19-1) + A000010 = [1, 1, 2, 2, 4, 2, 6, 4, 6, 4, 10, 4, 12, 6, 8, 8, 16, + 6, 18, 8, 12, 10, 22, 8, 20, 12, 18, 12, 28, 8, 30, 16, + 20, 16, 24, 12, 36, 18, 24, 16, 40, 12, 42, 20, 24, 22] + for n, val in enumerate(A000010, 1): + assert totient(n) == val + + +def test_reduced_totient(): + # error + m = Symbol('m', integer=False) + raises(TypeError, lambda: reduced_totient(m)) + raises(TypeError, lambda: reduced_totient(4.5)) + m = Symbol('m', positive=False) + raises(ValueError, lambda: reduced_totient(m)) + raises(ValueError, lambda: reduced_totient(0)) + + # special case + p = Symbol('p', prime=True) + assert reduced_totient(p) == p - 1 + + # property + n = Symbol('n', integer=True, positive=True) + assert reduced_totient(n).is_integer is True + assert reduced_totient(n).is_positive is True + + # Integer + assert reduced_totient(7*13) == reduced_totient(factorint(7*13)) == 12 + assert reduced_totient(2*17*19) == reduced_totient(factorint(2*17*19)) == 144 + assert reduced_totient(2**2 * 11) == reduced_totient({2: 2, 11: 1}) == 10 + assert reduced_totient(2**3 * 17 * 19**2) == reduced_totient({2: 3, 17: 1, 19: 2}) == 2736 + A002322 = [1, 1, 2, 2, 4, 2, 6, 2, 6, 4, 10, 2, 12, 6, 4, 4, 16, 6, + 18, 4, 6, 10, 22, 2, 20, 12, 18, 6, 28, 4, 30, 8, 10, 16, + 12, 6, 36, 18, 12, 4, 40, 6, 42, 10, 12, 22, 46, 4, 42] + for n, val in enumerate(A002322, 1): + assert reduced_totient(n) == val + + +def test_primepi(): + # error + z = Symbol('z', real=False) + raises(TypeError, lambda: primepi(z)) + raises(TypeError, lambda: primepi(I)) + + # property + n = Symbol('n', integer=True, positive=True) + assert primepi(n).is_integer is True + assert primepi(n).is_nonnegative is True + + # infinity + assert primepi(oo) == oo + assert primepi(-oo) == 0 + + # symbol + x = Symbol('x') + assert isinstance(primepi(x), primepi) + + # Integer + assert primepi(0) == 0 + A000720 = [0, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 8, + 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11, + 12, 12, 12, 12, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15] + for n, val in enumerate(A000720, 1): + assert primepi(n) == primepi(n + 0.5) == val + + +def test__nT(): + assert [_nT(i, j) for i in range(5) for j in range(i + 2)] == [ + 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 2, 1, 1, 0] + check = [_nT(10, i) for i in range(11)] + assert check == [0, 1, 5, 8, 9, 7, 5, 3, 2, 1, 1] + assert all(type(i) is int for i in check) + assert _nT(10, 5) == 7 + assert _nT(100, 98) == 2 + assert _nT(100, 100) == 1 + assert _nT(10, 3) == 8 + + +def test_nC_nP_nT(): + from sympy.utilities.iterables import ( + multiset_permutations, multiset_combinations, multiset_partitions, + partitions, subsets, permutations) + from sympy.functions.combinatorial.numbers import ( + nP, nC, nT, stirling, _stirling1, _stirling2, _multiset_histogram, _AOP_product) + + from sympy.combinatorics.permutations import Permutation + from sympy.core.random import choice + + c = string.ascii_lowercase + for i in range(100): + s = ''.join(choice(c) for i in range(7)) + u = len(s) == len(set(s)) + try: + tot = 0 + for i in range(8): + check = nP(s, i) + tot += check + assert len(list(multiset_permutations(s, i))) == check + if u: + assert nP(len(s), i) == check + assert nP(s) == tot + except AssertionError: + print(s, i, 'failed perm test') + raise ValueError() + + for i in range(100): + s = ''.join(choice(c) for i in range(7)) + u = len(s) == len(set(s)) + try: + tot = 0 + for i in range(8): + check = nC(s, i) + tot += check + assert len(list(multiset_combinations(s, i))) == check + if u: + assert nC(len(s), i) == check + assert nC(s) == tot + if u: + assert nC(len(s)) == tot + except AssertionError: + print(s, i, 'failed combo test') + raise ValueError() + + for i in range(1, 10): + tot = 0 + for j in range(1, i + 2): + check = nT(i, j) + assert check.is_Integer + tot += check + assert sum(1 for p in partitions(i, j, size=True) if p[0] == j) == check + assert nT(i) == tot + + for i in range(1, 10): + tot = 0 + for j in range(1, i + 2): + check = nT(range(i), j) + tot += check + assert len(list(multiset_partitions(list(range(i)), j))) == check + assert nT(range(i)) == tot + + for i in range(100): + s = ''.join(choice(c) for i in range(7)) + u = len(s) == len(set(s)) + try: + tot = 0 + for i in range(1, 8): + check = nT(s, i) + tot += check + assert len(list(multiset_partitions(s, i))) == check + if u: + assert nT(range(len(s)), i) == check + if u: + assert nT(range(len(s))) == tot + assert nT(s) == tot + except AssertionError: + print(s, i, 'failed partition test') + raise ValueError() + + # tests for Stirling numbers of the first kind that are not tested in the + # above + assert [stirling(9, i, kind=1) for i in range(11)] == [ + 0, 40320, 109584, 118124, 67284, 22449, 4536, 546, 36, 1, 0] + perms = list(permutations(range(4))) + assert [sum(1 for p in perms if Permutation(p).cycles == i) + for i in range(5)] == [0, 6, 11, 6, 1] == [ + stirling(4, i, kind=1) for i in range(5)] + # http://oeis.org/A008275 + assert [stirling(n, k, signed=1) + for n in range(10) for k in range(1, n + 1)] == [ + 1, -1, + 1, 2, -3, + 1, -6, 11, -6, + 1, 24, -50, 35, -10, + 1, -120, 274, -225, 85, -15, + 1, 720, -1764, 1624, -735, 175, -21, + 1, -5040, 13068, -13132, 6769, -1960, 322, -28, + 1, 40320, -109584, 118124, -67284, 22449, -4536, 546, -36, 1] + # https://en.wikipedia.org/wiki/Stirling_numbers_of_the_first_kind + assert [stirling(n, k, kind=1) + for n in range(10) for k in range(n+1)] == [ + 1, + 0, 1, + 0, 1, 1, + 0, 2, 3, 1, + 0, 6, 11, 6, 1, + 0, 24, 50, 35, 10, 1, + 0, 120, 274, 225, 85, 15, 1, + 0, 720, 1764, 1624, 735, 175, 21, 1, + 0, 5040, 13068, 13132, 6769, 1960, 322, 28, 1, + 0, 40320, 109584, 118124, 67284, 22449, 4536, 546, 36, 1] + # https://en.wikipedia.org/wiki/Stirling_numbers_of_the_second_kind + assert [stirling(n, k, kind=2) + for n in range(10) for k in range(n+1)] == [ + 1, + 0, 1, + 0, 1, 1, + 0, 1, 3, 1, + 0, 1, 7, 6, 1, + 0, 1, 15, 25, 10, 1, + 0, 1, 31, 90, 65, 15, 1, + 0, 1, 63, 301, 350, 140, 21, 1, + 0, 1, 127, 966, 1701, 1050, 266, 28, 1, + 0, 1, 255, 3025, 7770, 6951, 2646, 462, 36, 1] + assert stirling(3, 4, kind=1) == stirling(3, 4, kind=1) == 0 + raises(ValueError, lambda: stirling(-2, 2)) + + # Assertion that the return type is SymPy Integer. + assert isinstance(_stirling1(6, 3), Integer) + assert isinstance(_stirling2(6, 3), Integer) + + def delta(p): + if len(p) == 1: + return oo + return min(abs(i[0] - i[1]) for i in subsets(p, 2)) + parts = multiset_partitions(range(5), 3) + d = 2 + assert (sum(1 for p in parts if all(delta(i) >= d for i in p)) == + stirling(5, 3, d=d) == 7) + + # other coverage tests + assert nC('abb', 2) == nC('aab', 2) == 2 + assert nP(3, 3, replacement=True) == nP('aabc', 3, replacement=True) == 27 + assert nP(3, 4) == 0 + assert nP('aabc', 5) == 0 + assert nC(4, 2, replacement=True) == nC('abcdd', 2, replacement=True) == \ + len(list(multiset_combinations('aabbccdd', 2))) == 10 + assert nC('abcdd') == sum(nC('abcdd', i) for i in range(6)) == 24 + assert nC(list('abcdd'), 4) == 4 + assert nT('aaaa') == nT(4) == len(list(partitions(4))) == 5 + assert nT('aaab') == len(list(multiset_partitions('aaab'))) == 7 + assert nC('aabb'*3, 3) == 4 # aaa, bbb, abb, baa + assert dict(_AOP_product((4,1,1,1))) == { + 0: 1, 1: 4, 2: 7, 3: 8, 4: 8, 5: 7, 6: 4, 7: 1} + # the following was the first t that showed a problem in a previous form of + # the function, so it's not as random as it may appear + t = (3, 9, 4, 6, 6, 5, 5, 2, 10, 4) + assert sum(_AOP_product(t)[i] for i in range(55)) == 58212000 + raises(ValueError, lambda: _multiset_histogram({1:'a'})) + + +def test_PR_14617(): + from sympy.functions.combinatorial.numbers import nT + for n in (0, []): + for k in (-1, 0, 1): + if k == 0: + assert nT(n, k) == 1 + else: + assert nT(n, k) == 0 + + +def test_issue_8496(): + n = Symbol("n") + k = Symbol("k") + + raises(TypeError, lambda: catalan(n, k)) + + +def test_issue_8601(): + n = Symbol('n', integer=True, negative=True) + + assert catalan(n - 1) is S.Zero + assert catalan(Rational(-1, 2)) is S.ComplexInfinity + assert catalan(-S.One) == Rational(-1, 2) + c1 = catalan(-5.6).evalf() + assert str(c1) == '6.93334070531408e-5' + c2 = catalan(-35.4).evalf() + assert str(c2) == '-4.14189164517449e-24' + + +def test_motzkin(): + assert motzkin.is_motzkin(4) == True + assert motzkin.is_motzkin(9) == True + assert motzkin.is_motzkin(10) == False + assert motzkin.find_motzkin_numbers_in_range(10,200) == [21, 51, 127] + assert motzkin.find_motzkin_numbers_in_range(10,400) == [21, 51, 127, 323] + assert motzkin.find_motzkin_numbers_in_range(10,1600) == [21, 51, 127, 323, 835] + assert motzkin.find_first_n_motzkins(5) == [1, 1, 2, 4, 9] + assert motzkin.find_first_n_motzkins(7) == [1, 1, 2, 4, 9, 21, 51] + assert motzkin.find_first_n_motzkins(10) == [1, 1, 2, 4, 9, 21, 51, 127, 323, 835] + raises(ValueError, lambda: motzkin.eval(77.58)) + raises(ValueError, lambda: motzkin.eval(-8)) + raises(ValueError, lambda: motzkin.find_motzkin_numbers_in_range(-2,7)) + raises(ValueError, lambda: motzkin.find_motzkin_numbers_in_range(13,7)) + raises(ValueError, lambda: motzkin.find_first_n_motzkins(112.8)) + + +def test_nD_derangements(): + from sympy.utilities.iterables import (partitions, multiset, + multiset_derangements, multiset_permutations) + from sympy.functions.combinatorial.numbers import nD + + got = [] + for i in partitions(8, k=4): + s = [] + it = 0 + for k, v in i.items(): + for i in range(v): + s.extend([it]*k) + it += 1 + ms = multiset(s) + c1 = sum(1 for i in multiset_permutations(s) if + all(i != j for i, j in zip(i, s))) + assert c1 == nD(ms) == nD(ms, 0) == nD(ms, 1) + v = [tuple(i) for i in multiset_derangements(s)] + c2 = len(v) + assert c2 == len(set(v)) + assert c1 == c2 + got.append(c1) + assert got == [1, 4, 6, 12, 24, 24, 61, 126, 315, 780, 297, 772, + 2033, 5430, 14833] + + assert nD('1112233456', brute=True) == nD('1112233456') == 16356 + assert nD('') == nD([]) == nD({}) == 0 + assert nD({1: 0}) == 0 + raises(ValueError, lambda: nD({1: -1})) + assert nD('112') == 0 + assert nD(i='112') == 0 + assert [nD(n=i) for i in range(6)] == [0, 0, 1, 2, 9, 44] + assert nD((i for i in range(4))) == nD('0123') == 9 + assert nD(m=(i for i in range(4))) == 3 + assert nD(m={0: 1, 1: 1, 2: 1, 3: 1}) == 3 + assert nD(m=[0, 1, 2, 3]) == 3 + raises(TypeError, lambda: nD(m=0)) + raises(TypeError, lambda: nD(-1)) + assert nD({-1: 1, -2: 1}) == 1 + assert nD(m={0: 3}) == 0 + raises(ValueError, lambda: nD(i='123', n=3)) + raises(ValueError, lambda: nD(i='123', m=(1,2))) + raises(ValueError, lambda: nD(n=0, m=(1,2))) + raises(ValueError, lambda: nD({1: -1})) + raises(ValueError, lambda: nD(m={-1: 1, 2: 1})) + raises(ValueError, lambda: nD(m={1: -1, 2: 1})) + raises(ValueError, lambda: nD(m=[-1, 2])) + raises(TypeError, lambda: nD({1: x})) + raises(TypeError, lambda: nD(m={1: x})) + raises(TypeError, lambda: nD(m={x: 1})) + + +def test_deprecated_ntheory_symbolic_functions(): + from sympy.testing.pytest import warns_deprecated_sympy + + with warns_deprecated_sympy(): + assert not carmichael.is_carmichael(3) + with warns_deprecated_sympy(): + assert carmichael.find_carmichael_numbers_in_range(10, 20) == [] + with warns_deprecated_sympy(): + assert carmichael.find_first_n_carmichaels(1) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..78034e72ef2ed722c3ae685a87cf4df618a982b0 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/__init__.py @@ -0,0 +1 @@ +# Stub __init__.py for sympy.functions.elementary diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6a07d6b2748b85808810fa9d18c2de0181a638ab Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/__pycache__/_trigonometric_special.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/__pycache__/_trigonometric_special.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c62a248d21fac16478746860bf97826b3f60c95c Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/__pycache__/_trigonometric_special.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/__pycache__/complexes.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/__pycache__/complexes.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..767e660f8f667cb62144ac3cad94ab6276d6f1e4 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/__pycache__/complexes.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/__pycache__/exponential.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/__pycache__/exponential.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..33fb6020d1c0b2e3691949f93db156f6bf3b12bc Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/__pycache__/exponential.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/__pycache__/integers.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/__pycache__/integers.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9e0d330e9f6147e84d4bdd8783c8d56907f3f84d Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/__pycache__/integers.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/__pycache__/miscellaneous.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/__pycache__/miscellaneous.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4095362731e4ef4dfcb116e6813f99bbdd7de0bb Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/__pycache__/miscellaneous.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/__pycache__/piecewise.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/__pycache__/piecewise.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ce5ca17dbfb85c1bdaf9510e6ced60fd0cd6707a Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/__pycache__/piecewise.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/_trigonometric_special.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/_trigonometric_special.py new file mode 100644 index 0000000000000000000000000000000000000000..fdf8c9d06241b46e791afe76836ea33e6d4fb1c8 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/_trigonometric_special.py @@ -0,0 +1,261 @@ +r"""A module for special angle formulas for trigonometric functions + +TODO +==== + +This module should be developed in the future to contain direct square root +representation of + +.. math + F(\frac{n}{m} \pi) + +for every + +- $m \in \{ 3, 5, 17, 257, 65537 \}$ +- $n \in \mathbb{N}$, $0 \le n < m$ +- $F \in \{\sin, \cos, \tan, \csc, \sec, \cot\}$ + +Without multi-step rewrites +(e.g. $\tan \to \cos/\sin \to \cos/\sqrt \to \ sqrt$) +or using chebyshev identities +(e.g. $\cos \to \cos + \cos^2 + \cdots \to \sqrt{} + \sqrt{}^2 + \cdots $), +which are trivial to implement in sympy, +and had used to give overly complicated expressions. + +The reference can be found below, if anyone may need help implementing them. + +References +========== + +.. [*] Gottlieb, Christian. (1999). The Simple and straightforward construction + of the regular 257-gon. The Mathematical Intelligencer. 21. 31-37. + 10.1007/BF03024829. +.. [*] https://resources.wolframcloud.com/FunctionRepository/resources/Cos2PiOverFermatPrime +""" +from __future__ import annotations +from typing import Callable +from functools import reduce +from sympy.core.expr import Expr +from sympy.core.singleton import S +from sympy.core.intfunc import igcdex +from sympy.core.numbers import Integer +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.core.cache import cacheit + + +def migcdex(*x: int) -> tuple[tuple[int, ...], int]: + r"""Compute extended gcd for multiple integers. + + Explanation + =========== + + Given the integers $x_1, \cdots, x_n$ and + an extended gcd for multiple arguments are defined as a solution + $(y_1, \cdots, y_n), g$ for the diophantine equation + $x_1 y_1 + \cdots + x_n y_n = g$ such that + $g = \gcd(x_1, \cdots, x_n)$. + + Examples + ======== + + >>> from sympy.functions.elementary._trigonometric_special import migcdex + >>> migcdex() + ((), 0) + >>> migcdex(4) + ((1,), 4) + >>> migcdex(4, 6) + ((-1, 1), 2) + >>> migcdex(6, 10, 15) + ((1, 1, -1), 1) + """ + if not x: + return (), 0 + + if len(x) == 1: + return (1,), x[0] + + if len(x) == 2: + u, v, h = igcdex(x[0], x[1]) + return (u, v), h + + y, g = migcdex(*x[1:]) + u, v, h = igcdex(x[0], g) + return (u, *(v * i for i in y)), h + + +def ipartfrac(*denoms: int) -> tuple[int, ...]: + r"""Compute the partial fraction decomposition. + + Explanation + =========== + + Given a rational number $\frac{1}{q_1 \cdots q_n}$ where all + $q_1, \cdots, q_n$ are pairwise coprime, + + A partial fraction decomposition is defined as + + .. math:: + \frac{1}{q_1 \cdots q_n} = \frac{p_1}{q_1} + \cdots + \frac{p_n}{q_n} + + And it can be derived from solving the following diophantine equation for + the $p_1, \cdots, p_n$ + + .. math:: + 1 = p_1 \prod_{i \ne 1}q_i + \cdots + p_n \prod_{i \ne n}q_i + + Where $q_1, \cdots, q_n$ being pairwise coprime implies + $\gcd(\prod_{i \ne 1}q_i, \cdots, \prod_{i \ne n}q_i) = 1$, + which guarantees the existence of the solution. + + It is sufficient to compute partial fraction decomposition only + for numerator $1$ because partial fraction decomposition for any + $\frac{n}{q_1 \cdots q_n}$ can be easily computed by multiplying + the result by $n$ afterwards. + + Parameters + ========== + + denoms : int + The pairwise coprime integer denominators $q_i$ which defines the + rational number $\frac{1}{q_1 \cdots q_n}$ + + Returns + ======= + + tuple[int, ...] + The list of numerators which semantically corresponds to $p_i$ of the + partial fraction decomposition + $\frac{1}{q_1 \cdots q_n} = \frac{p_1}{q_1} + \cdots + \frac{p_n}{q_n}$ + + Examples + ======== + + >>> from sympy import Rational, Mul + >>> from sympy.functions.elementary._trigonometric_special import ipartfrac + + >>> denoms = 2, 3, 5 + >>> numers = ipartfrac(2, 3, 5) + >>> numers + (1, 7, -14) + + >>> Rational(1, Mul(*denoms)) + 1/30 + >>> out = 0 + >>> for n, d in zip(numers, denoms): + ... out += Rational(n, d) + >>> out + 1/30 + """ + if not denoms: + return () + + def mul(x: int, y: int) -> int: + return x * y + + denom = reduce(mul, denoms) + a = [denom // x for x in denoms] + h, _ = migcdex(*a) + return h + + +def fermat_coords(n: int) -> list[int] | None: + """If n can be factored in terms of Fermat primes with + multiplicity of each being 1, return those primes, else + None + """ + primes = [] + for p in [3, 5, 17, 257, 65537]: + quotient, remainder = divmod(n, p) + if remainder == 0: + n = quotient + primes.append(p) + if n == 1: + return primes + return None + + +@cacheit +def cos_3() -> Expr: + r"""Computes $\cos \frac{\pi}{3}$ in square roots""" + return S.Half + + +@cacheit +def cos_5() -> Expr: + r"""Computes $\cos \frac{\pi}{5}$ in square roots""" + return (sqrt(5) + 1) / 4 + + +@cacheit +def cos_17() -> Expr: + r"""Computes $\cos \frac{\pi}{17}$ in square roots""" + return sqrt( + (15 + sqrt(17)) / 32 + sqrt(2) * (sqrt(17 - sqrt(17)) + + sqrt(sqrt(2) * (-8 * sqrt(17 + sqrt(17)) - (1 - sqrt(17)) + * sqrt(17 - sqrt(17))) + 6 * sqrt(17) + 34)) / 32) + + +@cacheit +def cos_257() -> Expr: + r"""Computes $\cos \frac{\pi}{257}$ in square roots + + References + ========== + + .. [*] https://math.stackexchange.com/questions/516142/how-does-cos2-pi-257-look-like-in-real-radicals + .. [*] https://r-knott.surrey.ac.uk/Fibonacci/simpleTrig.html + """ + def f1(a: Expr, b: Expr) -> tuple[Expr, Expr]: + return (a + sqrt(a**2 + b)) / 2, (a - sqrt(a**2 + b)) / 2 + + def f2(a: Expr, b: Expr) -> Expr: + return (a - sqrt(a**2 + b))/2 + + t1, t2 = f1(S.NegativeOne, Integer(256)) + z1, z3 = f1(t1, Integer(64)) + z2, z4 = f1(t2, Integer(64)) + y1, y5 = f1(z1, 4*(5 + t1 + 2*z1)) + y6, y2 = f1(z2, 4*(5 + t2 + 2*z2)) + y3, y7 = f1(z3, 4*(5 + t1 + 2*z3)) + y8, y4 = f1(z4, 4*(5 + t2 + 2*z4)) + x1, x9 = f1(y1, -4*(t1 + y1 + y3 + 2*y6)) + x2, x10 = f1(y2, -4*(t2 + y2 + y4 + 2*y7)) + x3, x11 = f1(y3, -4*(t1 + y3 + y5 + 2*y8)) + x4, x12 = f1(y4, -4*(t2 + y4 + y6 + 2*y1)) + x5, x13 = f1(y5, -4*(t1 + y5 + y7 + 2*y2)) + x6, x14 = f1(y6, -4*(t2 + y6 + y8 + 2*y3)) + x15, x7 = f1(y7, -4*(t1 + y7 + y1 + 2*y4)) + x8, x16 = f1(y8, -4*(t2 + y8 + y2 + 2*y5)) + v1 = f2(x1, -4*(x1 + x2 + x3 + x6)) + v2 = f2(x2, -4*(x2 + x3 + x4 + x7)) + v3 = f2(x8, -4*(x8 + x9 + x10 + x13)) + v4 = f2(x9, -4*(x9 + x10 + x11 + x14)) + v5 = f2(x10, -4*(x10 + x11 + x12 + x15)) + v6 = f2(x16, -4*(x16 + x1 + x2 + x5)) + u1 = -f2(-v1, -4*(v2 + v3)) + u2 = -f2(-v4, -4*(v5 + v6)) + w1 = -2*f2(-u1, -4*u2) + return sqrt(sqrt(2)*sqrt(w1 + 4)/8 + S.Half) + + +def cos_table() -> dict[int, Callable[[], Expr]]: + r"""Lazily evaluated table for $\cos \frac{\pi}{n}$ in square roots for + $n \in \{3, 5, 17, 257, 65537\}$. + + Notes + ===== + + 65537 is the only other known Fermat prime and it is nearly impossible to + build in the current SymPy due to performance issues. + + References + ========== + + https://r-knott.surrey.ac.uk/Fibonacci/simpleTrig.html + """ + return { + 3: cos_3, + 5: cos_5, + 17: cos_17, + 257: cos_257 + } diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/benchmarks/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/benchmarks/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/benchmarks/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/benchmarks/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fa4433691c9f21a0fe4f5cc42908883409488c16 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/benchmarks/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/benchmarks/__pycache__/bench_exp.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/benchmarks/__pycache__/bench_exp.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ccecaa89b2304decbc503d63cb300aad480abf65 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/benchmarks/__pycache__/bench_exp.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/benchmarks/bench_exp.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/benchmarks/bench_exp.py new file mode 100644 index 0000000000000000000000000000000000000000..fa18d29f87bcd249baec1d278a030fa7a133c3ba --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/benchmarks/bench_exp.py @@ -0,0 +1,11 @@ +from sympy.core.symbol import symbols +from sympy.functions.elementary.exponential import exp + +x, y = symbols('x,y') + +e = exp(2*x) +q = exp(3*x) + + +def timeit_exp_subs(): + e.subs(q, y) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/complexes.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/complexes.py new file mode 100644 index 0000000000000000000000000000000000000000..dd837e4e242057050370f38c4b4e9c26aa5d06c9 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/complexes.py @@ -0,0 +1,1492 @@ +from __future__ import annotations + +from sympy.core import S, Add, Mul, sympify, Symbol, Dummy, Basic +from sympy.core.expr import Expr +from sympy.core.exprtools import factor_terms +from sympy.core.function import (DefinedFunction, Derivative, ArgumentIndexError, + AppliedUndef, expand_mul, PoleError) +from sympy.core.logic import fuzzy_not, fuzzy_or +from sympy.core.numbers import pi, I, oo +from sympy.core.power import Pow +from sympy.core.relational import Eq +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.piecewise import Piecewise + +############################################################################### +######################### REAL and IMAGINARY PARTS ############################ +############################################################################### + + +class re(DefinedFunction): + """ + Returns real part of expression. This function performs only + elementary analysis and so it will fail to decompose properly + more complicated expressions. If completely simplified result + is needed then use ``Basic.as_real_imag()`` or perform complex + expansion on instance of this function. + + Examples + ======== + + >>> from sympy import re, im, I, E, symbols + >>> x, y = symbols('x y', real=True) + >>> re(2*E) + 2*E + >>> re(2*I + 17) + 17 + >>> re(2*I) + 0 + >>> re(im(x) + x*I + 2) + 2 + >>> re(5 + I + 2) + 7 + + Parameters + ========== + + arg : Expr + Real or complex expression. + + Returns + ======= + + expr : Expr + Real part of expression. + + See Also + ======== + + im + """ + + args: tuple[Expr] + + is_extended_real = True + unbranched = True # implicitly works on the projection to C + _singularities = True # non-holomorphic + + @classmethod + def eval(cls, arg): + if arg is S.NaN: + return S.NaN + elif arg is S.ComplexInfinity: + return S.NaN + elif arg.is_extended_real: + return arg + elif arg.is_imaginary or (I*arg).is_extended_real: + return S.Zero + elif arg.is_Matrix: + return arg.as_real_imag()[0] + elif arg.is_Function and isinstance(arg, conjugate): + return re(arg.args[0]) + else: + + included, reverted, excluded = [], [], [] + args = Add.make_args(arg) + for term in args: + coeff = term.as_coefficient(I) + + if coeff is not None: + if not coeff.is_extended_real: + reverted.append(coeff) + elif not term.has(I) and term.is_extended_real: + excluded.append(term) + else: + # Try to do some advanced expansion. If + # impossible, don't try to do re(arg) again + # (because this is what we are trying to do now). + real_imag = term.as_real_imag(ignore=arg) + if real_imag: + excluded.append(real_imag[0]) + else: + included.append(term) + + if len(args) != len(included): + a, b, c = (Add(*xs) for xs in [included, reverted, excluded]) + + return cls(a) - im(b) + c + + def as_real_imag(self, deep=True, **hints): + """ + Returns the real number with a zero imaginary part. + + """ + return (self, S.Zero) + + def _eval_derivative(self, x): + if x.is_extended_real or self.args[0].is_extended_real: + return re(Derivative(self.args[0], x, evaluate=True)) + if x.is_imaginary or self.args[0].is_imaginary: + return -I \ + * im(Derivative(self.args[0], x, evaluate=True)) + + def _eval_rewrite_as_im(self, arg, **kwargs): + return self.args[0] - I*im(self.args[0]) + + def _eval_is_algebraic(self): + return self.args[0].is_algebraic + + def _eval_is_zero(self): + # is_imaginary implies nonzero + return fuzzy_or([self.args[0].is_imaginary, self.args[0].is_zero]) + + def _eval_is_finite(self): + if self.args[0].is_finite: + return True + + def _eval_is_complex(self): + if self.args[0].is_finite: + return True + + +class im(DefinedFunction): + """ + Returns imaginary part of expression. This function performs only + elementary analysis and so it will fail to decompose properly more + complicated expressions. If completely simplified result is needed then + use ``Basic.as_real_imag()`` or perform complex expansion on instance of + this function. + + Examples + ======== + + >>> from sympy import re, im, E, I + >>> from sympy.abc import x, y + >>> im(2*E) + 0 + >>> im(2*I + 17) + 2 + >>> im(x*I) + re(x) + >>> im(re(x) + y) + im(y) + >>> im(2 + 3*I) + 3 + + Parameters + ========== + + arg : Expr + Real or complex expression. + + Returns + ======= + + expr : Expr + Imaginary part of expression. + + See Also + ======== + + re + """ + + args: tuple[Expr] + + is_extended_real = True + unbranched = True # implicitly works on the projection to C + _singularities = True # non-holomorphic + + @classmethod + def eval(cls, arg): + if arg is S.NaN: + return S.NaN + elif arg is S.ComplexInfinity: + return S.NaN + elif arg.is_extended_real: + return S.Zero + elif arg.is_imaginary or (I*arg).is_extended_real: + return -I * arg + elif arg.is_Matrix: + return arg.as_real_imag()[1] + elif arg.is_Function and isinstance(arg, conjugate): + return -im(arg.args[0]) + else: + included, reverted, excluded = [], [], [] + args = Add.make_args(arg) + for term in args: + coeff = term.as_coefficient(I) + + if coeff is not None: + if not coeff.is_extended_real: + reverted.append(coeff) + else: + excluded.append(coeff) + elif term.has(I) or not term.is_extended_real: + # Try to do some advanced expansion. If + # impossible, don't try to do im(arg) again + # (because this is what we are trying to do now). + real_imag = term.as_real_imag(ignore=arg) + if real_imag: + excluded.append(real_imag[1]) + else: + included.append(term) + + if len(args) != len(included): + a, b, c = (Add(*xs) for xs in [included, reverted, excluded]) + + return cls(a) + re(b) + c + + def as_real_imag(self, deep=True, **hints): + """ + Return the imaginary part with a zero real part. + + """ + return (self, S.Zero) + + def _eval_derivative(self, x): + if x.is_extended_real or self.args[0].is_extended_real: + return im(Derivative(self.args[0], x, evaluate=True)) + if x.is_imaginary or self.args[0].is_imaginary: + return -I \ + * re(Derivative(self.args[0], x, evaluate=True)) + + def _eval_rewrite_as_re(self, arg, **kwargs): + return -I*(self.args[0] - re(self.args[0])) + + def _eval_is_algebraic(self): + return self.args[0].is_algebraic + + def _eval_is_zero(self): + return self.args[0].is_extended_real + + def _eval_is_finite(self): + if self.args[0].is_finite: + return True + + def _eval_is_complex(self): + if self.args[0].is_finite: + return True + +############################################################################### +############### SIGN, ABSOLUTE VALUE, ARGUMENT and CONJUGATION ################ +############################################################################### + +class sign(DefinedFunction): + """ + Returns the complex sign of an expression: + + Explanation + =========== + + If the expression is real the sign will be: + + * $1$ if expression is positive + * $0$ if expression is equal to zero + * $-1$ if expression is negative + + If the expression is imaginary the sign will be: + + * $I$ if im(expression) is positive + * $-I$ if im(expression) is negative + + Otherwise an unevaluated expression will be returned. When evaluated, the + result (in general) will be ``cos(arg(expr)) + I*sin(arg(expr))``. + + Examples + ======== + + >>> from sympy import sign, I + + >>> sign(-1) + -1 + >>> sign(0) + 0 + >>> sign(-3*I) + -I + >>> sign(1 + I) + sign(1 + I) + >>> _.evalf() + 0.707106781186548 + 0.707106781186548*I + + Parameters + ========== + + arg : Expr + Real or imaginary expression. + + Returns + ======= + + expr : Expr + Complex sign of expression. + + See Also + ======== + + Abs, conjugate + """ + + is_complex = True + _singularities = True + + def doit(self, **hints): + s = super().doit() + if s == self and self.args[0].is_zero is False: + return self.args[0] / Abs(self.args[0]) + return s + + @classmethod + def eval(cls, arg): + # handle what we can + if arg.is_Mul: + c, args = arg.as_coeff_mul() + unk = [] + s = sign(c) + for a in args: + if a.is_extended_negative: + s = -s + elif a.is_extended_positive: + pass + else: + if a.is_imaginary: + ai = im(a) + if ai.is_comparable: # i.e. a = I*real + s *= I + if ai.is_extended_negative: + # can't use sign(ai) here since ai might not be + # a Number + s = -s + else: + unk.append(a) + else: + unk.append(a) + if c is S.One and len(unk) == len(args): + return None + return s * cls(arg._new_rawargs(*unk)) + if arg is S.NaN: + return S.NaN + if arg.is_zero: # it may be an Expr that is zero + return S.Zero + if arg.is_extended_positive: + return S.One + if arg.is_extended_negative: + return S.NegativeOne + if arg.is_Function: + if isinstance(arg, sign): + return arg + if arg.is_imaginary: + if arg.is_Pow and arg.exp is S.Half: + # we catch this because non-trivial sqrt args are not expanded + # e.g. sqrt(1-sqrt(2)) --x--> to I*sqrt(sqrt(2) - 1) + return I + arg2 = -I * arg + if arg2.is_extended_positive: + return I + if arg2.is_extended_negative: + return -I + + def _eval_Abs(self): + if fuzzy_not(self.args[0].is_zero): + return S.One + + def _eval_conjugate(self): + return sign(conjugate(self.args[0])) + + def _eval_derivative(self, x): + if self.args[0].is_extended_real: + from sympy.functions.special.delta_functions import DiracDelta + return 2 * Derivative(self.args[0], x, evaluate=True) \ + * DiracDelta(self.args[0]) + elif self.args[0].is_imaginary: + from sympy.functions.special.delta_functions import DiracDelta + return 2 * Derivative(self.args[0], x, evaluate=True) \ + * DiracDelta(-I * self.args[0]) + + def _eval_is_nonnegative(self): + if self.args[0].is_nonnegative: + return True + + def _eval_is_nonpositive(self): + if self.args[0].is_nonpositive: + return True + + def _eval_is_imaginary(self): + return self.args[0].is_imaginary + + def _eval_is_integer(self): + return self.args[0].is_extended_real + + def _eval_is_zero(self): + return self.args[0].is_zero + + def _eval_power(self, other): + if ( + fuzzy_not(self.args[0].is_zero) and + other.is_integer and + other.is_even + ): + return S.One + + def _eval_nseries(self, x, n, logx, cdir=0): + arg0 = self.args[0] + x0 = arg0.subs(x, 0) + if x0 != 0: + return self.func(x0) + if cdir != 0: + cdir = arg0.dir(x, cdir) + return -S.One if re(cdir) < 0 else S.One + + def _eval_rewrite_as_Piecewise(self, arg, **kwargs): + if arg.is_extended_real: + return Piecewise((1, arg > 0), (-1, arg < 0), (0, True)) + + def _eval_rewrite_as_Heaviside(self, arg, **kwargs): + from sympy.functions.special.delta_functions import Heaviside + if arg.is_extended_real: + return Heaviside(arg) * 2 - 1 + + def _eval_rewrite_as_Abs(self, arg, **kwargs): + return Piecewise((0, Eq(arg, 0)), (arg / Abs(arg), True)) + + def _eval_simplify(self, **kwargs): + return self.func(factor_terms(self.args[0])) # XXX include doit? + + +class Abs(DefinedFunction): + """ + Return the absolute value of the argument. + + Explanation + =========== + + This is an extension of the built-in function ``abs()`` to accept symbolic + values. If you pass a SymPy expression to the built-in ``abs()``, it will + pass it automatically to ``Abs()``. + + Examples + ======== + + >>> from sympy import Abs, Symbol, S, I + >>> Abs(-1) + 1 + >>> x = Symbol('x', real=True) + >>> Abs(-x) + Abs(x) + >>> Abs(x**2) + x**2 + >>> abs(-x) # The Python built-in + Abs(x) + >>> Abs(3*x + 2*I) + sqrt(9*x**2 + 4) + >>> Abs(8*I) + 8 + + Note that the Python built-in will return either an Expr or int depending on + the argument:: + + >>> type(abs(-1)) + <... 'int'> + >>> type(abs(S.NegativeOne)) + + + Abs will always return a SymPy object. + + Parameters + ========== + + arg : Expr + Real or complex expression. + + Returns + ======= + + expr : Expr + Absolute value returned can be an expression or integer depending on + input arg. + + See Also + ======== + + sign, conjugate + """ + + args: tuple[Expr] + + is_extended_real = True + is_extended_negative = False + is_extended_nonnegative = True + unbranched = True + _singularities = True # non-holomorphic + + def fdiff(self, argindex=1): + """ + Get the first derivative of the argument to Abs(). + + """ + if argindex == 1: + return sign(self.args[0]) + else: + raise ArgumentIndexError(self, argindex) + + @classmethod + def eval(cls, arg): + from sympy.simplify.simplify import signsimp + + if hasattr(arg, '_eval_Abs'): + obj = arg._eval_Abs() + if obj is not None: + return obj + if not isinstance(arg, Expr): + raise TypeError("Bad argument type for Abs(): %s" % type(arg)) + + # handle what we can + arg = signsimp(arg, evaluate=False) + n, d = arg.as_numer_denom() + if d.free_symbols and not n.free_symbols: + return cls(n)/cls(d) + + if arg.is_Mul: + known = [] + unk = [] + for t in arg.args: + if t.is_Pow and t.exp.is_integer and t.exp.is_negative: + bnew = cls(t.base) + if isinstance(bnew, cls): + unk.append(t) + else: + known.append(Pow(bnew, t.exp)) + else: + tnew = cls(t) + if isinstance(tnew, cls): + unk.append(t) + else: + known.append(tnew) + known = Mul(*known) + unk = cls(Mul(*unk), evaluate=False) if unk else S.One + return known*unk + if arg is S.NaN: + return S.NaN + if arg is S.ComplexInfinity: + return oo + from sympy.functions.elementary.exponential import exp, log + + if arg.is_Pow: + base, exponent = arg.as_base_exp() + if base.is_extended_real: + if exponent.is_integer: + if exponent.is_even: + return arg + if base is S.NegativeOne: + return S.One + return Abs(base)**exponent + if base.is_extended_nonnegative: + return base**re(exponent) + if base.is_extended_negative: + return (-base)**re(exponent)*exp(-pi*im(exponent)) + return + elif not base.has(Symbol): # complex base + # express base**exponent as exp(exponent*log(base)) + a, b = log(base).as_real_imag() + z = a + I*b + return exp(re(exponent*z)) + if isinstance(arg, exp): + return exp(re(arg.args[0])) + if isinstance(arg, AppliedUndef): + if arg.is_positive: + return arg + elif arg.is_negative: + return -arg + return + if arg.is_Add and arg.has(oo, S.NegativeInfinity): + if any(a.is_infinite for a in arg.as_real_imag()): + return oo + if arg.is_zero: + return S.Zero + if arg.is_extended_nonnegative: + return arg + if arg.is_extended_nonpositive: + return -arg + if arg.is_imaginary: + arg2 = -I * arg + if arg2.is_extended_nonnegative: + return arg2 + if arg.is_extended_real: + return + # reject result if all new conjugates are just wrappers around + # an expression that was already in the arg + conj = signsimp(arg.conjugate(), evaluate=False) + new_conj = conj.atoms(conjugate) - arg.atoms(conjugate) + if new_conj and all(arg.has(i.args[0]) for i in new_conj): + return + if arg != conj and arg != -conj: + ignore = arg.atoms(Abs) + abs_free_arg = arg.xreplace({i: Dummy(real=True) for i in ignore}) + unk = [a for a in abs_free_arg.free_symbols if a.is_extended_real is None] + if not unk or not all(conj.has(conjugate(u)) for u in unk): + return sqrt(expand_mul(arg*conj)) + + def _eval_is_real(self): + if self.args[0].is_finite: + return True + + def _eval_is_integer(self): + if self.args[0].is_extended_real: + return self.args[0].is_integer + + def _eval_is_extended_nonzero(self): + return fuzzy_not(self._args[0].is_zero) + + def _eval_is_zero(self): + return self._args[0].is_zero + + def _eval_is_extended_positive(self): + return fuzzy_not(self._args[0].is_zero) + + def _eval_is_rational(self): + if self.args[0].is_extended_real: + return self.args[0].is_rational + + def _eval_is_even(self): + if self.args[0].is_extended_real: + return self.args[0].is_even + + def _eval_is_odd(self): + if self.args[0].is_extended_real: + return self.args[0].is_odd + + def _eval_is_algebraic(self): + return self.args[0].is_algebraic + + def _eval_power(self, exponent): + if self.args[0].is_extended_real and exponent.is_integer: + if exponent.is_even: + return self.args[0]**exponent + elif exponent is not S.NegativeOne and exponent.is_Integer: + return self.args[0]**(exponent - 1)*self + return + + def _eval_nseries(self, x, n, logx, cdir=0): + from sympy.functions.elementary.exponential import log + direction = self.args[0].leadterm(x)[0] + if direction.has(log(x)): + direction = direction.subs(log(x), logx) + s = self.args[0]._eval_nseries(x, n=n, logx=logx) + return (sign(direction)*s).expand() + + def _eval_derivative(self, x): + if self.args[0].is_extended_real or self.args[0].is_imaginary: + return Derivative(self.args[0], x, evaluate=True) \ + * sign(conjugate(self.args[0])) + rv = (re(self.args[0]) * Derivative(re(self.args[0]), x, + evaluate=True) + im(self.args[0]) * Derivative(im(self.args[0]), + x, evaluate=True)) / Abs(self.args[0]) + return rv.rewrite(sign) + + def _eval_rewrite_as_Heaviside(self, arg, **kwargs): + # Note this only holds for real arg (since Heaviside is not defined + # for complex arguments). + from sympy.functions.special.delta_functions import Heaviside + if arg.is_extended_real: + return arg*(Heaviside(arg) - Heaviside(-arg)) + + def _eval_rewrite_as_Piecewise(self, arg, **kwargs): + if arg.is_extended_real: + return Piecewise((arg, arg >= 0), (-arg, True)) + elif arg.is_imaginary: + return Piecewise((I*arg, I*arg >= 0), (-I*arg, True)) + + def _eval_rewrite_as_sign(self, arg, **kwargs): + return arg/sign(arg) + + def _eval_rewrite_as_conjugate(self, arg, **kwargs): + return sqrt(arg*conjugate(arg)) + + +class arg(DefinedFunction): + r""" + Returns the argument (in radians) of a complex number. The argument is + evaluated in consistent convention with ``atan2`` where the branch-cut is + taken along the negative real axis and ``arg(z)`` is in the interval + $(-\pi,\pi]$. For a positive number, the argument is always 0; the + argument of a negative number is $\pi$; and the argument of 0 + is undefined and returns ``nan``. So the ``arg`` function will never nest + greater than 3 levels since at the 4th application, the result must be + nan; for a real number, nan is returned on the 3rd application. + + Examples + ======== + + >>> from sympy import arg, I, sqrt, Dummy + >>> from sympy.abc import x + >>> arg(2.0) + 0 + >>> arg(I) + pi/2 + >>> arg(sqrt(2) + I*sqrt(2)) + pi/4 + >>> arg(sqrt(3)/2 + I/2) + pi/6 + >>> arg(4 + 3*I) + atan(3/4) + >>> arg(0.8 + 0.6*I) + 0.643501108793284 + >>> arg(arg(arg(arg(x)))) + nan + >>> real = Dummy(real=True) + >>> arg(arg(arg(real))) + nan + + Parameters + ========== + + arg : Expr + Real or complex expression. + + Returns + ======= + + value : Expr + Returns arc tangent of arg measured in radians. + + """ + + is_extended_real = True + is_real = True + is_finite = True + _singularities = True # non-holomorphic + + @classmethod + def eval(cls, arg): + a = arg + for i in range(3): + if isinstance(a, cls): + a = a.args[0] + else: + if i == 2 and a.is_extended_real: + return S.NaN + break + else: + return S.NaN + from sympy.functions.elementary.exponential import exp, exp_polar + if isinstance(arg, exp_polar): + return periodic_argument(arg, oo) + elif isinstance(arg, exp): + i_ = im(arg.args[0]) + if i_.is_comparable: + i_ %= 2*S.Pi + if i_ > S.Pi: + i_ -= 2*S.Pi + return i_ + + if not arg.is_Atom: + c, arg_ = factor_terms(arg).as_coeff_Mul() + if arg_.is_Mul: + arg_ = Mul(*[a if (sign(a) not in (-1, 1)) else + sign(a) for a in arg_.args]) + arg_ = sign(c)*arg_ + else: + arg_ = arg + if any(i.is_extended_positive is None for i in arg_.atoms(AppliedUndef)): + return + from sympy.functions.elementary.trigonometric import atan2 + x, y = arg_.as_real_imag() + rv = atan2(y, x) + if rv.is_number: + return rv + if arg_ != arg: + return cls(arg_, evaluate=False) + + def _eval_derivative(self, t): + x, y = self.args[0].as_real_imag() + return (x * Derivative(y, t, evaluate=True) - y * + Derivative(x, t, evaluate=True)) / (x**2 + y**2) + + def _eval_rewrite_as_atan2(self, arg, **kwargs): + from sympy.functions.elementary.trigonometric import atan2 + x, y = self.args[0].as_real_imag() + return atan2(y, x) + + def _eval_as_leading_term(self, x, logx, cdir): + arg0 = self.args[0] + t = Dummy('t', positive=True) + if cdir == 0: + cdir = 1 + z = arg0.subs(x, cdir*t) + if z.is_positive: + return S.Zero + elif z.is_negative: + return S.Pi + else: + raise PoleError("Cannot expand %s around 0" % (self)) + + def _eval_nseries(self, x, n, logx, cdir=0): + from sympy.series.order import Order + if n <= 0: + return Order(1) + return self._eval_as_leading_term(x, logx=logx, cdir=cdir) + + +class conjugate(DefinedFunction): + """ + Returns the *complex conjugate* [1]_ of an argument. + In mathematics, the complex conjugate of a complex number + is given by changing the sign of the imaginary part. + + Thus, the conjugate of the complex number + :math:`a + ib` (where $a$ and $b$ are real numbers) is :math:`a - ib` + + Examples + ======== + + >>> from sympy import conjugate, I + >>> conjugate(2) + 2 + >>> conjugate(I) + -I + >>> conjugate(3 + 2*I) + 3 - 2*I + >>> conjugate(5 - I) + 5 + I + + Parameters + ========== + + arg : Expr + Real or complex expression. + + Returns + ======= + + arg : Expr + Complex conjugate of arg as real, imaginary or mixed expression. + + See Also + ======== + + sign, Abs + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Complex_conjugation + """ + _singularities = True # non-holomorphic + + @classmethod + def eval(cls, arg): + obj = arg._eval_conjugate() + if obj is not None: + return obj + + def inverse(self): + return conjugate + + def _eval_Abs(self): + return Abs(self.args[0], evaluate=True) + + def _eval_adjoint(self): + return transpose(self.args[0]) + + def _eval_conjugate(self): + return self.args[0] + + def _eval_derivative(self, x): + if x.is_real: + return conjugate(Derivative(self.args[0], x, evaluate=True)) + elif x.is_imaginary: + return -conjugate(Derivative(self.args[0], x, evaluate=True)) + + def _eval_transpose(self): + return adjoint(self.args[0]) + + def _eval_is_algebraic(self): + return self.args[0].is_algebraic + + +class transpose(DefinedFunction): + """ + Linear map transposition. + + Examples + ======== + + >>> from sympy import transpose, Matrix, MatrixSymbol + >>> A = MatrixSymbol('A', 25, 9) + >>> transpose(A) + A.T + >>> B = MatrixSymbol('B', 9, 22) + >>> transpose(B) + B.T + >>> transpose(A*B) + B.T*A.T + >>> M = Matrix([[4, 5], [2, 1], [90, 12]]) + >>> M + Matrix([ + [ 4, 5], + [ 2, 1], + [90, 12]]) + >>> transpose(M) + Matrix([ + [4, 2, 90], + [5, 1, 12]]) + + Parameters + ========== + + arg : Matrix + Matrix or matrix expression to take the transpose of. + + Returns + ======= + + value : Matrix + Transpose of arg. + + """ + + @classmethod + def eval(cls, arg): + obj = arg._eval_transpose() + if obj is not None: + return obj + + def _eval_adjoint(self): + return conjugate(self.args[0]) + + def _eval_conjugate(self): + return adjoint(self.args[0]) + + def _eval_transpose(self): + return self.args[0] + + +class adjoint(DefinedFunction): + """ + Conjugate transpose or Hermite conjugation. + + Examples + ======== + + >>> from sympy import adjoint, MatrixSymbol + >>> A = MatrixSymbol('A', 10, 5) + >>> adjoint(A) + Adjoint(A) + + Parameters + ========== + + arg : Matrix + Matrix or matrix expression to take the adjoint of. + + Returns + ======= + + value : Matrix + Represents the conjugate transpose or Hermite + conjugation of arg. + + """ + + @classmethod + def eval(cls, arg): + obj = arg._eval_adjoint() + if obj is not None: + return obj + obj = arg._eval_transpose() + if obj is not None: + return conjugate(obj) + + def _eval_adjoint(self): + return self.args[0] + + def _eval_conjugate(self): + return transpose(self.args[0]) + + def _eval_transpose(self): + return conjugate(self.args[0]) + + def _latex(self, printer, exp=None, *args): + arg = printer._print(self.args[0]) + tex = r'%s^{\dagger}' % arg + if exp: + tex = r'\left(%s\right)^{%s}' % (tex, exp) + return tex + + def _pretty(self, printer, *args): + from sympy.printing.pretty.stringpict import prettyForm + pform = printer._print(self.args[0], *args) + if printer._use_unicode: + pform = pform**prettyForm('\N{DAGGER}') + else: + pform = pform**prettyForm('+') + return pform + +############################################################################### +############### HANDLING OF POLAR NUMBERS ##################################### +############################################################################### + + +class polar_lift(DefinedFunction): + """ + Lift argument to the Riemann surface of the logarithm, using the + standard branch. + + Examples + ======== + + >>> from sympy import Symbol, polar_lift, I + >>> p = Symbol('p', polar=True) + >>> x = Symbol('x') + >>> polar_lift(4) + 4*exp_polar(0) + >>> polar_lift(-4) + 4*exp_polar(I*pi) + >>> polar_lift(-I) + exp_polar(-I*pi/2) + >>> polar_lift(I + 2) + polar_lift(2 + I) + + >>> polar_lift(4*x) + 4*polar_lift(x) + >>> polar_lift(4*p) + 4*p + + Parameters + ========== + + arg : Expr + Real or complex expression. + + See Also + ======== + + sympy.functions.elementary.exponential.exp_polar + periodic_argument + """ + + is_polar = True + is_comparable = False # Cannot be evalf'd. + + @classmethod + def eval(cls, arg): + from sympy.functions.elementary.complexes import arg as argument + if arg.is_number: + ar = argument(arg) + # In general we want to affirm that something is known, + # e.g. `not ar.has(argument) and not ar.has(atan)` + # but for now we will just be more restrictive and + # see that it has evaluated to one of the known values. + if ar in (0, pi/2, -pi/2, pi): + from sympy.functions.elementary.exponential import exp_polar + return exp_polar(I*ar)*abs(arg) + + if arg.is_Mul: + args = arg.args + else: + args = [arg] + included = [] + excluded = [] + positive = [] + for arg in args: + if arg.is_polar: + included += [arg] + elif arg.is_positive: + positive += [arg] + else: + excluded += [arg] + if len(excluded) < len(args): + if excluded: + return Mul(*(included + positive))*polar_lift(Mul(*excluded)) + elif included: + return Mul(*(included + positive)) + else: + from sympy.functions.elementary.exponential import exp_polar + return Mul(*positive)*exp_polar(0) + + def _eval_evalf(self, prec): + """ Careful! any evalf of polar numbers is flaky """ + return self.args[0]._eval_evalf(prec) + + def _eval_Abs(self): + return Abs(self.args[0], evaluate=True) + + +class periodic_argument(DefinedFunction): + r""" + Represent the argument on a quotient of the Riemann surface of the + logarithm. That is, given a period $P$, always return a value in + $(-P/2, P/2]$, by using $\exp(PI) = 1$. + + Examples + ======== + + >>> from sympy import exp_polar, periodic_argument + >>> from sympy import I, pi + >>> periodic_argument(exp_polar(10*I*pi), 2*pi) + 0 + >>> periodic_argument(exp_polar(5*I*pi), 4*pi) + pi + >>> from sympy import exp_polar, periodic_argument + >>> from sympy import I, pi + >>> periodic_argument(exp_polar(5*I*pi), 2*pi) + pi + >>> periodic_argument(exp_polar(5*I*pi), 3*pi) + -pi + >>> periodic_argument(exp_polar(5*I*pi), pi) + 0 + + Parameters + ========== + + ar : Expr + A polar number. + + period : Expr + The period $P$. + + See Also + ======== + + sympy.functions.elementary.exponential.exp_polar + polar_lift : Lift argument to the Riemann surface of the logarithm + principal_branch + """ + + @classmethod + def _getunbranched(cls, ar): + from sympy.functions.elementary.exponential import exp_polar, log + if ar.is_Mul: + args = ar.args + else: + args = [ar] + unbranched = 0 + for a in args: + if not a.is_polar: + unbranched += arg(a) + elif isinstance(a, exp_polar): + unbranched += a.exp.as_real_imag()[1] + elif a.is_Pow: + re, im = a.exp.as_real_imag() + unbranched += re*unbranched_argument( + a.base) + im*log(abs(a.base)) + elif isinstance(a, polar_lift): + unbranched += arg(a.args[0]) + else: + return None + return unbranched + + @classmethod + def eval(cls, ar, period): + # Our strategy is to evaluate the argument on the Riemann surface of the + # logarithm, and then reduce. + # NOTE evidently this means it is a rather bad idea to use this with + # period != 2*pi and non-polar numbers. + if not period.is_extended_positive: + return None + if period == oo and isinstance(ar, principal_branch): + return periodic_argument(*ar.args) + if isinstance(ar, polar_lift) and period >= 2*pi: + return periodic_argument(ar.args[0], period) + if ar.is_Mul: + newargs = [x for x in ar.args if not x.is_positive] + if len(newargs) != len(ar.args): + return periodic_argument(Mul(*newargs), period) + unbranched = cls._getunbranched(ar) + if unbranched is None: + return None + from sympy.functions.elementary.trigonometric import atan, atan2 + if unbranched.has(periodic_argument, atan2, atan): + return None + if period == oo: + return unbranched + if period != oo: + from sympy.functions.elementary.integers import ceiling + n = ceiling(unbranched/period - S.Half)*period + if not n.has(ceiling): + return unbranched - n + + def _eval_evalf(self, prec): + z, period = self.args + if period == oo: + unbranched = periodic_argument._getunbranched(z) + if unbranched is None: + return self + return unbranched._eval_evalf(prec) + ub = periodic_argument(z, oo)._eval_evalf(prec) + from sympy.functions.elementary.integers import ceiling + return (ub - ceiling(ub/period - S.Half)*period)._eval_evalf(prec) + + +def unbranched_argument(arg): + ''' + Returns periodic argument of arg with period as infinity. + + Examples + ======== + + >>> from sympy import exp_polar, unbranched_argument + >>> from sympy import I, pi + >>> unbranched_argument(exp_polar(15*I*pi)) + 15*pi + >>> unbranched_argument(exp_polar(7*I*pi)) + 7*pi + + See also + ======== + + periodic_argument + ''' + return periodic_argument(arg, oo) + + +class principal_branch(DefinedFunction): + """ + Represent a polar number reduced to its principal branch on a quotient + of the Riemann surface of the logarithm. + + Explanation + =========== + + This is a function of two arguments. The first argument is a polar + number `z`, and the second one a positive real number or infinity, `p`. + The result is ``z mod exp_polar(I*p)``. + + Examples + ======== + + >>> from sympy import exp_polar, principal_branch, oo, I, pi + >>> from sympy.abc import z + >>> principal_branch(z, oo) + z + >>> principal_branch(exp_polar(2*pi*I)*3, 2*pi) + 3*exp_polar(0) + >>> principal_branch(exp_polar(2*pi*I)*3*z, 2*pi) + 3*principal_branch(z, 2*pi) + + Parameters + ========== + + x : Expr + A polar number. + + period : Expr + Positive real number or infinity. + + See Also + ======== + + sympy.functions.elementary.exponential.exp_polar + polar_lift : Lift argument to the Riemann surface of the logarithm + periodic_argument + """ + + is_polar = True + is_comparable = False # cannot always be evalf'd + + @classmethod + def eval(self, x, period): + from sympy.functions.elementary.exponential import exp_polar + if isinstance(x, polar_lift): + return principal_branch(x.args[0], period) + if period == oo: + return x + ub = periodic_argument(x, oo) + barg = periodic_argument(x, period) + if ub != barg and not ub.has(periodic_argument) \ + and not barg.has(periodic_argument): + pl = polar_lift(x) + + def mr(expr): + if not isinstance(expr, Symbol): + return polar_lift(expr) + return expr + pl = pl.replace(polar_lift, mr) + # Recompute unbranched argument + ub = periodic_argument(pl, oo) + if not pl.has(polar_lift): + if ub != barg: + res = exp_polar(I*(barg - ub))*pl + else: + res = pl + if not res.is_polar and not res.has(exp_polar): + res *= exp_polar(0) + return res + + if not x.free_symbols: + c, m = x, () + else: + c, m = x.as_coeff_mul(*x.free_symbols) + others = [] + for y in m: + if y.is_positive: + c *= y + else: + others += [y] + m = tuple(others) + arg = periodic_argument(c, period) + if arg.has(periodic_argument): + return None + if arg.is_number and (unbranched_argument(c) != arg or + (arg == 0 and m != () and c != 1)): + if arg == 0: + return abs(c)*principal_branch(Mul(*m), period) + return principal_branch(exp_polar(I*arg)*Mul(*m), period)*abs(c) + if arg.is_number and ((abs(arg) < period/2) == True or arg == period/2) \ + and m == (): + return exp_polar(arg*I)*abs(c) + + def _eval_evalf(self, prec): + z, period = self.args + p = periodic_argument(z, period)._eval_evalf(prec) + if abs(p) > pi or p == -pi: + return self # Cannot evalf for this argument. + from sympy.functions.elementary.exponential import exp + return (abs(z)*exp(I*p))._eval_evalf(prec) + + +def _polarify(eq, lift, pause=False): + from sympy.integrals.integrals import Integral + if eq.is_polar: + return eq + if eq.is_number and not pause: + return polar_lift(eq) + if isinstance(eq, Symbol) and not pause and lift: + return polar_lift(eq) + elif eq.is_Atom: + return eq + elif eq.is_Add: + r = eq.func(*[_polarify(arg, lift, pause=True) for arg in eq.args]) + if lift: + return polar_lift(r) + return r + elif eq.is_Pow and eq.base == S.Exp1: + return eq.func(S.Exp1, _polarify(eq.exp, lift, pause=False)) + elif eq.is_Function: + return eq.func(*[_polarify(arg, lift, pause=False) for arg in eq.args]) + elif isinstance(eq, Integral): + # Don't lift the integration variable + func = _polarify(eq.function, lift, pause=pause) + limits = [] + for limit in eq.args[1:]: + var = _polarify(limit[0], lift=False, pause=pause) + rest = _polarify(limit[1:], lift=lift, pause=pause) + limits.append((var,) + rest) + return Integral(*((func,) + tuple(limits))) + else: + return eq.func(*[_polarify(arg, lift, pause=pause) + if isinstance(arg, Expr) else arg for arg in eq.args]) + + +def polarify(eq, subs=True, lift=False): + """ + Turn all numbers in eq into their polar equivalents (under the standard + choice of argument). + + Note that no attempt is made to guess a formal convention of adding + polar numbers, expressions like $1 + x$ will generally not be altered. + + Note also that this function does not promote ``exp(x)`` to ``exp_polar(x)``. + + If ``subs`` is ``True``, all symbols which are not already polar will be + substituted for polar dummies; in this case the function behaves much + like :func:`~.posify`. + + If ``lift`` is ``True``, both addition statements and non-polar symbols are + changed to their ``polar_lift()``ed versions. + Note that ``lift=True`` implies ``subs=False``. + + Examples + ======== + + >>> from sympy import polarify, sin, I + >>> from sympy.abc import x, y + >>> expr = (-x)**y + >>> expr.expand() + (-x)**y + >>> polarify(expr) + ((_x*exp_polar(I*pi))**_y, {_x: x, _y: y}) + >>> polarify(expr)[0].expand() + _x**_y*exp_polar(_y*I*pi) + >>> polarify(x, lift=True) + polar_lift(x) + >>> polarify(x*(1+y), lift=True) + polar_lift(x)*polar_lift(y + 1) + + Adds are treated carefully: + + >>> polarify(1 + sin((1 + I)*x)) + (sin(_x*polar_lift(1 + I)) + 1, {_x: x}) + """ + if lift: + subs = False + eq = _polarify(sympify(eq), lift) + if not subs: + return eq + reps = {s: Dummy(s.name, polar=True) for s in eq.free_symbols} + eq = eq.subs(reps) + return eq, {r: s for s, r in reps.items()} + + +def _unpolarify(eq, exponents_only, pause=False): + if not isinstance(eq, Basic) or eq.is_Atom: + return eq + + if not pause: + from sympy.functions.elementary.exponential import exp, exp_polar + if isinstance(eq, exp_polar): + return exp(_unpolarify(eq.exp, exponents_only)) + if isinstance(eq, principal_branch) and eq.args[1] == 2*pi: + return _unpolarify(eq.args[0], exponents_only) + if ( + eq.is_Add or eq.is_Mul or eq.is_Boolean or + eq.is_Relational and ( + eq.rel_op in ('==', '!=') and 0 in eq.args or + eq.rel_op not in ('==', '!=')) + ): + return eq.func(*[_unpolarify(x, exponents_only) for x in eq.args]) + if isinstance(eq, polar_lift): + return _unpolarify(eq.args[0], exponents_only) + + if eq.is_Pow: + expo = _unpolarify(eq.exp, exponents_only) + base = _unpolarify(eq.base, exponents_only, + not (expo.is_integer and not pause)) + return base**expo + + if eq.is_Function and getattr(eq.func, 'unbranched', False): + return eq.func(*[_unpolarify(x, exponents_only, exponents_only) + for x in eq.args]) + + return eq.func(*[_unpolarify(x, exponents_only, True) for x in eq.args]) + + +def unpolarify(eq, subs=None, exponents_only=False): + """ + If `p` denotes the projection from the Riemann surface of the logarithm to + the complex line, return a simplified version `eq'` of `eq` such that + `p(eq') = p(eq)`. + Also apply the substitution subs in the end. (This is a convenience, since + ``unpolarify``, in a certain sense, undoes :func:`polarify`.) + + Examples + ======== + + >>> from sympy import unpolarify, polar_lift, sin, I + >>> unpolarify(polar_lift(I + 2)) + 2 + I + >>> unpolarify(sin(polar_lift(I + 7))) + sin(7 + I) + """ + if isinstance(eq, bool): + return eq + + eq = sympify(eq) + if subs is not None: + return unpolarify(eq.subs(subs)) + changed = True + pause = False + if exponents_only: + pause = True + while changed: + changed = False + res = _unpolarify(eq, exponents_only, pause) + if res != eq: + changed = True + eq = res + if isinstance(res, bool): + return res + # Finally, replacing Exp(0) by 1 is always correct. + # So is polar_lift(0) -> 0. + from sympy.functions.elementary.exponential import exp_polar + return res.subs({exp_polar(0): 1, polar_lift(0): 0}) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/exponential.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/exponential.py new file mode 100644 index 0000000000000000000000000000000000000000..2bb0333cb34a35a96248c12a4640e848986f2feb --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/exponential.py @@ -0,0 +1,1286 @@ +from __future__ import annotations +from itertools import product + +from sympy.core.add import Add +from sympy.core.cache import cacheit +from sympy.core.expr import Expr +from sympy.core.function import (DefinedFunction, ArgumentIndexError, expand_log, + expand_mul, FunctionClass, PoleError, expand_multinomial, expand_complex) +from sympy.core.logic import fuzzy_and, fuzzy_not, fuzzy_or +from sympy.core.mul import Mul +from sympy.core.numbers import Integer, Rational, pi, I +from sympy.core.parameters import global_parameters +from sympy.core.power import Pow +from sympy.core.singleton import S +from sympy.core.symbol import Wild, Dummy +from sympy.core.sympify import sympify +from sympy.functions.combinatorial.factorials import factorial +from sympy.functions.elementary.complexes import arg, unpolarify, im, re, Abs +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.ntheory import multiplicity, perfect_power +from sympy.ntheory.factor_ import factorint + +# NOTE IMPORTANT +# The series expansion code in this file is an important part of the gruntz +# algorithm for determining limits. _eval_nseries has to return a generalized +# power series with coefficients in C(log(x), log). +# In more detail, the result of _eval_nseries(self, x, n) must be +# c_0*x**e_0 + ... (finitely many terms) +# where e_i are numbers (not necessarily integers) and c_i involve only +# numbers, the function log, and log(x). [This also means it must not contain +# log(x(1+p)), this *has* to be expanded to log(x)+log(1+p) if x.is_positive and +# p.is_positive.] + + +class ExpBase(DefinedFunction): + + unbranched = True + _singularities = (S.ComplexInfinity,) + + @property + def kind(self): + return self.exp.kind + + def inverse(self, argindex=1): + """ + Returns the inverse function of ``exp(x)``. + """ + return log + + def as_numer_denom(self): + """ + Returns this with a positive exponent as a 2-tuple (a fraction). + + Examples + ======== + + >>> from sympy import exp + >>> from sympy.abc import x + >>> exp(-x).as_numer_denom() + (1, exp(x)) + >>> exp(x).as_numer_denom() + (exp(x), 1) + """ + # this should be the same as Pow.as_numer_denom wrt + # exponent handling + if not self.is_commutative: + return self, S.One + exp = self.exp + neg_exp = exp.is_negative + if not neg_exp and not (-exp).is_negative: + neg_exp = exp.could_extract_minus_sign() + if neg_exp: + return S.One, self.func(-exp) + return self, S.One + + @property + def exp(self): + """ + Returns the exponent of the function. + """ + return self.args[0] + + def as_base_exp(self): + """ + Returns the 2-tuple (base, exponent). + """ + return self.func(1), Mul(*self.args) + + def _eval_adjoint(self): + return self.func(self.exp.adjoint()) + + def _eval_conjugate(self): + return self.func(self.exp.conjugate()) + + def _eval_transpose(self): + return self.func(self.exp.transpose()) + + def _eval_is_finite(self): + arg = self.exp + if arg.is_infinite: + if arg.is_extended_negative: + return True + if arg.is_extended_positive: + return False + if arg.is_finite: + return True + + def _eval_is_rational(self): + s = self.func(*self.args) + if s.func == self.func: + z = s.exp.is_zero + if z: + return True + elif s.exp.is_rational and fuzzy_not(z): + return False + else: + return s.is_rational + + def _eval_is_zero(self): + return self.exp is S.NegativeInfinity + + def _eval_power(self, other): + """exp(arg)**e -> exp(arg*e) if assumptions allow it. + """ + b, e = self.as_base_exp() + return Pow._eval_power(Pow(b, e, evaluate=False), other) + + def _eval_expand_power_exp(self, **hints): + from sympy.concrete.products import Product + from sympy.concrete.summations import Sum + arg = self.args[0] + if arg.is_Add and arg.is_commutative: + return Mul.fromiter(self.func(x) for x in arg.args) + elif isinstance(arg, Sum) and arg.is_commutative: + return Product(self.func(arg.function), *arg.limits) + return self.func(arg) + + +class exp_polar(ExpBase): + r""" + Represent a *polar number* (see g-function Sphinx documentation). + + Explanation + =========== + + ``exp_polar`` represents the function + `Exp: \mathbb{C} \rightarrow \mathcal{S}`, sending the complex number + `z = a + bi` to the polar number `r = exp(a), \theta = b`. It is one of + the main functions to construct polar numbers. + + Examples + ======== + + >>> from sympy import exp_polar, pi, I, exp + + The main difference is that polar numbers do not "wrap around" at `2 \pi`: + + >>> exp(2*pi*I) + 1 + >>> exp_polar(2*pi*I) + exp_polar(2*I*pi) + + apart from that they behave mostly like classical complex numbers: + + >>> exp_polar(2)*exp_polar(3) + exp_polar(5) + + See Also + ======== + + sympy.simplify.powsimp.powsimp + polar_lift + periodic_argument + principal_branch + """ + + is_polar = True + is_comparable = False # cannot be evalf'd + + def _eval_Abs(self): # Abs is never a polar number + return exp(re(self.args[0])) + + def _eval_evalf(self, prec): + """ Careful! any evalf of polar numbers is flaky """ + i = im(self.args[0]) + try: + bad = (i <= -pi or i > pi) + except TypeError: + bad = True + if bad: + return self # cannot evalf for this argument + res = exp(self.args[0])._eval_evalf(prec) + if i > 0 and im(res) < 0: + # i ~ pi, but exp(I*i) evaluated to argument slightly bigger than pi + return re(res) + return res + + def _eval_power(self, other): + return self.func(self.args[0]*other) + + def _eval_is_extended_real(self): + if self.args[0].is_extended_real: + return True + + def as_base_exp(self): + # XXX exp_polar(0) is special! + if self.args[0] == 0: + return self, S.One + return ExpBase.as_base_exp(self) + + +class ExpMeta(FunctionClass): + def __instancecheck__(cls, instance): + if exp in instance.__class__.__mro__: + return True + return isinstance(instance, Pow) and instance.base is S.Exp1 + + +class exp(ExpBase, metaclass=ExpMeta): + """ + The exponential function, :math:`e^x`. + + Examples + ======== + + >>> from sympy import exp, I, pi + >>> from sympy.abc import x + >>> exp(x) + exp(x) + >>> exp(x).diff(x) + exp(x) + >>> exp(I*pi) + -1 + + Parameters + ========== + + arg : Expr + + See Also + ======== + + log + """ + + def fdiff(self, argindex=1): + """ + Returns the first derivative of this function. + """ + if argindex == 1: + return self + else: + raise ArgumentIndexError(self, argindex) + + def _eval_refine(self, assumptions): + from sympy.assumptions import ask, Q + arg = self.args[0] + if arg.is_Mul: + Ioo = I*S.Infinity + if arg in [Ioo, -Ioo]: + return S.NaN + + coeff = arg.as_coefficient(pi*I) + if coeff: + if ask(Q.integer(2*coeff)): + if ask(Q.even(coeff)): + return S.One + elif ask(Q.odd(coeff)): + return S.NegativeOne + elif ask(Q.even(coeff + S.Half)): + return -I + elif ask(Q.odd(coeff + S.Half)): + return I + + @classmethod + def eval(cls, arg): + from sympy.calculus import AccumBounds + from sympy.matrices.matrixbase import MatrixBase + from sympy.sets.setexpr import SetExpr + from sympy.simplify.simplify import logcombine + if isinstance(arg, MatrixBase): + return arg.exp() + elif global_parameters.exp_is_pow: + return Pow(S.Exp1, arg) + elif arg.is_Number: + if arg is S.NaN: + return S.NaN + elif arg.is_zero: + return S.One + elif arg is S.One: + return S.Exp1 + elif arg is S.Infinity: + return S.Infinity + elif arg is S.NegativeInfinity: + return S.Zero + elif arg is S.ComplexInfinity: + return S.NaN + elif isinstance(arg, log): + return arg.args[0] + elif isinstance(arg, AccumBounds): + return AccumBounds(exp(arg.min), exp(arg.max)) + elif isinstance(arg, SetExpr): + return arg._eval_func(cls) + elif arg.is_Mul: + coeff = arg.as_coefficient(pi*I) + if coeff: + if (2*coeff).is_integer: + if coeff.is_even: + return S.One + elif coeff.is_odd: + return S.NegativeOne + elif (coeff + S.Half).is_even: + return -I + elif (coeff + S.Half).is_odd: + return I + elif coeff.is_Rational: + ncoeff = coeff % 2 # restrict to [0, 2pi) + if ncoeff > 1: # restrict to (-pi, pi] + ncoeff -= 2 + if ncoeff != coeff: + return cls(ncoeff*pi*I) + + # Warning: code in risch.py will be very sensitive to changes + # in this (see DifferentialExtension). + + # look for a single log factor + + coeff, terms = arg.as_coeff_Mul() + + # but it can't be multiplied by oo + if coeff in [S.NegativeInfinity, S.Infinity]: + if terms.is_number: + if coeff is S.NegativeInfinity: + terms = -terms + if re(terms).is_zero and terms is not S.Zero: + return S.NaN + if re(terms).is_positive and im(terms) is not S.Zero: + return S.ComplexInfinity + if re(terms).is_negative: + return S.Zero + return None + + coeffs, log_term = [coeff], None + for term in Mul.make_args(terms): + term_ = logcombine(term) + if isinstance(term_, log): + if log_term is None: + log_term = term_.args[0] + else: + return None + elif term.is_comparable: + coeffs.append(term) + else: + return None + + return log_term**Mul(*coeffs) if log_term else None + + elif arg.is_Add: + out = [] + add = [] + argchanged = False + for a in arg.args: + if a is S.One: + add.append(a) + continue + newa = cls(a) + if isinstance(newa, cls): + if newa.args[0] != a: + add.append(newa.args[0]) + argchanged = True + else: + add.append(a) + else: + out.append(newa) + if out or argchanged: + return Mul(*out)*cls(Add(*add), evaluate=False) + + if arg.is_zero: + return S.One + + @property + def base(self): + """ + Returns the base of the exponential function. + """ + return S.Exp1 + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + """ + Calculates the next term in the Taylor series expansion. + """ + if n < 0: + return S.Zero + if n == 0: + return S.One + x = sympify(x) + if previous_terms: + p = previous_terms[-1] + if p is not None: + return p * x / n + return x**n/factorial(n) + + def as_real_imag(self, deep=True, **hints): + """ + Returns this function as a 2-tuple representing a complex number. + + Examples + ======== + + >>> from sympy import exp, I + >>> from sympy.abc import x + >>> exp(x).as_real_imag() + (exp(re(x))*cos(im(x)), exp(re(x))*sin(im(x))) + >>> exp(1).as_real_imag() + (E, 0) + >>> exp(I).as_real_imag() + (cos(1), sin(1)) + >>> exp(1+I).as_real_imag() + (E*cos(1), E*sin(1)) + + See Also + ======== + + sympy.functions.elementary.complexes.re + sympy.functions.elementary.complexes.im + """ + from sympy.functions.elementary.trigonometric import cos, sin + re, im = self.args[0].as_real_imag() + if deep: + re = re.expand(deep, **hints) + im = im.expand(deep, **hints) + cos, sin = cos(im), sin(im) + return (exp(re)*cos, exp(re)*sin) + + def _eval_subs(self, old, new): + # keep processing of power-like args centralized in Pow + if old.is_Pow: # handle (exp(3*log(x))).subs(x**2, z) -> z**(3/2) + old = exp(old.exp*log(old.base)) + elif old is S.Exp1 and new.is_Function: + old = exp + if isinstance(old, exp) or old is S.Exp1: + f = lambda a: Pow(*a.as_base_exp(), evaluate=False) if ( + a.is_Pow or isinstance(a, exp)) else a + return Pow._eval_subs(f(self), f(old), new) + + if old is exp and not new.is_Function: + return new**self.exp._subs(old, new) + return super()._eval_subs(old, new) + + def _eval_is_extended_real(self): + if self.args[0].is_extended_real: + return True + elif self.args[0].is_imaginary: + arg2 = -S(2) * I * self.args[0] / pi + return arg2.is_even + + def _eval_is_complex(self): + def complex_extended_negative(arg): + yield arg.is_complex + yield arg.is_extended_negative + return fuzzy_or(complex_extended_negative(self.args[0])) + + def _eval_is_algebraic(self): + if (self.exp / pi / I).is_rational: + return True + if fuzzy_not(self.exp.is_zero): + if self.exp.is_algebraic: + return False + elif (self.exp / pi).is_rational: + return False + + def _eval_is_extended_positive(self): + if self.exp.is_extended_real: + return self.args[0] is not S.NegativeInfinity + elif self.exp.is_imaginary: + arg2 = -I * self.args[0] / pi + return arg2.is_even + + def _eval_nseries(self, x, n, logx, cdir=0): + # NOTE Please see the comment at the beginning of this file, labelled + # IMPORTANT. + from sympy.functions.elementary.complexes import sign + from sympy.functions.elementary.integers import ceiling + from sympy.series.limits import limit + from sympy.series.order import Order + from sympy.simplify.powsimp import powsimp + arg = self.exp + arg_series = arg._eval_nseries(x, n=n, logx=logx) + if arg_series.is_Order: + return 1 + arg_series + arg0 = limit(arg_series.removeO(), x, 0) + if arg0 is S.NegativeInfinity: + return Order(x**n, x) + if arg0 is S.Infinity: + return self + if arg0.is_infinite: + raise PoleError("Cannot expand %s around 0" % (self)) + # checking for indecisiveness/ sign terms in arg0 + if any(isinstance(arg, sign) for arg in arg0.args): + return self + t = Dummy("t") + nterms = n + try: + cf = Order(arg.as_leading_term(x, logx=logx), x).getn() + except (NotImplementedError, PoleError): + cf = 0 + if cf and cf > 0: + nterms = ceiling(n/cf) + exp_series = exp(t)._taylor(t, nterms) + r = exp(arg0)*exp_series.subs(t, arg_series - arg0) + rep = {logx: log(x)} if logx is not None else {} + if r.subs(rep) == self: + return r + if cf and cf > 1: + r += Order((arg_series - arg0)**n, x)/x**((cf-1)*n) + else: + r += Order((arg_series - arg0)**n, x) + r = r.expand() + r = powsimp(r, deep=True, combine='exp') + # powsimp may introduce unexpanded (-1)**Rational; see PR #17201 + simplerat = lambda x: x.is_Rational and x.q in [3, 4, 6] + w = Wild('w', properties=[simplerat]) + r = r.replace(S.NegativeOne**w, expand_complex(S.NegativeOne**w)) + return r + + def _taylor(self, x, n): + l = [] + g = None + for i in range(n): + g = self.taylor_term(i, self.args[0], g) + g = g.nseries(x, n=n) + l.append(g.removeO()) + return Add(*l) + + def _eval_as_leading_term(self, x, logx, cdir): + from sympy.calculus.util import AccumBounds + arg = self.args[0].cancel().as_leading_term(x, logx=logx) + arg0 = arg.subs(x, 0) + if arg is S.NaN: + return S.NaN + if isinstance(arg0, AccumBounds): + # This check addresses a corner case involving AccumBounds. + # if isinstance(arg, AccumBounds) is True, then arg0 can either be 0, + # AccumBounds(-oo, 0) or AccumBounds(-oo, oo). + # Check out function: test_issue_18473() in test_exponential.py and + # test_limits.py for more information. + if re(cdir) < S.Zero: + return exp(-arg0) + return exp(arg0) + if arg0 is S.NaN: + arg0 = arg.limit(x, 0) + if arg0.is_infinite is False: + return exp(arg0) + raise PoleError("Cannot expand %s around 0" % (self)) + + def _eval_rewrite_as_sin(self, arg, **kwargs): + from sympy.functions.elementary.trigonometric import sin + return sin(I*arg + pi/2) - I*sin(I*arg) + + def _eval_rewrite_as_cos(self, arg, **kwargs): + from sympy.functions.elementary.trigonometric import cos + return cos(I*arg) + I*cos(I*arg + pi/2) + + def _eval_rewrite_as_tanh(self, arg, **kwargs): + from sympy.functions.elementary.hyperbolic import tanh + return (1 + tanh(arg/2))/(1 - tanh(arg/2)) + + def _eval_rewrite_as_sqrt(self, arg, **kwargs): + from sympy.functions.elementary.trigonometric import sin, cos + if arg.is_Mul: + coeff = arg.coeff(pi*I) + if coeff and coeff.is_number: + cosine, sine = cos(pi*coeff), sin(pi*coeff) + if not isinstance(cosine, cos) and not isinstance (sine, sin): + return cosine + I*sine + + def _eval_rewrite_as_Pow(self, arg, **kwargs): + if arg.is_Mul: + logs = [a for a in arg.args if isinstance(a, log) and len(a.args) == 1] + if logs: + return Pow(logs[0].args[0], arg.coeff(logs[0])) + + +def match_real_imag(expr): + r""" + Try to match expr with $a + Ib$ for real $a$ and $b$. + + ``match_real_imag`` returns a tuple containing the real and imaginary + parts of expr or ``(None, None)`` if direct matching is not possible. Contrary + to :func:`~.re`, :func:`~.im``, and ``as_real_imag()``, this helper will not force things + by returning expressions themselves containing ``re()`` or ``im()`` and it + does not expand its argument either. + + """ + r_, i_ = expr.as_independent(I, as_Add=True) + if i_ == 0 and r_.is_real: + return (r_, i_) + i_ = i_.as_coefficient(I) + if i_ and i_.is_real and r_.is_real: + return (r_, i_) + else: + return (None, None) # simpler to check for than None + + +class log(DefinedFunction): + r""" + The natural logarithm function `\ln(x)` or `\log(x)`. + + Explanation + =========== + + Logarithms are taken with the natural base, `e`. To get + a logarithm of a different base ``b``, use ``log(x, b)``, + which is essentially short-hand for ``log(x)/log(b)``. + + ``log`` represents the principal branch of the natural + logarithm. As such it has a branch cut along the negative + real axis and returns values having a complex argument in + `(-\pi, \pi]`. + + Examples + ======== + + >>> from sympy import log, sqrt, S, I + >>> log(8, 2) + 3 + >>> log(S(8)/3, 2) + -log(3)/log(2) + 3 + >>> log(-1 + I*sqrt(3)) + log(2) + 2*I*pi/3 + + See Also + ======== + + exp + + """ + + args: tuple[Expr] + + _singularities = (S.Zero, S.ComplexInfinity) + + def fdiff(self, argindex=1): + """ + Returns the first derivative of the function. + """ + if argindex == 1: + return 1/self.args[0] + else: + raise ArgumentIndexError(self, argindex) + + def inverse(self, argindex=1): + r""" + Returns `e^x`, the inverse function of `\log(x)`. + """ + return exp + + @classmethod + def eval(cls, arg, base=None): + from sympy.calculus import AccumBounds + from sympy.sets.setexpr import SetExpr + + arg = sympify(arg) + + if base is not None: + base = sympify(base) + if base == 1: + if arg == 1: + return S.NaN + else: + return S.ComplexInfinity + try: + # handle extraction of powers of the base now + # or else expand_log in Mul would have to handle this + n = multiplicity(base, arg) + if n: + return n + log(arg / base**n) / log(base) + else: + return log(arg)/log(base) + except ValueError: + pass + if base is not S.Exp1: + return cls(arg)/cls(base) + else: + return cls(arg) + + if arg.is_Number: + if arg.is_zero: + return S.ComplexInfinity + elif arg is S.One: + return S.Zero + elif arg is S.Infinity: + return S.Infinity + elif arg is S.NegativeInfinity: + return S.Infinity + elif arg is S.NaN: + return S.NaN + elif arg.is_Rational and arg.p == 1: + return -cls(arg.q) + + if arg.is_Pow and arg.base is S.Exp1 and arg.exp.is_extended_real: + return arg.exp + if isinstance(arg, exp) and arg.exp.is_extended_real: + return arg.exp + elif isinstance(arg, exp) and arg.exp.is_number: + r_, i_ = match_real_imag(arg.exp) + if i_ and i_.is_comparable: + i_ %= 2*pi + if i_ > pi: + i_ -= 2*pi + return r_ + expand_mul(i_ * I, deep=False) + elif isinstance(arg, exp_polar): + return unpolarify(arg.exp) + elif isinstance(arg, AccumBounds): + if arg.min.is_positive: + return AccumBounds(log(arg.min), log(arg.max)) + elif arg.min.is_zero: + return AccumBounds(S.NegativeInfinity, log(arg.max)) + else: + return S.NaN + elif isinstance(arg, SetExpr): + return arg._eval_func(cls) + + if arg.is_number: + if arg.is_negative: + return pi * I + cls(-arg) + elif arg is S.ComplexInfinity: + return S.ComplexInfinity + elif arg is S.Exp1: + return S.One + + if arg.is_zero: + return S.ComplexInfinity + + # don't autoexpand Pow or Mul (see the issue 3351): + if not arg.is_Add: + coeff = arg.as_coefficient(I) + + if coeff is not None: + if coeff is S.Infinity: + return S.Infinity + elif coeff is S.NegativeInfinity: + return S.Infinity + elif coeff.is_Rational: + if coeff.is_nonnegative: + return pi * I * S.Half + cls(coeff) + else: + return -pi * I * S.Half + cls(-coeff) + + if arg.is_number and arg.is_algebraic: + # Match arg = coeff*(r_ + i_*I) with coeff>0, r_ and i_ real. + coeff, arg_ = arg.as_independent(I, as_Add=False) + if coeff.is_negative: + coeff *= -1 + arg_ *= -1 + arg_ = expand_mul(arg_, deep=False) + r_, i_ = arg_.as_independent(I, as_Add=True) + i_ = i_.as_coefficient(I) + if coeff.is_real and i_ and i_.is_real and r_.is_real: + if r_.is_zero: + if i_.is_positive: + return pi * I * S.Half + cls(coeff * i_) + elif i_.is_negative: + return -pi * I * S.Half + cls(coeff * -i_) + else: + from sympy.simplify import ratsimp + # Check for arguments involving rational multiples of pi + t = (i_/r_).cancel() + t1 = (-t).cancel() + atan_table = _log_atan_table() + if t in atan_table: + modulus = ratsimp(coeff * Abs(arg_)) + if r_.is_positive: + return cls(modulus) + I * atan_table[t] + else: + return cls(modulus) + I * (atan_table[t] - pi) + elif t1 in atan_table: + modulus = ratsimp(coeff * Abs(arg_)) + if r_.is_positive: + return cls(modulus) + I * (-atan_table[t1]) + else: + return cls(modulus) + I * (pi - atan_table[t1]) + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): # of log(1+x) + r""" + Returns the next term in the Taylor series expansion of `\log(1+x)`. + """ + from sympy.simplify.powsimp import powsimp + if n < 0: + return S.Zero + x = sympify(x) + if n == 0: + return x + if previous_terms: + p = previous_terms[-1] + if p is not None: + return powsimp((-n) * p * x / (n + 1), deep=True, combine='exp') + return (1 - 2*(n % 2)) * x**(n + 1)/(n + 1) + + def _eval_expand_log(self, deep=True, **hints): + from sympy.concrete import Sum, Product + force = hints.get('force', False) + factor = hints.get('factor', False) + if (len(self.args) == 2): + return expand_log(self.func(*self.args), deep=deep, force=force) + arg = self.args[0] + if arg.is_Integer: + # remove perfect powers + p = perfect_power(arg) + logarg = None + coeff = 1 + if p is not False: + arg, coeff = p + logarg = self.func(arg) + # expand as product of its prime factors if factor=True + if factor: + p = factorint(arg) + if arg not in p.keys(): + logarg = sum(n*log(val) for val, n in p.items()) + if logarg is not None: + return coeff*logarg + elif arg.is_Rational: + return log(arg.p) - log(arg.q) + elif arg.is_Mul: + expr = [] + nonpos = [] + for x in arg.args: + if force or x.is_positive or x.is_polar: + a = self.func(x) + if isinstance(a, log): + expr.append(self.func(x)._eval_expand_log(**hints)) + else: + expr.append(a) + elif x.is_negative: + a = self.func(-x) + expr.append(a) + nonpos.append(S.NegativeOne) + else: + nonpos.append(x) + return Add(*expr) + log(Mul(*nonpos)) + elif arg.is_Pow or isinstance(arg, exp): + if force or (arg.exp.is_extended_real and (arg.base.is_positive or ((arg.exp+1) + .is_positive and (arg.exp-1).is_nonpositive))) or arg.base.is_polar: + b = arg.base + e = arg.exp + a = self.func(b) + if isinstance(a, log): + return unpolarify(e) * a._eval_expand_log(**hints) + else: + return unpolarify(e) * a + elif isinstance(arg, Product): + if force or arg.function.is_positive: + return Sum(log(arg.function), *arg.limits) + + return self.func(arg) + + def _eval_simplify(self, **kwargs): + from sympy.simplify.simplify import expand_log, simplify, inversecombine + if len(self.args) == 2: # it's unevaluated + return simplify(self.func(*self.args), **kwargs) + + expr = self.func(simplify(self.args[0], **kwargs)) + if kwargs['inverse']: + expr = inversecombine(expr) + expr = expand_log(expr, deep=True) + return min([expr, self], key=kwargs['measure']) + + def as_real_imag(self, deep=True, **hints): + """ + Returns this function as a complex coordinate. + + Examples + ======== + + >>> from sympy import I, log + >>> from sympy.abc import x + >>> log(x).as_real_imag() + (log(Abs(x)), arg(x)) + >>> log(I).as_real_imag() + (0, pi/2) + >>> log(1 + I).as_real_imag() + (log(sqrt(2)), pi/4) + >>> log(I*x).as_real_imag() + (log(Abs(x)), arg(I*x)) + + """ + sarg = self.args[0] + if deep: + sarg = self.args[0].expand(deep, **hints) + sarg_abs = Abs(sarg) + if sarg_abs == sarg: + return self, S.Zero + sarg_arg = arg(sarg) + if hints.get('log', False): # Expand the log + hints['complex'] = False + return (log(sarg_abs).expand(deep, **hints), sarg_arg) + else: + return log(sarg_abs), sarg_arg + + def _eval_is_rational(self): + s = self.func(*self.args) + if s.func == self.func: + if (self.args[0] - 1).is_zero: + return True + if s.args[0].is_rational and fuzzy_not((self.args[0] - 1).is_zero): + return False + else: + return s.is_rational + + def _eval_is_algebraic(self): + s = self.func(*self.args) + if s.func == self.func: + if (self.args[0] - 1).is_zero: + return True + elif fuzzy_not((self.args[0] - 1).is_zero): + if self.args[0].is_algebraic: + return False + else: + return s.is_algebraic + + def _eval_is_extended_real(self): + return self.args[0].is_extended_positive + + def _eval_is_complex(self): + z = self.args[0] + return fuzzy_and([z.is_complex, fuzzy_not(z.is_zero)]) + + def _eval_is_finite(self): + arg = self.args[0] + if arg.is_zero: + return False + return arg.is_finite + + def _eval_is_extended_positive(self): + return (self.args[0] - 1).is_extended_positive + + def _eval_is_zero(self): + return (self.args[0] - 1).is_zero + + def _eval_is_extended_nonnegative(self): + return (self.args[0] - 1).is_extended_nonnegative + + def _eval_nseries(self, x, n, logx, cdir=0): + # NOTE Please see the comment at the beginning of this file, labelled + # IMPORTANT. + from sympy.series.order import Order + from sympy.simplify.simplify import logcombine + from sympy.core.symbol import Dummy + + if self.args[0] == x: + return log(x) if logx is None else logx + arg = self.args[0] + t = Dummy('t', positive=True) + if cdir == 0: + cdir = 1 + z = arg.subs(x, cdir*t) + + k, l = Wild("k"), Wild("l") + r = z.match(k*t**l) + if r is not None: + k, l = r[k], r[l] + if l != 0 and not l.has(t) and not k.has(t): + r = l*log(x) if logx is None else l*logx + r += log(k) - l*log(cdir) # XXX true regardless of assumptions? + return r + + def coeff_exp(term, x): + coeff, exp = S.One, S.Zero + for factor in Mul.make_args(term): + if factor.has(x): + base, exp = factor.as_base_exp() + if base != x: + try: + return term.leadterm(x) + except ValueError: + return term, S.Zero + else: + coeff *= factor + return coeff, exp + + # TODO new and probably slow + try: + a, b = z.leadterm(t, logx=logx, cdir=1) + except (ValueError, NotImplementedError, PoleError): + s = z._eval_nseries(t, n=n, logx=logx, cdir=1) + while s.is_Order: + n += 1 + s = z._eval_nseries(t, n=n, logx=logx, cdir=1) + try: + a, b = s.removeO().leadterm(t, cdir=1) + except ValueError: + a, b = s.removeO().as_leading_term(t, cdir=1), S.Zero + + p = (z/(a*t**b) - 1).cancel()._eval_nseries(t, n=n, logx=logx, cdir=1) + if p.has(exp): + p = logcombine(p) + if isinstance(p, Order): + n = p.getn() + _, d = coeff_exp(p, t) + logx = log(x) if logx is None else logx + + if not d.is_positive: + res = log(a) - b*log(cdir) + b*logx + _res = res + logflags = {"deep": True, "log": True, "mul": False, "power_exp": False, + "power_base": False, "multinomial": False, "basic": False, "force": True, + "factor": False} + expr = self.expand(**logflags) + if (not a.could_extract_minus_sign() and + logx.could_extract_minus_sign()): + _res = _res.subs(-logx, -log(x)).expand(**logflags) + else: + _res = _res.subs(logx, log(x)).expand(**logflags) + if _res == expr: + return res + return res + Order(x**n, x) + + def mul(d1, d2): + res = {} + for e1, e2 in product(d1, d2): + ex = e1 + e2 + if ex < n: + res[ex] = res.get(ex, S.Zero) + d1[e1]*d2[e2] + return res + + pterms = {} + + for term in Add.make_args(p.removeO()): + co1, e1 = coeff_exp(term, t) + pterms[e1] = pterms.get(e1, S.Zero) + co1 + + k = S.One + terms = {} + pk = pterms + + while k*d < n: + coeff = -S.NegativeOne**k/k + for ex in pk: + terms[ex] = terms.get(ex, S.Zero) + coeff*pk[ex] + pk = mul(pk, pterms) + k += S.One + + res = log(a) - b*log(cdir) + b*logx + for ex in terms: + res += terms[ex].cancel()*t**(ex) + + if a.is_negative and im(z) != 0: + from sympy.functions.special.delta_functions import Heaviside + for i, term in enumerate(z.lseries(t)): + if not term.is_real or i == 5: + break + if i < 5: + coeff, _ = term.as_coeff_exponent(t) + res += -2*I*pi*Heaviside(-im(coeff), 0) + + res = res.subs(t, x/cdir) + return res + Order(x**n, x) + + def _eval_as_leading_term(self, x, logx, cdir): + # NOTE + # Refer https://github.com/sympy/sympy/pull/23592 for more information + # on each of the following steps involved in this method. + arg0 = self.args[0].together() + + # STEP 1 + t = Dummy('t', positive=True) + if cdir == 0: + cdir = 1 + z = arg0.subs(x, cdir*t) + + # STEP 2 + try: + c, e = z.leadterm(t, logx=logx, cdir=1) + except ValueError: + arg = arg0.as_leading_term(x, logx=logx, cdir=cdir) + return log(arg) + if c.has(t): + c = c.subs(t, x/cdir) + if e != 0: + raise PoleError("Cannot expand %s around 0" % (self)) + return log(c) + + # STEP 3 + if c == S.One and e == S.Zero: + return (arg0 - S.One).as_leading_term(x, logx=logx) + + # STEP 4 + res = log(c) - e*log(cdir) + logx = log(x) if logx is None else logx + res += e*logx + + # STEP 5 + if c.is_negative and im(z) != 0: + from sympy.functions.special.delta_functions import Heaviside + for i, term in enumerate(z.lseries(t)): + if not term.is_real or i == 5: + break + if i < 5: + coeff, _ = term.as_coeff_exponent(t) + res += -2*I*pi*Heaviside(-im(coeff), 0) + return res + + +class LambertW(DefinedFunction): + r""" + The Lambert W function $W(z)$ is defined as the inverse + function of $w \exp(w)$ [1]_. + + Explanation + =========== + + In other words, the value of $W(z)$ is such that $z = W(z) \exp(W(z))$ + for any complex number $z$. The Lambert W function is a multivalued + function with infinitely many branches $W_k(z)$, indexed by + $k \in \mathbb{Z}$. Each branch gives a different solution $w$ + of the equation $z = w \exp(w)$. + + The Lambert W function has two partially real branches: the + principal branch ($k = 0$) is real for real $z > -1/e$, and the + $k = -1$ branch is real for $-1/e < z < 0$. All branches except + $k = 0$ have a logarithmic singularity at $z = 0$. + + Examples + ======== + + >>> from sympy import LambertW + >>> LambertW(1.2) + 0.635564016364870 + >>> LambertW(1.2, -1).n() + -1.34747534407696 - 4.41624341514535*I + >>> LambertW(-1).is_real + False + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Lambert_W_function + """ + _singularities = (-Pow(S.Exp1, -1, evaluate=False), S.ComplexInfinity) + + @classmethod + def eval(cls, x, k=None): + if k == S.Zero: + return cls(x) + elif k is None: + k = S.Zero + + if k.is_zero: + if x.is_zero: + return S.Zero + if x is S.Exp1: + return S.One + if x == -1/S.Exp1: + return S.NegativeOne + if x == -log(2)/2: + return -log(2) + if x == 2*log(2): + return log(2) + if x == -pi/2: + return I*pi/2 + if x == exp(1 + S.Exp1): + return S.Exp1 + if x is S.Infinity: + return S.Infinity + + if fuzzy_not(k.is_zero): + if x.is_zero: + return S.NegativeInfinity + if k is S.NegativeOne: + if x == -pi/2: + return -I*pi/2 + elif x == -1/S.Exp1: + return S.NegativeOne + elif x == -2*exp(-2): + return -Integer(2) + + def fdiff(self, argindex=1): + """ + Return the first derivative of this function. + """ + x = self.args[0] + + if len(self.args) == 1: + if argindex == 1: + return LambertW(x)/(x*(1 + LambertW(x))) + else: + k = self.args[1] + if argindex == 1: + return LambertW(x, k)/(x*(1 + LambertW(x, k))) + + raise ArgumentIndexError(self, argindex) + + def _eval_is_extended_real(self): + x = self.args[0] + if len(self.args) == 1: + k = S.Zero + else: + k = self.args[1] + if k.is_zero: + if (x + 1/S.Exp1).is_positive: + return True + elif (x + 1/S.Exp1).is_nonpositive: + return False + elif (k + 1).is_zero: + if x.is_negative and (x + 1/S.Exp1).is_positive: + return True + elif x.is_nonpositive or (x + 1/S.Exp1).is_nonnegative: + return False + elif fuzzy_not(k.is_zero) and fuzzy_not((k + 1).is_zero): + if x.is_extended_real: + return False + + def _eval_is_finite(self): + return self.args[0].is_finite + + def _eval_is_algebraic(self): + s = self.func(*self.args) + if s.func == self.func: + if fuzzy_not(self.args[0].is_zero) and self.args[0].is_algebraic: + return False + else: + return s.is_algebraic + + def _eval_as_leading_term(self, x, logx, cdir): + if len(self.args) == 1: + arg = self.args[0] + arg0 = arg.subs(x, 0).cancel() + if not arg0.is_zero: + return self.func(arg0) + return arg.as_leading_term(x) + + def _eval_nseries(self, x, n, logx, cdir=0): + if len(self.args) == 1: + from sympy.functions.elementary.integers import ceiling + from sympy.series.order import Order + arg = self.args[0].nseries(x, n=n, logx=logx) + lt = arg.as_leading_term(x, logx=logx) + lte = 1 + if lt.is_Pow: + lte = lt.exp + if ceiling(n/lte) >= 1: + s = Add(*[(-S.One)**(k - 1)*Integer(k)**(k - 2)/ + factorial(k - 1)*arg**k for k in range(1, ceiling(n/lte))]) + s = expand_multinomial(s) + else: + s = S.Zero + + return s + Order(x**n, x) + return super()._eval_nseries(x, n, logx) + + def _eval_is_zero(self): + x = self.args[0] + if len(self.args) == 1: + return x.is_zero + else: + return fuzzy_and([x.is_zero, self.args[1].is_zero]) + + +@cacheit +def _log_atan_table(): + return { + # first quadrant only + sqrt(3): pi / 3, + 1: pi / 4, + sqrt(5 - 2 * sqrt(5)): pi / 5, + sqrt(2) * sqrt(5 - sqrt(5)) / (1 + sqrt(5)): pi / 5, + sqrt(5 + 2 * sqrt(5)): pi * Rational(2, 5), + sqrt(2) * sqrt(sqrt(5) + 5) / (-1 + sqrt(5)): pi * Rational(2, 5), + sqrt(3) / 3: pi / 6, + sqrt(2) - 1: pi / 8, + sqrt(2 - sqrt(2)) / sqrt(sqrt(2) + 2): pi / 8, + sqrt(2) + 1: pi * Rational(3, 8), + sqrt(sqrt(2) + 2) / sqrt(2 - sqrt(2)): pi * Rational(3, 8), + sqrt(1 - 2 * sqrt(5) / 5): pi / 10, + (-sqrt(2) + sqrt(10)) / (2 * sqrt(sqrt(5) + 5)): pi / 10, + sqrt(1 + 2 * sqrt(5) / 5): pi * Rational(3, 10), + (sqrt(2) + sqrt(10)) / (2 * sqrt(5 - sqrt(5))): pi * Rational(3, 10), + 2 - sqrt(3): pi / 12, + (-1 + sqrt(3)) / (1 + sqrt(3)): pi / 12, + 2 + sqrt(3): pi * Rational(5, 12), + (1 + sqrt(3)) / (-1 + sqrt(3)): pi * Rational(5, 12) + } diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/hyperbolic.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/hyperbolic.py new file mode 100644 index 0000000000000000000000000000000000000000..1031d035373bb641d26e61a395e6048906285bfe --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/hyperbolic.py @@ -0,0 +1,2285 @@ +from sympy.core import S, sympify, cacheit +from sympy.core.add import Add +from sympy.core.function import DefinedFunction, ArgumentIndexError +from sympy.core.logic import fuzzy_or, fuzzy_and, fuzzy_not, FuzzyBool +from sympy.core.numbers import I, pi, Rational +from sympy.core.symbol import Dummy +from sympy.functions.combinatorial.factorials import (binomial, factorial, + RisingFactorial) +from sympy.functions.combinatorial.numbers import bernoulli, euler, nC +from sympy.functions.elementary.complexes import Abs, im, re +from sympy.functions.elementary.exponential import exp, log, match_real_imag +from sympy.functions.elementary.integers import floor +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import ( + acos, acot, asin, atan, cos, cot, csc, sec, sin, tan, + _imaginary_unit_as_coefficient) +from sympy.polys.specialpolys import symmetric_poly + + +def _rewrite_hyperbolics_as_exp(expr): + return expr.xreplace({h: h.rewrite(exp) + for h in expr.atoms(HyperbolicFunction)}) + + +@cacheit +def _acosh_table(): + return { + I: log(I*(1 + sqrt(2))), + -I: log(-I*(1 + sqrt(2))), + S.Half: pi/3, + Rational(-1, 2): pi*Rational(2, 3), + sqrt(2)/2: pi/4, + -sqrt(2)/2: pi*Rational(3, 4), + 1/sqrt(2): pi/4, + -1/sqrt(2): pi*Rational(3, 4), + sqrt(3)/2: pi/6, + -sqrt(3)/2: pi*Rational(5, 6), + (sqrt(3) - 1)/sqrt(2**3): pi*Rational(5, 12), + -(sqrt(3) - 1)/sqrt(2**3): pi*Rational(7, 12), + sqrt(2 + sqrt(2))/2: pi/8, + -sqrt(2 + sqrt(2))/2: pi*Rational(7, 8), + sqrt(2 - sqrt(2))/2: pi*Rational(3, 8), + -sqrt(2 - sqrt(2))/2: pi*Rational(5, 8), + (1 + sqrt(3))/(2*sqrt(2)): pi/12, + -(1 + sqrt(3))/(2*sqrt(2)): pi*Rational(11, 12), + (sqrt(5) + 1)/4: pi/5, + -(sqrt(5) + 1)/4: pi*Rational(4, 5) + } + + +@cacheit +def _acsch_table(): + return { + I: -pi / 2, + I*(sqrt(2) + sqrt(6)): -pi / 12, + I*(1 + sqrt(5)): -pi / 10, + I*2 / sqrt(2 - sqrt(2)): -pi / 8, + I*2: -pi / 6, + I*sqrt(2 + 2/sqrt(5)): -pi / 5, + I*sqrt(2): -pi / 4, + I*(sqrt(5)-1): -3*pi / 10, + I*2 / sqrt(3): -pi / 3, + I*2 / sqrt(2 + sqrt(2)): -3*pi / 8, + I*sqrt(2 - 2/sqrt(5)): -2*pi / 5, + I*(sqrt(6) - sqrt(2)): -5*pi / 12, + S(2): -I*log((1+sqrt(5))/2), + } + + +@cacheit +def _asech_table(): + return { + I: - (pi*I / 2) + log(1 + sqrt(2)), + -I: (pi*I / 2) + log(1 + sqrt(2)), + (sqrt(6) - sqrt(2)): pi / 12, + (sqrt(2) - sqrt(6)): 11*pi / 12, + sqrt(2 - 2/sqrt(5)): pi / 10, + -sqrt(2 - 2/sqrt(5)): 9*pi / 10, + 2 / sqrt(2 + sqrt(2)): pi / 8, + -2 / sqrt(2 + sqrt(2)): 7*pi / 8, + 2 / sqrt(3): pi / 6, + -2 / sqrt(3): 5*pi / 6, + (sqrt(5) - 1): pi / 5, + (1 - sqrt(5)): 4*pi / 5, + sqrt(2): pi / 4, + -sqrt(2): 3*pi / 4, + sqrt(2 + 2/sqrt(5)): 3*pi / 10, + -sqrt(2 + 2/sqrt(5)): 7*pi / 10, + S(2): pi / 3, + -S(2): 2*pi / 3, + sqrt(2*(2 + sqrt(2))): 3*pi / 8, + -sqrt(2*(2 + sqrt(2))): 5*pi / 8, + (1 + sqrt(5)): 2*pi / 5, + (-1 - sqrt(5)): 3*pi / 5, + (sqrt(6) + sqrt(2)): 5*pi / 12, + (-sqrt(6) - sqrt(2)): 7*pi / 12, + I*S.Infinity: -pi*I / 2, + I*S.NegativeInfinity: pi*I / 2, + } + +############################################################################### +########################### HYPERBOLIC FUNCTIONS ############################## +############################################################################### + + +class HyperbolicFunction(DefinedFunction): + """ + Base class for hyperbolic functions. + + See Also + ======== + + sinh, cosh, tanh, coth + """ + + unbranched = True + + +def _peeloff_ipi(arg): + r""" + Split ARG into two parts, a "rest" and a multiple of $I\pi$. + This assumes ARG to be an ``Add``. + The multiple of $I\pi$ returned in the second position is always a ``Rational``. + + Examples + ======== + + >>> from sympy.functions.elementary.hyperbolic import _peeloff_ipi as peel + >>> from sympy import pi, I + >>> from sympy.abc import x, y + >>> peel(x + I*pi/2) + (x, 1/2) + >>> peel(x + I*2*pi/3 + I*pi*y) + (x + I*pi*y + I*pi/6, 1/2) + """ + ipi = pi*I + for a in Add.make_args(arg): + if a == ipi: + K = S.One + break + elif a.is_Mul: + K, p = a.as_two_terms() + if p == ipi and K.is_Rational: + break + else: + return arg, S.Zero + + m1 = (K % S.Half) + m2 = K - m1 + return arg - m2*ipi, m2 + + +class sinh(HyperbolicFunction): + r""" + ``sinh(x)`` is the hyperbolic sine of ``x``. + + The hyperbolic sine function is $\frac{e^x - e^{-x}}{2}$. + + Examples + ======== + + >>> from sympy import sinh + >>> from sympy.abc import x + >>> sinh(x) + sinh(x) + + See Also + ======== + + cosh, tanh, asinh + """ + + def fdiff(self, argindex=1): + """ + Returns the first derivative of this function. + """ + if argindex == 1: + return cosh(self.args[0]) + else: + raise ArgumentIndexError(self, argindex) + + def inverse(self, argindex=1): + """ + Returns the inverse of this function. + """ + return asinh + + @classmethod + def eval(cls, arg): + if arg.is_Number: + if arg is S.NaN: + return S.NaN + elif arg is S.Infinity: + return S.Infinity + elif arg is S.NegativeInfinity: + return S.NegativeInfinity + elif arg.is_zero: + return S.Zero + elif arg.is_negative: + return -cls(-arg) + else: + if arg is S.ComplexInfinity: + return S.NaN + + i_coeff = _imaginary_unit_as_coefficient(arg) + + if i_coeff is not None: + return I * sin(i_coeff) + else: + if arg.could_extract_minus_sign(): + return -cls(-arg) + + if arg.is_Add: + x, m = _peeloff_ipi(arg) + if m: + m = m*pi*I + return sinh(m)*cosh(x) + cosh(m)*sinh(x) + + if arg.is_zero: + return S.Zero + + if arg.func == asinh: + return arg.args[0] + + if arg.func == acosh: + x = arg.args[0] + return sqrt(x - 1) * sqrt(x + 1) + + if arg.func == atanh: + x = arg.args[0] + return x/sqrt(1 - x**2) + + if arg.func == acoth: + x = arg.args[0] + return 1/(sqrt(x - 1) * sqrt(x + 1)) + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + """ + Returns the next term in the Taylor series expansion. + """ + if n < 0 or n % 2 == 0: + return S.Zero + else: + x = sympify(x) + + if len(previous_terms) > 2: + p = previous_terms[-2] + return p * x**2 / (n*(n - 1)) + else: + return x**(n) / factorial(n) + + def _eval_conjugate(self): + return self.func(self.args[0].conjugate()) + + def as_real_imag(self, deep=True, **hints): + """ + Returns this function as a complex coordinate. + """ + if self.args[0].is_extended_real: + if deep: + hints['complex'] = False + return (self.expand(deep, **hints), S.Zero) + else: + return (self, S.Zero) + if deep: + re, im = self.args[0].expand(deep, **hints).as_real_imag() + else: + re, im = self.args[0].as_real_imag() + return (sinh(re)*cos(im), cosh(re)*sin(im)) + + def _eval_expand_complex(self, deep=True, **hints): + re_part, im_part = self.as_real_imag(deep=deep, **hints) + return re_part + im_part*I + + def _eval_expand_trig(self, deep=True, **hints): + if deep: + arg = self.args[0].expand(deep, **hints) + else: + arg = self.args[0] + x = None + if arg.is_Add: # TODO, implement more if deep stuff here + x, y = arg.as_two_terms() + else: + coeff, terms = arg.as_coeff_Mul(rational=True) + if coeff is not S.One and coeff.is_Integer and terms is not S.One: + x = terms + y = (coeff - 1)*x + if x is not None: + return (sinh(x)*cosh(y) + sinh(y)*cosh(x)).expand(trig=True) + return sinh(arg) + + def _eval_rewrite_as_tractable(self, arg, limitvar=None, **kwargs): + return (exp(arg) - exp(-arg)) / 2 + + def _eval_rewrite_as_exp(self, arg, **kwargs): + return (exp(arg) - exp(-arg)) / 2 + + def _eval_rewrite_as_sin(self, arg, **kwargs): + return -I * sin(I * arg) + + def _eval_rewrite_as_csc(self, arg, **kwargs): + return -I / csc(I * arg) + + def _eval_rewrite_as_cosh(self, arg, **kwargs): + return -I*cosh(arg + pi*I/2) + + def _eval_rewrite_as_tanh(self, arg, **kwargs): + tanh_half = tanh(S.Half*arg) + return 2*tanh_half/(1 - tanh_half**2) + + def _eval_rewrite_as_coth(self, arg, **kwargs): + coth_half = coth(S.Half*arg) + return 2*coth_half/(coth_half**2 - 1) + + def _eval_rewrite_as_csch(self, arg, **kwargs): + return 1 / csch(arg) + + def _eval_as_leading_term(self, x, logx, cdir): + arg = self.args[0].as_leading_term(x, logx=logx, cdir=cdir) + arg0 = arg.subs(x, 0) + + if arg0 is S.NaN: + arg0 = arg.limit(x, 0, dir='-' if cdir.is_negative else '+') + if arg0.is_zero: + return arg + elif arg0.is_finite: + return self.func(arg0) + else: + return self + + def _eval_is_real(self): + arg = self.args[0] + if arg.is_real: + return True + + # if `im` is of the form n*pi + # else, check if it is a number + re, im = arg.as_real_imag() + return (im%pi).is_zero + + def _eval_is_extended_real(self): + if self.args[0].is_extended_real: + return True + + def _eval_is_positive(self): + if self.args[0].is_extended_real: + return self.args[0].is_positive + + def _eval_is_negative(self): + if self.args[0].is_extended_real: + return self.args[0].is_negative + + def _eval_is_finite(self): + arg = self.args[0] + return arg.is_finite + + def _eval_is_zero(self): + rest, ipi_mult = _peeloff_ipi(self.args[0]) + if rest.is_zero: + return ipi_mult.is_integer + + +class cosh(HyperbolicFunction): + r""" + ``cosh(x)`` is the hyperbolic cosine of ``x``. + + The hyperbolic cosine function is $\frac{e^x + e^{-x}}{2}$. + + Examples + ======== + + >>> from sympy import cosh + >>> from sympy.abc import x + >>> cosh(x) + cosh(x) + + See Also + ======== + + sinh, tanh, acosh + """ + + def fdiff(self, argindex=1): + if argindex == 1: + return sinh(self.args[0]) + else: + raise ArgumentIndexError(self, argindex) + + @classmethod + def eval(cls, arg): + from sympy.functions.elementary.trigonometric import cos + if arg.is_Number: + if arg is S.NaN: + return S.NaN + elif arg is S.Infinity: + return S.Infinity + elif arg is S.NegativeInfinity: + return S.Infinity + elif arg.is_zero: + return S.One + elif arg.is_negative: + return cls(-arg) + else: + if arg is S.ComplexInfinity: + return S.NaN + + i_coeff = _imaginary_unit_as_coefficient(arg) + + if i_coeff is not None: + return cos(i_coeff) + else: + if arg.could_extract_minus_sign(): + return cls(-arg) + + if arg.is_Add: + x, m = _peeloff_ipi(arg) + if m: + m = m*pi*I + return cosh(m)*cosh(x) + sinh(m)*sinh(x) + + if arg.is_zero: + return S.One + + if arg.func == asinh: + return sqrt(1 + arg.args[0]**2) + + if arg.func == acosh: + return arg.args[0] + + if arg.func == atanh: + return 1/sqrt(1 - arg.args[0]**2) + + if arg.func == acoth: + x = arg.args[0] + return x/(sqrt(x - 1) * sqrt(x + 1)) + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + if n < 0 or n % 2 == 1: + return S.Zero + else: + x = sympify(x) + + if len(previous_terms) > 2: + p = previous_terms[-2] + return p * x**2 / (n*(n - 1)) + else: + return x**(n)/factorial(n) + + def _eval_conjugate(self): + return self.func(self.args[0].conjugate()) + + def as_real_imag(self, deep=True, **hints): + if self.args[0].is_extended_real: + if deep: + hints['complex'] = False + return (self.expand(deep, **hints), S.Zero) + else: + return (self, S.Zero) + if deep: + re, im = self.args[0].expand(deep, **hints).as_real_imag() + else: + re, im = self.args[0].as_real_imag() + + return (cosh(re)*cos(im), sinh(re)*sin(im)) + + def _eval_expand_complex(self, deep=True, **hints): + re_part, im_part = self.as_real_imag(deep=deep, **hints) + return re_part + im_part*I + + def _eval_expand_trig(self, deep=True, **hints): + if deep: + arg = self.args[0].expand(deep, **hints) + else: + arg = self.args[0] + x = None + if arg.is_Add: # TODO, implement more if deep stuff here + x, y = arg.as_two_terms() + else: + coeff, terms = arg.as_coeff_Mul(rational=True) + if coeff is not S.One and coeff.is_Integer and terms is not S.One: + x = terms + y = (coeff - 1)*x + if x is not None: + return (cosh(x)*cosh(y) + sinh(x)*sinh(y)).expand(trig=True) + return cosh(arg) + + def _eval_rewrite_as_tractable(self, arg, limitvar=None, **kwargs): + return (exp(arg) + exp(-arg)) / 2 + + def _eval_rewrite_as_exp(self, arg, **kwargs): + return (exp(arg) + exp(-arg)) / 2 + + def _eval_rewrite_as_cos(self, arg, **kwargs): + return cos(I * arg, evaluate=False) + + def _eval_rewrite_as_sec(self, arg, **kwargs): + return 1 / sec(I * arg, evaluate=False) + + def _eval_rewrite_as_sinh(self, arg, **kwargs): + return -I*sinh(arg + pi*I/2, evaluate=False) + + def _eval_rewrite_as_tanh(self, arg, **kwargs): + tanh_half = tanh(S.Half*arg)**2 + return (1 + tanh_half)/(1 - tanh_half) + + def _eval_rewrite_as_coth(self, arg, **kwargs): + coth_half = coth(S.Half*arg)**2 + return (coth_half + 1)/(coth_half - 1) + + def _eval_rewrite_as_sech(self, arg, **kwargs): + return 1 / sech(arg) + + def _eval_as_leading_term(self, x, logx, cdir): + arg = self.args[0].as_leading_term(x, logx=logx, cdir=cdir) + arg0 = arg.subs(x, 0) + + if arg0 is S.NaN: + arg0 = arg.limit(x, 0, dir='-' if cdir.is_negative else '+') + if arg0.is_zero: + return S.One + elif arg0.is_finite: + return self.func(arg0) + else: + return self + + def _eval_is_real(self): + arg = self.args[0] + + # `cosh(x)` is real for real OR purely imaginary `x` + if arg.is_real or arg.is_imaginary: + return True + + # cosh(a+ib) = cos(b)*cosh(a) + i*sin(b)*sinh(a) + # the imaginary part can be an expression like n*pi + # if not, check if the imaginary part is a number + re, im = arg.as_real_imag() + return (im%pi).is_zero + + def _eval_is_positive(self): + # cosh(x+I*y) = cos(y)*cosh(x) + I*sin(y)*sinh(x) + # cosh(z) is positive iff it is real and the real part is positive. + # So we need sin(y)*sinh(x) = 0 which gives x=0 or y=n*pi + # Case 1 (y=n*pi): cosh(z) = (-1)**n * cosh(x) -> positive for n even + # Case 2 (x=0): cosh(z) = cos(y) -> positive when cos(y) is positive + z = self.args[0] + + x, y = z.as_real_imag() + ymod = y % (2*pi) + + yzero = ymod.is_zero + # shortcut if ymod is zero + if yzero: + return True + + xzero = x.is_zero + # shortcut x is not zero + if xzero is False: + return yzero + + return fuzzy_or([ + # Case 1: + yzero, + # Case 2: + fuzzy_and([ + xzero, + fuzzy_or([ymod < pi/2, ymod > 3*pi/2]) + ]) + ]) + + + def _eval_is_nonnegative(self): + z = self.args[0] + + x, y = z.as_real_imag() + ymod = y % (2*pi) + + yzero = ymod.is_zero + # shortcut if ymod is zero + if yzero: + return True + + xzero = x.is_zero + # shortcut x is not zero + if xzero is False: + return yzero + + return fuzzy_or([ + # Case 1: + yzero, + # Case 2: + fuzzy_and([ + xzero, + fuzzy_or([ymod <= pi/2, ymod >= 3*pi/2]) + ]) + ]) + + def _eval_is_finite(self): + arg = self.args[0] + return arg.is_finite + + def _eval_is_zero(self): + rest, ipi_mult = _peeloff_ipi(self.args[0]) + if ipi_mult and rest.is_zero: + return (ipi_mult - S.Half).is_integer + + +class tanh(HyperbolicFunction): + r""" + ``tanh(x)`` is the hyperbolic tangent of ``x``. + + The hyperbolic tangent function is $\frac{\sinh(x)}{\cosh(x)}$. + + Examples + ======== + + >>> from sympy import tanh + >>> from sympy.abc import x + >>> tanh(x) + tanh(x) + + See Also + ======== + + sinh, cosh, atanh + """ + + def fdiff(self, argindex=1): + if argindex == 1: + return S.One - tanh(self.args[0])**2 + else: + raise ArgumentIndexError(self, argindex) + + def inverse(self, argindex=1): + """ + Returns the inverse of this function. + """ + return atanh + + @classmethod + def eval(cls, arg): + if arg.is_Number: + if arg is S.NaN: + return S.NaN + elif arg is S.Infinity: + return S.One + elif arg is S.NegativeInfinity: + return S.NegativeOne + elif arg.is_zero: + return S.Zero + elif arg.is_negative: + return -cls(-arg) + else: + if arg is S.ComplexInfinity: + return S.NaN + + i_coeff = _imaginary_unit_as_coefficient(arg) + + if i_coeff is not None: + if i_coeff.could_extract_minus_sign(): + return -I * tan(-i_coeff) + return I * tan(i_coeff) + else: + if arg.could_extract_minus_sign(): + return -cls(-arg) + + if arg.is_Add: + x, m = _peeloff_ipi(arg) + if m: + tanhm = tanh(m*pi*I) + if tanhm is S.ComplexInfinity: + return coth(x) + else: # tanhm == 0 + return tanh(x) + + if arg.is_zero: + return S.Zero + + if arg.func == asinh: + x = arg.args[0] + return x/sqrt(1 + x**2) + + if arg.func == acosh: + x = arg.args[0] + return sqrt(x - 1) * sqrt(x + 1) / x + + if arg.func == atanh: + return arg.args[0] + + if arg.func == acoth: + return 1/arg.args[0] + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + if n < 0 or n % 2 == 0: + return S.Zero + else: + x = sympify(x) + + a = 2**(n + 1) + + B = bernoulli(n + 1) + F = factorial(n + 1) + + return a*(a - 1) * B/F * x**n + + def _eval_conjugate(self): + return self.func(self.args[0].conjugate()) + + def as_real_imag(self, deep=True, **hints): + if self.args[0].is_extended_real: + if deep: + hints['complex'] = False + return (self.expand(deep, **hints), S.Zero) + else: + return (self, S.Zero) + if deep: + re, im = self.args[0].expand(deep, **hints).as_real_imag() + else: + re, im = self.args[0].as_real_imag() + denom = sinh(re)**2 + cos(im)**2 + return (sinh(re)*cosh(re)/denom, sin(im)*cos(im)/denom) + + def _eval_expand_trig(self, **hints): + arg = self.args[0] + if arg.is_Add: + n = len(arg.args) + TX = [tanh(x, evaluate=False)._eval_expand_trig() + for x in arg.args] + p = [0, 0] # [den, num] + for i in range(n + 1): + p[i % 2] += symmetric_poly(i, TX) + return p[1]/p[0] + elif arg.is_Mul: + coeff, terms = arg.as_coeff_Mul() + if coeff.is_Integer and coeff > 1: + T = tanh(terms) + n = [nC(range(coeff), k)*T**k for k in range(1, coeff + 1, 2)] + d = [nC(range(coeff), k)*T**k for k in range(0, coeff + 1, 2)] + return Add(*n)/Add(*d) + return tanh(arg) + + def _eval_rewrite_as_tractable(self, arg, limitvar=None, **kwargs): + neg_exp, pos_exp = exp(-arg), exp(arg) + return (pos_exp - neg_exp)/(pos_exp + neg_exp) + + def _eval_rewrite_as_exp(self, arg, **kwargs): + neg_exp, pos_exp = exp(-arg), exp(arg) + return (pos_exp - neg_exp)/(pos_exp + neg_exp) + + def _eval_rewrite_as_tan(self, arg, **kwargs): + return -I * tan(I * arg, evaluate=False) + + def _eval_rewrite_as_cot(self, arg, **kwargs): + return -I / cot(I * arg, evaluate=False) + + def _eval_rewrite_as_sinh(self, arg, **kwargs): + return I*sinh(arg)/sinh(pi*I/2 - arg, evaluate=False) + + def _eval_rewrite_as_cosh(self, arg, **kwargs): + return I*cosh(pi*I/2 - arg, evaluate=False)/cosh(arg) + + def _eval_rewrite_as_coth(self, arg, **kwargs): + return 1/coth(arg) + + def _eval_as_leading_term(self, x, logx, cdir): + from sympy.series.order import Order + arg = self.args[0].as_leading_term(x) + + if x in arg.free_symbols and Order(1, x).contains(arg): + return arg + else: + return self.func(arg) + + def _eval_is_real(self): + arg = self.args[0] + if arg.is_real: + return True + + re, im = arg.as_real_imag() + + # if denom = 0, tanh(arg) = zoo + if re == 0 and im % pi == pi/2: + return None + + # check if im is of the form n*pi/2 to make sin(2*im) = 0 + # if not, im could be a number, return False in that case + return (im % (pi/2)).is_zero + + def _eval_is_extended_real(self): + if self.args[0].is_extended_real: + return True + + def _eval_is_positive(self): + if self.args[0].is_extended_real: + return self.args[0].is_positive + + def _eval_is_negative(self): + if self.args[0].is_extended_real: + return self.args[0].is_negative + + def _eval_is_finite(self): + arg = self.args[0] + + re, im = arg.as_real_imag() + denom = cos(im)**2 + sinh(re)**2 + if denom == 0: + return False + elif denom.is_number: + return True + if arg.is_extended_real: + return True + + def _eval_is_zero(self): + arg = self.args[0] + if arg.is_zero: + return True + + +class coth(HyperbolicFunction): + r""" + ``coth(x)`` is the hyperbolic cotangent of ``x``. + + The hyperbolic cotangent function is $\frac{\cosh(x)}{\sinh(x)}$. + + Examples + ======== + + >>> from sympy import coth + >>> from sympy.abc import x + >>> coth(x) + coth(x) + + See Also + ======== + + sinh, cosh, acoth + """ + + def fdiff(self, argindex=1): + if argindex == 1: + return -1/sinh(self.args[0])**2 + else: + raise ArgumentIndexError(self, argindex) + + def inverse(self, argindex=1): + """ + Returns the inverse of this function. + """ + return acoth + + @classmethod + def eval(cls, arg): + if arg.is_Number: + if arg is S.NaN: + return S.NaN + elif arg is S.Infinity: + return S.One + elif arg is S.NegativeInfinity: + return S.NegativeOne + elif arg.is_zero: + return S.ComplexInfinity + elif arg.is_negative: + return -cls(-arg) + else: + if arg is S.ComplexInfinity: + return S.NaN + + i_coeff = _imaginary_unit_as_coefficient(arg) + + if i_coeff is not None: + if i_coeff.could_extract_minus_sign(): + return I * cot(-i_coeff) + return -I * cot(i_coeff) + else: + if arg.could_extract_minus_sign(): + return -cls(-arg) + + if arg.is_Add: + x, m = _peeloff_ipi(arg) + if m: + cothm = coth(m*pi*I) + if cothm is S.ComplexInfinity: + return coth(x) + else: # cothm == 0 + return tanh(x) + + if arg.is_zero: + return S.ComplexInfinity + + if arg.func == asinh: + x = arg.args[0] + return sqrt(1 + x**2)/x + + if arg.func == acosh: + x = arg.args[0] + return x/(sqrt(x - 1) * sqrt(x + 1)) + + if arg.func == atanh: + return 1/arg.args[0] + + if arg.func == acoth: + return arg.args[0] + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + if n == 0: + return 1 / sympify(x) + elif n < 0 or n % 2 == 0: + return S.Zero + else: + x = sympify(x) + + B = bernoulli(n + 1) + F = factorial(n + 1) + + return 2**(n + 1) * B/F * x**n + + def _eval_conjugate(self): + return self.func(self.args[0].conjugate()) + + def as_real_imag(self, deep=True, **hints): + from sympy.functions.elementary.trigonometric import (cos, sin) + if self.args[0].is_extended_real: + if deep: + hints['complex'] = False + return (self.expand(deep, **hints), S.Zero) + else: + return (self, S.Zero) + if deep: + re, im = self.args[0].expand(deep, **hints).as_real_imag() + else: + re, im = self.args[0].as_real_imag() + denom = sinh(re)**2 + sin(im)**2 + return (sinh(re)*cosh(re)/denom, -sin(im)*cos(im)/denom) + + def _eval_rewrite_as_tractable(self, arg, limitvar=None, **kwargs): + neg_exp, pos_exp = exp(-arg), exp(arg) + return (pos_exp + neg_exp)/(pos_exp - neg_exp) + + def _eval_rewrite_as_exp(self, arg, **kwargs): + neg_exp, pos_exp = exp(-arg), exp(arg) + return (pos_exp + neg_exp)/(pos_exp - neg_exp) + + def _eval_rewrite_as_sinh(self, arg, **kwargs): + return -I*sinh(pi*I/2 - arg, evaluate=False)/sinh(arg) + + def _eval_rewrite_as_cosh(self, arg, **kwargs): + return -I*cosh(arg)/cosh(pi*I/2 - arg, evaluate=False) + + def _eval_rewrite_as_tanh(self, arg, **kwargs): + return 1/tanh(arg) + + def _eval_is_positive(self): + if self.args[0].is_extended_real: + return self.args[0].is_positive + + def _eval_is_negative(self): + if self.args[0].is_extended_real: + return self.args[0].is_negative + + def _eval_as_leading_term(self, x, logx, cdir): + from sympy.series.order import Order + arg = self.args[0].as_leading_term(x) + + if x in arg.free_symbols and Order(1, x).contains(arg): + return 1/arg + else: + return self.func(arg) + + def _eval_expand_trig(self, **hints): + arg = self.args[0] + if arg.is_Add: + CX = [coth(x, evaluate=False)._eval_expand_trig() for x in arg.args] + p = [[], []] + n = len(arg.args) + for i in range(n, -1, -1): + p[(n - i) % 2].append(symmetric_poly(i, CX)) + return Add(*p[0])/Add(*p[1]) + elif arg.is_Mul: + coeff, x = arg.as_coeff_Mul(rational=True) + if coeff.is_Integer and coeff > 1: + c = coth(x, evaluate=False) + p = [[], []] + for i in range(coeff, -1, -1): + p[(coeff - i) % 2].append(binomial(coeff, i)*c**i) + return Add(*p[0])/Add(*p[1]) + return coth(arg) + + +class ReciprocalHyperbolicFunction(HyperbolicFunction): + """Base class for reciprocal functions of hyperbolic functions. """ + + #To be defined in class + _reciprocal_of = None + _is_even: FuzzyBool = None + _is_odd: FuzzyBool = None + + @classmethod + def eval(cls, arg): + if arg.could_extract_minus_sign(): + if cls._is_even: + return cls(-arg) + if cls._is_odd: + return -cls(-arg) + + t = cls._reciprocal_of.eval(arg) + if hasattr(arg, 'inverse') and arg.inverse() == cls: + return arg.args[0] + return 1/t if t is not None else t + + def _call_reciprocal(self, method_name, *args, **kwargs): + # Calls method_name on _reciprocal_of + o = self._reciprocal_of(self.args[0]) + return getattr(o, method_name)(*args, **kwargs) + + def _calculate_reciprocal(self, method_name, *args, **kwargs): + # If calling method_name on _reciprocal_of returns a value != None + # then return the reciprocal of that value + t = self._call_reciprocal(method_name, *args, **kwargs) + return 1/t if t is not None else t + + def _rewrite_reciprocal(self, method_name, arg): + # Special handling for rewrite functions. If reciprocal rewrite returns + # unmodified expression, then return None + t = self._call_reciprocal(method_name, arg) + if t is not None and t != self._reciprocal_of(arg): + return 1/t + + def _eval_rewrite_as_exp(self, arg, **kwargs): + return self._rewrite_reciprocal("_eval_rewrite_as_exp", arg) + + def _eval_rewrite_as_tractable(self, arg, limitvar=None, **kwargs): + return self._rewrite_reciprocal("_eval_rewrite_as_tractable", arg) + + def _eval_rewrite_as_tanh(self, arg, **kwargs): + return self._rewrite_reciprocal("_eval_rewrite_as_tanh", arg) + + def _eval_rewrite_as_coth(self, arg, **kwargs): + return self._rewrite_reciprocal("_eval_rewrite_as_coth", arg) + + def as_real_imag(self, deep = True, **hints): + return (1 / self._reciprocal_of(self.args[0])).as_real_imag(deep, **hints) + + def _eval_conjugate(self): + return self.func(self.args[0].conjugate()) + + def _eval_expand_complex(self, deep=True, **hints): + re_part, im_part = self.as_real_imag(deep=True, **hints) + return re_part + I*im_part + + def _eval_expand_trig(self, **hints): + return self._calculate_reciprocal("_eval_expand_trig", **hints) + + def _eval_as_leading_term(self, x, logx, cdir): + return (1/self._reciprocal_of(self.args[0]))._eval_as_leading_term(x, logx=logx, cdir=cdir) + + def _eval_is_extended_real(self): + return self._reciprocal_of(self.args[0]).is_extended_real + + def _eval_is_finite(self): + return (1/self._reciprocal_of(self.args[0])).is_finite + + +class csch(ReciprocalHyperbolicFunction): + r""" + ``csch(x)`` is the hyperbolic cosecant of ``x``. + + The hyperbolic cosecant function is $\frac{2}{e^x - e^{-x}}$ + + Examples + ======== + + >>> from sympy import csch + >>> from sympy.abc import x + >>> csch(x) + csch(x) + + See Also + ======== + + sinh, cosh, tanh, sech, asinh, acosh + """ + + _reciprocal_of = sinh + _is_odd = True + + def fdiff(self, argindex=1): + """ + Returns the first derivative of this function + """ + if argindex == 1: + return -coth(self.args[0]) * csch(self.args[0]) + else: + raise ArgumentIndexError(self, argindex) + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + """ + Returns the next term in the Taylor series expansion + """ + if n == 0: + return 1/sympify(x) + elif n < 0 or n % 2 == 0: + return S.Zero + else: + x = sympify(x) + + B = bernoulli(n + 1) + F = factorial(n + 1) + + return 2 * (1 - 2**n) * B/F * x**n + + def _eval_rewrite_as_sin(self, arg, **kwargs): + return I / sin(I * arg, evaluate=False) + + def _eval_rewrite_as_csc(self, arg, **kwargs): + return I * csc(I * arg, evaluate=False) + + def _eval_rewrite_as_cosh(self, arg, **kwargs): + return I / cosh(arg + I * pi / 2, evaluate=False) + + def _eval_rewrite_as_sinh(self, arg, **kwargs): + return 1 / sinh(arg) + + def _eval_is_positive(self): + if self.args[0].is_extended_real: + return self.args[0].is_positive + + def _eval_is_negative(self): + if self.args[0].is_extended_real: + return self.args[0].is_negative + + +class sech(ReciprocalHyperbolicFunction): + r""" + ``sech(x)`` is the hyperbolic secant of ``x``. + + The hyperbolic secant function is $\frac{2}{e^x + e^{-x}}$ + + Examples + ======== + + >>> from sympy import sech + >>> from sympy.abc import x + >>> sech(x) + sech(x) + + See Also + ======== + + sinh, cosh, tanh, coth, csch, asinh, acosh + """ + + _reciprocal_of = cosh + _is_even = True + + def fdiff(self, argindex=1): + if argindex == 1: + return - tanh(self.args[0])*sech(self.args[0]) + else: + raise ArgumentIndexError(self, argindex) + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + if n < 0 or n % 2 == 1: + return S.Zero + else: + x = sympify(x) + return euler(n) / factorial(n) * x**(n) + + def _eval_rewrite_as_cos(self, arg, **kwargs): + return 1 / cos(I * arg, evaluate=False) + + def _eval_rewrite_as_sec(self, arg, **kwargs): + return sec(I * arg, evaluate=False) + + def _eval_rewrite_as_sinh(self, arg, **kwargs): + return I / sinh(arg + I * pi /2, evaluate=False) + + def _eval_rewrite_as_cosh(self, arg, **kwargs): + return 1 / cosh(arg) + + def _eval_is_positive(self): + if self.args[0].is_extended_real: + return True + + +############################################################################### +############################# HYPERBOLIC INVERSES ############################# +############################################################################### + +class InverseHyperbolicFunction(DefinedFunction): + """Base class for inverse hyperbolic functions.""" + + pass + + +class asinh(InverseHyperbolicFunction): + """ + ``asinh(x)`` is the inverse hyperbolic sine of ``x``. + + The inverse hyperbolic sine function. + + Examples + ======== + + >>> from sympy import asinh + >>> from sympy.abc import x + >>> asinh(x).diff(x) + 1/sqrt(x**2 + 1) + >>> asinh(1) + log(1 + sqrt(2)) + + See Also + ======== + + acosh, atanh, sinh + """ + + def fdiff(self, argindex=1): + if argindex == 1: + return 1/sqrt(self.args[0]**2 + 1) + else: + raise ArgumentIndexError(self, argindex) + + @classmethod + def eval(cls, arg): + if arg.is_Number: + if arg is S.NaN: + return S.NaN + elif arg is S.Infinity: + return S.Infinity + elif arg is S.NegativeInfinity: + return S.NegativeInfinity + elif arg.is_zero: + return S.Zero + elif arg is S.One: + return log(sqrt(2) + 1) + elif arg is S.NegativeOne: + return log(sqrt(2) - 1) + elif arg.is_negative: + return -cls(-arg) + else: + if arg is S.ComplexInfinity: + return S.ComplexInfinity + + if arg.is_zero: + return S.Zero + + i_coeff = _imaginary_unit_as_coefficient(arg) + + if i_coeff is not None: + return I * asin(i_coeff) + else: + if arg.could_extract_minus_sign(): + return -cls(-arg) + + if isinstance(arg, sinh) and arg.args[0].is_number: + z = arg.args[0] + if z.is_real: + return z + r, i = match_real_imag(z) + if r is not None and i is not None: + f = floor((i + pi/2)/pi) + m = z - I*pi*f + even = f.is_even + if even is True: + return m + elif even is False: + return -m + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + if n < 0 or n % 2 == 0: + return S.Zero + else: + x = sympify(x) + if len(previous_terms) >= 2 and n > 2: + p = previous_terms[-2] + return -p * (n - 2)**2/(n*(n - 1)) * x**2 + else: + k = (n - 1) // 2 + R = RisingFactorial(S.Half, k) + F = factorial(k) + return S.NegativeOne**k * R / F * x**n / n + + def _eval_as_leading_term(self, x, logx, cdir): + arg = self.args[0] + x0 = arg.subs(x, 0).cancel() + if x0.is_zero: + return arg.as_leading_term(x) + + if x0 is S.NaN: + expr = self.func(arg.as_leading_term(x)) + if expr.is_finite: + return expr + else: + return self + + # Handling branch points + if x0 in (-I, I, S.ComplexInfinity): + return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir) + # Handling points lying on branch cuts (-I*oo, -I) U (I, I*oo) + if (1 + x0**2).is_negative: + ndir = arg.dir(x, cdir if cdir else 1) + if re(ndir).is_positive: + if im(x0).is_negative: + return -self.func(x0) - I*pi + elif re(ndir).is_negative: + if im(x0).is_positive: + return -self.func(x0) + I*pi + else: + return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir) + return self.func(x0) + + def _eval_nseries(self, x, n, logx, cdir=0): # asinh + arg = self.args[0] + arg0 = arg.subs(x, 0) + + # Handling branch points + if arg0 in (I, -I): + return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir) + + res = super()._eval_nseries(x, n=n, logx=logx) + if arg0 is S.ComplexInfinity: + return res + + # Handling points lying on branch cuts (-I*oo, -I) U (I, I*oo) + if (1 + arg0**2).is_negative: + ndir = arg.dir(x, cdir if cdir else 1) + if re(ndir).is_positive: + if im(arg0).is_negative: + return -res - I*pi + elif re(ndir).is_negative: + if im(arg0).is_positive: + return -res + I*pi + else: + return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir) + return res + + def _eval_rewrite_as_log(self, x, **kwargs): + return log(x + sqrt(x**2 + 1)) + + _eval_rewrite_as_tractable = _eval_rewrite_as_log + + def _eval_rewrite_as_atanh(self, x, **kwargs): + return atanh(x/sqrt(1 + x**2)) + + def _eval_rewrite_as_acosh(self, x, **kwargs): + ix = I*x + return I*(sqrt(1 - ix)/sqrt(ix - 1) * acosh(ix) - pi/2) + + def _eval_rewrite_as_asin(self, x, **kwargs): + return -I * asin(I * x, evaluate=False) + + def _eval_rewrite_as_acos(self, x, **kwargs): + return I * acos(I * x, evaluate=False) - I*pi/2 + + def inverse(self, argindex=1): + """ + Returns the inverse of this function. + """ + return sinh + + def _eval_is_zero(self): + return self.args[0].is_zero + + def _eval_is_extended_real(self): + return self.args[0].is_extended_real + + def _eval_is_finite(self): + return self.args[0].is_finite + + +class acosh(InverseHyperbolicFunction): + """ + ``acosh(x)`` is the inverse hyperbolic cosine of ``x``. + + The inverse hyperbolic cosine function. + + Examples + ======== + + >>> from sympy import acosh + >>> from sympy.abc import x + >>> acosh(x).diff(x) + 1/(sqrt(x - 1)*sqrt(x + 1)) + >>> acosh(1) + 0 + + See Also + ======== + + asinh, atanh, cosh + """ + + def fdiff(self, argindex=1): + if argindex == 1: + arg = self.args[0] + return 1/(sqrt(arg - 1)*sqrt(arg + 1)) + else: + raise ArgumentIndexError(self, argindex) + + @classmethod + def eval(cls, arg): + if arg.is_Number: + if arg is S.NaN: + return S.NaN + elif arg is S.Infinity: + return S.Infinity + elif arg is S.NegativeInfinity: + return S.Infinity + elif arg.is_zero: + return pi*I / 2 + elif arg is S.One: + return S.Zero + elif arg is S.NegativeOne: + return pi*I + + if arg.is_number: + cst_table = _acosh_table() + + if arg in cst_table: + if arg.is_extended_real: + return cst_table[arg]*I + return cst_table[arg] + + if arg is S.ComplexInfinity: + return S.ComplexInfinity + if arg == I*S.Infinity: + return S.Infinity + I*pi/2 + if arg == -I*S.Infinity: + return S.Infinity - I*pi/2 + + if arg.is_zero: + return pi*I*S.Half + + if isinstance(arg, cosh) and arg.args[0].is_number: + z = arg.args[0] + if z.is_real: + return Abs(z) + r, i = match_real_imag(z) + if r is not None and i is not None: + f = floor(i/pi) + m = z - I*pi*f + even = f.is_even + if even is True: + if r.is_nonnegative: + return m + elif r.is_negative: + return -m + elif even is False: + m -= I*pi + if r.is_nonpositive: + return -m + elif r.is_positive: + return m + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + if n == 0: + return I*pi/2 + elif n < 0 or n % 2 == 0: + return S.Zero + else: + x = sympify(x) + if len(previous_terms) >= 2 and n > 2: + p = previous_terms[-2] + return p * (n - 2)**2/(n*(n - 1)) * x**2 + else: + k = (n - 1) // 2 + R = RisingFactorial(S.Half, k) + F = factorial(k) + return -R / F * I * x**n / n + + def _eval_as_leading_term(self, x, logx, cdir): + arg = self.args[0] + x0 = arg.subs(x, 0).cancel() + # Handling branch points + if x0 in (-S.One, S.Zero, S.One, S.ComplexInfinity): + return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir) + + if x0 is S.NaN: + expr = self.func(arg.as_leading_term(x)) + if expr.is_finite: + return expr + else: + return self + + # Handling points lying on branch cuts (-oo, 1) + if (x0 - 1).is_negative: + ndir = arg.dir(x, cdir if cdir else 1) + if im(ndir).is_negative: + if (x0 + 1).is_negative: + return self.func(x0) - 2*I*pi + return -self.func(x0) + elif not im(ndir).is_positive: + return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir) + return self.func(x0) + + def _eval_nseries(self, x, n, logx, cdir=0): # acosh + arg = self.args[0] + arg0 = arg.subs(x, 0) + + # Handling branch points + if arg0 in (S.One, S.NegativeOne): + return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir) + + res = super()._eval_nseries(x, n=n, logx=logx) + if arg0 is S.ComplexInfinity: + return res + + # Handling points lying on branch cuts (-oo, 1) + if (arg0 - 1).is_negative: + ndir = arg.dir(x, cdir if cdir else 1) + if im(ndir).is_negative: + if (arg0 + 1).is_negative: + return res - 2*I*pi + return -res + elif not im(ndir).is_positive: + return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir) + return res + + def _eval_rewrite_as_log(self, x, **kwargs): + return log(x + sqrt(x + 1) * sqrt(x - 1)) + + _eval_rewrite_as_tractable = _eval_rewrite_as_log + + def _eval_rewrite_as_acos(self, x, **kwargs): + return sqrt(x - 1)/sqrt(1 - x) * acos(x) + + def _eval_rewrite_as_asin(self, x, **kwargs): + return sqrt(x - 1)/sqrt(1 - x) * (pi/2 - asin(x)) + + def _eval_rewrite_as_asinh(self, x, **kwargs): + return sqrt(x - 1)/sqrt(1 - x) * (pi/2 + I*asinh(I*x, evaluate=False)) + + def _eval_rewrite_as_atanh(self, x, **kwargs): + sxm1 = sqrt(x - 1) + s1mx = sqrt(1 - x) + sx2m1 = sqrt(x**2 - 1) + return (pi/2*sxm1/s1mx*(1 - x * sqrt(1/x**2)) + + sxm1*sqrt(x + 1)/sx2m1 * atanh(sx2m1/x)) + + def inverse(self, argindex=1): + """ + Returns the inverse of this function. + """ + return cosh + + def _eval_is_zero(self): + if (self.args[0] - 1).is_zero: + return True + + def _eval_is_extended_real(self): + return fuzzy_and([self.args[0].is_extended_real, (self.args[0] - 1).is_extended_nonnegative]) + + def _eval_is_finite(self): + return self.args[0].is_finite + + +class atanh(InverseHyperbolicFunction): + """ + ``atanh(x)`` is the inverse hyperbolic tangent of ``x``. + + The inverse hyperbolic tangent function. + + Examples + ======== + + >>> from sympy import atanh + >>> from sympy.abc import x + >>> atanh(x).diff(x) + 1/(1 - x**2) + + See Also + ======== + + asinh, acosh, tanh + """ + + def fdiff(self, argindex=1): + if argindex == 1: + return 1/(1 - self.args[0]**2) + else: + raise ArgumentIndexError(self, argindex) + + @classmethod + def eval(cls, arg): + if arg.is_Number: + if arg is S.NaN: + return S.NaN + elif arg.is_zero: + return S.Zero + elif arg is S.One: + return S.Infinity + elif arg is S.NegativeOne: + return S.NegativeInfinity + elif arg is S.Infinity: + return -I * atan(arg) + elif arg is S.NegativeInfinity: + return I * atan(-arg) + elif arg.is_negative: + return -cls(-arg) + else: + if arg is S.ComplexInfinity: + from sympy.calculus.accumulationbounds import AccumBounds + return I*AccumBounds(-pi/2, pi/2) + + i_coeff = _imaginary_unit_as_coefficient(arg) + + if i_coeff is not None: + return I * atan(i_coeff) + else: + if arg.could_extract_minus_sign(): + return -cls(-arg) + + if arg.is_zero: + return S.Zero + + if isinstance(arg, tanh) and arg.args[0].is_number: + z = arg.args[0] + if z.is_real: + return z + r, i = match_real_imag(z) + if r is not None and i is not None: + f = floor(2*i/pi) + even = f.is_even + m = z - I*f*pi/2 + if even is True: + return m + elif even is False: + return m - I*pi/2 + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + if n < 0 or n % 2 == 0: + return S.Zero + else: + x = sympify(x) + return x**n / n + + def _eval_as_leading_term(self, x, logx, cdir): + arg = self.args[0] + x0 = arg.subs(x, 0).cancel() + if x0.is_zero: + return arg.as_leading_term(x) + if x0 is S.NaN: + expr = self.func(arg.as_leading_term(x)) + if expr.is_finite: + return expr + else: + return self + + # Handling branch points + if x0 in (-S.One, S.One, S.ComplexInfinity): + return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir) + # Handling points lying on branch cuts (-oo, -1] U [1, oo) + if (1 - x0**2).is_negative: + ndir = arg.dir(x, cdir if cdir else 1) + if im(ndir).is_negative: + if x0.is_negative: + return self.func(x0) - I*pi + elif im(ndir).is_positive: + if x0.is_positive: + return self.func(x0) + I*pi + else: + return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir) + return self.func(x0) + + def _eval_nseries(self, x, n, logx, cdir=0): # atanh + arg = self.args[0] + arg0 = arg.subs(x, 0) + + # Handling branch points + if arg0 in (S.One, S.NegativeOne): + return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir) + + res = super()._eval_nseries(x, n=n, logx=logx) + if arg0 is S.ComplexInfinity: + return res + + # Handling points lying on branch cuts (-oo, -1] U [1, oo) + if (1 - arg0**2).is_negative: + ndir = arg.dir(x, cdir if cdir else 1) + if im(ndir).is_negative: + if arg0.is_negative: + return res - I*pi + elif im(ndir).is_positive: + if arg0.is_positive: + return res + I*pi + else: + return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir) + return res + + def _eval_rewrite_as_log(self, x, **kwargs): + return (log(1 + x) - log(1 - x)) / 2 + + _eval_rewrite_as_tractable = _eval_rewrite_as_log + + def _eval_rewrite_as_asinh(self, x, **kwargs): + f = sqrt(1/(x**2 - 1)) + return (pi*x/(2*sqrt(-x**2)) - + sqrt(-x)*sqrt(1 - x**2)/sqrt(x)*f*asinh(f)) + + def _eval_is_zero(self): + if self.args[0].is_zero: + return True + + def _eval_is_extended_real(self): + return fuzzy_and([self.args[0].is_extended_real, (1 - self.args[0]).is_nonnegative, (self.args[0] + 1).is_nonnegative]) + + def _eval_is_finite(self): + return fuzzy_not(fuzzy_or([(self.args[0] - 1).is_zero, (self.args[0] + 1).is_zero])) + + def _eval_is_imaginary(self): + return self.args[0].is_imaginary + + def inverse(self, argindex=1): + """ + Returns the inverse of this function. + """ + return tanh + + +class acoth(InverseHyperbolicFunction): + """ + ``acoth(x)`` is the inverse hyperbolic cotangent of ``x``. + + The inverse hyperbolic cotangent function. + + Examples + ======== + + >>> from sympy import acoth + >>> from sympy.abc import x + >>> acoth(x).diff(x) + 1/(1 - x**2) + + See Also + ======== + + asinh, acosh, coth + """ + + def fdiff(self, argindex=1): + if argindex == 1: + return 1/(1 - self.args[0]**2) + else: + raise ArgumentIndexError(self, argindex) + + @classmethod + def eval(cls, arg): + if arg.is_Number: + if arg is S.NaN: + return S.NaN + elif arg is S.Infinity: + return S.Zero + elif arg is S.NegativeInfinity: + return S.Zero + elif arg.is_zero: + return pi*I / 2 + elif arg is S.One: + return S.Infinity + elif arg is S.NegativeOne: + return S.NegativeInfinity + elif arg.is_negative: + return -cls(-arg) + else: + if arg is S.ComplexInfinity: + return S.Zero + + i_coeff = _imaginary_unit_as_coefficient(arg) + + if i_coeff is not None: + return -I * acot(i_coeff) + else: + if arg.could_extract_minus_sign(): + return -cls(-arg) + + if arg.is_zero: + return pi*I*S.Half + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + if n == 0: + return -I*pi/2 + elif n < 0 or n % 2 == 0: + return S.Zero + else: + x = sympify(x) + return x**n / n + + def _eval_as_leading_term(self, x, logx, cdir): + arg = self.args[0] + x0 = arg.subs(x, 0).cancel() + if x0 is S.ComplexInfinity: + return (1/arg).as_leading_term(x) + if x0 is S.NaN: + expr = self.func(arg.as_leading_term(x)) + if expr.is_finite: + return expr + else: + return self + + # Handling branch points + if x0 in (-S.One, S.One, S.Zero): + return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir) + # Handling points lying on branch cuts [-1, 1] + if x0.is_real and (1 - x0**2).is_positive: + ndir = arg.dir(x, cdir if cdir else 1) + if im(ndir).is_negative: + if x0.is_positive: + return self.func(x0) + I*pi + elif im(ndir).is_positive: + if x0.is_negative: + return self.func(x0) - I*pi + else: + return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir) + return self.func(x0) + + def _eval_nseries(self, x, n, logx, cdir=0): # acoth + arg = self.args[0] + arg0 = arg.subs(x, 0) + + # Handling branch points + if arg0 in (S.One, S.NegativeOne): + return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir) + + res = super()._eval_nseries(x, n=n, logx=logx) + if arg0 is S.ComplexInfinity: + return res + + # Handling points lying on branch cuts [-1, 1] + if arg0.is_real and (1 - arg0**2).is_positive: + ndir = arg.dir(x, cdir if cdir else 1) + if im(ndir).is_negative: + if arg0.is_positive: + return res + I*pi + elif im(ndir).is_positive: + if arg0.is_negative: + return res - I*pi + else: + return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir) + return res + + def _eval_rewrite_as_log(self, x, **kwargs): + return (log(1 + 1/x) - log(1 - 1/x)) / 2 + + _eval_rewrite_as_tractable = _eval_rewrite_as_log + + def _eval_rewrite_as_atanh(self, x, **kwargs): + return atanh(1/x) + + def _eval_rewrite_as_asinh(self, x, **kwargs): + return (pi*I/2*(sqrt((x - 1)/x)*sqrt(x/(x - 1)) - sqrt(1 + 1/x)*sqrt(x/(x + 1))) + + x*sqrt(1/x**2)*asinh(sqrt(1/(x**2 - 1)))) + + def inverse(self, argindex=1): + """ + Returns the inverse of this function. + """ + return coth + + def _eval_is_extended_real(self): + return fuzzy_and([self.args[0].is_extended_real, fuzzy_or([(self.args[0] - 1).is_extended_nonnegative, (self.args[0] + 1).is_extended_nonpositive])]) + + def _eval_is_finite(self): + return fuzzy_not(fuzzy_or([(self.args[0] - 1).is_zero, (self.args[0] + 1).is_zero])) + + +class asech(InverseHyperbolicFunction): + """ + ``asech(x)`` is the inverse hyperbolic secant of ``x``. + + The inverse hyperbolic secant function. + + Examples + ======== + + >>> from sympy import asech, sqrt, S + >>> from sympy.abc import x + >>> asech(x).diff(x) + -1/(x*sqrt(1 - x**2)) + >>> asech(1).diff(x) + 0 + >>> asech(1) + 0 + >>> asech(S(2)) + I*pi/3 + >>> asech(-sqrt(2)) + 3*I*pi/4 + >>> asech((sqrt(6) - sqrt(2))) + I*pi/12 + + See Also + ======== + + asinh, atanh, cosh, acoth + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Hyperbolic_function + .. [2] https://dlmf.nist.gov/4.37 + .. [3] https://functions.wolfram.com/ElementaryFunctions/ArcSech/ + + """ + + def fdiff(self, argindex=1): + if argindex == 1: + z = self.args[0] + return -1/(z*sqrt(1 - z**2)) + else: + raise ArgumentIndexError(self, argindex) + + @classmethod + def eval(cls, arg): + if arg.is_Number: + if arg is S.NaN: + return S.NaN + elif arg is S.Infinity: + return pi*I / 2 + elif arg is S.NegativeInfinity: + return pi*I / 2 + elif arg.is_zero: + return S.Infinity + elif arg is S.One: + return S.Zero + elif arg is S.NegativeOne: + return pi*I + + if arg.is_number: + cst_table = _asech_table() + + if arg in cst_table: + if arg.is_extended_real: + return cst_table[arg]*I + return cst_table[arg] + + if arg is S.ComplexInfinity: + from sympy.calculus.accumulationbounds import AccumBounds + return I*AccumBounds(-pi/2, pi/2) + + if arg.is_zero: + return S.Infinity + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + if n == 0: + return log(2 / x) + elif n < 0 or n % 2 == 1: + return S.Zero + else: + x = sympify(x) + if len(previous_terms) > 2 and n > 2: + p = previous_terms[-2] + return p * ((n - 1)*(n-2)) * x**2/(4 * (n//2)**2) + else: + k = n // 2 + R = RisingFactorial(S.Half, k) * n + F = factorial(k) * n // 2 * n // 2 + return -1 * R / F * x**n / 4 + + def _eval_as_leading_term(self, x, logx, cdir): + arg = self.args[0] + x0 = arg.subs(x, 0).cancel() + # Handling branch points + if x0 in (-S.One, S.Zero, S.One, S.ComplexInfinity): + return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir) + + if x0 is S.NaN: + expr = self.func(arg.as_leading_term(x)) + if expr.is_finite: + return expr + else: + return self + + # Handling points lying on branch cuts (-oo, 0] U (1, oo) + if x0.is_negative or (1 - x0).is_negative: + ndir = arg.dir(x, cdir if cdir else 1) + if im(ndir).is_positive: + if x0.is_positive or (x0 + 1).is_negative: + return -self.func(x0) + return self.func(x0) - 2*I*pi + elif not im(ndir).is_negative: + return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir) + return self.func(x0) + + def _eval_nseries(self, x, n, logx, cdir=0): # asech + from sympy.series.order import O + arg = self.args[0] + arg0 = arg.subs(x, 0) + + # Handling branch points + if arg0 is S.One: + t = Dummy('t', positive=True) + ser = asech(S.One - t**2).rewrite(log).nseries(t, 0, 2*n) + arg1 = S.One - self.args[0] + f = arg1.as_leading_term(x) + g = (arg1 - f)/ f + if not g.is_meromorphic(x, 0): # cannot be expanded + return O(1) if n == 0 else O(sqrt(x)) + res1 = sqrt(S.One + g)._eval_nseries(x, n=n, logx=logx) + res = (res1.removeO()*sqrt(f)).expand() + return ser.removeO().subs(t, res).expand().powsimp() + O(x**n, x) + + if arg0 is S.NegativeOne: + t = Dummy('t', positive=True) + ser = asech(S.NegativeOne + t**2).rewrite(log).nseries(t, 0, 2*n) + arg1 = S.One + self.args[0] + f = arg1.as_leading_term(x) + g = (arg1 - f)/ f + if not g.is_meromorphic(x, 0): # cannot be expanded + return O(1) if n == 0 else I*pi + O(sqrt(x)) + res1 = sqrt(S.One + g)._eval_nseries(x, n=n, logx=logx) + res = (res1.removeO()*sqrt(f)).expand() + return ser.removeO().subs(t, res).expand().powsimp() + O(x**n, x) + + res = super()._eval_nseries(x, n=n, logx=logx) + if arg0 is S.ComplexInfinity: + return res + + # Handling points lying on branch cuts (-oo, 0] U (1, oo) + if arg0.is_negative or (1 - arg0).is_negative: + ndir = arg.dir(x, cdir if cdir else 1) + if im(ndir).is_positive: + if arg0.is_positive or (arg0 + 1).is_negative: + return -res + return res - 2*I*pi + elif not im(ndir).is_negative: + return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir) + return res + + def inverse(self, argindex=1): + """ + Returns the inverse of this function. + """ + return sech + + def _eval_rewrite_as_log(self, arg, **kwargs): + return log(1/arg + sqrt(1/arg - 1) * sqrt(1/arg + 1)) + + _eval_rewrite_as_tractable = _eval_rewrite_as_log + + def _eval_rewrite_as_acosh(self, arg, **kwargs): + return acosh(1/arg) + + def _eval_rewrite_as_asinh(self, arg, **kwargs): + return sqrt(1/arg - 1)/sqrt(1 - 1/arg)*(I*asinh(I/arg, evaluate=False) + + pi*S.Half) + + def _eval_rewrite_as_atanh(self, x, **kwargs): + return (I*pi*(1 - sqrt(x)*sqrt(1/x) - I/2*sqrt(-x)/sqrt(x) - I/2*sqrt(x**2)/sqrt(-x**2)) + + sqrt(1/(x + 1))*sqrt(x + 1)*atanh(sqrt(1 - x**2))) + + def _eval_rewrite_as_acsch(self, x, **kwargs): + return sqrt(1/x - 1)/sqrt(1 - 1/x)*(pi/2 - I*acsch(I*x, evaluate=False)) + + def _eval_is_extended_real(self): + return fuzzy_and([self.args[0].is_extended_real, self.args[0].is_nonnegative, (1 - self.args[0]).is_nonnegative]) + + def _eval_is_finite(self): + return fuzzy_not(self.args[0].is_zero) + + +class acsch(InverseHyperbolicFunction): + """ + ``acsch(x)`` is the inverse hyperbolic cosecant of ``x``. + + The inverse hyperbolic cosecant function. + + Examples + ======== + + >>> from sympy import acsch, sqrt, I + >>> from sympy.abc import x + >>> acsch(x).diff(x) + -1/(x**2*sqrt(1 + x**(-2))) + >>> acsch(1).diff(x) + 0 + >>> acsch(1) + log(1 + sqrt(2)) + >>> acsch(I) + -I*pi/2 + >>> acsch(-2*I) + I*pi/6 + >>> acsch(I*(sqrt(6) - sqrt(2))) + -5*I*pi/12 + + See Also + ======== + + asinh + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Hyperbolic_function + .. [2] https://dlmf.nist.gov/4.37 + .. [3] https://functions.wolfram.com/ElementaryFunctions/ArcCsch/ + + """ + + def fdiff(self, argindex=1): + if argindex == 1: + z = self.args[0] + return -1/(z**2*sqrt(1 + 1/z**2)) + else: + raise ArgumentIndexError(self, argindex) + + @classmethod + def eval(cls, arg): + if arg.is_Number: + if arg is S.NaN: + return S.NaN + elif arg is S.Infinity: + return S.Zero + elif arg is S.NegativeInfinity: + return S.Zero + elif arg.is_zero: + return S.ComplexInfinity + elif arg is S.One: + return log(1 + sqrt(2)) + elif arg is S.NegativeOne: + return - log(1 + sqrt(2)) + + if arg.is_number: + cst_table = _acsch_table() + + if arg in cst_table: + return cst_table[arg]*I + + if arg is S.ComplexInfinity: + return S.Zero + + if arg.is_infinite: + return S.Zero + + if arg.is_zero: + return S.ComplexInfinity + + if arg.could_extract_minus_sign(): + return -cls(-arg) + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + if n == 0: + return log(2 / x) + elif n < 0 or n % 2 == 1: + return S.Zero + else: + x = sympify(x) + if len(previous_terms) > 2 and n > 2: + p = previous_terms[-2] + return -p * ((n - 1)*(n-2)) * x**2/(4 * (n//2)**2) + else: + k = n // 2 + R = RisingFactorial(S.Half, k) * n + F = factorial(k) * n // 2 * n // 2 + return S.NegativeOne**(k +1) * R / F * x**n / 4 + + def _eval_as_leading_term(self, x, logx, cdir): + arg = self.args[0] + x0 = arg.subs(x, 0).cancel() + # Handling branch points + if x0 in (-I, I, S.Zero): + return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir) + + if x0 is S.NaN: + expr = self.func(arg.as_leading_term(x)) + if expr.is_finite: + return expr + else: + return self + + if x0 is S.ComplexInfinity: + return (1/arg).as_leading_term(x) + # Handling points lying on branch cuts (-I, I) + if x0.is_imaginary and (1 + x0**2).is_positive: + ndir = arg.dir(x, cdir if cdir else 1) + if re(ndir).is_positive: + if im(x0).is_positive: + return -self.func(x0) - I*pi + elif re(ndir).is_negative: + if im(x0).is_negative: + return -self.func(x0) + I*pi + else: + return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir) + return self.func(x0) + + def _eval_nseries(self, x, n, logx, cdir=0): # acsch + from sympy.series.order import O + arg = self.args[0] + arg0 = arg.subs(x, 0) + + # Handling branch points + if arg0 is I: + t = Dummy('t', positive=True) + ser = acsch(I + t**2).rewrite(log).nseries(t, 0, 2*n) + arg1 = -I + self.args[0] + f = arg1.as_leading_term(x) + g = (arg1 - f)/ f + if not g.is_meromorphic(x, 0): # cannot be expanded + return O(1) if n == 0 else -I*pi/2 + O(sqrt(x)) + res1 = sqrt(S.One + g)._eval_nseries(x, n=n, logx=logx) + res = (res1.removeO()*sqrt(f)).expand() + res = ser.removeO().subs(t, res).expand().powsimp() + O(x**n, x) + return res + + if arg0 == S.NegativeOne*I: + t = Dummy('t', positive=True) + ser = acsch(-I + t**2).rewrite(log).nseries(t, 0, 2*n) + arg1 = I + self.args[0] + f = arg1.as_leading_term(x) + g = (arg1 - f)/ f + if not g.is_meromorphic(x, 0): # cannot be expanded + return O(1) if n == 0 else I*pi/2 + O(sqrt(x)) + res1 = sqrt(S.One + g)._eval_nseries(x, n=n, logx=logx) + res = (res1.removeO()*sqrt(f)).expand() + return ser.removeO().subs(t, res).expand().powsimp() + O(x**n, x) + + res = super()._eval_nseries(x, n=n, logx=logx) + if arg0 is S.ComplexInfinity: + return res + + # Handling points lying on branch cuts (-I, I) + if arg0.is_imaginary and (1 + arg0**2).is_positive: + ndir = self.args[0].dir(x, cdir if cdir else 1) + if re(ndir).is_positive: + if im(arg0).is_positive: + return -res - I*pi + elif re(ndir).is_negative: + if im(arg0).is_negative: + return -res + I*pi + else: + return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir) + return res + + def inverse(self, argindex=1): + """ + Returns the inverse of this function. + """ + return csch + + def _eval_rewrite_as_log(self, arg, **kwargs): + return log(1/arg + sqrt(1/arg**2 + 1)) + + _eval_rewrite_as_tractable = _eval_rewrite_as_log + + def _eval_rewrite_as_asinh(self, arg, **kwargs): + return asinh(1/arg) + + def _eval_rewrite_as_acosh(self, arg, **kwargs): + return I*(sqrt(1 - I/arg)/sqrt(I/arg - 1)* + acosh(I/arg, evaluate=False) - pi*S.Half) + + def _eval_rewrite_as_atanh(self, arg, **kwargs): + arg2 = arg**2 + arg2p1 = arg2 + 1 + return sqrt(-arg2)/arg*(pi*S.Half - + sqrt(-arg2p1**2)/arg2p1*atanh(sqrt(arg2p1))) + + def _eval_is_zero(self): + return self.args[0].is_infinite + + def _eval_is_extended_real(self): + return self.args[0].is_extended_real + + def _eval_is_finite(self): + return fuzzy_not(self.args[0].is_zero) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/integers.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/integers.py new file mode 100644 index 0000000000000000000000000000000000000000..d0b58d32399144c39133855475d70c01b70b1a3f --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/integers.py @@ -0,0 +1,710 @@ +from __future__ import annotations + +from sympy.core.basic import Basic +from sympy.core.expr import Expr + +from sympy.core import Add, S +from sympy.core.evalf import get_integer_part, PrecisionExhausted +from sympy.core.function import DefinedFunction +from sympy.core.logic import fuzzy_or, fuzzy_and +from sympy.core.numbers import Integer, int_valued +from sympy.core.relational import Gt, Lt, Ge, Le, Relational, is_eq, is_le, is_lt +from sympy.core.sympify import _sympify +from sympy.functions.elementary.complexes import im, re +from sympy.multipledispatch import dispatch + +############################################################################### +######################### FLOOR and CEILING FUNCTIONS ######################### +############################################################################### + + +class RoundFunction(DefinedFunction): + """Abstract base class for rounding functions.""" + + args: tuple[Expr] + + @classmethod + def eval(cls, arg): + if (v := cls._eval_number(arg)) is not None: + return v + if (v := cls._eval_const_number(arg)) is not None: + return v + + if arg.is_integer or arg.is_finite is False: + return arg + if arg.is_imaginary or (S.ImaginaryUnit*arg).is_real: + i = im(arg) + if not i.has(S.ImaginaryUnit): + return cls(i)*S.ImaginaryUnit + return cls(arg, evaluate=False) + + # Integral, numerical, symbolic part + ipart = npart = spart = S.Zero + + # Extract integral (or complex integral) terms + intof = lambda x: int(x) if int_valued(x) else ( + x if x.is_integer else None) + for t in Add.make_args(arg): + if t.is_imaginary and (i := intof(im(t))) is not None: + ipart += i*S.ImaginaryUnit + elif (i := intof(t)) is not None: + ipart += i + elif t.is_number: + npart += t + else: + spart += t + + if not (npart or spart): + return ipart + + # Evaluate npart numerically if independent of spart + if npart and ( + not spart or + npart.is_real and (spart.is_imaginary or (S.ImaginaryUnit*spart).is_real) or + npart.is_imaginary and spart.is_real): + try: + r, i = get_integer_part( + npart, cls._dir, {}, return_ints=True) + ipart += Integer(r) + Integer(i)*S.ImaginaryUnit + npart = S.Zero + except (PrecisionExhausted, NotImplementedError): + pass + + spart += npart + if not spart: + return ipart + elif spart.is_imaginary or (S.ImaginaryUnit*spart).is_real: + return ipart + cls(im(spart), evaluate=False)*S.ImaginaryUnit + elif isinstance(spart, (floor, ceiling)): + return ipart + spart + else: + return ipart + cls(spart, evaluate=False) + + @classmethod + def _eval_number(cls, arg): + raise NotImplementedError() + + def _eval_is_finite(self): + return self.args[0].is_finite + + def _eval_is_real(self): + return self.args[0].is_real + + def _eval_is_integer(self): + return self.args[0].is_real + + +class floor(RoundFunction): + """ + Floor is a univariate function which returns the largest integer + value not greater than its argument. This implementation + generalizes floor to complex numbers by taking the floor of the + real and imaginary parts separately. + + Examples + ======== + + >>> from sympy import floor, E, I, S, Float, Rational + >>> floor(17) + 17 + >>> floor(Rational(23, 10)) + 2 + >>> floor(2*E) + 5 + >>> floor(-Float(0.567)) + -1 + >>> floor(-I/2) + -I + >>> floor(S(5)/2 + 5*I/2) + 2 + 2*I + + See Also + ======== + + sympy.functions.elementary.integers.ceiling + + References + ========== + + .. [1] "Concrete mathematics" by Graham, pp. 87 + .. [2] https://mathworld.wolfram.com/FloorFunction.html + + """ + _dir = -1 + + @classmethod + def _eval_number(cls, arg): + if arg.is_Number: + return arg.floor() + if any(isinstance(i, j) + for i in (arg, -arg) for j in (floor, ceiling)): + return arg + if arg.is_NumberSymbol: + return arg.approximation_interval(Integer)[0] + + @classmethod + def _eval_const_number(cls, arg): + if arg.is_real: + if arg.is_zero: + return S.Zero + if arg.is_positive: + num, den = arg.as_numer_denom() + s = den.is_negative + if s is None: + return None + if s: + num, den = -num, -den + # 0 <= num/den < 1 -> 0 + if is_lt(num, den): + return S.Zero + # 1 <= num/den < 2 -> 1 + if fuzzy_and([is_le(den, num), is_lt(num, 2*den)]): + return S.One + if arg.is_negative: + num, den = arg.as_numer_denom() + s = den.is_negative + if s is None: + return None + if s: + num, den = -num, -den + # -1 <= num/den < 0 -> -1 + if is_le(-den, num): + return S.NegativeOne + # -2 <= num/den < -1 -> -2 + if fuzzy_and([is_le(-2*den, num), is_lt(num, -den)]): + return Integer(-2) + + def _eval_as_leading_term(self, x, logx, cdir): + from sympy.calculus.accumulationbounds import AccumBounds + arg = self.args[0] + arg0 = arg.subs(x, 0) + r = self.subs(x, 0) + if arg0 is S.NaN or isinstance(arg0, AccumBounds): + arg0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+') + r = floor(arg0) + if arg0.is_finite: + if arg0 == r: + ndir = arg.dir(x, cdir=cdir if cdir != 0 else 1) + if ndir.is_negative: + return r - 1 + elif ndir.is_positive: + return r + else: + raise NotImplementedError("Not sure of sign of %s" % ndir) + else: + return r + return arg.as_leading_term(x, logx=logx, cdir=cdir) + + def _eval_nseries(self, x, n, logx, cdir=0): + arg = self.args[0] + arg0 = arg.subs(x, 0) + r = self.subs(x, 0) + if arg0 is S.NaN: + arg0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+') + r = floor(arg0) + if arg0.is_infinite: + from sympy.calculus.accumulationbounds import AccumBounds + from sympy.series.order import Order + s = arg._eval_nseries(x, n, logx, cdir) + o = Order(1, (x, 0)) if n <= 0 else AccumBounds(-1, 0) + return s + o + if arg0 == r: + ndir = arg.dir(x, cdir=cdir if cdir != 0 else 1) + if ndir.is_negative: + return r - 1 + elif ndir.is_positive: + return r + else: + raise NotImplementedError("Not sure of sign of %s" % ndir) + else: + return r + + def _eval_is_negative(self): + return self.args[0].is_negative + + def _eval_is_nonnegative(self): + return self.args[0].is_nonnegative + + def _eval_rewrite_as_ceiling(self, arg, **kwargs): + return -ceiling(-arg) + + def _eval_rewrite_as_frac(self, arg, **kwargs): + return arg - frac(arg) + + def __le__(self, other): + other = S(other) + if self.args[0].is_real: + if other.is_integer: + return self.args[0] < other + 1 + if other.is_number and other.is_real: + return self.args[0] < ceiling(other) + if self.args[0] == other and other.is_real: + return S.true + if other is S.Infinity and self.is_finite: + return S.true + + return Le(self, other, evaluate=False) + + def __ge__(self, other): + other = S(other) + if self.args[0].is_real: + if other.is_integer: + return self.args[0] >= other + if other.is_number and other.is_real: + return self.args[0] >= ceiling(other) + if self.args[0] == other and other.is_real and other.is_noninteger: + return S.false + if other is S.NegativeInfinity and self.is_finite: + return S.true + + return Ge(self, other, evaluate=False) + + def __gt__(self, other): + other = S(other) + if self.args[0].is_real: + if other.is_integer: + return self.args[0] >= other + 1 + if other.is_number and other.is_real: + return self.args[0] >= ceiling(other) + if self.args[0] == other and other.is_real: + return S.false + if other is S.NegativeInfinity and self.is_finite: + return S.true + + return Gt(self, other, evaluate=False) + + def __lt__(self, other): + other = S(other) + if self.args[0].is_real: + if other.is_integer: + return self.args[0] < other + if other.is_number and other.is_real: + return self.args[0] < ceiling(other) + if self.args[0] == other and other.is_real and other.is_noninteger: + return S.true + if other is S.Infinity and self.is_finite: + return S.true + + return Lt(self, other, evaluate=False) + + +@dispatch(floor, Expr) +def _eval_is_eq(lhs, rhs): # noqa:F811 + return is_eq(lhs.rewrite(ceiling), rhs) or \ + is_eq(lhs.rewrite(frac),rhs) + + +class ceiling(RoundFunction): + """ + Ceiling is a univariate function which returns the smallest integer + value not less than its argument. This implementation + generalizes ceiling to complex numbers by taking the ceiling of the + real and imaginary parts separately. + + Examples + ======== + + >>> from sympy import ceiling, E, I, S, Float, Rational + >>> ceiling(17) + 17 + >>> ceiling(Rational(23, 10)) + 3 + >>> ceiling(2*E) + 6 + >>> ceiling(-Float(0.567)) + 0 + >>> ceiling(I/2) + I + >>> ceiling(S(5)/2 + 5*I/2) + 3 + 3*I + + See Also + ======== + + sympy.functions.elementary.integers.floor + + References + ========== + + .. [1] "Concrete mathematics" by Graham, pp. 87 + .. [2] https://mathworld.wolfram.com/CeilingFunction.html + + """ + _dir = 1 + + @classmethod + def _eval_number(cls, arg): + if arg.is_Number: + return arg.ceiling() + if any(isinstance(i, j) + for i in (arg, -arg) for j in (floor, ceiling)): + return arg + if arg.is_NumberSymbol: + return arg.approximation_interval(Integer)[1] + + @classmethod + def _eval_const_number(cls, arg): + if arg.is_real: + if arg.is_zero: + return S.Zero + if arg.is_positive: + num, den = arg.as_numer_denom() + s = den.is_negative + if s is None: + return None + if s: + num, den = -num, -den + # 0 < num/den <= 1 -> 1 + if is_le(num, den): + return S.One + # 1 < num/den <= 2 -> 2 + if fuzzy_and([is_lt(den, num), is_le(num, 2*den)]): + return Integer(2) + if arg.is_negative: + num, den = arg.as_numer_denom() + s = den.is_negative + if s is None: + return None + if s: + num, den = -num, -den + # -1 < num/den <= 0 -> 0 + if is_lt(-den, num): + return S.Zero + # -2 < num/den <= -1 -> -1 + if fuzzy_and([is_lt(-2*den, num), is_le(num, -den)]): + return S.NegativeOne + + def _eval_as_leading_term(self, x, logx, cdir): + from sympy.calculus.accumulationbounds import AccumBounds + arg = self.args[0] + arg0 = arg.subs(x, 0) + r = self.subs(x, 0) + if arg0 is S.NaN or isinstance(arg0, AccumBounds): + arg0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+') + r = ceiling(arg0) + if arg0.is_finite: + if arg0 == r: + ndir = arg.dir(x, cdir=cdir if cdir != 0 else 1) + if ndir.is_negative: + return r + elif ndir.is_positive: + return r + 1 + else: + raise NotImplementedError("Not sure of sign of %s" % ndir) + else: + return r + return arg.as_leading_term(x, logx=logx, cdir=cdir) + + def _eval_nseries(self, x, n, logx, cdir=0): + arg = self.args[0] + arg0 = arg.subs(x, 0) + r = self.subs(x, 0) + if arg0 is S.NaN: + arg0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+') + r = ceiling(arg0) + if arg0.is_infinite: + from sympy.calculus.accumulationbounds import AccumBounds + from sympy.series.order import Order + s = arg._eval_nseries(x, n, logx, cdir) + o = Order(1, (x, 0)) if n <= 0 else AccumBounds(0, 1) + return s + o + if arg0 == r: + ndir = arg.dir(x, cdir=cdir if cdir != 0 else 1) + if ndir.is_negative: + return r + elif ndir.is_positive: + return r + 1 + else: + raise NotImplementedError("Not sure of sign of %s" % ndir) + else: + return r + + def _eval_rewrite_as_floor(self, arg, **kwargs): + return -floor(-arg) + + def _eval_rewrite_as_frac(self, arg, **kwargs): + return arg + frac(-arg) + + def _eval_is_positive(self): + return self.args[0].is_positive + + def _eval_is_nonpositive(self): + return self.args[0].is_nonpositive + + def __lt__(self, other): + other = S(other) + if self.args[0].is_real: + if other.is_integer: + return self.args[0] <= other - 1 + if other.is_number and other.is_real: + return self.args[0] <= floor(other) + if self.args[0] == other and other.is_real: + return S.false + if other is S.Infinity and self.is_finite: + return S.true + + return Lt(self, other, evaluate=False) + + def __gt__(self, other): + other = S(other) + if self.args[0].is_real: + if other.is_integer: + return self.args[0] > other + if other.is_number and other.is_real: + return self.args[0] > floor(other) + if self.args[0] == other and other.is_real and other.is_noninteger: + return S.true + if other is S.NegativeInfinity and self.is_finite: + return S.true + + return Gt(self, other, evaluate=False) + + def __ge__(self, other): + other = S(other) + if self.args[0].is_real: + if other.is_integer: + return self.args[0] > other - 1 + if other.is_number and other.is_real: + return self.args[0] > floor(other) + if self.args[0] == other and other.is_real: + return S.true + if other is S.NegativeInfinity and self.is_finite: + return S.true + + return Ge(self, other, evaluate=False) + + def __le__(self, other): + other = S(other) + if self.args[0].is_real: + if other.is_integer: + return self.args[0] <= other + if other.is_number and other.is_real: + return self.args[0] <= floor(other) + if self.args[0] == other and other.is_real and other.is_noninteger: + return S.false + if other is S.Infinity and self.is_finite: + return S.true + + return Le(self, other, evaluate=False) + + +@dispatch(ceiling, Basic) # type:ignore +def _eval_is_eq(lhs, rhs): # noqa:F811 + return is_eq(lhs.rewrite(floor), rhs) or is_eq(lhs.rewrite(frac),rhs) + + +class frac(DefinedFunction): + r"""Represents the fractional part of x + + For real numbers it is defined [1]_ as + + .. math:: + x - \left\lfloor{x}\right\rfloor + + Examples + ======== + + >>> from sympy import Symbol, frac, Rational, floor, I + >>> frac(Rational(4, 3)) + 1/3 + >>> frac(-Rational(4, 3)) + 2/3 + + returns zero for integer arguments + + >>> n = Symbol('n', integer=True) + >>> frac(n) + 0 + + rewrite as floor + + >>> x = Symbol('x') + >>> frac(x).rewrite(floor) + x - floor(x) + + for complex arguments + + >>> r = Symbol('r', real=True) + >>> t = Symbol('t', real=True) + >>> frac(t + I*r) + I*frac(r) + frac(t) + + See Also + ======== + + sympy.functions.elementary.integers.floor + sympy.functions.elementary.integers.ceiling + + References + =========== + + .. [1] https://en.wikipedia.org/wiki/Fractional_part + .. [2] https://mathworld.wolfram.com/FractionalPart.html + + """ + @classmethod + def eval(cls, arg): + from sympy.calculus.accumulationbounds import AccumBounds + + def _eval(arg): + if arg in (S.Infinity, S.NegativeInfinity): + return AccumBounds(0, 1) + if arg.is_integer: + return S.Zero + if arg.is_number: + if arg is S.NaN: + return S.NaN + elif arg is S.ComplexInfinity: + return S.NaN + else: + return arg - floor(arg) + return cls(arg, evaluate=False) + + real, imag = S.Zero, S.Zero + for t in Add.make_args(arg): + # Two checks are needed for complex arguments + # see issue-7649 for details + if t.is_imaginary or (S.ImaginaryUnit*t).is_real: + i = im(t) + if not i.has(S.ImaginaryUnit): + imag += i + else: + real += t + else: + real += t + + real = _eval(real) + imag = _eval(imag) + return real + S.ImaginaryUnit*imag + + def _eval_rewrite_as_floor(self, arg, **kwargs): + return arg - floor(arg) + + def _eval_rewrite_as_ceiling(self, arg, **kwargs): + return arg + ceiling(-arg) + + def _eval_is_finite(self): + return True + + def _eval_is_real(self): + return self.args[0].is_extended_real + + def _eval_is_imaginary(self): + return self.args[0].is_imaginary + + def _eval_is_integer(self): + return self.args[0].is_integer + + def _eval_is_zero(self): + return fuzzy_or([self.args[0].is_zero, self.args[0].is_integer]) + + def _eval_is_negative(self): + return False + + def __ge__(self, other): + if self.is_extended_real: + other = _sympify(other) + # Check if other <= 0 + if other.is_extended_nonpositive: + return S.true + # Check if other >= 1 + res = self._value_one_or_more(other) + if res is not None: + return not(res) + return Ge(self, other, evaluate=False) + + def __gt__(self, other): + if self.is_extended_real: + other = _sympify(other) + # Check if other < 0 + res = self._value_one_or_more(other) + if res is not None: + return not(res) + # Check if other >= 1 + if other.is_extended_negative: + return S.true + return Gt(self, other, evaluate=False) + + def __le__(self, other): + if self.is_extended_real: + other = _sympify(other) + # Check if other < 0 + if other.is_extended_negative: + return S.false + # Check if other >= 1 + res = self._value_one_or_more(other) + if res is not None: + return res + return Le(self, other, evaluate=False) + + def __lt__(self, other): + if self.is_extended_real: + other = _sympify(other) + # Check if other <= 0 + if other.is_extended_nonpositive: + return S.false + # Check if other >= 1 + res = self._value_one_or_more(other) + if res is not None: + return res + return Lt(self, other, evaluate=False) + + def _value_one_or_more(self, other): + if other.is_extended_real: + if other.is_number: + res = other >= 1 + if res and not isinstance(res, Relational): + return S.true + if other.is_integer and other.is_positive: + return S.true + + def _eval_as_leading_term(self, x, logx, cdir): + from sympy.calculus.accumulationbounds import AccumBounds + arg = self.args[0] + arg0 = arg.subs(x, 0) + r = self.subs(x, 0) + + if arg0.is_finite: + if r.is_zero: + ndir = arg.dir(x, cdir=cdir) + if ndir.is_negative: + return S.One + return (arg - arg0).as_leading_term(x, logx=logx, cdir=cdir) + else: + return r + elif arg0 in (S.ComplexInfinity, S.Infinity, S.NegativeInfinity): + return AccumBounds(0, 1) + return arg.as_leading_term(x, logx=logx, cdir=cdir) + + def _eval_nseries(self, x, n, logx, cdir=0): + from sympy.series.order import Order + arg = self.args[0] + arg0 = arg.subs(x, 0) + r = self.subs(x, 0) + + if arg0.is_infinite: + from sympy.calculus.accumulationbounds import AccumBounds + o = Order(1, (x, 0)) if n <= 0 else AccumBounds(0, 1) + Order(x**n, (x, 0)) + return o + else: + res = (arg - arg0)._eval_nseries(x, n, logx=logx, cdir=cdir) + if r.is_zero: + ndir = arg.dir(x, cdir=cdir) + res += S.One if ndir.is_negative else S.Zero + else: + res += r + return res + + +@dispatch(frac, Basic) # type:ignore +def _eval_is_eq(lhs, rhs): # noqa:F811 + if (lhs.rewrite(floor) == rhs) or \ + (lhs.rewrite(ceiling) == rhs): + return True + # Check if other < 0 + if rhs.is_extended_negative: + return False + # Check if other >= 1 + res = lhs._value_one_or_more(rhs) + if res is not None: + return False diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/miscellaneous.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/miscellaneous.py new file mode 100644 index 0000000000000000000000000000000000000000..c7f3016bc7ea0d5c4ad778cf9922c941acb7fc44 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/miscellaneous.py @@ -0,0 +1,915 @@ +from sympy.core import S, sympify, NumberKind +from sympy.utilities.iterables import sift +from sympy.core.add import Add +from sympy.core.containers import Tuple +from sympy.core.operations import LatticeOp, ShortCircuit +from sympy.core.function import (Application, Lambda, + ArgumentIndexError, DefinedFunction) +from sympy.core.expr import Expr +from sympy.core.exprtools import factor_terms +from sympy.core.mod import Mod +from sympy.core.mul import Mul +from sympy.core.numbers import Rational +from sympy.core.power import Pow +from sympy.core.relational import Eq, Relational +from sympy.core.singleton import Singleton +from sympy.core.sorting import ordered +from sympy.core.symbol import Dummy +from sympy.core.rules import Transform +from sympy.core.logic import fuzzy_and, fuzzy_or, _torf +from sympy.core.traversal import walk +from sympy.core.numbers import Integer +from sympy.logic.boolalg import And, Or + + +def _minmax_as_Piecewise(op, *args): + # helper for Min/Max rewrite as Piecewise + from sympy.functions.elementary.piecewise import Piecewise + ec = [] + for i, a in enumerate(args): + c = [Relational(a, args[j], op) for j in range(i + 1, len(args))] + ec.append((a, And(*c))) + return Piecewise(*ec) + + +class IdentityFunction(Lambda, metaclass=Singleton): + """ + The identity function + + Examples + ======== + + >>> from sympy import Id, Symbol + >>> x = Symbol('x') + >>> Id(x) + x + + """ + + _symbol = Dummy('x') + + @property + def signature(self): + return Tuple(self._symbol) + + @property + def expr(self): + return self._symbol + + +Id = S.IdentityFunction + +############################################################################### +############################# ROOT and SQUARE ROOT FUNCTION ################### +############################################################################### + + +def sqrt(arg, evaluate=None): + """Returns the principal square root. + + Parameters + ========== + + evaluate : bool, optional + The parameter determines if the expression should be evaluated. + If ``None``, its value is taken from + ``global_parameters.evaluate``. + + Examples + ======== + + >>> from sympy import sqrt, Symbol, S + >>> x = Symbol('x') + + >>> sqrt(x) + sqrt(x) + + >>> sqrt(x)**2 + x + + Note that sqrt(x**2) does not simplify to x. + + >>> sqrt(x**2) + sqrt(x**2) + + This is because the two are not equal to each other in general. + For example, consider x == -1: + + >>> from sympy import Eq + >>> Eq(sqrt(x**2), x).subs(x, -1) + False + + This is because sqrt computes the principal square root, so the square may + put the argument in a different branch. This identity does hold if x is + positive: + + >>> y = Symbol('y', positive=True) + >>> sqrt(y**2) + y + + You can force this simplification by using the powdenest() function with + the force option set to True: + + >>> from sympy import powdenest + >>> sqrt(x**2) + sqrt(x**2) + >>> powdenest(sqrt(x**2), force=True) + x + + To get both branches of the square root you can use the rootof function: + + >>> from sympy import rootof + + >>> [rootof(x**2-3,i) for i in (0,1)] + [-sqrt(3), sqrt(3)] + + Although ``sqrt`` is printed, there is no ``sqrt`` function so looking for + ``sqrt`` in an expression will fail: + + >>> from sympy.utilities.misc import func_name + >>> func_name(sqrt(x)) + 'Pow' + >>> sqrt(x).has(sqrt) + False + + To find ``sqrt`` look for ``Pow`` with an exponent of ``1/2``: + + >>> (x + 1/sqrt(x)).find(lambda i: i.is_Pow and abs(i.exp) is S.Half) + {1/sqrt(x)} + + See Also + ======== + + sympy.polys.rootoftools.rootof, root, real_root + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Square_root + .. [2] https://en.wikipedia.org/wiki/Principal_value + """ + # arg = sympify(arg) is handled by Pow + return Pow(arg, S.Half, evaluate=evaluate) + + +def cbrt(arg, evaluate=None): + """Returns the principal cube root. + + Parameters + ========== + + evaluate : bool, optional + The parameter determines if the expression should be evaluated. + If ``None``, its value is taken from + ``global_parameters.evaluate``. + + Examples + ======== + + >>> from sympy import cbrt, Symbol + >>> x = Symbol('x') + + >>> cbrt(x) + x**(1/3) + + >>> cbrt(x)**3 + x + + Note that cbrt(x**3) does not simplify to x. + + >>> cbrt(x**3) + (x**3)**(1/3) + + This is because the two are not equal to each other in general. + For example, consider `x == -1`: + + >>> from sympy import Eq + >>> Eq(cbrt(x**3), x).subs(x, -1) + False + + This is because cbrt computes the principal cube root, this + identity does hold if `x` is positive: + + >>> y = Symbol('y', positive=True) + >>> cbrt(y**3) + y + + See Also + ======== + + sympy.polys.rootoftools.rootof, root, real_root + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Cube_root + .. [2] https://en.wikipedia.org/wiki/Principal_value + + """ + return Pow(arg, Rational(1, 3), evaluate=evaluate) + + +def root(arg, n, k=0, evaluate=None): + r"""Returns the *k*-th *n*-th root of ``arg``. + + Parameters + ========== + + k : int, optional + Should be an integer in $\{0, 1, ..., n-1\}$. + Defaults to the principal root if $0$. + + evaluate : bool, optional + The parameter determines if the expression should be evaluated. + If ``None``, its value is taken from + ``global_parameters.evaluate``. + + Examples + ======== + + >>> from sympy import root, Rational + >>> from sympy.abc import x, n + + >>> root(x, 2) + sqrt(x) + + >>> root(x, 3) + x**(1/3) + + >>> root(x, n) + x**(1/n) + + >>> root(x, -Rational(2, 3)) + x**(-3/2) + + To get the k-th n-th root, specify k: + + >>> root(-2, 3, 2) + -(-1)**(2/3)*2**(1/3) + + To get all n n-th roots you can use the rootof function. + The following examples show the roots of unity for n + equal 2, 3 and 4: + + >>> from sympy import rootof + + >>> [rootof(x**2 - 1, i) for i in range(2)] + [-1, 1] + + >>> [rootof(x**3 - 1,i) for i in range(3)] + [1, -1/2 - sqrt(3)*I/2, -1/2 + sqrt(3)*I/2] + + >>> [rootof(x**4 - 1,i) for i in range(4)] + [-1, 1, -I, I] + + SymPy, like other symbolic algebra systems, returns the + complex root of negative numbers. This is the principal + root and differs from the text-book result that one might + be expecting. For example, the cube root of -8 does not + come back as -2: + + >>> root(-8, 3) + 2*(-1)**(1/3) + + The real_root function can be used to either make the principal + result real (or simply to return the real root directly): + + >>> from sympy import real_root + >>> real_root(_) + -2 + >>> real_root(-32, 5) + -2 + + Alternatively, the n//2-th n-th root of a negative number can be + computed with root: + + >>> root(-32, 5, 5//2) + -2 + + See Also + ======== + + sympy.polys.rootoftools.rootof + sympy.core.intfunc.integer_nthroot + sqrt, real_root + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Square_root + .. [2] https://en.wikipedia.org/wiki/Real_root + .. [3] https://en.wikipedia.org/wiki/Root_of_unity + .. [4] https://en.wikipedia.org/wiki/Principal_value + .. [5] https://mathworld.wolfram.com/CubeRoot.html + + """ + n = sympify(n) + if k: + return Mul(Pow(arg, S.One/n, evaluate=evaluate), S.NegativeOne**(2*k/n), evaluate=evaluate) + return Pow(arg, 1/n, evaluate=evaluate) + + +def real_root(arg, n=None, evaluate=None): + r"""Return the real *n*'th-root of *arg* if possible. + + Parameters + ========== + + n : int or None, optional + If *n* is ``None``, then all instances of + $(-n)^{1/\text{odd}}$ will be changed to $-n^{1/\text{odd}}$. + This will only create a real root of a principal root. + The presence of other factors may cause the result to not be + real. + + evaluate : bool, optional + The parameter determines if the expression should be evaluated. + If ``None``, its value is taken from + ``global_parameters.evaluate``. + + Examples + ======== + + >>> from sympy import root, real_root + + >>> real_root(-8, 3) + -2 + >>> root(-8, 3) + 2*(-1)**(1/3) + >>> real_root(_) + -2 + + If one creates a non-principal root and applies real_root, the + result will not be real (so use with caution): + + >>> root(-8, 3, 2) + -2*(-1)**(2/3) + >>> real_root(_) + -2*(-1)**(2/3) + + See Also + ======== + + sympy.polys.rootoftools.rootof + sympy.core.intfunc.integer_nthroot + root, sqrt + """ + from sympy.functions.elementary.complexes import Abs, im, sign + from sympy.functions.elementary.piecewise import Piecewise + if n is not None: + return Piecewise( + (root(arg, n, evaluate=evaluate), Or(Eq(n, S.One), Eq(n, S.NegativeOne))), + (Mul(sign(arg), root(Abs(arg), n, evaluate=evaluate), evaluate=evaluate), + And(Eq(im(arg), S.Zero), Eq(Mod(n, 2), S.One))), + (root(arg, n, evaluate=evaluate), True)) + rv = sympify(arg) + n1pow = Transform(lambda x: -(-x.base)**x.exp, + lambda x: + x.is_Pow and + x.base.is_negative and + x.exp.is_Rational and + x.exp.p == 1 and x.exp.q % 2) + return rv.xreplace(n1pow) + +############################################################################### +############################# MINIMUM and MAXIMUM ############################# +############################################################################### + + +class MinMaxBase(Expr, LatticeOp): + def __new__(cls, *args, **assumptions): + from sympy.core.parameters import global_parameters + evaluate = assumptions.pop('evaluate', global_parameters.evaluate) + args = (sympify(arg) for arg in args) + + # first standard filter, for cls.zero and cls.identity + # also reshape Max(a, Max(b, c)) to Max(a, b, c) + + if evaluate: + try: + args = frozenset(cls._new_args_filter(args)) + except ShortCircuit: + return cls.zero + # remove redundant args that are easily identified + args = cls._collapse_arguments(args, **assumptions) + # find local zeros + args = cls._find_localzeros(args, **assumptions) + args = frozenset(args) + + if not args: + return cls.identity + + if len(args) == 1: + return list(args).pop() + + # base creation + obj = Expr.__new__(cls, *ordered(args), **assumptions) + obj._argset = args + return obj + + @classmethod + def _collapse_arguments(cls, args, **assumptions): + """Remove redundant args. + + Examples + ======== + + >>> from sympy import Min, Max + >>> from sympy.abc import a, b, c, d, e + + Any arg in parent that appears in any + parent-like function in any of the flat args + of parent can be removed from that sub-arg: + + >>> Min(a, Max(b, Min(a, c, d))) + Min(a, Max(b, Min(c, d))) + + If the arg of parent appears in an opposite-than parent + function in any of the flat args of parent that function + can be replaced with the arg: + + >>> Min(a, Max(b, Min(c, d, Max(a, e)))) + Min(a, Max(b, Min(a, c, d))) + """ + if not args: + return args + args = list(ordered(args)) + if cls == Min: + other = Max + else: + other = Min + + # find global comparable max of Max and min of Min if a new + # value is being introduced in these args at position 0 of + # the ordered args + if args[0].is_number: + sifted = mins, maxs = [], [] + for i in args: + for v in walk(i, Min, Max): + if v.args[0].is_comparable: + sifted[isinstance(v, Max)].append(v) + small = Min.identity + for i in mins: + v = i.args[0] + if v.is_number and (v < small) == True: + small = v + big = Max.identity + for i in maxs: + v = i.args[0] + if v.is_number and (v > big) == True: + big = v + # at the point when this function is called from __new__, + # there may be more than one numeric arg present since + # local zeros have not been handled yet, so look through + # more than the first arg + if cls == Min: + for arg in args: + if not arg.is_number: + break + if (arg < small) == True: + small = arg + elif cls == Max: + for arg in args: + if not arg.is_number: + break + if (arg > big) == True: + big = arg + T = None + if cls == Min: + if small != Min.identity: + other = Max + T = small + elif big != Max.identity: + other = Min + T = big + if T is not None: + # remove numerical redundancy + for i in range(len(args)): + a = args[i] + if isinstance(a, other): + a0 = a.args[0] + if ((a0 > T) if other == Max else (a0 < T)) == True: + args[i] = cls.identity + + # remove redundant symbolic args + def do(ai, a): + if not isinstance(ai, (Min, Max)): + return ai + cond = a in ai.args + if not cond: + return ai.func(*[do(i, a) for i in ai.args], + evaluate=False) + if isinstance(ai, cls): + return ai.func(*[do(i, a) for i in ai.args if i != a], + evaluate=False) + return a + for i, a in enumerate(args): + args[i + 1:] = [do(ai, a) for ai in args[i + 1:]] + + # factor out common elements as for + # Min(Max(x, y), Max(x, z)) -> Max(x, Min(y, z)) + # and vice versa when swapping Min/Max -- do this only for the + # easy case where all functions contain something in common; + # trying to find some optimal subset of args to modify takes + # too long + + def factor_minmax(args): + is_other = lambda arg: isinstance(arg, other) + other_args, remaining_args = sift(args, is_other, binary=True) + if not other_args: + return args + + # Min(Max(x, y, z), Max(x, y, u, v)) -> {x,y}, ({z}, {u,v}) + arg_sets = [set(arg.args) for arg in other_args] + common = set.intersection(*arg_sets) + if not common: + return args + + new_other_args = list(common) + arg_sets_diff = [arg_set - common for arg_set in arg_sets] + + # If any set is empty after removing common then all can be + # discarded e.g. Min(Max(a, b, c), Max(a, b)) -> Max(a, b) + if all(arg_sets_diff): + other_args_diff = [other(*s, evaluate=False) for s in arg_sets_diff] + new_other_args.append(cls(*other_args_diff, evaluate=False)) + + other_args_factored = other(*new_other_args, evaluate=False) + return remaining_args + [other_args_factored] + + if len(args) > 1: + args = factor_minmax(args) + + return args + + @classmethod + def _new_args_filter(cls, arg_sequence): + """ + Generator filtering args. + + first standard filter, for cls.zero and cls.identity. + Also reshape ``Max(a, Max(b, c))`` to ``Max(a, b, c)``, + and check arguments for comparability + """ + for arg in arg_sequence: + # pre-filter, checking comparability of arguments + if not isinstance(arg, Expr) or arg.is_extended_real is False or ( + arg.is_number and + not arg.is_comparable): + raise ValueError("The argument '%s' is not comparable." % arg) + + if arg == cls.zero: + raise ShortCircuit(arg) + elif arg == cls.identity: + continue + elif arg.func == cls: + yield from arg.args + else: + yield arg + + @classmethod + def _find_localzeros(cls, values, **options): + """ + Sequentially allocate values to localzeros. + + When a value is identified as being more extreme than another member it + replaces that member; if this is never true, then the value is simply + appended to the localzeros. + """ + localzeros = set() + for v in values: + is_newzero = True + localzeros_ = list(localzeros) + for z in localzeros_: + if id(v) == id(z): + is_newzero = False + else: + con = cls._is_connected(v, z) + if con: + is_newzero = False + if con is True or con == cls: + localzeros.remove(z) + localzeros.update([v]) + if is_newzero: + localzeros.update([v]) + return localzeros + + @classmethod + def _is_connected(cls, x, y): + """ + Check if x and y are connected somehow. + """ + for i in range(2): + if x == y: + return True + t, f = Max, Min + for op in "><": + for j in range(2): + try: + if op == ">": + v = x >= y + else: + v = x <= y + except TypeError: + return False # non-real arg + if not v.is_Relational: + return t if v else f + t, f = f, t + x, y = y, x + x, y = y, x # run next pass with reversed order relative to start + # simplification can be expensive, so be conservative + # in what is attempted + x = factor_terms(x - y) + y = S.Zero + + return False + + def _eval_derivative(self, s): + # f(x).diff(s) -> x.diff(s) * f.fdiff(1)(s) + i = 0 + l = [] + for a in self.args: + i += 1 + da = a.diff(s) + if da.is_zero: + continue + try: + df = self.fdiff(i) + except ArgumentIndexError: + df = super().fdiff(i) + l.append(df * da) + return Add(*l) + + def _eval_rewrite_as_Abs(self, *args, **kwargs): + from sympy.functions.elementary.complexes import Abs + s = (args[0] + self.func(*args[1:]))/2 + d = abs(args[0] - self.func(*args[1:]))/2 + return (s + d if isinstance(self, Max) else s - d).rewrite(Abs) + + def evalf(self, n=15, **options): + return self.func(*[a.evalf(n, **options) for a in self.args]) + + def n(self, *args, **kwargs): + return self.evalf(*args, **kwargs) + + _eval_is_algebraic = lambda s: _torf(i.is_algebraic for i in s.args) + _eval_is_antihermitian = lambda s: _torf(i.is_antihermitian for i in s.args) + _eval_is_commutative = lambda s: _torf(i.is_commutative for i in s.args) + _eval_is_complex = lambda s: _torf(i.is_complex for i in s.args) + _eval_is_composite = lambda s: _torf(i.is_composite for i in s.args) + _eval_is_even = lambda s: _torf(i.is_even for i in s.args) + _eval_is_finite = lambda s: _torf(i.is_finite for i in s.args) + _eval_is_hermitian = lambda s: _torf(i.is_hermitian for i in s.args) + _eval_is_imaginary = lambda s: _torf(i.is_imaginary for i in s.args) + _eval_is_infinite = lambda s: _torf(i.is_infinite for i in s.args) + _eval_is_integer = lambda s: _torf(i.is_integer for i in s.args) + _eval_is_irrational = lambda s: _torf(i.is_irrational for i in s.args) + _eval_is_negative = lambda s: _torf(i.is_negative for i in s.args) + _eval_is_noninteger = lambda s: _torf(i.is_noninteger for i in s.args) + _eval_is_nonnegative = lambda s: _torf(i.is_nonnegative for i in s.args) + _eval_is_nonpositive = lambda s: _torf(i.is_nonpositive for i in s.args) + _eval_is_nonzero = lambda s: _torf(i.is_nonzero for i in s.args) + _eval_is_odd = lambda s: _torf(i.is_odd for i in s.args) + _eval_is_polar = lambda s: _torf(i.is_polar for i in s.args) + _eval_is_positive = lambda s: _torf(i.is_positive for i in s.args) + _eval_is_prime = lambda s: _torf(i.is_prime for i in s.args) + _eval_is_rational = lambda s: _torf(i.is_rational for i in s.args) + _eval_is_real = lambda s: _torf(i.is_real for i in s.args) + _eval_is_extended_real = lambda s: _torf(i.is_extended_real for i in s.args) + _eval_is_transcendental = lambda s: _torf(i.is_transcendental for i in s.args) + _eval_is_zero = lambda s: _torf(i.is_zero for i in s.args) + + +class Max(MinMaxBase, Application): + r""" + Return, if possible, the maximum value of the list. + + When number of arguments is equal one, then + return this argument. + + When number of arguments is equal two, then + return, if possible, the value from (a, b) that is $\ge$ the other. + + In common case, when the length of list greater than 2, the task + is more complicated. Return only the arguments, which are greater + than others, if it is possible to determine directional relation. + + If is not possible to determine such a relation, return a partially + evaluated result. + + Assumptions are used to make the decision too. + + Also, only comparable arguments are permitted. + + It is named ``Max`` and not ``max`` to avoid conflicts + with the built-in function ``max``. + + + Examples + ======== + + >>> from sympy import Max, Symbol, oo + >>> from sympy.abc import x, y, z + >>> p = Symbol('p', positive=True) + >>> n = Symbol('n', negative=True) + + >>> Max(x, -2) + Max(-2, x) + >>> Max(x, -2).subs(x, 3) + 3 + >>> Max(p, -2) + p + >>> Max(x, y) + Max(x, y) + >>> Max(x, y) == Max(y, x) + True + >>> Max(x, Max(y, z)) + Max(x, y, z) + >>> Max(n, 8, p, 7, -oo) + Max(8, p) + >>> Max (1, x, oo) + oo + + * Algorithm + + The task can be considered as searching of supremums in the + directed complete partial orders [1]_. + + The source values are sequentially allocated by the isolated subsets + in which supremums are searched and result as Max arguments. + + If the resulted supremum is single, then it is returned. + + The isolated subsets are the sets of values which are only the comparable + with each other in the current set. E.g. natural numbers are comparable with + each other, but not comparable with the `x` symbol. Another example: the + symbol `x` with negative assumption is comparable with a natural number. + + Also there are "least" elements, which are comparable with all others, + and have a zero property (maximum or minimum for all elements). + For example, in case of $\infty$, the allocation operation is terminated + and only this value is returned. + + Assumption: + - if $A > B > C$ then $A > C$ + - if $A = B$ then $B$ can be removed + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Directed_complete_partial_order + .. [2] https://en.wikipedia.org/wiki/Lattice_%28order%29 + + See Also + ======== + + Min : find minimum values + """ + zero = S.Infinity + identity = S.NegativeInfinity + + def fdiff( self, argindex ): + from sympy.functions.special.delta_functions import Heaviside + n = len(self.args) + if 0 < argindex and argindex <= n: + argindex -= 1 + if n == 2: + return Heaviside(self.args[argindex] - self.args[1 - argindex]) + newargs = tuple([self.args[i] for i in range(n) if i != argindex]) + return Heaviside(self.args[argindex] - Max(*newargs)) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_rewrite_as_Heaviside(self, *args, **kwargs): + from sympy.functions.special.delta_functions import Heaviside + return Add(*[j*Mul(*[Heaviside(j - i) for i in args if i!=j]) \ + for j in args]) + + def _eval_rewrite_as_Piecewise(self, *args, **kwargs): + return _minmax_as_Piecewise('>=', *args) + + def _eval_is_positive(self): + return fuzzy_or(a.is_positive for a in self.args) + + def _eval_is_nonnegative(self): + return fuzzy_or(a.is_nonnegative for a in self.args) + + def _eval_is_negative(self): + return fuzzy_and(a.is_negative for a in self.args) + + +class Min(MinMaxBase, Application): + """ + Return, if possible, the minimum value of the list. + It is named ``Min`` and not ``min`` to avoid conflicts + with the built-in function ``min``. + + Examples + ======== + + >>> from sympy import Min, Symbol, oo + >>> from sympy.abc import x, y + >>> p = Symbol('p', positive=True) + >>> n = Symbol('n', negative=True) + + >>> Min(x, -2) + Min(-2, x) + >>> Min(x, -2).subs(x, 3) + -2 + >>> Min(p, -3) + -3 + >>> Min(x, y) + Min(x, y) + >>> Min(n, 8, p, -7, p, oo) + Min(-7, n) + + See Also + ======== + + Max : find maximum values + """ + zero = S.NegativeInfinity + identity = S.Infinity + + def fdiff( self, argindex ): + from sympy.functions.special.delta_functions import Heaviside + n = len(self.args) + if 0 < argindex and argindex <= n: + argindex -= 1 + if n == 2: + return Heaviside( self.args[1-argindex] - self.args[argindex] ) + newargs = tuple([ self.args[i] for i in range(n) if i != argindex]) + return Heaviside( Min(*newargs) - self.args[argindex] ) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_rewrite_as_Heaviside(self, *args, **kwargs): + from sympy.functions.special.delta_functions import Heaviside + return Add(*[j*Mul(*[Heaviside(i-j) for i in args if i!=j]) \ + for j in args]) + + def _eval_rewrite_as_Piecewise(self, *args, **kwargs): + return _minmax_as_Piecewise('<=', *args) + + def _eval_is_positive(self): + return fuzzy_and(a.is_positive for a in self.args) + + def _eval_is_nonnegative(self): + return fuzzy_and(a.is_nonnegative for a in self.args) + + def _eval_is_negative(self): + return fuzzy_or(a.is_negative for a in self.args) + + +class Rem(DefinedFunction): + """Returns the remainder when ``p`` is divided by ``q`` where ``p`` is finite + and ``q`` is not equal to zero. The result, ``p - int(p/q)*q``, has the same sign + as the divisor. + + Parameters + ========== + + p : Expr + Dividend. + + q : Expr + Divisor. + + Notes + ===== + + ``Rem`` corresponds to the ``%`` operator in C. + + Examples + ======== + + >>> from sympy.abc import x, y + >>> from sympy import Rem + >>> Rem(x**3, y) + Rem(x**3, y) + >>> Rem(x**3, y).subs({x: -5, y: 3}) + -2 + + See Also + ======== + + Mod + """ + kind = NumberKind + + @classmethod + def eval(cls, p, q): + """Return the function remainder if both p, q are numbers and q is not + zero. + """ + + if q.is_zero: + raise ZeroDivisionError("Division by zero") + if p is S.NaN or q is S.NaN or p.is_finite is False or q.is_finite is False: + return S.NaN + if p is S.Zero or p in (q, -q) or (p.is_integer and q == 1): + return S.Zero + + if q.is_Number: + if p.is_Number: + return p - Integer(p/q)*q diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/piecewise.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/piecewise.py new file mode 100644 index 0000000000000000000000000000000000000000..fe4a4d4f57e2c3af170dac994e11782b9ed54b8f --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/piecewise.py @@ -0,0 +1,1517 @@ +from sympy.core import S, diff, Tuple, Dummy, Mul +from sympy.core.basic import Basic, as_Basic +from sympy.core.function import DefinedFunction +from sympy.core.numbers import Rational, NumberSymbol, _illegal +from sympy.core.parameters import global_parameters +from sympy.core.relational import (Lt, Gt, Eq, Ne, Relational, + _canonical, _canonical_coeff) +from sympy.core.sorting import ordered +from sympy.functions.elementary.miscellaneous import Max, Min +from sympy.logic.boolalg import (And, Boolean, distribute_and_over_or, Not, + true, false, Or, ITE, simplify_logic, to_cnf, distribute_or_over_and) +from sympy.utilities.iterables import uniq, sift, common_prefix +from sympy.utilities.misc import filldedent, func_name + +from itertools import product + +Undefined = S.NaN # Piecewise() + +class ExprCondPair(Tuple): + """Represents an expression, condition pair.""" + + def __new__(cls, expr, cond): + expr = as_Basic(expr) + if cond == True: + return Tuple.__new__(cls, expr, true) + elif cond == False: + return Tuple.__new__(cls, expr, false) + elif isinstance(cond, Basic) and cond.has(Piecewise): + cond = piecewise_fold(cond) + if isinstance(cond, Piecewise): + cond = cond.rewrite(ITE) + + if not isinstance(cond, Boolean): + raise TypeError(filldedent(''' + Second argument must be a Boolean, + not `%s`''' % func_name(cond))) + return Tuple.__new__(cls, expr, cond) + + @property + def expr(self): + """ + Returns the expression of this pair. + """ + return self.args[0] + + @property + def cond(self): + """ + Returns the condition of this pair. + """ + return self.args[1] + + @property + def is_commutative(self): + return self.expr.is_commutative + + def __iter__(self): + yield self.expr + yield self.cond + + def _eval_simplify(self, **kwargs): + return self.func(*[a.simplify(**kwargs) for a in self.args]) + + +class Piecewise(DefinedFunction): + """ + Represents a piecewise function. + + Usage: + + Piecewise( (expr,cond), (expr,cond), ... ) + - Each argument is a 2-tuple defining an expression and condition + - The conds are evaluated in turn returning the first that is True. + If any of the evaluated conds are not explicitly False, + e.g. ``x < 1``, the function is returned in symbolic form. + - If the function is evaluated at a place where all conditions are False, + nan will be returned. + - Pairs where the cond is explicitly False, will be removed and no pair + appearing after a True condition will ever be retained. If a single + pair with a True condition remains, it will be returned, even when + evaluation is False. + + Examples + ======== + + >>> from sympy import Piecewise, log, piecewise_fold + >>> from sympy.abc import x, y + >>> f = x**2 + >>> g = log(x) + >>> p = Piecewise((0, x < -1), (f, x <= 1), (g, True)) + >>> p.subs(x,1) + 1 + >>> p.subs(x,5) + log(5) + + Booleans can contain Piecewise elements: + + >>> cond = (x < y).subs(x, Piecewise((2, x < 0), (3, True))); cond + Piecewise((2, x < 0), (3, True)) < y + + The folded version of this results in a Piecewise whose + expressions are Booleans: + + >>> folded_cond = piecewise_fold(cond); folded_cond + Piecewise((2 < y, x < 0), (3 < y, True)) + + When a Boolean containing Piecewise (like cond) or a Piecewise + with Boolean expressions (like folded_cond) is used as a condition, + it is converted to an equivalent :class:`~.ITE` object: + + >>> Piecewise((1, folded_cond)) + Piecewise((1, ITE(x < 0, y > 2, y > 3))) + + When a condition is an ``ITE``, it will be converted to a simplified + Boolean expression: + + >>> piecewise_fold(_) + Piecewise((1, ((x >= 0) | (y > 2)) & ((y > 3) | (x < 0)))) + + See Also + ======== + + piecewise_fold + piecewise_exclusive + ITE + """ + + nargs = None + is_Piecewise = True + + def __new__(cls, *args, **options): + if len(args) == 0: + raise TypeError("At least one (expr, cond) pair expected.") + # (Try to) sympify args first + newargs = [] + for ec in args: + # ec could be a ExprCondPair or a tuple + pair = ExprCondPair(*getattr(ec, 'args', ec)) + cond = pair.cond + if cond is false: + continue + newargs.append(pair) + if cond is true: + break + + eval = options.pop('evaluate', global_parameters.evaluate) + if eval: + r = cls.eval(*newargs) + if r is not None: + return r + elif len(newargs) == 1 and newargs[0].cond == True: + return newargs[0].expr + + return Basic.__new__(cls, *newargs, **options) + + @classmethod + def eval(cls, *_args): + """Either return a modified version of the args or, if no + modifications were made, return None. + + Modifications that are made here: + + 1. relationals are made canonical + 2. any False conditions are dropped + 3. any repeat of a previous condition is ignored + 4. any args past one with a true condition are dropped + + If there are no args left, nan will be returned. + If there is a single arg with a True condition, its + corresponding expression will be returned. + + EXAMPLES + ======== + + >>> from sympy import Piecewise + >>> from sympy.abc import x + >>> cond = -x < -1 + >>> args = [(1, cond), (4, cond), (3, False), (2, True), (5, x < 1)] + >>> Piecewise(*args, evaluate=False) + Piecewise((1, -x < -1), (4, -x < -1), (2, True)) + >>> Piecewise(*args) + Piecewise((1, x > 1), (2, True)) + """ + if not _args: + return Undefined + + if len(_args) == 1 and _args[0][-1] == True: + return _args[0][0] + + newargs = _piecewise_collapse_arguments(_args) + + # some conditions may have been redundant + missing = len(newargs) != len(_args) + # some conditions may have changed + same = all(a == b for a, b in zip(newargs, _args)) + # if either change happened we return the expr with the + # updated args + if not newargs: + raise ValueError(filldedent(''' + There are no conditions (or none that + are not trivially false) to define an + expression.''')) + if missing or not same: + return cls(*newargs) + + def doit(self, **hints): + """ + Evaluate this piecewise function. + """ + newargs = [] + for e, c in self.args: + if hints.get('deep', True): + if isinstance(e, Basic): + newe = e.doit(**hints) + if newe != self: + e = newe + if isinstance(c, Basic): + c = c.doit(**hints) + newargs.append((e, c)) + return self.func(*newargs) + + def _eval_simplify(self, **kwargs): + return piecewise_simplify(self, **kwargs) + + def _eval_as_leading_term(self, x, logx, cdir): + for e, c in self.args: + if c == True or c.subs(x, 0) == True: + return e.as_leading_term(x) + + def _eval_adjoint(self): + return self.func(*[(e.adjoint(), c) for e, c in self.args]) + + def _eval_conjugate(self): + return self.func(*[(e.conjugate(), c) for e, c in self.args]) + + def _eval_derivative(self, x): + return self.func(*[(diff(e, x), c) for e, c in self.args]) + + def _eval_evalf(self, prec): + return self.func(*[(e._evalf(prec), c) for e, c in self.args]) + + def _eval_is_meromorphic(self, x, a): + # Conditions often implicitly assume that the argument is real. + # Hence, there needs to be some check for as_set. + if not a.is_real: + return None + + # Then, scan ExprCondPairs in the given order to find a piece that would contain a, + # possibly as a boundary point. + for e, c in self.args: + cond = c.subs(x, a) + + if cond.is_Relational: + return None + if a in c.as_set().boundary: + return None + # Apply expression if a is an interior point of the domain of e. + if cond: + return e._eval_is_meromorphic(x, a) + + def piecewise_integrate(self, x, **kwargs): + """Return the Piecewise with each expression being + replaced with its antiderivative. To obtain a continuous + antiderivative, use the :func:`~.integrate` function or method. + + Examples + ======== + + >>> from sympy import Piecewise + >>> from sympy.abc import x + >>> p = Piecewise((0, x < 0), (1, x < 1), (2, True)) + >>> p.piecewise_integrate(x) + Piecewise((0, x < 0), (x, x < 1), (2*x, True)) + + Note that this does not give a continuous function, e.g. + at x = 1 the 3rd condition applies and the antiderivative + there is 2*x so the value of the antiderivative is 2: + + >>> anti = _ + >>> anti.subs(x, 1) + 2 + + The continuous derivative accounts for the integral *up to* + the point of interest, however: + + >>> p.integrate(x) + Piecewise((0, x < 0), (x, x < 1), (2*x - 1, True)) + >>> _.subs(x, 1) + 1 + + See Also + ======== + Piecewise._eval_integral + """ + from sympy.integrals import integrate + return self.func(*[(integrate(e, x, **kwargs), c) for e, c in self.args]) + + def _handle_irel(self, x, handler): + """Return either None (if the conditions of self depend only on x) else + a Piecewise expression whose expressions (handled by the handler that + was passed) are paired with the governing x-independent relationals, + e.g. Piecewise((A, a(x) & b(y)), (B, c(x) | c(y)) -> + Piecewise( + (handler(Piecewise((A, a(x) & True), (B, c(x) | True)), b(y) & c(y)), + (handler(Piecewise((A, a(x) & True), (B, c(x) | False)), b(y)), + (handler(Piecewise((A, a(x) & False), (B, c(x) | True)), c(y)), + (handler(Piecewise((A, a(x) & False), (B, c(x) | False)), True)) + """ + # identify governing relationals + rel = self.atoms(Relational) + irel = list(ordered([r for r in rel if x not in r.free_symbols + and r not in (S.true, S.false)])) + if irel: + args = {} + exprinorder = [] + for truth in product((1, 0), repeat=len(irel)): + reps = dict(zip(irel, truth)) + # only store the true conditions since the false are implied + # when they appear lower in the Piecewise args + if 1 not in truth: + cond = None # flag this one so it doesn't get combined + else: + andargs = Tuple(*[i for i in reps if reps[i]]) + free = list(andargs.free_symbols) + if len(free) == 1: + from sympy.solvers.inequalities import ( + reduce_inequalities, _solve_inequality) + try: + t = reduce_inequalities(andargs, free[0]) + # ValueError when there are potentially + # nonvanishing imaginary parts + except (ValueError, NotImplementedError): + # at least isolate free symbol on left + t = And(*[_solve_inequality( + a, free[0], linear=True) + for a in andargs]) + else: + t = And(*andargs) + if t is S.false: + continue # an impossible combination + cond = t + expr = handler(self.xreplace(reps)) + if isinstance(expr, self.func) and len(expr.args) == 1: + expr, econd = expr.args[0] + cond = And(econd, True if cond is None else cond) + # the ec pairs are being collected since all possibilities + # are being enumerated, but don't put the last one in since + # its expr might match a previous expression and it + # must appear last in the args + if cond is not None: + args.setdefault(expr, []).append(cond) + # but since we only store the true conditions we must maintain + # the order so that the expression with the most true values + # comes first + exprinorder.append(expr) + # convert collected conditions as args of Or + for k in args: + args[k] = Or(*args[k]) + # take them in the order obtained + args = [(e, args[e]) for e in uniq(exprinorder)] + # add in the last arg + args.append((expr, True)) + return Piecewise(*args) + + def _eval_integral(self, x, _first=True, **kwargs): + """Return the indefinite integral of the + Piecewise such that subsequent substitution of x with a + value will give the value of the integral (not including + the constant of integration) up to that point. To only + integrate the individual parts of Piecewise, use the + ``piecewise_integrate`` method. + + Examples + ======== + + >>> from sympy import Piecewise + >>> from sympy.abc import x + >>> p = Piecewise((0, x < 0), (1, x < 1), (2, True)) + >>> p.integrate(x) + Piecewise((0, x < 0), (x, x < 1), (2*x - 1, True)) + >>> p.piecewise_integrate(x) + Piecewise((0, x < 0), (x, x < 1), (2*x, True)) + + See Also + ======== + Piecewise.piecewise_integrate + """ + from sympy.integrals.integrals import integrate + + if _first: + def handler(ipw): + if isinstance(ipw, self.func): + return ipw._eval_integral(x, _first=False, **kwargs) + else: + return ipw.integrate(x, **kwargs) + irv = self._handle_irel(x, handler) + if irv is not None: + return irv + + # handle a Piecewise from -oo to oo with and no x-independent relationals + # ----------------------------------------------------------------------- + ok, abei = self._intervals(x) + if not ok: + from sympy.integrals.integrals import Integral + return Integral(self, x) # unevaluated + + pieces = [(a, b) for a, b, _, _ in abei] + oo = S.Infinity + done = [(-oo, oo, -1)] + for k, p in enumerate(pieces): + if p == (-oo, oo): + # all undone intervals will get this key + for j, (a, b, i) in enumerate(done): + if i == -1: + done[j] = a, b, k + break # nothing else to consider + N = len(done) - 1 + for j, (a, b, i) in enumerate(reversed(done)): + if i == -1: + j = N - j + done[j: j + 1] = _clip(p, (a, b), k) + done = [(a, b, i) for a, b, i in done if a != b] + + # append an arg if there is a hole so a reference to + # argument -1 will give Undefined + if any(i == -1 for (a, b, i) in done): + abei.append((-oo, oo, Undefined, -1)) + + # return the sum of the intervals + args = [] + sum = None + for a, b, i in done: + anti = integrate(abei[i][-2], x, **kwargs) + if sum is None: + sum = anti + else: + sum = sum.subs(x, a) + e = anti._eval_interval(x, a, x) + if sum.has(*_illegal) or e.has(*_illegal): + sum = anti + else: + sum += e + # see if we know whether b is contained in original + # condition + if b is S.Infinity: + cond = True + elif self.args[abei[i][-1]].cond.subs(x, b) == False: + cond = (x < b) + else: + cond = (x <= b) + args.append((sum, cond)) + return Piecewise(*args) + + def _eval_interval(self, sym, a, b, _first=True): + """Evaluates the function along the sym in a given interval [a, b]""" + # FIXME: Currently complex intervals are not supported. A possible + # replacement algorithm, discussed in issue 5227, can be found in the + # following papers; + # http://portal.acm.org/citation.cfm?id=281649 + # http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.70.4127&rep=rep1&type=pdf + + if a is None or b is None: + # In this case, it is just simple substitution + return super()._eval_interval(sym, a, b) + else: + x, lo, hi = map(as_Basic, (sym, a, b)) + + if _first: # get only x-dependent relationals + def handler(ipw): + if isinstance(ipw, self.func): + return ipw._eval_interval(x, lo, hi, _first=None) + else: + return ipw._eval_interval(x, lo, hi) + irv = self._handle_irel(x, handler) + if irv is not None: + return irv + + if (lo < hi) is S.false or ( + lo is S.Infinity or hi is S.NegativeInfinity): + rv = self._eval_interval(x, hi, lo, _first=False) + if isinstance(rv, Piecewise): + rv = Piecewise(*[(-e, c) for e, c in rv.args]) + else: + rv = -rv + return rv + + if (lo < hi) is S.true or ( + hi is S.Infinity or lo is S.NegativeInfinity): + pass + else: + _a = Dummy('lo') + _b = Dummy('hi') + a = lo if lo.is_comparable else _a + b = hi if hi.is_comparable else _b + pos = self._eval_interval(x, a, b, _first=False) + if a == _a and b == _b: + # it's purely symbolic so just swap lo and hi and + # change the sign to get the value for when lo > hi + neg, pos = (-pos.xreplace({_a: hi, _b: lo}), + pos.xreplace({_a: lo, _b: hi})) + else: + # at least one of the bounds was comparable, so allow + # _eval_interval to use that information when computing + # the interval with lo and hi reversed + neg, pos = (-self._eval_interval(x, hi, lo, _first=False), + pos.xreplace({_a: lo, _b: hi})) + + # allow simplification based on ordering of lo and hi + p = Dummy('', positive=True) + if lo.is_Symbol: + pos = pos.xreplace({lo: hi - p}).xreplace({p: hi - lo}) + neg = neg.xreplace({lo: hi + p}).xreplace({p: lo - hi}) + elif hi.is_Symbol: + pos = pos.xreplace({hi: lo + p}).xreplace({p: hi - lo}) + neg = neg.xreplace({hi: lo - p}).xreplace({p: lo - hi}) + # evaluate limits that may have unevaluate Min/Max + touch = lambda _: _.replace( + lambda x: isinstance(x, (Min, Max)), + lambda x: x.func(*x.args)) + neg = touch(neg) + pos = touch(pos) + # assemble return expression; make the first condition be Lt + # b/c then the first expression will look the same whether + # the lo or hi limit is symbolic + if a == _a: # the lower limit was symbolic + rv = Piecewise( + (pos, + lo < hi), + (neg, + True)) + else: + rv = Piecewise( + (neg, + hi < lo), + (pos, + True)) + + if rv == Undefined: + raise ValueError("Can't integrate across undefined region.") + if any(isinstance(i, Piecewise) for i in (pos, neg)): + rv = piecewise_fold(rv) + return rv + + # handle a Piecewise with lo <= hi and no x-independent relationals + # ----------------------------------------------------------------- + ok, abei = self._intervals(x) + if not ok: + from sympy.integrals.integrals import Integral + # not being able to do the interval of f(x) can + # be stated as not being able to do the integral + # of f'(x) over the same range + return Integral(self.diff(x), (x, lo, hi)) # unevaluated + + pieces = [(a, b) for a, b, _, _ in abei] + done = [(lo, hi, -1)] + oo = S.Infinity + for k, p in enumerate(pieces): + if p[:2] == (-oo, oo): + # all undone intervals will get this key + for j, (a, b, i) in enumerate(done): + if i == -1: + done[j] = a, b, k + break # nothing else to consider + N = len(done) - 1 + for j, (a, b, i) in enumerate(reversed(done)): + if i == -1: + j = N - j + done[j: j + 1] = _clip(p, (a, b), k) + done = [(a, b, i) for a, b, i in done if a != b] + + # return the sum of the intervals + sum = S.Zero + upto = None + for a, b, i in done: + if i == -1: + if upto is None: + return Undefined + # TODO simplify hi <= upto + return Piecewise((sum, hi <= upto), (Undefined, True)) + sum += abei[i][-2]._eval_interval(x, a, b) + upto = b + return sum + + def _intervals(self, sym, err_on_Eq=False): + r"""Return a bool and a message (when bool is False), else a + list of unique tuples, (a, b, e, i), where a and b + are the lower and upper bounds in which the expression e of + argument i in self is defined and $a < b$ (when involving + numbers) or $a \le b$ when involving symbols. + + If there are any relationals not involving sym, or any + relational cannot be solved for sym, the bool will be False + a message be given as the second return value. The calling + routine should have removed such relationals before calling + this routine. + + The evaluated conditions will be returned as ranges. + Discontinuous ranges will be returned separately with + identical expressions. The first condition that evaluates to + True will be returned as the last tuple with a, b = -oo, oo. + """ + from sympy.solvers.inequalities import _solve_inequality + + assert isinstance(self, Piecewise) + + def nonsymfail(cond): + return False, filldedent(''' + A condition not involving + %s appeared: %s''' % (sym, cond)) + + def _solve_relational(r): + if sym not in r.free_symbols: + return nonsymfail(r) + try: + rv = _solve_inequality(r, sym) + except NotImplementedError: + return False, 'Unable to solve relational %s for %s.' % (r, sym) + if isinstance(rv, Relational): + free = rv.args[1].free_symbols + if rv.args[0] != sym or sym in free: + return False, 'Unable to solve relational %s for %s.' % (r, sym) + if rv.rel_op == '==': + # this equality has been affirmed to have the form + # Eq(sym, rhs) where rhs is sym-free; it represents + # a zero-width interval which will be ignored + # whether it is an isolated condition or contained + # within an And or an Or + rv = S.false + elif rv.rel_op == '!=': + try: + rv = Or(sym < rv.rhs, sym > rv.rhs) + except TypeError: + # e.g. x != I ==> all real x satisfy + rv = S.true + elif rv == (S.NegativeInfinity < sym) & (sym < S.Infinity): + rv = S.true + return True, rv + + args = list(self.args) + # make self canonical wrt Relationals + keys = self.atoms(Relational) + reps = {} + for r in keys: + ok, s = _solve_relational(r) + if ok != True: + return False, ok + reps[r] = s + # process args individually so if any evaluate, their position + # in the original Piecewise will be known + args = [i.xreplace(reps) for i in self.args] + + # precondition args + expr_cond = [] + default = idefault = None + for i, (expr, cond) in enumerate(args): + if cond is S.false: + continue + if cond is S.true: + default = expr + idefault = i + break + if isinstance(cond, Eq): + # unanticipated condition, but it is here in case a + # replacement caused an Eq to appear + if err_on_Eq: + return False, 'encountered Eq condition: %s' % cond + continue # zero width interval + + cond = to_cnf(cond) + if isinstance(cond, And): + cond = distribute_or_over_and(cond) + + if isinstance(cond, Or): + expr_cond.extend( + [(i, expr, o) for o in cond.args + if not isinstance(o, Eq)]) + elif cond is not S.false: + expr_cond.append((i, expr, cond)) + elif cond is S.true: + default = expr + idefault = i + break + + # determine intervals represented by conditions + int_expr = [] + for iarg, expr, cond in expr_cond: + if isinstance(cond, And): + lower = S.NegativeInfinity + upper = S.Infinity + exclude = [] + for cond2 in cond.args: + if not isinstance(cond2, Relational): + return False, 'expecting only Relationals' + if isinstance(cond2, Eq): + lower = upper # ignore + if err_on_Eq: + return False, 'encountered secondary Eq condition' + break + elif isinstance(cond2, Ne): + l, r = cond2.args + if l == sym: + exclude.append(r) + elif r == sym: + exclude.append(l) + else: + return nonsymfail(cond2) + continue + elif cond2.lts == sym: + upper = Min(cond2.gts, upper) + elif cond2.gts == sym: + lower = Max(cond2.lts, lower) + else: + return nonsymfail(cond2) # should never get here + if exclude: + exclude = list(ordered(exclude)) + newcond = [] + for i, e in enumerate(exclude): + if e < lower == True or e > upper == True: + continue + if not newcond: + newcond.append((None, lower)) # add a primer + newcond.append((newcond[-1][1], e)) + newcond.append((newcond[-1][1], upper)) + newcond.pop(0) # remove the primer + expr_cond.extend([(iarg, expr, And(i[0] < sym, sym < i[1])) for i in newcond]) + continue + elif isinstance(cond, Relational) and cond.rel_op != '!=': + lower, upper = cond.lts, cond.gts # part 1: initialize with givens + if cond.lts == sym: # part 1a: expand the side ... + lower = S.NegativeInfinity # e.g. x <= 0 ---> -oo <= 0 + elif cond.gts == sym: # part 1a: ... that can be expanded + upper = S.Infinity # e.g. x >= 0 ---> oo >= 0 + else: + return nonsymfail(cond) + else: + return False, 'unrecognized condition: %s' % cond + + upper = Max(lower, upper) + if err_on_Eq and lower == upper: + return False, 'encountered Eq condition' + if (lower >= upper) is not S.true: + int_expr.append((lower, upper, expr, iarg)) + + if default is not None: + int_expr.append( + (S.NegativeInfinity, S.Infinity, default, idefault)) + + return True, list(uniq(int_expr)) + + def _eval_nseries(self, x, n, logx, cdir=0): + args = [(ec.expr._eval_nseries(x, n, logx), ec.cond) for ec in self.args] + return self.func(*args) + + def _eval_power(self, s): + return self.func(*[(e**s, c) for e, c in self.args]) + + def _eval_subs(self, old, new): + # this is strictly not necessary, but we can keep track + # of whether True or False conditions arise and be + # somewhat more efficient by avoiding other substitutions + # and avoiding invalid conditions that appear after a + # True condition + args = list(self.args) + args_exist = False + for i, (e, c) in enumerate(args): + c = c._subs(old, new) + if c != False: + args_exist = True + e = e._subs(old, new) + args[i] = (e, c) + if c == True: + break + if not args_exist: + args = ((Undefined, True),) + return self.func(*args) + + def _eval_transpose(self): + return self.func(*[(e.transpose(), c) for e, c in self.args]) + + def _eval_template_is_attr(self, is_attr): + b = None + for expr, _ in self.args: + a = getattr(expr, is_attr) + if a is None: + return + if b is None: + b = a + elif b is not a: + return + return b + + _eval_is_finite = lambda self: self._eval_template_is_attr( + 'is_finite') + _eval_is_complex = lambda self: self._eval_template_is_attr('is_complex') + _eval_is_even = lambda self: self._eval_template_is_attr('is_even') + _eval_is_imaginary = lambda self: self._eval_template_is_attr( + 'is_imaginary') + _eval_is_integer = lambda self: self._eval_template_is_attr('is_integer') + _eval_is_irrational = lambda self: self._eval_template_is_attr( + 'is_irrational') + _eval_is_negative = lambda self: self._eval_template_is_attr('is_negative') + _eval_is_nonnegative = lambda self: self._eval_template_is_attr( + 'is_nonnegative') + _eval_is_nonpositive = lambda self: self._eval_template_is_attr( + 'is_nonpositive') + _eval_is_nonzero = lambda self: self._eval_template_is_attr( + 'is_nonzero') + _eval_is_odd = lambda self: self._eval_template_is_attr('is_odd') + _eval_is_polar = lambda self: self._eval_template_is_attr('is_polar') + _eval_is_positive = lambda self: self._eval_template_is_attr('is_positive') + _eval_is_extended_real = lambda self: self._eval_template_is_attr( + 'is_extended_real') + _eval_is_extended_positive = lambda self: self._eval_template_is_attr( + 'is_extended_positive') + _eval_is_extended_negative = lambda self: self._eval_template_is_attr( + 'is_extended_negative') + _eval_is_extended_nonzero = lambda self: self._eval_template_is_attr( + 'is_extended_nonzero') + _eval_is_extended_nonpositive = lambda self: self._eval_template_is_attr( + 'is_extended_nonpositive') + _eval_is_extended_nonnegative = lambda self: self._eval_template_is_attr( + 'is_extended_nonnegative') + _eval_is_real = lambda self: self._eval_template_is_attr('is_real') + _eval_is_zero = lambda self: self._eval_template_is_attr( + 'is_zero') + + @classmethod + def __eval_cond(cls, cond): + """Return the truth value of the condition.""" + if cond == True: + return True + if isinstance(cond, Eq): + try: + diff = cond.lhs - cond.rhs + if diff.is_commutative: + return diff.is_zero + except TypeError: + pass + + def as_expr_set_pairs(self, domain=None): + """Return tuples for each argument of self that give + the expression and the interval in which it is valid + which is contained within the given domain. + If a condition cannot be converted to a set, an error + will be raised. The variable of the conditions is + assumed to be real; sets of real values are returned. + + Examples + ======== + + >>> from sympy import Piecewise, Interval + >>> from sympy.abc import x + >>> p = Piecewise( + ... (1, x < 2), + ... (2,(x > 0) & (x < 4)), + ... (3, True)) + >>> p.as_expr_set_pairs() + [(1, Interval.open(-oo, 2)), + (2, Interval.Ropen(2, 4)), + (3, Interval(4, oo))] + >>> p.as_expr_set_pairs(Interval(0, 3)) + [(1, Interval.Ropen(0, 2)), + (2, Interval(2, 3))] + """ + if domain is None: + domain = S.Reals + exp_sets = [] + U = domain + complex = not domain.is_subset(S.Reals) + cond_free = set() + for expr, cond in self.args: + cond_free |= cond.free_symbols + if len(cond_free) > 1: + raise NotImplementedError(filldedent(''' + multivariate conditions are not handled.''')) + if complex: + for i in cond.atoms(Relational): + if not isinstance(i, (Eq, Ne)): + raise ValueError(filldedent(''' + Inequalities in the complex domain are + not supported. Try the real domain by + setting domain=S.Reals''')) + cond_int = U.intersect(cond.as_set()) + U = U - cond_int + if cond_int != S.EmptySet: + exp_sets.append((expr, cond_int)) + return exp_sets + + def _eval_rewrite_as_ITE(self, *args, **kwargs): + byfree = {} + args = list(args) + default = any(c == True for b, c in args) + for i, (b, c) in enumerate(args): + if not isinstance(b, Boolean) and b != True: + raise TypeError(filldedent(''' + Expecting Boolean or bool but got `%s` + ''' % func_name(b))) + if c == True: + break + # loop over independent conditions for this b + for c in c.args if isinstance(c, Or) else [c]: + free = c.free_symbols + x = free.pop() + try: + byfree[x] = byfree.setdefault( + x, S.EmptySet).union(c.as_set()) + except NotImplementedError: + if not default: + raise NotImplementedError(filldedent(''' + A method to determine whether a multivariate + conditional is consistent with a complete coverage + of all variables has not been implemented so the + rewrite is being stopped after encountering `%s`. + This error would not occur if a default expression + like `(foo, True)` were given. + ''' % c)) + if byfree[x] in (S.UniversalSet, S.Reals): + # collapse the ith condition to True and break + args[i] = list(args[i]) + c = args[i][1] = True + break + if c == True: + break + if c != True: + raise ValueError(filldedent(''' + Conditions must cover all reals or a final default + condition `(foo, True)` must be given. + ''')) + last, _ = args[i] # ignore all past ith arg + for a, c in reversed(args[:i]): + last = ITE(c, a, last) + return _canonical(last) + + def _eval_rewrite_as_KroneckerDelta(self, *args, **kwargs): + from sympy.functions.special.tensor_functions import KroneckerDelta + + rules = { + And: [False, False], + Or: [True, True], + Not: [True, False], + Eq: [None, None], + Ne: [None, None] + } + + class UnrecognizedCondition(Exception): + pass + + def rewrite(cond): + if isinstance(cond, Eq): + return KroneckerDelta(*cond.args) + if isinstance(cond, Ne): + return 1 - KroneckerDelta(*cond.args) + + cls, args = type(cond), cond.args + if cls not in rules: + raise UnrecognizedCondition(cls) + + b1, b2 = rules[cls] + k = Mul(*[1 - rewrite(c) for c in args]) if b1 else Mul(*[rewrite(c) for c in args]) + + if b2: + return 1 - k + return k + + conditions = [] + true_value = None + for value, cond in args: + if type(cond) in rules: + conditions.append((value, cond)) + elif cond is S.true: + if true_value is None: + true_value = value + else: + return + + if true_value is not None: + result = true_value + + for value, cond in conditions[::-1]: + try: + k = rewrite(cond) + result = k * value + (1 - k) * result + except UnrecognizedCondition: + return + + return result + + +def piecewise_fold(expr, evaluate=True): + """ + Takes an expression containing a piecewise function and returns the + expression in piecewise form. In addition, any ITE conditions are + rewritten in negation normal form and simplified. + + The final Piecewise is evaluated (default) but if the raw form + is desired, send ``evaluate=False``; if trivial evaluation is + desired, send ``evaluate=None`` and duplicate conditions and + processing of True and False will be handled. + + Examples + ======== + + >>> from sympy import Piecewise, piecewise_fold, S + >>> from sympy.abc import x + >>> p = Piecewise((x, x < 1), (1, S(1) <= x)) + >>> piecewise_fold(x*p) + Piecewise((x**2, x < 1), (x, True)) + + See Also + ======== + + Piecewise + piecewise_exclusive + """ + if not isinstance(expr, Basic) or not expr.has(Piecewise): + return expr + + new_args = [] + if isinstance(expr, (ExprCondPair, Piecewise)): + for e, c in expr.args: + if not isinstance(e, Piecewise): + e = piecewise_fold(e) + # we don't keep Piecewise in condition because + # it has to be checked to see that it's complete + # and we convert it to ITE at that time + assert not c.has(Piecewise) # pragma: no cover + if isinstance(c, ITE): + c = c.to_nnf() + c = simplify_logic(c, form='cnf') + if isinstance(e, Piecewise): + new_args.extend([(piecewise_fold(ei), And(ci, c)) + for ei, ci in e.args]) + else: + new_args.append((e, c)) + else: + # Given + # P1 = Piecewise((e11, c1), (e12, c2), A) + # P2 = Piecewise((e21, c1), (e22, c2), B) + # ... + # the folding of f(P1, P2) is trivially + # Piecewise( + # (f(e11, e21), c1), + # (f(e12, e22), c2), + # (f(Piecewise(A), Piecewise(B)), True)) + # Certain objects end up rewriting themselves as thus, so + # we do that grouping before the more generic folding. + # The following applies this idea when f = Add or f = Mul + # (and the expression is commutative). + if expr.is_Add or expr.is_Mul and expr.is_commutative: + p, args = sift(expr.args, lambda x: x.is_Piecewise, binary=True) + pc = sift(p, lambda x: tuple([c for e,c in x.args])) + for c in list(ordered(pc)): + if len(pc[c]) > 1: + pargs = [list(i.args) for i in pc[c]] + # the first one is the same; there may be more + com = common_prefix(*[ + [i.cond for i in j] for j in pargs]) + n = len(com) + collected = [] + for i in range(n): + collected.append(( + expr.func(*[ai[i].expr for ai in pargs]), + com[i])) + remains = [] + for a in pargs: + if n == len(a): # no more args + continue + if a[n].cond == True: # no longer Piecewise + remains.append(a[n].expr) + else: # restore the remaining Piecewise + remains.append( + Piecewise(*a[n:], evaluate=False)) + if remains: + collected.append((expr.func(*remains), True)) + args.append(Piecewise(*collected, evaluate=False)) + continue + args.extend(pc[c]) + else: + args = expr.args + # fold + folded = list(map(piecewise_fold, args)) + for ec in product(*[ + (i.args if isinstance(i, Piecewise) else + [(i, true)]) for i in folded]): + e, c = zip(*ec) + new_args.append((expr.func(*e), And(*c))) + + if evaluate is None: + # don't return duplicate conditions, otherwise don't evaluate + new_args = list(reversed([(e, c) for c, e in { + c: e for e, c in reversed(new_args)}.items()])) + rv = Piecewise(*new_args, evaluate=evaluate) + if evaluate is None and len(rv.args) == 1 and rv.args[0].cond == True: + return rv.args[0].expr + if any(s.expr.has(Piecewise) for p in rv.atoms(Piecewise) for s in p.args): + return piecewise_fold(rv) + return rv + + +def _clip(A, B, k): + """Return interval B as intervals that are covered by A (keyed + to k) and all other intervals of B not covered by A keyed to -1. + + The reference point of each interval is the rhs; if the lhs is + greater than the rhs then an interval of zero width interval will + result, e.g. (4, 1) is treated like (1, 1). + + Examples + ======== + + >>> from sympy.functions.elementary.piecewise import _clip + >>> from sympy import Tuple + >>> A = Tuple(1, 3) + >>> B = Tuple(2, 4) + >>> _clip(A, B, 0) + [(2, 3, 0), (3, 4, -1)] + + Interpretation: interval portion (2, 3) of interval (2, 4) is + covered by interval (1, 3) and is keyed to 0 as requested; + interval (3, 4) was not covered by (1, 3) and is keyed to -1. + """ + a, b = B + c, d = A + c, d = Min(Max(c, a), b), Min(Max(d, a), b) + a = Min(a, b) + p = [] + if a != c: + p.append((a, c, -1)) + else: + pass + if c != d: + p.append((c, d, k)) + else: + pass + if b != d: + if d == c and p and p[-1][-1] == -1: + p[-1] = p[-1][0], b, -1 + else: + p.append((d, b, -1)) + else: + pass + + return p + + +def piecewise_simplify_arguments(expr, **kwargs): + from sympy.simplify.simplify import simplify + + # simplify conditions + f1 = expr.args[0].cond.free_symbols + args = None + if len(f1) == 1 and not expr.atoms(Eq): + x = f1.pop() + # this won't return intervals involving Eq + # and it won't handle symbols treated as + # booleans + ok, abe_ = expr._intervals(x, err_on_Eq=True) + def include(c, x, a): + "return True if c.subs(x, a) is True, else False" + try: + return c.subs(x, a) == True + except TypeError: + return False + if ok: + args = [] + covered = S.EmptySet + from sympy.sets.sets import Interval + for a, b, e, i in abe_: + c = expr.args[i].cond + incl_a = include(c, x, a) + incl_b = include(c, x, b) + iv = Interval(a, b, not incl_a, not incl_b) + cset = iv - covered + if not cset: + continue + try: + a = cset.inf + except NotImplementedError: + pass # continue with the given `a` + else: + incl_a = include(c, x, a) + if incl_a and incl_b: + if a.is_infinite and b.is_infinite: + c = S.true + elif b.is_infinite: + c = (x > a) if a in covered else (x >= a) + elif a.is_infinite: + c = (x <= b) + elif a in covered: + c = And(a < x, x <= b) + else: + c = And(a <= x, x <= b) + elif incl_a: + if a.is_infinite: + c = (x < b) + elif a in covered: + c = And(a < x, x < b) + else: + c = And(a <= x, x < b) + elif incl_b: + if b.is_infinite: + c = (x > a) + else: + c = And(a < x, x <= b) + else: + if a in covered: + c = (x < b) + else: + c = And(a < x, x < b) + covered |= iv + if a is S.NegativeInfinity and incl_a: + covered |= {S.NegativeInfinity} + if b is S.Infinity and incl_b: + covered |= {S.Infinity} + args.append((e, c)) + if not S.Reals.is_subset(covered): + args.append((Undefined, True)) + if args is None: + args = list(expr.args) + for i in range(len(args)): + e, c = args[i] + if isinstance(c, Basic): + c = simplify(c, **kwargs) + args[i] = (e, c) + + # simplify expressions + doit = kwargs.pop('doit', None) + for i in range(len(args)): + e, c = args[i] + if isinstance(e, Basic): + # Skip doit to avoid growth at every call for some integrals + # and sums, see sympy/sympy#17165 + newe = simplify(e, doit=False, **kwargs) + if newe != e: + e = newe + args[i] = (e, c) + + # restore kwargs flag + if doit is not None: + kwargs['doit'] = doit + + return Piecewise(*args) + + +def _piecewise_collapse_arguments(_args): + newargs = [] # the unevaluated conditions + current_cond = set() # the conditions up to a given e, c pair + for expr, cond in _args: + cond = cond.replace( + lambda _: _.is_Relational, _canonical_coeff) + # Check here if expr is a Piecewise and collapse if one of + # the conds in expr matches cond. This allows the collapsing + # of Piecewise((Piecewise((x,x<0)),x<0)) to Piecewise((x,x<0)). + # This is important when using piecewise_fold to simplify + # multiple Piecewise instances having the same conds. + # Eventually, this code should be able to collapse Piecewise's + # having different intervals, but this will probably require + # using the new assumptions. + if isinstance(expr, Piecewise): + unmatching = [] + for i, (e, c) in enumerate(expr.args): + if c in current_cond: + # this would already have triggered + continue + if c == cond: + if c != True: + # nothing past this condition will ever + # trigger and only those args before this + # that didn't match a previous condition + # could possibly trigger + if unmatching: + expr = Piecewise(*( + unmatching + [(e, c)])) + else: + expr = e + break + else: + unmatching.append((e, c)) + + # check for condition repeats + got = False + # -- if an And contains a condition that was + # already encountered, then the And will be + # False: if the previous condition was False + # then the And will be False and if the previous + # condition is True then then we wouldn't get to + # this point. In either case, we can skip this condition. + for i in ([cond] + + (list(cond.args) if isinstance(cond, And) else + [])): + if i in current_cond: + got = True + break + if got: + continue + + # -- if not(c) is already in current_cond then c is + # a redundant condition in an And. This does not + # apply to Or, however: (e1, c), (e2, Or(~c, d)) + # is not (e1, c), (e2, d) because if c and d are + # both False this would give no results when the + # true answer should be (e2, True) + if isinstance(cond, And): + nonredundant = [] + for c in cond.args: + if isinstance(c, Relational): + if c.negated.canonical in current_cond: + continue + # if a strict inequality appears after + # a non-strict one, then the condition is + # redundant + if isinstance(c, (Lt, Gt)) and ( + c.weak in current_cond): + cond = False + break + nonredundant.append(c) + else: + cond = cond.func(*nonredundant) + elif isinstance(cond, Relational): + if cond.negated.canonical in current_cond: + cond = S.true + + current_cond.add(cond) + + # collect successive e,c pairs when exprs or cond match + if newargs: + if newargs[-1].expr == expr: + orcond = Or(cond, newargs[-1].cond) + if isinstance(orcond, (And, Or)): + orcond = distribute_and_over_or(orcond) + newargs[-1] = ExprCondPair(expr, orcond) + continue + elif newargs[-1].cond == cond: + continue + newargs.append(ExprCondPair(expr, cond)) + return newargs + + +_blessed = lambda e: getattr(e.lhs, '_diff_wrt', False) and ( + getattr(e.rhs, '_diff_wrt', None) or + isinstance(e.rhs, (Rational, NumberSymbol))) + + +def piecewise_simplify(expr, **kwargs): + expr = piecewise_simplify_arguments(expr, **kwargs) + if not isinstance(expr, Piecewise): + return expr + args = list(expr.args) + + args = _piecewise_simplify_eq_and(args) + args = _piecewise_simplify_equal_to_next_segment(args) + return Piecewise(*args) + + +def _piecewise_simplify_equal_to_next_segment(args): + """ + See if expressions valid for an Equal expression happens to evaluate + to the same function as in the next piecewise segment, see: + https://github.com/sympy/sympy/issues/8458 + """ + prevexpr = None + for i, (expr, cond) in reversed(list(enumerate(args))): + if prevexpr is not None: + if isinstance(cond, And): + eqs, other = sift(cond.args, + lambda i: isinstance(i, Eq), binary=True) + elif isinstance(cond, Eq): + eqs, other = [cond], [] + else: + eqs = other = [] + _prevexpr = prevexpr + _expr = expr + if eqs and not other: + eqs = list(ordered(eqs)) + for e in eqs: + # allow 2 args to collapse into 1 for any e + # otherwise limit simplification to only simple-arg + # Eq instances + if len(args) == 2 or _blessed(e): + _prevexpr = _prevexpr.subs(*e.args) + _expr = _expr.subs(*e.args) + # Did it evaluate to the same? + if _prevexpr == _expr: + # Set the expression for the Not equal section to the same + # as the next. These will be merged when creating the new + # Piecewise + args[i] = args[i].func(args[i + 1][0], cond) + else: + # Update the expression that we compare against + prevexpr = expr + else: + prevexpr = expr + return args + + +def _piecewise_simplify_eq_and(args): + """ + Try to simplify conditions and the expression for + equalities that are part of the condition, e.g. + Piecewise((n, And(Eq(n,0), Eq(n + m, 0))), (1, True)) + -> Piecewise((0, And(Eq(n, 0), Eq(m, 0))), (1, True)) + """ + for i, (expr, cond) in enumerate(args): + if isinstance(cond, And): + eqs, other = sift(cond.args, + lambda i: isinstance(i, Eq), binary=True) + elif isinstance(cond, Eq): + eqs, other = [cond], [] + else: + eqs = other = [] + if eqs: + eqs = list(ordered(eqs)) + for j, e in enumerate(eqs): + # these blessed lhs objects behave like Symbols + # and the rhs are simple replacements for the "symbols" + if _blessed(e): + expr = expr.subs(*e.args) + eqs[j + 1:] = [ei.subs(*e.args) for ei in eqs[j + 1:]] + other = [ei.subs(*e.args) for ei in other] + cond = And(*(eqs + other)) + args[i] = args[i].func(expr, cond) + return args + + +def piecewise_exclusive(expr, *, skip_nan=False, deep=True): + """ + Rewrite :class:`Piecewise` with mutually exclusive conditions. + + Explanation + =========== + + SymPy represents the conditions of a :class:`Piecewise` in an + "if-elif"-fashion, allowing more than one condition to be simultaneously + True. The interpretation is that the first condition that is True is the + case that holds. While this is a useful representation computationally it + is not how a piecewise formula is typically shown in a mathematical text. + The :func:`piecewise_exclusive` function can be used to rewrite any + :class:`Piecewise` with more typical mutually exclusive conditions. + + Note that further manipulation of the resulting :class:`Piecewise`, e.g. + simplifying it, will most likely make it non-exclusive. Hence, this is + primarily a function to be used in conjunction with printing the Piecewise + or if one would like to reorder the expression-condition pairs. + + If it is not possible to determine that all possibilities are covered by + the different cases of the :class:`Piecewise` then a final + :class:`~sympy.core.numbers.NaN` case will be included explicitly. This + can be prevented by passing ``skip_nan=True``. + + Examples + ======== + + >>> from sympy import piecewise_exclusive, Symbol, Piecewise, S + >>> x = Symbol('x', real=True) + >>> p = Piecewise((0, x < 0), (S.Half, x <= 0), (1, True)) + >>> piecewise_exclusive(p) + Piecewise((0, x < 0), (1/2, Eq(x, 0)), (1, x > 0)) + >>> piecewise_exclusive(Piecewise((2, x > 1))) + Piecewise((2, x > 1), (nan, x <= 1)) + >>> piecewise_exclusive(Piecewise((2, x > 1)), skip_nan=True) + Piecewise((2, x > 1)) + + Parameters + ========== + + expr: a SymPy expression. + Any :class:`Piecewise` in the expression will be rewritten. + skip_nan: ``bool`` (default ``False``) + If ``skip_nan`` is set to ``True`` then a final + :class:`~sympy.core.numbers.NaN` case will not be included. + deep: ``bool`` (default ``True``) + If ``deep`` is ``True`` then :func:`piecewise_exclusive` will rewrite + any :class:`Piecewise` subexpressions in ``expr`` rather than just + rewriting ``expr`` itself. + + Returns + ======= + + An expression equivalent to ``expr`` but where all :class:`Piecewise` have + been rewritten with mutually exclusive conditions. + + See Also + ======== + + Piecewise + piecewise_fold + """ + + def make_exclusive(*pwargs): + + cumcond = false + newargs = [] + + # Handle the first n-1 cases + for expr_i, cond_i in pwargs[:-1]: + cancond = And(cond_i, Not(cumcond)).simplify() + cumcond = Or(cond_i, cumcond).simplify() + newargs.append((expr_i, cancond)) + + # For the nth case defer simplification of cumcond + expr_n, cond_n = pwargs[-1] + cancond_n = And(cond_n, Not(cumcond)).simplify() + newargs.append((expr_n, cancond_n)) + + if not skip_nan: + cumcond = Or(cond_n, cumcond).simplify() + if cumcond is not true: + newargs.append((Undefined, Not(cumcond).simplify())) + + return Piecewise(*newargs, evaluate=False) + + if deep: + return expr.replace(Piecewise, make_exclusive) + elif isinstance(expr, Piecewise): + return make_exclusive(*expr.args) + else: + return expr diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..51fe3a0a131ec4c85d2653e7da1b3744099a0284 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/__pycache__/test_complexes.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/__pycache__/test_complexes.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1fd902c25452ca75a46107329aac858932a0e509 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/__pycache__/test_complexes.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/__pycache__/test_exponential.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/__pycache__/test_exponential.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..59b4a077a57078e3871a29059382339e1327a1a9 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/__pycache__/test_exponential.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/__pycache__/test_integers.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/__pycache__/test_integers.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2f251ae1d8413b55b1063af0fb632d83011a35ec Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/__pycache__/test_integers.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/__pycache__/test_interface.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/__pycache__/test_interface.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9f5816aded4d611825ec66b484ca9e77b5d7dae5 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/__pycache__/test_interface.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/__pycache__/test_miscellaneous.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/__pycache__/test_miscellaneous.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..61347a27e7a5f412b7ec9de7dd04036b1ce4daa0 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/__pycache__/test_miscellaneous.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/test_complexes.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/test_complexes.py new file mode 100644 index 0000000000000000000000000000000000000000..699c0fef966c99147b713aaa80710b7b8cf21c73 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/test_complexes.py @@ -0,0 +1,1030 @@ +from sympy.core.function import (Derivative, Function, Lambda, expand, PoleError) +from sympy.core.numbers import (E, I, Rational, comp, nan, oo, pi, zoo) +from sympy.core.relational import Eq +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.elementary.complexes import (Abs, adjoint, arg, conjugate, im, re, sign, transpose) +from sympy.functions.elementary.exponential import (exp, exp_polar, log) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.piecewise import Piecewise +from sympy.functions.elementary.trigonometric import (acos, atan, atan2, cos, sin) +from sympy.functions.elementary.hyperbolic import sinh +from sympy.functions.special.delta_functions import (DiracDelta, Heaviside) +from sympy.integrals.integrals import Integral +from sympy.matrices.dense import Matrix +from sympy.matrices.expressions.funcmatrix import FunctionMatrix +from sympy.matrices.expressions.matexpr import MatrixSymbol +from sympy.matrices.immutable import (ImmutableMatrix, ImmutableSparseMatrix) +from sympy.matrices import SparseMatrix +from sympy.sets.sets import Interval +from sympy.core.expr import unchanged +from sympy.core.function import ArgumentIndexError +from sympy.series.order import Order +from sympy.testing.pytest import XFAIL, raises, _both_exp_pow + + +def N_equals(a, b): + """Check whether two complex numbers are numerically close""" + return comp(a.n(), b.n(), 1.e-6) + + +def test_re(): + x, y = symbols('x,y') + a, b = symbols('a,b', real=True) + + r = Symbol('r', real=True) + i = Symbol('i', imaginary=True) + + assert re(nan) is nan + + assert re(oo) is oo + assert re(-oo) is -oo + + assert re(0) == 0 + + assert re(1) == 1 + assert re(-1) == -1 + + assert re(E) == E + assert re(-E) == -E + + assert unchanged(re, x) + assert re(x*I) == -im(x) + assert re(r*I) == 0 + assert re(r) == r + assert re(i*I) == I * i + assert re(i) == 0 + + assert re(x + y) == re(x) + re(y) + assert re(x + r) == re(x) + r + + assert re(re(x)) == re(x) + + assert re(2 + I) == 2 + assert re(x + I) == re(x) + + assert re(x + y*I) == re(x) - im(y) + assert re(x + r*I) == re(x) + + assert re(log(2*I)) == log(2) + + assert re((2 + I)**2).expand(complex=True) == 3 + + assert re(conjugate(x)) == re(x) + assert conjugate(re(x)) == re(x) + + assert re(x).as_real_imag() == (re(x), 0) + + assert re(i*r*x).diff(r) == re(i*x) + assert re(i*r*x).diff(i) == I*r*im(x) + + assert re( + sqrt(a + b*I)) == (a**2 + b**2)**Rational(1, 4)*cos(atan2(b, a)/2) + assert re(a * (2 + b*I)) == 2*a + + assert re((1 + sqrt(a + b*I))/2) == \ + (a**2 + b**2)**Rational(1, 4)*cos(atan2(b, a)/2)/2 + S.Half + + assert re(x).rewrite(im) == x - S.ImaginaryUnit*im(x) + assert (x + re(y)).rewrite(re, im) == x + y - S.ImaginaryUnit*im(y) + + a = Symbol('a', algebraic=True) + t = Symbol('t', transcendental=True) + x = Symbol('x') + assert re(a).is_algebraic + assert re(x).is_algebraic is None + assert re(t).is_algebraic is False + + assert re(S.ComplexInfinity) is S.NaN + + n, m, l = symbols('n m l') + A = MatrixSymbol('A',n,m) + assert re(A) == (S.Half) * (A + conjugate(A)) + + A = Matrix([[1 + 4*I,2],[0, -3*I]]) + assert re(A) == Matrix([[1, 2],[0, 0]]) + + A = ImmutableMatrix([[1 + 3*I, 3-2*I],[0, 2*I]]) + assert re(A) == ImmutableMatrix([[1, 3],[0, 0]]) + + X = SparseMatrix([[2*j + i*I for i in range(5)] for j in range(5)]) + assert re(X) - Matrix([[0, 0, 0, 0, 0], + [2, 2, 2, 2, 2], + [4, 4, 4, 4, 4], + [6, 6, 6, 6, 6], + [8, 8, 8, 8, 8]]) == Matrix.zeros(5) + + assert im(X) - Matrix([[0, 1, 2, 3, 4], + [0, 1, 2, 3, 4], + [0, 1, 2, 3, 4], + [0, 1, 2, 3, 4], + [0, 1, 2, 3, 4]]) == Matrix.zeros(5) + + X = FunctionMatrix(3, 3, Lambda((n, m), n + m*I)) + assert re(X) == Matrix([[0, 0, 0], [1, 1, 1], [2, 2, 2]]) + + +def test_im(): + x, y = symbols('x,y') + a, b = symbols('a,b', real=True) + + r = Symbol('r', real=True) + i = Symbol('i', imaginary=True) + + assert im(nan) is nan + + assert im(oo*I) is oo + assert im(-oo*I) is -oo + + assert im(0) == 0 + + assert im(1) == 0 + assert im(-1) == 0 + + assert im(E*I) == E + assert im(-E*I) == -E + + assert unchanged(im, x) + assert im(x*I) == re(x) + assert im(r*I) == r + assert im(r) == 0 + assert im(i*I) == 0 + assert im(i) == -I * i + + assert im(x + y) == im(x) + im(y) + assert im(x + r) == im(x) + assert im(x + r*I) == im(x) + r + + assert im(im(x)*I) == im(x) + + assert im(2 + I) == 1 + assert im(x + I) == im(x) + 1 + + assert im(x + y*I) == im(x) + re(y) + assert im(x + r*I) == im(x) + r + + assert im(log(2*I)) == pi/2 + + assert im((2 + I)**2).expand(complex=True) == 4 + + assert im(conjugate(x)) == -im(x) + assert conjugate(im(x)) == im(x) + + assert im(x).as_real_imag() == (im(x), 0) + + assert im(i*r*x).diff(r) == im(i*x) + assert im(i*r*x).diff(i) == -I * re(r*x) + + assert im( + sqrt(a + b*I)) == (a**2 + b**2)**Rational(1, 4)*sin(atan2(b, a)/2) + assert im(a * (2 + b*I)) == a*b + + assert im((1 + sqrt(a + b*I))/2) == \ + (a**2 + b**2)**Rational(1, 4)*sin(atan2(b, a)/2)/2 + + assert im(x).rewrite(re) == -S.ImaginaryUnit * (x - re(x)) + assert (x + im(y)).rewrite(im, re) == x - S.ImaginaryUnit * (y - re(y)) + + a = Symbol('a', algebraic=True) + t = Symbol('t', transcendental=True) + x = Symbol('x') + assert re(a).is_algebraic + assert re(x).is_algebraic is None + assert re(t).is_algebraic is False + + assert im(S.ComplexInfinity) is S.NaN + + n, m, l = symbols('n m l') + A = MatrixSymbol('A',n,m) + + assert im(A) == (S.One/(2*I)) * (A - conjugate(A)) + + A = Matrix([[1 + 4*I, 2],[0, -3*I]]) + assert im(A) == Matrix([[4, 0],[0, -3]]) + + A = ImmutableMatrix([[1 + 3*I, 3-2*I],[0, 2*I]]) + assert im(A) == ImmutableMatrix([[3, -2],[0, 2]]) + + X = ImmutableSparseMatrix( + [[i*I + i for i in range(5)] for i in range(5)]) + Y = SparseMatrix([list(range(5)) for i in range(5)]) + assert im(X).as_immutable() == Y + + X = FunctionMatrix(3, 3, Lambda((n, m), n + m*I)) + assert im(X) == Matrix([[0, 1, 2], [0, 1, 2], [0, 1, 2]]) + +def test_sign(): + assert sign(1.2) == 1 + assert sign(-1.2) == -1 + assert sign(3*I) == I + assert sign(-3*I) == -I + assert sign(0) == 0 + assert sign(0, evaluate=False).doit() == 0 + assert sign(oo, evaluate=False).doit() == 1 + assert sign(nan) is nan + assert sign(2 + 2*I).doit() == sqrt(2)*(2 + 2*I)/4 + assert sign(2 + 3*I).simplify() == sign(2 + 3*I) + assert sign(2 + 2*I).simplify() == sign(1 + I) + assert sign(im(sqrt(1 - sqrt(3)))) == 1 + assert sign(sqrt(1 - sqrt(3))) == I + + x = Symbol('x') + assert sign(x).is_finite is True + assert sign(x).is_complex is True + assert sign(x).is_imaginary is None + assert sign(x).is_integer is None + assert sign(x).is_real is None + assert sign(x).is_zero is None + assert sign(x).doit() == sign(x) + assert sign(1.2*x) == sign(x) + assert sign(2*x) == sign(x) + assert sign(I*x) == I*sign(x) + assert sign(-2*I*x) == -I*sign(x) + assert sign(conjugate(x)) == conjugate(sign(x)) + + p = Symbol('p', positive=True) + n = Symbol('n', negative=True) + m = Symbol('m', negative=True) + assert sign(2*p*x) == sign(x) + assert sign(n*x) == -sign(x) + assert sign(n*m*x) == sign(x) + + x = Symbol('x', imaginary=True) + assert sign(x).is_imaginary is True + assert sign(x).is_integer is False + assert sign(x).is_real is False + assert sign(x).is_zero is False + assert sign(x).diff(x) == 2*DiracDelta(-I*x) + assert sign(x).doit() == x / Abs(x) + assert conjugate(sign(x)) == -sign(x) + + x = Symbol('x', real=True) + assert sign(x).is_imaginary is False + assert sign(x).is_integer is True + assert sign(x).is_real is True + assert sign(x).is_zero is None + assert sign(x).diff(x) == 2*DiracDelta(x) + assert sign(x).doit() == sign(x) + assert conjugate(sign(x)) == sign(x) + + x = Symbol('x', nonzero=True) + assert sign(x).is_imaginary is False + assert sign(x).is_integer is True + assert sign(x).is_real is True + assert sign(x).is_zero is False + assert sign(x).doit() == x / Abs(x) + assert sign(Abs(x)) == 1 + assert Abs(sign(x)) == 1 + + x = Symbol('x', positive=True) + assert sign(x).is_imaginary is False + assert sign(x).is_integer is True + assert sign(x).is_real is True + assert sign(x).is_zero is False + assert sign(x).doit() == x / Abs(x) + assert sign(Abs(x)) == 1 + assert Abs(sign(x)) == 1 + + x = 0 + assert sign(x).is_imaginary is False + assert sign(x).is_integer is True + assert sign(x).is_real is True + assert sign(x).is_zero is True + assert sign(x).doit() == 0 + assert sign(Abs(x)) == 0 + assert Abs(sign(x)) == 0 + + nz = Symbol('nz', nonzero=True, integer=True) + assert sign(nz).is_imaginary is False + assert sign(nz).is_integer is True + assert sign(nz).is_real is True + assert sign(nz).is_zero is False + assert sign(nz)**2 == 1 + assert (sign(nz)**3).args == (sign(nz), 3) + + assert sign(Symbol('x', nonnegative=True)).is_nonnegative + assert sign(Symbol('x', nonnegative=True)).is_nonpositive is None + assert sign(Symbol('x', nonpositive=True)).is_nonnegative is None + assert sign(Symbol('x', nonpositive=True)).is_nonpositive + assert sign(Symbol('x', real=True)).is_nonnegative is None + assert sign(Symbol('x', real=True)).is_nonpositive is None + assert sign(Symbol('x', real=True, zero=False)).is_nonpositive is None + + x, y = Symbol('x', real=True), Symbol('y') + f = Function('f') + assert sign(x).rewrite(Piecewise) == \ + Piecewise((1, x > 0), (-1, x < 0), (0, True)) + assert sign(y).rewrite(Piecewise) == sign(y) + assert sign(x).rewrite(Heaviside) == 2*Heaviside(x, H0=S(1)/2) - 1 + assert sign(y).rewrite(Heaviside) == sign(y) + assert sign(y).rewrite(Abs) == Piecewise((0, Eq(y, 0)), (y/Abs(y), True)) + assert sign(f(y)).rewrite(Abs) == Piecewise((0, Eq(f(y), 0)), (f(y)/Abs(f(y)), True)) + + # evaluate what can be evaluated + assert sign(exp_polar(I*pi)*pi) is S.NegativeOne + + eq = -sqrt(10 + 6*sqrt(3)) + sqrt(1 + sqrt(3)) + sqrt(3 + 3*sqrt(3)) + # if there is a fast way to know when and when you cannot prove an + # expression like this is zero then the equality to zero is ok + assert sign(eq).func is sign or sign(eq) == 0 + # but sometimes it's hard to do this so it's better not to load + # abs down with tests that will be very slow + q = 1 + sqrt(2) - 2*sqrt(3) + 1331*sqrt(6) + p = expand(q**3)**Rational(1, 3) + d = p - q + assert sign(d).func is sign or sign(d) == 0 + + +def test_as_real_imag(): + n = pi**1000 + # the special code for working out the real + # and complex parts of a power with Integer exponent + # should not run if there is no imaginary part, hence + # this should not hang + assert n.as_real_imag() == (n, 0) + + # issue 6261 + x = Symbol('x') + assert sqrt(x).as_real_imag() == \ + ((re(x)**2 + im(x)**2)**Rational(1, 4)*cos(atan2(im(x), re(x))/2), + (re(x)**2 + im(x)**2)**Rational(1, 4)*sin(atan2(im(x), re(x))/2)) + + # issue 3853 + a, b = symbols('a,b', real=True) + assert ((1 + sqrt(a + b*I))/2).as_real_imag() == \ + ( + (a**2 + b**2)**Rational( + 1, 4)*cos(atan2(b, a)/2)/2 + S.Half, + (a**2 + b**2)**Rational(1, 4)*sin(atan2(b, a)/2)/2) + + assert sqrt(a**2).as_real_imag() == (sqrt(a**2), 0) + i = symbols('i', imaginary=True) + assert sqrt(i**2).as_real_imag() == (0, abs(i)) + + assert ((1 + I)/(1 - I)).as_real_imag() == (0, 1) + assert ((1 + I)**3/(1 - I)).as_real_imag() == (-2, 0) + + +@XFAIL +def test_sign_issue_3068(): + n = pi**1000 + i = int(n) + x = Symbol('x') + assert (n - i).round() == 1 # doesn't hang + assert sign(n - i) == 1 + # perhaps it's not possible to get the sign right when + # only 1 digit is being requested for this situation; + # 2 digits works + assert (n - x).n(1, subs={x: i}) > 0 + assert (n - x).n(2, subs={x: i}) > 0 + + +def test_Abs(): + raises(TypeError, lambda: Abs(Interval(2, 3))) # issue 8717 + + x, y = symbols('x,y') + assert sign(sign(x)) == sign(x) + assert sign(x*y).func is sign + assert Abs(0) == 0 + assert Abs(1) == 1 + assert Abs(-1) == 1 + assert Abs(I) == 1 + assert Abs(-I) == 1 + assert Abs(nan) is nan + assert Abs(zoo) is oo + assert Abs(I * pi) == pi + assert Abs(-I * pi) == pi + assert Abs(I * x) == Abs(x) + assert Abs(-I * x) == Abs(x) + assert Abs(-2*x) == 2*Abs(x) + assert Abs(-2.0*x) == 2.0*Abs(x) + assert Abs(2*pi*x*y) == 2*pi*Abs(x*y) + assert Abs(conjugate(x)) == Abs(x) + assert conjugate(Abs(x)) == Abs(x) + assert Abs(x).expand(complex=True) == sqrt(re(x)**2 + im(x)**2) + + a = Symbol('a', positive=True) + assert Abs(2*pi*x*a) == 2*pi*a*Abs(x) + assert Abs(2*pi*I*x*a) == 2*pi*a*Abs(x) + + x = Symbol('x', real=True) + n = Symbol('n', integer=True) + assert Abs((-1)**n) == 1 + assert x**(2*n) == Abs(x)**(2*n) + assert Abs(x).diff(x) == sign(x) + assert abs(x) == Abs(x) # Python built-in + assert Abs(x)**3 == x**2*Abs(x) + assert Abs(x)**4 == x**4 + assert ( + Abs(x)**(3*n)).args == (Abs(x), 3*n) # leave symbolic odd unchanged + assert (1/Abs(x)).args == (Abs(x), -1) + assert 1/Abs(x)**3 == 1/(x**2*Abs(x)) + assert Abs(x)**-3 == Abs(x)/(x**4) + assert Abs(x**3) == x**2*Abs(x) + assert Abs(I**I) == exp(-pi/2) + assert Abs((4 + 5*I)**(6 + 7*I)) == 68921*exp(-7*atan(Rational(5, 4))) + y = Symbol('y', real=True) + assert Abs(I**y) == 1 + y = Symbol('y') + assert Abs(I**y) == exp(-pi*im(y)/2) + + x = Symbol('x', imaginary=True) + assert Abs(x).diff(x) == -sign(x) + + eq = -sqrt(10 + 6*sqrt(3)) + sqrt(1 + sqrt(3)) + sqrt(3 + 3*sqrt(3)) + # if there is a fast way to know when you can and when you cannot prove an + # expression like this is zero then the equality to zero is ok + assert abs(eq).func is Abs or abs(eq) == 0 + # but sometimes it's hard to do this so it's better not to load + # abs down with tests that will be very slow + q = 1 + sqrt(2) - 2*sqrt(3) + 1331*sqrt(6) + p = expand(q**3)**Rational(1, 3) + d = p - q + assert abs(d).func is Abs or abs(d) == 0 + + assert Abs(4*exp(pi*I/4)) == 4 + assert Abs(3**(2 + I)) == 9 + assert Abs((-3)**(1 - I)) == 3*exp(pi) + + assert Abs(oo) is oo + assert Abs(-oo) is oo + assert Abs(oo + I) is oo + assert Abs(oo + I*oo) is oo + + a = Symbol('a', algebraic=True) + t = Symbol('t', transcendental=True) + x = Symbol('x') + assert re(a).is_algebraic + assert re(x).is_algebraic is None + assert re(t).is_algebraic is False + assert Abs(x).fdiff() == sign(x) + raises(ArgumentIndexError, lambda: Abs(x).fdiff(2)) + + # doesn't have recursion error + arg = sqrt(acos(1 - I)*acos(1 + I)) + assert abs(arg) == arg + + # special handling to put Abs in denom + assert abs(1/x) == 1/Abs(x) + e = abs(2/x**2) + assert e.is_Mul and e == 2/Abs(x**2) + assert unchanged(Abs, y/x) + assert unchanged(Abs, x/(x + 1)) + assert unchanged(Abs, x*y) + p = Symbol('p', positive=True) + assert abs(x/p) == abs(x)/p + + # coverage + assert unchanged(Abs, Symbol('x', real=True)**y) + # issue 19627 + f = Function('f', positive=True) + assert sqrt(f(x)**2) == f(x) + # issue 21625 + assert unchanged(Abs, S("im(acos(-i + acosh(-g + i)))")) + + +def test_Abs_rewrite(): + x = Symbol('x', real=True) + a = Abs(x).rewrite(Heaviside).expand() + assert a == x*Heaviside(x) - x*Heaviside(-x) + for i in [-2, -1, 0, 1, 2]: + assert a.subs(x, i) == abs(i) + y = Symbol('y') + assert Abs(y).rewrite(Heaviside) == Abs(y) + + x, y = Symbol('x', real=True), Symbol('y') + assert Abs(x).rewrite(Piecewise) == Piecewise((x, x >= 0), (-x, True)) + assert Abs(y).rewrite(Piecewise) == Abs(y) + assert Abs(y).rewrite(sign) == y/sign(y) + + i = Symbol('i', imaginary=True) + assert abs(i).rewrite(Piecewise) == Piecewise((I*i, I*i >= 0), (-I*i, True)) + + + assert Abs(y).rewrite(conjugate) == sqrt(y*conjugate(y)) + assert Abs(i).rewrite(conjugate) == sqrt(-i**2) # == -I*i + + y = Symbol('y', extended_real=True) + assert (Abs(exp(-I*x)-exp(-I*y))**2).rewrite(conjugate) == \ + -exp(I*x)*exp(-I*y) + 2 - exp(-I*x)*exp(I*y) + + +def test_Abs_real(): + # test some properties of abs that only apply + # to real numbers + x = Symbol('x', complex=True) + assert sqrt(x**2) != Abs(x) + assert Abs(x**2) != x**2 + + x = Symbol('x', real=True) + assert sqrt(x**2) == Abs(x) + assert Abs(x**2) == x**2 + + # if the symbol is zero, the following will still apply + nn = Symbol('nn', nonnegative=True, real=True) + np = Symbol('np', nonpositive=True, real=True) + assert Abs(nn) == nn + assert Abs(np) == -np + + +def test_Abs_properties(): + x = Symbol('x') + assert Abs(x).is_real is None + assert Abs(x).is_extended_real is True + assert Abs(x).is_rational is None + assert Abs(x).is_positive is None + assert Abs(x).is_nonnegative is None + assert Abs(x).is_extended_positive is None + assert Abs(x).is_extended_nonnegative is True + + f = Symbol('x', finite=True) + assert Abs(f).is_real is True + assert Abs(f).is_extended_real is True + assert Abs(f).is_rational is None + assert Abs(f).is_positive is None + assert Abs(f).is_nonnegative is True + assert Abs(f).is_extended_positive is None + assert Abs(f).is_extended_nonnegative is True + + z = Symbol('z', complex=True, zero=False) + assert Abs(z).is_real is True # since complex implies finite + assert Abs(z).is_extended_real is True + assert Abs(z).is_rational is None + assert Abs(z).is_positive is True + assert Abs(z).is_extended_positive is True + assert Abs(z).is_zero is False + + p = Symbol('p', positive=True) + assert Abs(p).is_real is True + assert Abs(p).is_extended_real is True + assert Abs(p).is_rational is None + assert Abs(p).is_positive is True + assert Abs(p).is_zero is False + + q = Symbol('q', rational=True) + assert Abs(q).is_real is True + assert Abs(q).is_rational is True + assert Abs(q).is_integer is None + assert Abs(q).is_positive is None + assert Abs(q).is_nonnegative is True + + i = Symbol('i', integer=True) + assert Abs(i).is_real is True + assert Abs(i).is_integer is True + assert Abs(i).is_positive is None + assert Abs(i).is_nonnegative is True + + e = Symbol('n', even=True) + ne = Symbol('ne', real=True, even=False) + assert Abs(e).is_even is True + assert Abs(ne).is_even is False + assert Abs(i).is_even is None + + o = Symbol('n', odd=True) + no = Symbol('no', real=True, odd=False) + assert Abs(o).is_odd is True + assert Abs(no).is_odd is False + assert Abs(i).is_odd is None + + +def test_abs(): + # this tests that abs calls Abs; don't rename to + # test_Abs since that test is already above + a = Symbol('a', positive=True) + assert abs(I*(1 + a)**2) == (1 + a)**2 + + +def test_arg(): + assert arg(0) is nan + assert arg(1) == 0 + assert arg(-1) == pi + assert arg(I) == pi/2 + assert arg(-I) == -pi/2 + assert arg(1 + I) == pi/4 + assert arg(-1 + I) == pi*Rational(3, 4) + assert arg(1 - I) == -pi/4 + assert arg(exp_polar(4*pi*I)) == 4*pi + assert arg(exp_polar(-7*pi*I)) == -7*pi + assert arg(exp_polar(5 - 3*pi*I/4)) == pi*Rational(-3, 4) + + assert arg(exp(I*pi/7)) == pi/7 # issue 17300 + assert arg(exp(16*I)) == 16 - 6*pi + assert arg(exp(13*I*pi/12)) == -11*pi/12 + assert arg(exp(123 - 5*I)) == -5 + 2*pi + assert arg(exp(sin(1 + 3*I))) == -2*pi + cos(1)*sinh(3) + r = Symbol('r', real=True) + assert arg(exp(r - 2*I)) == -2 + + f = Function('f') + assert not arg(f(0) + I*f(1)).atoms(re) + + # check nesting + x = Symbol('x') + assert arg(arg(arg(x))) is not S.NaN + assert arg(arg(arg(arg(x)))) is S.NaN + r = Symbol('r', extended_real=True) + assert arg(arg(r)) is not S.NaN + assert arg(arg(arg(r))) is S.NaN + + p = Function('p', extended_positive=True) + assert arg(p(x)) == 0 + assert arg((3 + I)*p(x)) == arg(3 + I) + + p = Symbol('p', positive=True) + assert arg(p) == 0 + assert arg(p*I) == pi/2 + + n = Symbol('n', negative=True) + assert arg(n) == pi + assert arg(n*I) == -pi/2 + + x = Symbol('x') + assert conjugate(arg(x)) == arg(x) + + e = p + I*p**2 + assert arg(e) == arg(1 + p*I) + # make sure sign doesn't swap + e = -2*p + 4*I*p**2 + assert arg(e) == arg(-1 + 2*p*I) + # make sure sign isn't lost + x = symbols('x', real=True) # could be zero + e = x + I*x + assert arg(e) == arg(x*(1 + I)) + assert arg(e/p) == arg(x*(1 + I)) + e = p*cos(p) + I*log(p)*exp(p) + assert arg(e).args[0] == e + # keep it simple -- let the user do more advanced cancellation + e = (p + 1) + I*(p**2 - 1) + assert arg(e).args[0] == e + + f = Function('f') + e = 2*x*(f(0) - 1) - 2*x*f(0) + assert arg(e) == arg(-2*x) + assert arg(f(0)).func == arg and arg(f(0)).args == (f(0),) + + +def test_arg_rewrite(): + assert arg(1 + I) == atan2(1, 1) + + x = Symbol('x', real=True) + y = Symbol('y', real=True) + assert arg(x + I*y).rewrite(atan2) == atan2(y, x) + + +def test_arg_leading_term_and_series(): + x = Symbol('x') + assert arg(x).as_leading_term(x, cdir = 1) == 0 + assert arg(x).as_leading_term(x, cdir = -1) == pi + raises(PoleError, lambda: arg(x + I).as_leading_term(x, cdir = 1)) + raises(PoleError, lambda: arg(2*x).as_leading_term(x, cdir = I)) + + assert arg(x).nseries(x) == 0 + assert arg(x).nseries(x, n=0) == Order(1) + + +def test_adjoint(): + a = Symbol('a', antihermitian=True) + b = Symbol('b', hermitian=True) + assert adjoint(a) == -a + assert adjoint(I*a) == I*a + assert adjoint(b) == b + assert adjoint(I*b) == -I*b + assert adjoint(a*b) == -b*a + assert adjoint(I*a*b) == I*b*a + + x, y = symbols('x y') + assert adjoint(adjoint(x)) == x + assert adjoint(x + y) == conjugate(x) + conjugate(y) + assert adjoint(x - y) == conjugate(x) - conjugate(y) + assert adjoint(x * y) == conjugate(x) * conjugate(y) + assert adjoint(x / y) == conjugate(x) / conjugate(y) + assert adjoint(-x) == -conjugate(x) + + x, y = symbols('x y', commutative=False) + assert adjoint(adjoint(x)) == x + assert adjoint(x + y) == adjoint(x) + adjoint(y) + assert adjoint(x - y) == adjoint(x) - adjoint(y) + assert adjoint(x * y) == adjoint(y) * adjoint(x) + assert adjoint(x / y) == 1 / adjoint(y) * adjoint(x) + assert adjoint(-x) == -adjoint(x) + + +def test_conjugate(): + a = Symbol('a', real=True) + b = Symbol('b', imaginary=True) + assert conjugate(a) == a + assert conjugate(I*a) == -I*a + assert conjugate(b) == -b + assert conjugate(I*b) == I*b + assert conjugate(a*b) == -a*b + assert conjugate(I*a*b) == I*a*b + + x, y = symbols('x y') + assert conjugate(conjugate(x)) == x + assert conjugate(x).inverse() == conjugate + assert conjugate(x + y) == conjugate(x) + conjugate(y) + assert conjugate(x - y) == conjugate(x) - conjugate(y) + assert conjugate(x * y) == conjugate(x) * conjugate(y) + assert conjugate(x / y) == conjugate(x) / conjugate(y) + assert conjugate(-x) == -conjugate(x) + + a = Symbol('a', algebraic=True) + t = Symbol('t', transcendental=True) + assert re(a).is_algebraic + assert re(x).is_algebraic is None + assert re(t).is_algebraic is False + + +def test_conjugate_transpose(): + x = Symbol('x', commutative=False) + assert conjugate(transpose(x)) == adjoint(x) + assert transpose(conjugate(x)) == adjoint(x) + assert adjoint(transpose(x)) == conjugate(x) + assert transpose(adjoint(x)) == conjugate(x) + assert adjoint(conjugate(x)) == transpose(x) + assert conjugate(adjoint(x)) == transpose(x) + + x = Symbol('x') + assert conjugate(x) == adjoint(x) + assert transpose(x) == x + + +def test_transpose(): + a = Symbol('a', complex=True) + assert transpose(a) == a + assert transpose(I*a) == I*a + + x, y = symbols('x y') + assert transpose(transpose(x)) == x + assert transpose(x + y) == x + y + assert transpose(x - y) == x - y + assert transpose(x * y) == x * y + assert transpose(x / y) == x / y + assert transpose(-x) == -x + + x, y = symbols('x y', commutative=False) + assert transpose(transpose(x)) == x + assert transpose(x + y) == transpose(x) + transpose(y) + assert transpose(x - y) == transpose(x) - transpose(y) + assert transpose(x * y) == transpose(y) * transpose(x) + assert transpose(x / y) == 1 / transpose(y) * transpose(x) + assert transpose(-x) == -transpose(x) + + +@_both_exp_pow +def test_polarify(): + from sympy.functions.elementary.complexes import (polar_lift, polarify) + x = Symbol('x') + z = Symbol('z', polar=True) + f = Function('f') + ES = {} + + assert polarify(-1) == (polar_lift(-1), ES) + assert polarify(1 + I) == (polar_lift(1 + I), ES) + + assert polarify(exp(x), subs=False) == exp(x) + assert polarify(1 + x, subs=False) == 1 + x + assert polarify(f(I) + x, subs=False) == f(polar_lift(I)) + x + + assert polarify(x, lift=True) == polar_lift(x) + assert polarify(z, lift=True) == z + assert polarify(f(x), lift=True) == f(polar_lift(x)) + assert polarify(1 + x, lift=True) == polar_lift(1 + x) + assert polarify(1 + f(x), lift=True) == polar_lift(1 + f(polar_lift(x))) + + newex, subs = polarify(f(x) + z) + assert newex.subs(subs) == f(x) + z + + mu = Symbol("mu") + sigma = Symbol("sigma", positive=True) + + # Make sure polarify(lift=True) doesn't try to lift the integration + # variable + assert polarify( + Integral(sqrt(2)*x*exp(-(-mu + x)**2/(2*sigma**2))/(2*sqrt(pi)*sigma), + (x, -oo, oo)), lift=True) == Integral(sqrt(2)*(sigma*exp_polar(0))**exp_polar(I*pi)* + exp((sigma*exp_polar(0))**(2*exp_polar(I*pi))*exp_polar(I*pi)*polar_lift(-mu + x)** + (2*exp_polar(0))/2)*exp_polar(0)*polar_lift(x)/(2*sqrt(pi)), (x, -oo, oo)) + + +def test_unpolarify(): + from sympy.functions.elementary.complexes import (polar_lift, principal_branch, unpolarify) + from sympy.core.relational import Ne + from sympy.functions.elementary.hyperbolic import tanh + from sympy.functions.special.error_functions import erf + from sympy.functions.special.gamma_functions import (gamma, uppergamma) + from sympy.abc import x + p = exp_polar(7*I) + 1 + u = exp(7*I) + 1 + + assert unpolarify(1) == 1 + assert unpolarify(p) == u + assert unpolarify(p**2) == u**2 + assert unpolarify(p**x) == p**x + assert unpolarify(p*x) == u*x + assert unpolarify(p + x) == u + x + assert unpolarify(sqrt(sin(p))) == sqrt(sin(u)) + + # Test reduction to principal branch 2*pi. + t = principal_branch(x, 2*pi) + assert unpolarify(t) == x + assert unpolarify(sqrt(t)) == sqrt(t) + + # Test exponents_only. + assert unpolarify(p**p, exponents_only=True) == p**u + assert unpolarify(uppergamma(x, p**p)) == uppergamma(x, p**u) + + # Test functions. + assert unpolarify(sin(p)) == sin(u) + assert unpolarify(tanh(p)) == tanh(u) + assert unpolarify(gamma(p)) == gamma(u) + assert unpolarify(erf(p)) == erf(u) + assert unpolarify(uppergamma(x, p)) == uppergamma(x, p) + + assert unpolarify(uppergamma(sin(p), sin(p + exp_polar(0)))) == \ + uppergamma(sin(u), sin(u + 1)) + assert unpolarify(uppergamma(polar_lift(0), 2*exp_polar(0))) == \ + uppergamma(0, 2) + + assert unpolarify(Eq(p, 0)) == Eq(u, 0) + assert unpolarify(Ne(p, 0)) == Ne(u, 0) + assert unpolarify(polar_lift(x) > 0) == (x > 0) + + # Test bools + assert unpolarify(True) is True + + +def test_issue_4035(): + x = Symbol('x') + assert Abs(x).expand(trig=True) == Abs(x) + assert sign(x).expand(trig=True) == sign(x) + assert arg(x).expand(trig=True) == arg(x) + + +def test_issue_3206(): + x = Symbol('x') + assert Abs(Abs(x)) == Abs(x) + + +def test_issue_4754_derivative_conjugate(): + x = Symbol('x', real=True) + y = Symbol('y', imaginary=True) + f = Function('f') + assert (f(x).conjugate()).diff(x) == (f(x).diff(x)).conjugate() + assert (f(y).conjugate()).diff(y) == -(f(y).diff(y)).conjugate() + + +def test_derivatives_issue_4757(): + x = Symbol('x', real=True) + y = Symbol('y', imaginary=True) + f = Function('f') + assert re(f(x)).diff(x) == re(f(x).diff(x)) + assert im(f(x)).diff(x) == im(f(x).diff(x)) + assert re(f(y)).diff(y) == -I*im(f(y).diff(y)) + assert im(f(y)).diff(y) == -I*re(f(y).diff(y)) + assert Abs(f(x)).diff(x).subs(f(x), 1 + I*x).doit() == x/sqrt(1 + x**2) + assert arg(f(x)).diff(x).subs(f(x), 1 + I*x**2).doit() == 2*x/(1 + x**4) + assert Abs(f(y)).diff(y).subs(f(y), 1 + y).doit() == -y/sqrt(1 - y**2) + assert arg(f(y)).diff(y).subs(f(y), I + y**2).doit() == 2*y/(1 + y**4) + + +def test_issue_11413(): + from sympy.simplify.simplify import simplify + v0 = Symbol('v0') + v1 = Symbol('v1') + v2 = Symbol('v2') + V = Matrix([[v0],[v1],[v2]]) + U = V.normalized() + assert U == Matrix([ + [v0/sqrt(Abs(v0)**2 + Abs(v1)**2 + Abs(v2)**2)], + [v1/sqrt(Abs(v0)**2 + Abs(v1)**2 + Abs(v2)**2)], + [v2/sqrt(Abs(v0)**2 + Abs(v1)**2 + Abs(v2)**2)]]) + U.norm = sqrt(v0**2/(v0**2 + v1**2 + v2**2) + v1**2/(v0**2 + v1**2 + v2**2) + v2**2/(v0**2 + v1**2 + v2**2)) + assert simplify(U.norm) == 1 + + +def test_periodic_argument(): + from sympy.functions.elementary.complexes import (periodic_argument, polar_lift, principal_branch, unbranched_argument) + x = Symbol('x') + p = Symbol('p', positive=True) + + assert unbranched_argument(2 + I) == periodic_argument(2 + I, oo) + assert unbranched_argument(1 + x) == periodic_argument(1 + x, oo) + assert N_equals(unbranched_argument((1 + I)**2), pi/2) + assert N_equals(unbranched_argument((1 - I)**2), -pi/2) + assert N_equals(periodic_argument((1 + I)**2, 3*pi), pi/2) + assert N_equals(periodic_argument((1 - I)**2, 3*pi), -pi/2) + + assert unbranched_argument(principal_branch(x, pi)) == \ + periodic_argument(x, pi) + + assert unbranched_argument(polar_lift(2 + I)) == unbranched_argument(2 + I) + assert periodic_argument(polar_lift(2 + I), 2*pi) == \ + periodic_argument(2 + I, 2*pi) + assert periodic_argument(polar_lift(2 + I), 3*pi) == \ + periodic_argument(2 + I, 3*pi) + assert periodic_argument(polar_lift(2 + I), pi) == \ + periodic_argument(polar_lift(2 + I), pi) + + assert unbranched_argument(polar_lift(1 + I)) == pi/4 + assert periodic_argument(2*p, p) == periodic_argument(p, p) + assert periodic_argument(pi*p, p) == periodic_argument(p, p) + + assert Abs(polar_lift(1 + I)) == Abs(1 + I) + + +@XFAIL +def test_principal_branch_fail(): + # TODO XXX why does abs(x)._eval_evalf() not fall back to global evalf? + from sympy.functions.elementary.complexes import principal_branch + assert N_equals(principal_branch((1 + I)**2, pi/2), 0) + + +def test_principal_branch(): + from sympy.functions.elementary.complexes import (polar_lift, principal_branch) + p = Symbol('p', positive=True) + x = Symbol('x') + neg = Symbol('x', negative=True) + + assert principal_branch(polar_lift(x), p) == principal_branch(x, p) + assert principal_branch(polar_lift(2 + I), p) == principal_branch(2 + I, p) + assert principal_branch(2*x, p) == 2*principal_branch(x, p) + assert principal_branch(1, pi) == exp_polar(0) + assert principal_branch(-1, 2*pi) == exp_polar(I*pi) + assert principal_branch(-1, pi) == exp_polar(0) + assert principal_branch(exp_polar(3*pi*I)*x, 2*pi) == \ + principal_branch(exp_polar(I*pi)*x, 2*pi) + assert principal_branch(neg*exp_polar(pi*I), 2*pi) == neg*exp_polar(-I*pi) + # related to issue #14692 + assert principal_branch(exp_polar(-I*pi/2)/polar_lift(neg), 2*pi) == \ + exp_polar(-I*pi/2)/neg + + assert N_equals(principal_branch((1 + I)**2, 2*pi), 2*I) + assert N_equals(principal_branch((1 + I)**2, 3*pi), 2*I) + assert N_equals(principal_branch((1 + I)**2, 1*pi), 2*I) + + # test argument sanitization + assert principal_branch(x, I).func is principal_branch + assert principal_branch(x, -4).func is principal_branch + assert principal_branch(x, -oo).func is principal_branch + assert principal_branch(x, zoo).func is principal_branch + + +@XFAIL +def test_issue_6167_6151(): + n = pi**1000 + i = int(n) + assert sign(n - i) == 1 + assert abs(n - i) == n - i + x = Symbol('x') + eps = pi**-1500 + big = pi**1000 + one = cos(x)**2 + sin(x)**2 + e = big*one - big + eps + from sympy.simplify.simplify import simplify + assert sign(simplify(e)) == 1 + for xi in (111, 11, 1, Rational(1, 10)): + assert sign(e.subs(x, xi)) == 1 + + +def test_issue_14216(): + from sympy.functions.elementary.complexes import unpolarify + A = MatrixSymbol("A", 2, 2) + assert unpolarify(A[0, 0]) == A[0, 0] + assert unpolarify(A[0, 0]*A[1, 0]) == A[0, 0]*A[1, 0] + + +def test_issue_14238(): + # doesn't cause recursion error + r = Symbol('r', real=True) + assert Abs(r + Piecewise((0, r > 0), (1 - r, True))) + + +def test_issue_22189(): + x = Symbol('x') + for a in (sqrt(7 - 2*x) - 2, 1 - x): + assert Abs(a) - Abs(-a) == 0, a + + +def test_zero_assumptions(): + nr = Symbol('nonreal', real=False, finite=True) + ni = Symbol('nonimaginary', imaginary=False) + # imaginary implies not zero + nzni = Symbol('nonzerononimaginary', zero=False, imaginary=False) + + assert re(nr).is_zero is None + assert im(nr).is_zero is False + + assert re(ni).is_zero is None + assert im(ni).is_zero is None + + assert re(nzni).is_zero is False + assert im(nzni).is_zero is None + + +@_both_exp_pow +def test_issue_15893(): + f = Function('f', real=True) + x = Symbol('x', real=True) + eq = Derivative(Abs(f(x)), f(x)) + assert eq.doit() == sign(f(x)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/test_exponential.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/test_exponential.py new file mode 100644 index 0000000000000000000000000000000000000000..ee8c311d01e98d7fd6831ad754e854fae409aa0c --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/test_exponential.py @@ -0,0 +1,810 @@ +from sympy.assumptions.refine import refine +from sympy.calculus.accumulationbounds import AccumBounds +from sympy.concrete.products import Product +from sympy.concrete.summations import Sum +from sympy.core.function import expand_log +from sympy.core.numbers import (E, Float, I, Rational, nan, oo, pi, zoo) +from sympy.core.power import Pow +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.elementary.complexes import (adjoint, conjugate, re, sign, transpose) +from sympy.functions.elementary.exponential import (LambertW, exp, exp_polar, log) +from sympy.functions.elementary.hyperbolic import (cosh, sinh, tanh) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (cos, sin, tan) +from sympy.matrices.expressions.matexpr import MatrixSymbol +from sympy.polys.polytools import gcd +from sympy.series.order import O +from sympy.simplify.simplify import simplify +from sympy.core.parameters import global_parameters +from sympy.functions.elementary.exponential import match_real_imag +from sympy.abc import x, y, z +from sympy.core.expr import unchanged +from sympy.core.function import ArgumentIndexError +from sympy.testing.pytest import raises, XFAIL, _both_exp_pow + + +@_both_exp_pow +def test_exp_values(): + if global_parameters.exp_is_pow: + assert type(exp(x)) is Pow + else: + assert type(exp(x)) is exp + + k = Symbol('k', integer=True) + + assert exp(nan) is nan + + assert exp(oo) is oo + assert exp(-oo) == 0 + + assert exp(0) == 1 + assert exp(1) == E + assert exp(-1 + x).as_base_exp() == (S.Exp1, x - 1) + assert exp(1 + x).as_base_exp() == (S.Exp1, x + 1) + + assert exp(pi*I/2) == I + assert exp(pi*I) == -1 + assert exp(pi*I*Rational(3, 2)) == -I + assert exp(2*pi*I) == 1 + + assert refine(exp(pi*I*2*k)) == 1 + assert refine(exp(pi*I*2*(k + S.Half))) == -1 + assert refine(exp(pi*I*2*(k + Rational(1, 4)))) == I + assert refine(exp(pi*I*2*(k + Rational(3, 4)))) == -I + + assert exp(log(x)) == x + assert exp(2*log(x)) == x**2 + assert exp(pi*log(x)) == x**pi + + assert exp(17*log(x) + E*log(y)) == x**17 * y**E + + assert exp(x*log(x)) != x**x + assert exp(sin(x)*log(x)) != x + + assert exp(3*log(x) + oo*x) == exp(oo*x) * x**3 + assert exp(4*log(x)*log(y) + 3*log(x)) == x**3 * exp(4*log(x)*log(y)) + + assert exp(-oo, evaluate=False).is_finite is True + assert exp(oo, evaluate=False).is_finite is False + + +@_both_exp_pow +def test_exp_period(): + assert exp(I*pi*Rational(9, 4)) == exp(I*pi/4) + assert exp(I*pi*Rational(46, 18)) == exp(I*pi*Rational(5, 9)) + assert exp(I*pi*Rational(25, 7)) == exp(I*pi*Rational(-3, 7)) + assert exp(I*pi*Rational(-19, 3)) == exp(-I*pi/3) + assert exp(I*pi*Rational(37, 8)) - exp(I*pi*Rational(-11, 8)) == 0 + assert exp(I*pi*Rational(-5, 3)) / exp(I*pi*Rational(11, 5)) * exp(I*pi*Rational(148, 15)) == 1 + + assert exp(2 - I*pi*Rational(17, 5)) == exp(2 + I*pi*Rational(3, 5)) + assert exp(log(3) + I*pi*Rational(29, 9)) == 3 * exp(I*pi*Rational(-7, 9)) + + n = Symbol('n', integer=True) + e = Symbol('e', even=True) + assert exp(e*I*pi) == 1 + assert exp((e + 1)*I*pi) == -1 + assert exp((1 + 4*n)*I*pi/2) == I + assert exp((-1 + 4*n)*I*pi/2) == -I + + +@_both_exp_pow +def test_exp_log(): + x = Symbol("x", real=True) + assert log(exp(x)) == x + assert exp(log(x)) == x + + if not global_parameters.exp_is_pow: + assert log(x).inverse() == exp + assert exp(x).inverse() == log + + y = Symbol("y", polar=True) + assert log(exp_polar(z)) == z + assert exp(log(y)) == y + + +@_both_exp_pow +def test_exp_expand(): + e = exp(log(Rational(2))*(1 + x) - log(Rational(2))*x) + assert e.expand() == 2 + assert exp(x + y) != exp(x)*exp(y) + assert exp(x + y).expand() == exp(x)*exp(y) + + +@_both_exp_pow +def test_exp__as_base_exp(): + assert exp(x).as_base_exp() == (E, x) + assert exp(2*x).as_base_exp() == (E, 2*x) + assert exp(x*y).as_base_exp() == (E, x*y) + assert exp(-x).as_base_exp() == (E, -x) + + # Pow( *expr.as_base_exp() ) == expr invariant should hold + assert E**x == exp(x) + assert E**(2*x) == exp(2*x) + assert E**(x*y) == exp(x*y) + + assert exp(x).base is S.Exp1 + assert exp(x).exp == x + + +@_both_exp_pow +def test_exp_infinity(): + assert exp(I*y) != nan + assert refine(exp(I*oo)) is nan + assert refine(exp(-I*oo)) is nan + assert exp(y*I*oo) != nan + assert exp(zoo) is nan + x = Symbol('x', extended_real=True, finite=False) + assert exp(x).is_complex is None + + +@_both_exp_pow +def test_exp_subs(): + x = Symbol('x') + e = (exp(3*log(x), evaluate=False)) # evaluates to x**3 + assert e.subs(x**3, y**3) == e + assert e.subs(x**2, 5) == e + assert (x**3).subs(x**2, y) != y**Rational(3, 2) + assert exp(exp(x) + exp(x**2)).subs(exp(exp(x)), y) == y * exp(exp(x**2)) + assert exp(x).subs(E, y) == y**x + x = symbols('x', real=True) + assert exp(5*x).subs(exp(7*x), y) == y**Rational(5, 7) + assert exp(2*x + 7).subs(exp(3*x), y) == y**Rational(2, 3) * exp(7) + x = symbols('x', positive=True) + assert exp(3*log(x)).subs(x**2, y) == y**Rational(3, 2) + # differentiate between E and exp + assert exp(exp(x + E)).subs(exp, 3) == 3**(3**(x + E)) + assert exp(exp(x + E)).subs(exp, sin) == sin(sin(x + E)) + assert exp(exp(x + E)).subs(E, 3) == 3**(3**(x + 3)) + assert exp(3).subs(E, sin) == sin(3) + + +def test_exp_adjoint(): + x = Symbol('x', commutative=False) + assert adjoint(exp(x)) == exp(adjoint(x)) + + +def test_exp_conjugate(): + assert conjugate(exp(x)) == exp(conjugate(x)) + + +@_both_exp_pow +def test_exp_transpose(): + assert transpose(exp(x)) == exp(transpose(x)) + + +@_both_exp_pow +def test_exp_rewrite(): + assert exp(x).rewrite(sin) == sinh(x) + cosh(x) + assert exp(x*I).rewrite(cos) == cos(x) + I*sin(x) + assert exp(1).rewrite(cos) == sinh(1) + cosh(1) + assert exp(1).rewrite(sin) == sinh(1) + cosh(1) + assert exp(1).rewrite(sin) == sinh(1) + cosh(1) + assert exp(x).rewrite(tanh) == (1 + tanh(x/2))/(1 - tanh(x/2)) + assert exp(pi*I/4).rewrite(sqrt) == sqrt(2)/2 + sqrt(2)*I/2 + assert exp(pi*I/3).rewrite(sqrt) == S.Half + sqrt(3)*I/2 + if not global_parameters.exp_is_pow: + assert exp(x*log(y)).rewrite(Pow) == y**x + assert exp(log(x)*log(y)).rewrite(Pow) in [x**log(y), y**log(x)] + assert exp(log(log(x))*y).rewrite(Pow) == log(x)**y + + n = Symbol('n', integer=True) + + assert Sum((exp(pi*I/2)/2)**n, (n, 0, oo)).rewrite(sqrt).doit() == Rational(4, 5) + I*2/5 + assert Sum((exp(pi*I/4)/2)**n, (n, 0, oo)).rewrite(sqrt).doit() == 1/(1 - sqrt(2)*(1 + I)/4) + assert (Sum((exp(pi*I/3)/2)**n, (n, 0, oo)).rewrite(sqrt).doit().cancel() + == 4*I/(sqrt(3) + 3*I)) + + +@_both_exp_pow +def test_exp_leading_term(): + assert exp(x).as_leading_term(x) == 1 + assert exp(2 + x).as_leading_term(x) == exp(2) + assert exp((2*x + 3) / (x+1)).as_leading_term(x) == exp(3) + + # The following tests are commented, since now SymPy returns the + # original function when the leading term in the series expansion does + # not exist. + # raises(NotImplementedError, lambda: exp(1/x).as_leading_term(x)) + # raises(NotImplementedError, lambda: exp((x + 1) / x**2).as_leading_term(x)) + # raises(NotImplementedError, lambda: exp(x + 1/x).as_leading_term(x)) + + +@_both_exp_pow +def test_exp_taylor_term(): + x = symbols('x') + assert exp(x).taylor_term(1, x) == x + assert exp(x).taylor_term(3, x) == x**3/6 + assert exp(x).taylor_term(4, x) == x**4/24 + assert exp(x).taylor_term(-1, x) is S.Zero + + +def test_exp_MatrixSymbol(): + A = MatrixSymbol("A", 2, 2) + assert exp(A).has(exp) + + +def test_exp_fdiff(): + x = Symbol('x') + raises(ArgumentIndexError, lambda: exp(x).fdiff(2)) + + +def test_log_values(): + assert log(nan) is nan + + assert log(oo) is oo + assert log(-oo) is oo + + assert log(zoo) is zoo + assert log(-zoo) is zoo + + assert log(0) is zoo + + assert log(1) == 0 + assert log(-1) == I*pi + + assert log(E) == 1 + assert log(-E).expand() == 1 + I*pi + + assert unchanged(log, pi) + assert log(-pi).expand() == log(pi) + I*pi + + assert unchanged(log, 17) + assert log(-17) == log(17) + I*pi + + assert log(I) == I*pi/2 + assert log(-I) == -I*pi/2 + + assert log(17*I) == I*pi/2 + log(17) + assert log(-17*I).expand() == -I*pi/2 + log(17) + + assert log(oo*I) is oo + assert log(-oo*I) is oo + assert log(0, 2) is zoo + assert log(0, 5) is zoo + + assert exp(-log(3))**(-1) == 3 + + assert log(S.Half) == -log(2) + assert log(2*3).func is log + assert log(2*3**2).func is log + + +def test_match_real_imag(): + x, y = symbols('x,y', real=True) + i = Symbol('i', imaginary=True) + assert match_real_imag(S.One) == (1, 0) + assert match_real_imag(I) == (0, 1) + assert match_real_imag(3 - 5*I) == (3, -5) + assert match_real_imag(-sqrt(3) + S.Half*I) == (-sqrt(3), S.Half) + assert match_real_imag(x + y*I) == (x, y) + assert match_real_imag(x*I + y*I) == (0, x + y) + assert match_real_imag((x + y)*I) == (0, x + y) + assert match_real_imag(Rational(-2, 3)*i*I) == (None, None) + assert match_real_imag(1 - 2*i) == (None, None) + assert match_real_imag(sqrt(2)*(3 - 5*I)) == (None, None) + + +def test_log_exact(): + # check for pi/2, pi/3, pi/4, pi/6, pi/8, pi/12; pi/5, pi/10: + for n in range(-23, 24): + if gcd(n, 24) != 1: + assert log(exp(n*I*pi/24).rewrite(sqrt)) == n*I*pi/24 + for n in range(-9, 10): + assert log(exp(n*I*pi/10).rewrite(sqrt)) == n*I*pi/10 + + assert log(S.Half - I*sqrt(3)/2) == -I*pi/3 + assert log(Rational(-1, 2) + I*sqrt(3)/2) == I*pi*Rational(2, 3) + assert log(-sqrt(2)/2 - I*sqrt(2)/2) == -I*pi*Rational(3, 4) + assert log(-sqrt(3)/2 - I*S.Half) == -I*pi*Rational(5, 6) + + assert log(Rational(-1, 4) + sqrt(5)/4 - I*sqrt(sqrt(5)/8 + Rational(5, 8))) == -I*pi*Rational(2, 5) + assert log(sqrt(Rational(5, 8) - sqrt(5)/8) + I*(Rational(1, 4) + sqrt(5)/4)) == I*pi*Rational(3, 10) + assert log(-sqrt(sqrt(2)/4 + S.Half) + I*sqrt(S.Half - sqrt(2)/4)) == I*pi*Rational(7, 8) + assert log(-sqrt(6)/4 - sqrt(2)/4 + I*(-sqrt(6)/4 + sqrt(2)/4)) == -I*pi*Rational(11, 12) + + assert log(-1 + I*sqrt(3)) == log(2) + I*pi*Rational(2, 3) + assert log(5 + 5*I) == log(5*sqrt(2)) + I*pi/4 + assert log(sqrt(-12)) == log(2*sqrt(3)) + I*pi/2 + assert log(-sqrt(6) + sqrt(2) - I*sqrt(6) - I*sqrt(2)) == log(4) - I*pi*Rational(7, 12) + assert log(-sqrt(6-3*sqrt(2)) - I*sqrt(6+3*sqrt(2))) == log(2*sqrt(3)) - I*pi*Rational(5, 8) + assert log(1 + I*sqrt(2-sqrt(2))/sqrt(2+sqrt(2))) == log(2/sqrt(sqrt(2) + 2)) + I*pi/8 + assert log(cos(pi*Rational(7, 12)) + I*sin(pi*Rational(7, 12))) == I*pi*Rational(7, 12) + assert log(cos(pi*Rational(6, 5)) + I*sin(pi*Rational(6, 5))) == I*pi*Rational(-4, 5) + + assert log(5*(1 + I)/sqrt(2)) == log(5) + I*pi/4 + assert log(sqrt(2)*(-sqrt(3) + 1 - sqrt(3)*I - I)) == log(4) - I*pi*Rational(7, 12) + assert log(-sqrt(2)*(1 - I*sqrt(3))) == log(2*sqrt(2)) + I*pi*Rational(2, 3) + assert log(sqrt(3)*I*(-sqrt(6 - 3*sqrt(2)) - I*sqrt(3*sqrt(2) + 6))) == log(6) - I*pi/8 + + zero = (1 + sqrt(2))**2 - 3 - 2*sqrt(2) + assert log(zero - I*sqrt(3)) == log(sqrt(3)) - I*pi/2 + assert unchanged(log, zero + I*zero) or log(zero + zero*I) is zoo + + # bail quickly if no obvious simplification is possible: + assert unchanged(log, (sqrt(2)-1/sqrt(sqrt(3)+I))**1000) + # beware of non-real coefficients + assert unchanged(log, sqrt(2-sqrt(5))*(1 + I)) + + +def test_log_base(): + assert log(1, 2) == 0 + assert log(2, 2) == 1 + assert log(3, 2) == log(3)/log(2) + assert log(6, 2) == 1 + log(3)/log(2) + assert log(6, 3) == 1 + log(2)/log(3) + assert log(2**3, 2) == 3 + assert log(3**3, 3) == 3 + assert log(5, 1) is zoo + assert log(1, 1) is nan + assert log(Rational(2, 3), 10) == log(Rational(2, 3))/log(10) + assert log(Rational(2, 3), Rational(1, 3)) == -log(2)/log(3) + 1 + assert log(Rational(2, 3), Rational(2, 5)) == \ + log(Rational(2, 3))/log(Rational(2, 5)) + # issue 17148 + assert log(Rational(8, 3), 2) == -log(3)/log(2) + 3 + + +def test_log_symbolic(): + assert log(x, exp(1)) == log(x) + assert log(exp(x)) != x + + assert log(x, exp(1)) == log(x) + assert log(x*y) != log(x) + log(y) + assert log(x/y).expand() != log(x) - log(y) + assert log(x/y).expand(force=True) == log(x) - log(y) + assert log(x**y).expand() != y*log(x) + assert log(x**y).expand(force=True) == y*log(x) + + assert log(x, 2) == log(x)/log(2) + assert log(E, 2) == 1/log(2) + + p, q = symbols('p,q', positive=True) + r = Symbol('r', real=True) + + assert log(p**2) != 2*log(p) + assert log(p**2).expand() == 2*log(p) + assert log(x**2).expand() != 2*log(x) + assert log(p**q) != q*log(p) + assert log(exp(p)) == p + assert log(p*q) != log(p) + log(q) + assert log(p*q).expand() == log(p) + log(q) + + assert log(-sqrt(3)) == log(sqrt(3)) + I*pi + assert log(-exp(p)) != p + I*pi + assert log(-exp(x)).expand() != x + I*pi + assert log(-exp(r)).expand() == r + I*pi + + assert log(x**y) != y*log(x) + + assert (log(x**-5)**-1).expand() != -1/log(x)/5 + assert (log(p**-5)**-1).expand() == -1/log(p)/5 + assert log(-x).func is log and log(-x).args[0] == -x + assert log(-p).func is log and log(-p).args[0] == -p + + +def test_log_exp(): + assert log(exp(4*I*pi)) == 0 # exp evaluates + assert log(exp(-5*I*pi)) == I*pi # exp evaluates + assert log(exp(I*pi*Rational(19, 4))) == I*pi*Rational(3, 4) + assert log(exp(I*pi*Rational(25, 7))) == I*pi*Rational(-3, 7) + assert log(exp(-5*I)) == -5*I + 2*I*pi + + +@_both_exp_pow +def test_exp_assumptions(): + r = Symbol('r', real=True) + i = Symbol('i', imaginary=True) + for e in exp, exp_polar: + assert e(x).is_real is None + assert e(x).is_imaginary is None + assert e(i).is_real is None + assert e(i).is_imaginary is None + assert e(r).is_real is True + assert e(r).is_imaginary is False + assert e(re(x)).is_extended_real is True + assert e(re(x)).is_imaginary is False + + assert Pow(E, I*pi, evaluate=False).is_imaginary == False + assert Pow(E, 2*I*pi, evaluate=False).is_imaginary == False + assert Pow(E, I*pi/2, evaluate=False).is_imaginary == True + assert Pow(E, I*pi/3, evaluate=False).is_imaginary is None + + assert exp(0, evaluate=False).is_algebraic + + a = Symbol('a', algebraic=True) + an = Symbol('an', algebraic=True, nonzero=True) + r = Symbol('r', rational=True) + rn = Symbol('rn', rational=True, nonzero=True) + assert exp(a).is_algebraic is None + assert exp(an).is_algebraic is False + assert exp(pi*r).is_algebraic is None + assert exp(pi*rn).is_algebraic is False + + assert exp(0, evaluate=False).is_algebraic is True + assert exp(I*pi/3, evaluate=False).is_algebraic is True + assert exp(I*pi*r, evaluate=False).is_algebraic is True + + +@_both_exp_pow +def test_exp_AccumBounds(): + assert exp(AccumBounds(1, 2)) == AccumBounds(E, E**2) + + +def test_log_assumptions(): + p = symbols('p', positive=True) + n = symbols('n', negative=True) + z = symbols('z', zero=True) + x = symbols('x', infinite=True, extended_positive=True) + + assert log(z).is_positive is False + assert log(x).is_extended_positive is True + assert log(2) > 0 + assert log(1, evaluate=False).is_zero + assert log(1 + z).is_zero + assert log(p).is_zero is None + assert log(n).is_zero is False + assert log(0.5).is_negative is True + assert log(exp(p) + 1).is_positive + + assert log(1, evaluate=False).is_algebraic + assert log(42, evaluate=False).is_algebraic is False + + assert log(1 + z).is_rational + + +def test_log_hashing(): + assert x != log(log(x)) + assert hash(x) != hash(log(log(x))) + assert log(x) != log(log(log(x))) + + e = 1/log(log(x) + log(log(x))) + assert e.base.func is log + e = 1/log(log(x) + log(log(log(x)))) + assert e.base.func is log + + e = log(log(x)) + assert e.func is log + assert x.func is not log + assert hash(log(log(x))) != hash(x) + assert e != x + + +def test_log_sign(): + assert sign(log(2)) == 1 + + +def test_log_expand_complex(): + assert log(1 + I).expand(complex=True) == log(2)/2 + I*pi/4 + assert log(1 - sqrt(2)).expand(complex=True) == log(sqrt(2) - 1) + I*pi + + +def test_log_apply_evalf(): + value = (log(3)/log(2) - 1).evalf() + assert value.epsilon_eq(Float("0.58496250072115618145373")) + + +def test_log_leading_term(): + p = Symbol('p') + + # Test for STEP 3 + assert log(1 + x + x**2).as_leading_term(x, cdir=1) == x + # Test for STEP 4 + assert log(2*x).as_leading_term(x, cdir=1) == log(x) + log(2) + assert log(2*x).as_leading_term(x, cdir=-1) == log(x) + log(2) + assert log(-2*x).as_leading_term(x, cdir=1, logx=p) == p + log(2) + I*pi + assert log(-2*x).as_leading_term(x, cdir=-1, logx=p) == p + log(2) - I*pi + # Test for STEP 5 + assert log(-2*x + (3 - I)*x**2).as_leading_term(x, cdir=1) == log(x) + log(2) - I*pi + assert log(-2*x + (3 - I)*x**2).as_leading_term(x, cdir=-1) == log(x) + log(2) - I*pi + assert log(2*x + (3 - I)*x**2).as_leading_term(x, cdir=1) == log(x) + log(2) + assert log(2*x + (3 - I)*x**2).as_leading_term(x, cdir=-1) == log(x) + log(2) - 2*I*pi + assert log(-1 + x - I*x**2 + I*x**3).as_leading_term(x, cdir=1) == -I*pi + assert log(-1 + x - I*x**2 + I*x**3).as_leading_term(x, cdir=-1) == -I*pi + assert log(-1/(1 - x)).as_leading_term(x, cdir=1) == I*pi + assert log(-1/(1 - x)).as_leading_term(x, cdir=-1) == I*pi + + +def test_log_nseries(): + p = Symbol('p') + assert log(1/x)._eval_nseries(x, 4, logx=-p, cdir=1) == p + assert log(1/x)._eval_nseries(x, 4, logx=-p, cdir=-1) == p + 2*I*pi + assert log(x - 1)._eval_nseries(x, 4, None, I) == I*pi - x - x**2/2 - x**3/3 + O(x**4) + assert log(x - 1)._eval_nseries(x, 4, None, -I) == -I*pi - x - x**2/2 - x**3/3 + O(x**4) + assert log(I*x + I*x**3 - 1)._eval_nseries(x, 3, None, 1) == I*pi - I*x + x**2/2 + O(x**3) + assert log(I*x + I*x**3 - 1)._eval_nseries(x, 3, None, -1) == -I*pi - I*x + x**2/2 + O(x**3) + assert log(I*x**2 + I*x**3 - 1)._eval_nseries(x, 3, None, 1) == I*pi - I*x**2 + O(x**3) + assert log(I*x**2 + I*x**3 - 1)._eval_nseries(x, 3, None, -1) == I*pi - I*x**2 + O(x**3) + assert log(2*x + (3 - I)*x**2)._eval_nseries(x, 3, None, 1) == log(2) + log(x) + \ + x*(S(3)/2 - I/2) + x**2*(-1 + 3*I/4) + O(x**3) + assert log(2*x + (3 - I)*x**2)._eval_nseries(x, 3, None, -1) == -2*I*pi + log(2) + \ + log(x) - x*(-S(3)/2 + I/2) + x**2*(-1 + 3*I/4) + O(x**3) + assert log(-2*x + (3 - I)*x**2)._eval_nseries(x, 3, None, 1) == -I*pi + log(2) + log(x) + \ + x*(-S(3)/2 + I/2) + x**2*(-1 + 3*I/4) + O(x**3) + assert log(-2*x + (3 - I)*x**2)._eval_nseries(x, 3, None, -1) == -I*pi + log(2) + log(x) - \ + x*(S(3)/2 - I/2) + x**2*(-1 + 3*I/4) + O(x**3) + assert log(sqrt(-I*x**2 - 3)*sqrt(-I*x**2 - 1) - 2)._eval_nseries(x, 3, None, 1) == -I*pi + \ + log(sqrt(3) + 2) + 2*sqrt(3)*I*x**2/(3*sqrt(3) + 6) + O(x**3) + assert log(-1/(1 - x))._eval_nseries(x, 3, None, 1) == I*pi + x + x**2/2 + O(x**3) + assert log(-1/(1 - x))._eval_nseries(x, 3, None, -1) == I*pi + x + x**2/2 + O(x**3) + + +def test_log_series(): + # Note Series at infinities other than oo/-oo were introduced as a part of + # pull request 23798. Refer https://github.com/sympy/sympy/pull/23798 for + # more information. + expr1 = log(1 + x) + expr2 = log(x + sqrt(x**2 + 1)) + + assert expr1.series(x, x0=I*oo, n=4) == 1/(3*x**3) - 1/(2*x**2) + 1/x + \ + I*pi/2 - log(I/x) + O(x**(-4), (x, oo*I)) + assert expr1.series(x, x0=-I*oo, n=4) == 1/(3*x**3) - 1/(2*x**2) + 1/x - \ + I*pi/2 - log(-I/x) + O(x**(-4), (x, -oo*I)) + assert expr2.series(x, x0=I*oo, n=4) == 1/(4*x**2) + I*pi/2 + log(2) - \ + log(I/x) + O(x**(-4), (x, oo*I)) + assert expr2.series(x, x0=-I*oo, n=4) == -1/(4*x**2) - I*pi/2 - log(2) + \ + log(-I/x) + O(x**(-4), (x, -oo*I)) + + +def test_log_expand(): + w = Symbol("w", positive=True) + e = log(w**(log(5)/log(3))) + assert e.expand() == log(5)/log(3) * log(w) + x, y, z = symbols('x,y,z', positive=True) + assert log(x*(y + z)).expand(mul=False) == log(x) + log(y + z) + assert log(log(x**2)*log(y*z)).expand() in [log(2*log(x)*log(y) + + 2*log(x)*log(z)), log(log(x)*log(z) + log(y)*log(x)) + log(2), + log((log(y) + log(z))*log(x)) + log(2)] + assert log(x**log(x**2)).expand(deep=False) == log(x)*log(x**2) + assert log(x**log(x**2)).expand() == 2*log(x)**2 + x, y = symbols('x,y') + assert log(x*y).expand(force=True) == log(x) + log(y) + assert log(x**y).expand(force=True) == y*log(x) + assert log(exp(x)).expand(force=True) == x + + # there's generally no need to expand out logs since this requires + # factoring and if simplification is sought, it's cheaper to put + # logs together than it is to take them apart. + assert log(2*3**2).expand() != 2*log(3) + log(2) + + +@XFAIL +def test_log_expand_fail(): + x, y, z = symbols('x,y,z', positive=True) + assert (log(x*(y + z))*(x + y)).expand(mul=True, log=True) == y*log( + x) + y*log(y + z) + z*log(x) + z*log(y + z) + + +def test_log_simplify(): + x = Symbol("x", positive=True) + assert log(x**2).expand() == 2*log(x) + assert expand_log(log(x**(2 + log(2)))) == (2 + log(2))*log(x) + + z = Symbol('z') + assert log(sqrt(z)).expand() == log(z)/2 + assert expand_log(log(z**(log(2) - 1))) == (log(2) - 1)*log(z) + assert log(z**(-1)).expand() != -log(z) + assert log(z**(x/(x+1))).expand() == x*log(z)/(x + 1) + + +def test_log_AccumBounds(): + assert log(AccumBounds(1, E)) == AccumBounds(0, 1) + assert log(AccumBounds(0, E)) == AccumBounds(-oo, 1) + assert log(AccumBounds(-1, E)) == S.NaN + assert log(AccumBounds(0, oo)) == AccumBounds(-oo, oo) + assert log(AccumBounds(-oo, 0)) == S.NaN + assert log(AccumBounds(-oo, oo)) == S.NaN + + +@_both_exp_pow +def test_lambertw(): + k = Symbol('k') + + assert LambertW(x, 0) == LambertW(x) + assert LambertW(x, 0, evaluate=False) != LambertW(x) + assert LambertW(0) == 0 + assert LambertW(E) == 1 + assert LambertW(-1/E) == -1 + assert LambertW(-log(2)/2) == -log(2) + assert LambertW(oo) is oo + assert LambertW(0, 1) is -oo + assert LambertW(0, 42) is -oo + assert LambertW(-pi/2, -1) == -I*pi/2 + assert LambertW(-1/E, -1) == -1 + assert LambertW(-2*exp(-2), -1) == -2 + assert LambertW(2*log(2)) == log(2) + assert LambertW(-pi/2) == I*pi/2 + assert LambertW(exp(1 + E)) == E + + assert LambertW(x**2).diff(x) == 2*LambertW(x**2)/x/(1 + LambertW(x**2)) + assert LambertW(x, k).diff(x) == LambertW(x, k)/x/(1 + LambertW(x, k)) + + assert LambertW(sqrt(2)).evalf(30).epsilon_eq( + Float("0.701338383413663009202120278965", 30), 1e-29) + assert re(LambertW(2, -1)).evalf().epsilon_eq(Float("-0.834310366631110")) + + assert LambertW(-1).is_real is False # issue 5215 + assert LambertW(2, evaluate=False).is_real + p = Symbol('p', positive=True) + assert LambertW(p, evaluate=False).is_real + assert LambertW(p - 1, evaluate=False).is_real is None + assert LambertW(-p - 2/S.Exp1, evaluate=False).is_real is False + assert LambertW(S.Half, -1, evaluate=False).is_real is False + assert LambertW(Rational(-1, 10), -1, evaluate=False).is_real + assert LambertW(-10, -1, evaluate=False).is_real is False + assert LambertW(-2, 2, evaluate=False).is_real is False + + assert LambertW(0, evaluate=False).is_algebraic + na = Symbol('na', nonzero=True, algebraic=True) + assert LambertW(na).is_algebraic is False + assert LambertW(p).is_zero is False + n = Symbol('n', negative=True) + assert LambertW(n).is_zero is False + + +def test_issue_5673(): + e = LambertW(-1) + assert e.is_comparable is False + assert e.is_positive is not True + e2 = 1 - 1/(1 - exp(-1000)) + assert e2.is_positive is not True + e3 = -2 + exp(exp(LambertW(log(2)))*LambertW(log(2))) + assert e3.is_nonzero is not True + + +def test_log_fdiff(): + x = Symbol('x') + raises(ArgumentIndexError, lambda: log(x).fdiff(2)) + + +def test_log_taylor_term(): + x = symbols('x') + assert log(x).taylor_term(0, x) == x + assert log(x).taylor_term(1, x) == -x**2/2 + assert log(x).taylor_term(4, x) == x**5/5 + assert log(x).taylor_term(-1, x) is S.Zero + + +def test_exp_expand_NC(): + A, B, C = symbols('A,B,C', commutative=False) + + assert exp(A + B).expand() == exp(A + B) + assert exp(A + B + C).expand() == exp(A + B + C) + assert exp(x + y).expand() == exp(x)*exp(y) + assert exp(x + y + z).expand() == exp(x)*exp(y)*exp(z) + + +@_both_exp_pow +def test_as_numer_denom(): + n = symbols('n', negative=True) + assert exp(x).as_numer_denom() == (exp(x), 1) + assert exp(-x).as_numer_denom() == (1, exp(x)) + assert exp(-2*x).as_numer_denom() == (1, exp(2*x)) + assert exp(-2).as_numer_denom() == (1, exp(2)) + assert exp(n).as_numer_denom() == (1, exp(-n)) + assert exp(-n).as_numer_denom() == (exp(-n), 1) + assert exp(-I*x).as_numer_denom() == (1, exp(I*x)) + assert exp(-I*n).as_numer_denom() == (1, exp(I*n)) + assert exp(-n).as_numer_denom() == (exp(-n), 1) + # Check noncommutativity + a = symbols('a', commutative=False) + assert exp(-a).as_numer_denom() == (exp(-a), 1) + + +@_both_exp_pow +def test_polar(): + x, y = symbols('x y', polar=True) + + assert abs(exp_polar(I*4)) == 1 + assert abs(exp_polar(0)) == 1 + assert abs(exp_polar(2 + 3*I)) == exp(2) + assert exp_polar(I*10).n() == exp_polar(I*10) + + assert log(exp_polar(z)) == z + assert log(x*y).expand() == log(x) + log(y) + assert log(x**z).expand() == z*log(x) + + assert exp_polar(3).exp == 3 + + # Compare exp(1.0*pi*I). + assert (exp_polar(1.0*pi*I).n(n=5)).as_real_imag()[1] >= 0 + + assert exp_polar(0).is_rational is True # issue 8008 + + +def test_exp_summation(): + w = symbols("w") + m, n, i, j = symbols("m n i j") + expr = exp(Sum(w*i, (i, 0, n), (j, 0, m))) + assert expr.expand() == Product(exp(w*i), (i, 0, n), (j, 0, m)) + + +def test_log_product(): + from sympy.abc import n, m + + i, j = symbols('i,j', positive=True, integer=True) + x, y = symbols('x,y', positive=True) + z = symbols('z', real=True) + w = symbols('w') + + expr = log(Product(x**i, (i, 1, n))) + assert simplify(expr) == expr + assert expr.expand() == Sum(i*log(x), (i, 1, n)) + expr = log(Product(x**i*y**j, (i, 1, n), (j, 1, m))) + assert simplify(expr) == expr + assert expr.expand() == Sum(i*log(x) + j*log(y), (i, 1, n), (j, 1, m)) + + expr = log(Product(-2, (n, 0, 4))) + assert simplify(expr) == expr + assert expr.expand() == expr + assert expr.expand(force=True) == Sum(log(-2), (n, 0, 4)) + + expr = log(Product(exp(z*i), (i, 0, n))) + assert expr.expand() == Sum(z*i, (i, 0, n)) + + expr = log(Product(exp(w*i), (i, 0, n))) + assert expr.expand() == expr + assert expr.expand(force=True) == Sum(w*i, (i, 0, n)) + + expr = log(Product(i**2*abs(j), (i, 1, n), (j, 1, m))) + assert expr.expand() == Sum(2*log(i) + log(j), (i, 1, n), (j, 1, m)) + + +@XFAIL +def test_log_product_simplify_to_sum(): + from sympy.abc import n, m + i, j = symbols('i,j', positive=True, integer=True) + x, y = symbols('x,y', positive=True) + assert simplify(log(Product(x**i, (i, 1, n)))) == Sum(i*log(x), (i, 1, n)) + assert simplify(log(Product(x**i*y**j, (i, 1, n), (j, 1, m)))) == \ + Sum(i*log(x) + j*log(y), (i, 1, n), (j, 1, m)) + + +def test_issue_8866(): + assert simplify(log(x, 10, evaluate=False)) == simplify(log(x, 10)) + assert expand_log(log(x, 10, evaluate=False)) == expand_log(log(x, 10)) + + y = Symbol('y', positive=True) + l1 = log(exp(y), exp(10)) + b1 = log(exp(y), exp(5)) + l2 = log(exp(y), exp(10), evaluate=False) + b2 = log(exp(y), exp(5), evaluate=False) + assert simplify(log(l1, b1)) == simplify(log(l2, b2)) + assert expand_log(log(l1, b1)) == expand_log(log(l2, b2)) + + +def test_log_expand_factor(): + assert (log(18)/log(3) - 2).expand(factor=True) == log(2)/log(3) + assert (log(12)/log(2)).expand(factor=True) == log(3)/log(2) + 2 + assert (log(15)/log(3)).expand(factor=True) == 1 + log(5)/log(3) + assert (log(2)/(-log(12) + log(24))).expand(factor=True) == 1 + + assert expand_log(log(12), factor=True) == log(3) + 2*log(2) + assert expand_log(log(21)/log(7), factor=False) == log(3)/log(7) + 1 + assert expand_log(log(45)/log(5) + log(20), factor=False) == \ + 1 + 2*log(3)/log(5) + log(20) + assert expand_log(log(45)/log(5) + log(26), factor=True) == \ + log(2) + log(13) + (log(5) + 2*log(3))/log(5) + + +def test_issue_9116(): + n = Symbol('n', positive=True, integer=True) + assert log(n).is_nonnegative is True + + +def test_issue_18473(): + assert exp(x*log(cos(1/x))).as_leading_term(x) == S.NaN + assert exp(x*log(tan(1/x))).as_leading_term(x) == S.NaN + assert log(cos(1/x)).as_leading_term(x) == S.NaN + assert log(tan(1/x)).as_leading_term(x) == S.NaN + assert log(cos(1/x) + 2).as_leading_term(x) == AccumBounds(0, log(3)) + assert exp(x*log(cos(1/x) + 2)).as_leading_term(x) == 1 + assert log(cos(1/x) - 2).as_leading_term(x) == S.NaN + assert exp(x*log(cos(1/x) - 2)).as_leading_term(x) == S.NaN + assert log(cos(1/x) + 1).as_leading_term(x) == AccumBounds(-oo, log(2)) + assert exp(x*log(cos(1/x) + 1)).as_leading_term(x) == AccumBounds(0, 1) + assert log(sin(1/x)**2).as_leading_term(x) == AccumBounds(-oo, 0) + assert exp(x*log(sin(1/x)**2)).as_leading_term(x) == AccumBounds(0, 1) + assert log(tan(1/x)**2).as_leading_term(x) == AccumBounds(-oo, oo) + assert exp(2*x*(log(tan(1/x)**2))).as_leading_term(x) == AccumBounds(0, oo) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/test_hyperbolic.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/test_hyperbolic.py new file mode 100644 index 0000000000000000000000000000000000000000..1ad9f1d51598b9d605b0472e254c5a710d4ed4f5 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/test_hyperbolic.py @@ -0,0 +1,1553 @@ +from sympy.calculus.accumulationbounds import AccumBounds +from sympy.core.function import (expand_mul, expand_trig) +from sympy.core.numbers import (E, I, Integer, Rational, nan, oo, pi, zoo) +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.elementary.complexes import (im, re) +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.hyperbolic import (acosh, acoth, acsch, asech, asinh, atanh, cosh, coth, csch, sech, sinh, tanh) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (acos, asin, cos, cot, sec, sin, tan) +from sympy.series.order import O + +from sympy.core.expr import unchanged +from sympy.core.function import ArgumentIndexError, PoleError +from sympy.testing.pytest import raises + + +def test_sinh(): + x, y = symbols('x,y') + + k = Symbol('k', integer=True) + + assert sinh(nan) is nan + assert sinh(zoo) is nan + + assert sinh(oo) is oo + assert sinh(-oo) is -oo + + assert sinh(0) == 0 + + assert unchanged(sinh, 1) + assert sinh(-1) == -sinh(1) + + assert unchanged(sinh, x) + assert sinh(-x) == -sinh(x) + + assert unchanged(sinh, pi) + assert sinh(-pi) == -sinh(pi) + + assert unchanged(sinh, 2**1024 * E) + assert sinh(-2**1024 * E) == -sinh(2**1024 * E) + + assert sinh(pi*I) == 0 + assert sinh(-pi*I) == 0 + assert sinh(2*pi*I) == 0 + assert sinh(-2*pi*I) == 0 + assert sinh(-3*10**73*pi*I) == 0 + assert sinh(7*10**103*pi*I) == 0 + + assert sinh(pi*I/2) == I + assert sinh(-pi*I/2) == -I + assert sinh(pi*I*Rational(5, 2)) == I + assert sinh(pi*I*Rational(7, 2)) == -I + + assert sinh(pi*I/3) == S.Half*sqrt(3)*I + assert sinh(pi*I*Rational(-2, 3)) == Rational(-1, 2)*sqrt(3)*I + + assert sinh(pi*I/4) == S.Half*sqrt(2)*I + assert sinh(-pi*I/4) == Rational(-1, 2)*sqrt(2)*I + assert sinh(pi*I*Rational(17, 4)) == S.Half*sqrt(2)*I + assert sinh(pi*I*Rational(-3, 4)) == Rational(-1, 2)*sqrt(2)*I + + assert sinh(pi*I/6) == S.Half*I + assert sinh(-pi*I/6) == Rational(-1, 2)*I + assert sinh(pi*I*Rational(7, 6)) == Rational(-1, 2)*I + assert sinh(pi*I*Rational(-5, 6)) == Rational(-1, 2)*I + + assert sinh(pi*I/105) == sin(pi/105)*I + assert sinh(-pi*I/105) == -sin(pi/105)*I + + assert unchanged(sinh, 2 + 3*I) + + assert sinh(x*I) == sin(x)*I + + assert sinh(k*pi*I) == 0 + assert sinh(17*k*pi*I) == 0 + + assert sinh(k*pi*I/2) == sin(k*pi/2)*I + + assert sinh(x).as_real_imag(deep=False) == (cos(im(x))*sinh(re(x)), + sin(im(x))*cosh(re(x))) + x = Symbol('x', extended_real=True) + assert sinh(x).as_real_imag(deep=False) == (sinh(x), 0) + + x = Symbol('x', real=True) + assert sinh(I*x).is_finite is True + assert sinh(x).is_real is True + assert sinh(I).is_real is False + p = Symbol('p', positive=True) + assert sinh(p).is_zero is False + assert sinh(0, evaluate=False).is_zero is True + assert sinh(2*pi*I, evaluate=False).is_zero is True + + +def test_sinh_series(): + x = Symbol('x') + assert sinh(x).series(x, 0, 10) == \ + x + x**3/6 + x**5/120 + x**7/5040 + x**9/362880 + O(x**10) + + +def test_sinh_fdiff(): + x = Symbol('x') + raises(ArgumentIndexError, lambda: sinh(x).fdiff(2)) + + +def test_cosh(): + x, y = symbols('x,y') + + k = Symbol('k', integer=True) + + assert cosh(nan) is nan + assert cosh(zoo) is nan + + assert cosh(oo) is oo + assert cosh(-oo) is oo + + assert cosh(0) == 1 + + assert unchanged(cosh, 1) + assert cosh(-1) == cosh(1) + + assert unchanged(cosh, x) + assert cosh(-x) == cosh(x) + + assert cosh(pi*I) == cos(pi) + assert cosh(-pi*I) == cos(pi) + + assert unchanged(cosh, 2**1024 * E) + assert cosh(-2**1024 * E) == cosh(2**1024 * E) + + assert cosh(pi*I/2) == 0 + assert cosh(-pi*I/2) == 0 + assert cosh((-3*10**73 + 1)*pi*I/2) == 0 + assert cosh((7*10**103 + 1)*pi*I/2) == 0 + + assert cosh(pi*I) == -1 + assert cosh(-pi*I) == -1 + assert cosh(5*pi*I) == -1 + assert cosh(8*pi*I) == 1 + + assert cosh(pi*I/3) == S.Half + assert cosh(pi*I*Rational(-2, 3)) == Rational(-1, 2) + + assert cosh(pi*I/4) == S.Half*sqrt(2) + assert cosh(-pi*I/4) == S.Half*sqrt(2) + assert cosh(pi*I*Rational(11, 4)) == Rational(-1, 2)*sqrt(2) + assert cosh(pi*I*Rational(-3, 4)) == Rational(-1, 2)*sqrt(2) + + assert cosh(pi*I/6) == S.Half*sqrt(3) + assert cosh(-pi*I/6) == S.Half*sqrt(3) + assert cosh(pi*I*Rational(7, 6)) == Rational(-1, 2)*sqrt(3) + assert cosh(pi*I*Rational(-5, 6)) == Rational(-1, 2)*sqrt(3) + + assert cosh(pi*I/105) == cos(pi/105) + assert cosh(-pi*I/105) == cos(pi/105) + + assert unchanged(cosh, 2 + 3*I) + + assert cosh(x*I) == cos(x) + + assert cosh(k*pi*I) == cos(k*pi) + assert cosh(17*k*pi*I) == cos(17*k*pi) + + assert unchanged(cosh, k*pi) + + assert cosh(x).as_real_imag(deep=False) == (cos(im(x))*cosh(re(x)), + sin(im(x))*sinh(re(x))) + x = Symbol('x', extended_real=True) + assert cosh(x).as_real_imag(deep=False) == (cosh(x), 0) + + x = Symbol('x', real=True) + assert cosh(I*x).is_finite is True + assert cosh(I*x).is_real is True + assert cosh(I*2 + 1).is_real is False + assert cosh(5*I*S.Pi/2, evaluate=False).is_zero is True + assert cosh(x).is_zero is False + + +def test_cosh_series(): + x = Symbol('x') + assert cosh(x).series(x, 0, 10) == \ + 1 + x**2/2 + x**4/24 + x**6/720 + x**8/40320 + O(x**10) + + +def test_cosh_fdiff(): + x = Symbol('x') + raises(ArgumentIndexError, lambda: cosh(x).fdiff(2)) + + +def test_tanh(): + x, y = symbols('x,y') + + k = Symbol('k', integer=True) + + assert tanh(nan) is nan + assert tanh(zoo) is nan + + assert tanh(oo) == 1 + assert tanh(-oo) == -1 + + assert tanh(0) == 0 + + assert unchanged(tanh, 1) + assert tanh(-1) == -tanh(1) + + assert unchanged(tanh, x) + assert tanh(-x) == -tanh(x) + + assert unchanged(tanh, pi) + assert tanh(-pi) == -tanh(pi) + + assert unchanged(tanh, 2**1024 * E) + assert tanh(-2**1024 * E) == -tanh(2**1024 * E) + + assert tanh(pi*I) == 0 + assert tanh(-pi*I) == 0 + assert tanh(2*pi*I) == 0 + assert tanh(-2*pi*I) == 0 + assert tanh(-3*10**73*pi*I) == 0 + assert tanh(7*10**103*pi*I) == 0 + + assert tanh(pi*I/2) is zoo + assert tanh(-pi*I/2) is zoo + assert tanh(pi*I*Rational(5, 2)) is zoo + assert tanh(pi*I*Rational(7, 2)) is zoo + + assert tanh(pi*I/3) == sqrt(3)*I + assert tanh(pi*I*Rational(-2, 3)) == sqrt(3)*I + + assert tanh(pi*I/4) == I + assert tanh(-pi*I/4) == -I + assert tanh(pi*I*Rational(17, 4)) == I + assert tanh(pi*I*Rational(-3, 4)) == I + + assert tanh(pi*I/6) == I/sqrt(3) + assert tanh(-pi*I/6) == -I/sqrt(3) + assert tanh(pi*I*Rational(7, 6)) == I/sqrt(3) + assert tanh(pi*I*Rational(-5, 6)) == I/sqrt(3) + + assert tanh(pi*I/105) == tan(pi/105)*I + assert tanh(-pi*I/105) == -tan(pi/105)*I + + assert unchanged(tanh, 2 + 3*I) + + assert tanh(x*I) == tan(x)*I + + assert tanh(k*pi*I) == 0 + assert tanh(17*k*pi*I) == 0 + + assert tanh(k*pi*I/2) == tan(k*pi/2)*I + + assert tanh(x).as_real_imag(deep=False) == (sinh(re(x))*cosh(re(x))/(cos(im(x))**2 + + sinh(re(x))**2), + sin(im(x))*cos(im(x))/(cos(im(x))**2 + sinh(re(x))**2)) + x = Symbol('x', extended_real=True) + assert tanh(x).as_real_imag(deep=False) == (tanh(x), 0) + assert tanh(I*pi/3 + 1).is_real is False + assert tanh(x).is_real is True + assert tanh(I*pi*x/2).is_real is None + + +def test_tanh_series(): + x = Symbol('x') + assert tanh(x).series(x, 0, 10) == \ + x - x**3/3 + 2*x**5/15 - 17*x**7/315 + 62*x**9/2835 + O(x**10) + + +def test_tanh_fdiff(): + x = Symbol('x') + raises(ArgumentIndexError, lambda: tanh(x).fdiff(2)) + + +def test_coth(): + x, y = symbols('x,y') + + k = Symbol('k', integer=True) + + assert coth(nan) is nan + assert coth(zoo) is nan + + assert coth(oo) == 1 + assert coth(-oo) == -1 + + assert coth(0) is zoo + assert unchanged(coth, 1) + assert coth(-1) == -coth(1) + + assert unchanged(coth, x) + assert coth(-x) == -coth(x) + + assert coth(pi*I) == -I*cot(pi) + assert coth(-pi*I) == cot(pi)*I + + assert unchanged(coth, 2**1024 * E) + assert coth(-2**1024 * E) == -coth(2**1024 * E) + + assert coth(pi*I) == -I*cot(pi) + assert coth(-pi*I) == I*cot(pi) + assert coth(2*pi*I) == -I*cot(2*pi) + assert coth(-2*pi*I) == I*cot(2*pi) + assert coth(-3*10**73*pi*I) == I*cot(3*10**73*pi) + assert coth(7*10**103*pi*I) == -I*cot(7*10**103*pi) + + assert coth(pi*I/2) == 0 + assert coth(-pi*I/2) == 0 + assert coth(pi*I*Rational(5, 2)) == 0 + assert coth(pi*I*Rational(7, 2)) == 0 + + assert coth(pi*I/3) == -I/sqrt(3) + assert coth(pi*I*Rational(-2, 3)) == -I/sqrt(3) + + assert coth(pi*I/4) == -I + assert coth(-pi*I/4) == I + assert coth(pi*I*Rational(17, 4)) == -I + assert coth(pi*I*Rational(-3, 4)) == -I + + assert coth(pi*I/6) == -sqrt(3)*I + assert coth(-pi*I/6) == sqrt(3)*I + assert coth(pi*I*Rational(7, 6)) == -sqrt(3)*I + assert coth(pi*I*Rational(-5, 6)) == -sqrt(3)*I + + assert coth(pi*I/105) == -cot(pi/105)*I + assert coth(-pi*I/105) == cot(pi/105)*I + + assert unchanged(coth, 2 + 3*I) + + assert coth(x*I) == -cot(x)*I + + assert coth(k*pi*I) == -cot(k*pi)*I + assert coth(17*k*pi*I) == -cot(17*k*pi)*I + + assert coth(k*pi*I) == -cot(k*pi)*I + + assert coth(log(tan(2))) == coth(log(-tan(2))) + assert coth(1 + I*pi/2) == tanh(1) + + assert coth(x).as_real_imag(deep=False) == (sinh(re(x))*cosh(re(x))/(sin(im(x))**2 + + sinh(re(x))**2), + -sin(im(x))*cos(im(x))/(sin(im(x))**2 + sinh(re(x))**2)) + x = Symbol('x', extended_real=True) + assert coth(x).as_real_imag(deep=False) == (coth(x), 0) + + assert expand_trig(coth(2*x)) == (coth(x)**2 + 1)/(2*coth(x)) + assert expand_trig(coth(3*x)) == (coth(x)**3 + 3*coth(x))/(1 + 3*coth(x)**2) + + assert expand_trig(coth(x + y)) == (1 + coth(x)*coth(y))/(coth(x) + coth(y)) + + +def test_coth_series(): + x = Symbol('x') + assert coth(x).series(x, 0, 8) == \ + 1/x + x/3 - x**3/45 + 2*x**5/945 - x**7/4725 + O(x**8) + + +def test_coth_fdiff(): + x = Symbol('x') + raises(ArgumentIndexError, lambda: coth(x).fdiff(2)) + + +def test_csch(): + x, y = symbols('x,y') + + k = Symbol('k', integer=True) + n = Symbol('n', positive=True) + + assert csch(nan) is nan + assert csch(zoo) is nan + + assert csch(oo) == 0 + assert csch(-oo) == 0 + + assert csch(0) is zoo + + assert csch(-1) == -csch(1) + + assert csch(-x) == -csch(x) + assert csch(-pi) == -csch(pi) + assert csch(-2**1024 * E) == -csch(2**1024 * E) + + assert csch(pi*I) is zoo + assert csch(-pi*I) is zoo + assert csch(2*pi*I) is zoo + assert csch(-2*pi*I) is zoo + assert csch(-3*10**73*pi*I) is zoo + assert csch(7*10**103*pi*I) is zoo + + assert csch(pi*I/2) == -I + assert csch(-pi*I/2) == I + assert csch(pi*I*Rational(5, 2)) == -I + assert csch(pi*I*Rational(7, 2)) == I + + assert csch(pi*I/3) == -2/sqrt(3)*I + assert csch(pi*I*Rational(-2, 3)) == 2/sqrt(3)*I + + assert csch(pi*I/4) == -sqrt(2)*I + assert csch(-pi*I/4) == sqrt(2)*I + assert csch(pi*I*Rational(7, 4)) == sqrt(2)*I + assert csch(pi*I*Rational(-3, 4)) == sqrt(2)*I + + assert csch(pi*I/6) == -2*I + assert csch(-pi*I/6) == 2*I + assert csch(pi*I*Rational(7, 6)) == 2*I + assert csch(pi*I*Rational(-7, 6)) == -2*I + assert csch(pi*I*Rational(-5, 6)) == 2*I + + assert csch(pi*I/105) == -1/sin(pi/105)*I + assert csch(-pi*I/105) == 1/sin(pi/105)*I + + assert csch(x*I) == -1/sin(x)*I + + assert csch(k*pi*I) is zoo + assert csch(17*k*pi*I) is zoo + + assert csch(k*pi*I/2) == -1/sin(k*pi/2)*I + + assert csch(n).is_real is True + + assert expand_trig(csch(x + y)) == 1/(sinh(x)*cosh(y) + cosh(x)*sinh(y)) + + +def test_csch_series(): + x = Symbol('x') + assert csch(x).series(x, 0, 10) == \ + 1/ x - x/6 + 7*x**3/360 - 31*x**5/15120 + 127*x**7/604800 \ + - 73*x**9/3421440 + O(x**10) + + +def test_csch_fdiff(): + x = Symbol('x') + raises(ArgumentIndexError, lambda: csch(x).fdiff(2)) + + +def test_sech(): + x, y = symbols('x, y') + + k = Symbol('k', integer=True) + n = Symbol('n', positive=True) + + assert sech(nan) is nan + assert sech(zoo) is nan + + assert sech(oo) == 0 + assert sech(-oo) == 0 + + assert sech(0) == 1 + + assert sech(-1) == sech(1) + assert sech(-x) == sech(x) + + assert sech(pi*I) == sec(pi) + + assert sech(-pi*I) == sec(pi) + assert sech(-2**1024 * E) == sech(2**1024 * E) + + assert sech(pi*I/2) is zoo + assert sech(-pi*I/2) is zoo + assert sech((-3*10**73 + 1)*pi*I/2) is zoo + assert sech((7*10**103 + 1)*pi*I/2) is zoo + + assert sech(pi*I) == -1 + assert sech(-pi*I) == -1 + assert sech(5*pi*I) == -1 + assert sech(8*pi*I) == 1 + + assert sech(pi*I/3) == 2 + assert sech(pi*I*Rational(-2, 3)) == -2 + + assert sech(pi*I/4) == sqrt(2) + assert sech(-pi*I/4) == sqrt(2) + assert sech(pi*I*Rational(5, 4)) == -sqrt(2) + assert sech(pi*I*Rational(-5, 4)) == -sqrt(2) + + assert sech(pi*I/6) == 2/sqrt(3) + assert sech(-pi*I/6) == 2/sqrt(3) + assert sech(pi*I*Rational(7, 6)) == -2/sqrt(3) + assert sech(pi*I*Rational(-5, 6)) == -2/sqrt(3) + + assert sech(pi*I/105) == 1/cos(pi/105) + assert sech(-pi*I/105) == 1/cos(pi/105) + + assert sech(x*I) == 1/cos(x) + + assert sech(k*pi*I) == 1/cos(k*pi) + assert sech(17*k*pi*I) == 1/cos(17*k*pi) + + assert sech(n).is_real is True + + assert expand_trig(sech(x + y)) == 1/(cosh(x)*cosh(y) + sinh(x)*sinh(y)) + + +def test_sech_series(): + x = Symbol('x') + assert sech(x).series(x, 0, 10) == \ + 1 - x**2/2 + 5*x**4/24 - 61*x**6/720 + 277*x**8/8064 + O(x**10) + + +def test_sech_fdiff(): + x = Symbol('x') + raises(ArgumentIndexError, lambda: sech(x).fdiff(2)) + + +def test_asinh(): + x, y = symbols('x,y') + assert unchanged(asinh, x) + assert asinh(-x) == -asinh(x) + + # at specific points + assert asinh(nan) is nan + assert asinh( 0) == 0 + assert asinh(+1) == log(sqrt(2) + 1) + + assert asinh(-1) == log(sqrt(2) - 1) + assert asinh(I) == pi*I/2 + assert asinh(-I) == -pi*I/2 + assert asinh(I/2) == pi*I/6 + assert asinh(-I/2) == -pi*I/6 + + # at infinites + assert asinh(oo) is oo + assert asinh(-oo) is -oo + + assert asinh(I*oo) is oo + assert asinh(-I *oo) is -oo + + assert asinh(zoo) is zoo + + # properties + assert asinh(I *(sqrt(3) - 1)/(2**Rational(3, 2))) == pi*I/12 + assert asinh(-I *(sqrt(3) - 1)/(2**Rational(3, 2))) == -pi*I/12 + + assert asinh(I*(sqrt(5) - 1)/4) == pi*I/10 + assert asinh(-I*(sqrt(5) - 1)/4) == -pi*I/10 + + assert asinh(I*(sqrt(5) + 1)/4) == pi*I*Rational(3, 10) + assert asinh(-I*(sqrt(5) + 1)/4) == pi*I*Rational(-3, 10) + + # reality + assert asinh(S(2)).is_real is True + assert asinh(S(2)).is_finite is True + assert asinh(S(-2)).is_real is True + assert asinh(S(oo)).is_extended_real is True + assert asinh(-S(oo)).is_real is False + assert (asinh(2) - oo) == -oo + assert asinh(symbols('y', real=True)).is_real is True + + # Symmetry + assert asinh(Rational(-1, 2)) == -asinh(S.Half) + + # inverse composition + assert unchanged(asinh, sinh(Symbol('v1'))) + + assert asinh(sinh(0, evaluate=False)) == 0 + assert asinh(sinh(-3, evaluate=False)) == -3 + assert asinh(sinh(2, evaluate=False)) == 2 + assert asinh(sinh(I, evaluate=False)) == I + assert asinh(sinh(-I, evaluate=False)) == -I + assert asinh(sinh(5*I, evaluate=False)) == -2*I*pi + 5*I + assert asinh(sinh(15 + 11*I)) == 15 - 4*I*pi + 11*I + assert asinh(sinh(-73 + 97*I)) == 73 - 97*I + 31*I*pi + assert asinh(sinh(-7 - 23*I)) == 7 - 7*I*pi + 23*I + assert asinh(sinh(13 - 3*I)) == -13 - I*pi + 3*I + p = Symbol('p', positive=True) + assert asinh(p).is_zero is False + assert asinh(sinh(0, evaluate=False), evaluate=False).is_zero is True + + +def test_asinh_rewrite(): + x = Symbol('x') + assert asinh(x).rewrite(log) == log(x + sqrt(x**2 + 1)) + assert asinh(x).rewrite(atanh) == atanh(x/sqrt(1 + x**2)) + assert asinh(x).rewrite(asin) == -I*asin(I*x, evaluate=False) + assert asinh(x*(1 + I)).rewrite(asin) == -I*asin(I*x*(1+I)) + assert asinh(x).rewrite(acos) == I*acos(I*x, evaluate=False) - I*pi/2 + + +def test_asinh_leading_term(): + x = Symbol('x') + assert asinh(x).as_leading_term(x, cdir=1) == x + # Tests concerning branch points + assert asinh(x + I).as_leading_term(x, cdir=1) == I*pi/2 + assert asinh(x - I).as_leading_term(x, cdir=1) == -I*pi/2 + assert asinh(1/x).as_leading_term(x, cdir=1) == -log(x) + log(2) + assert asinh(1/x).as_leading_term(x, cdir=-1) == log(x) - log(2) - I*pi + # Tests concerning points lying on branch cuts + assert asinh(x + 2*I).as_leading_term(x, cdir=1) == I*asin(2) + assert asinh(x + 2*I).as_leading_term(x, cdir=-1) == -I*asin(2) + I*pi + assert asinh(x - 2*I).as_leading_term(x, cdir=1) == -I*pi + I*asin(2) + assert asinh(x - 2*I).as_leading_term(x, cdir=-1) == -I*asin(2) + # Tests concerning re(ndir) == 0 + assert asinh(2*I + I*x - x**2).as_leading_term(x, cdir=1) == log(2 - sqrt(3)) + I*pi/2 + assert asinh(2*I + I*x - x**2).as_leading_term(x, cdir=-1) == log(2 - sqrt(3)) + I*pi/2 + + +def test_asinh_series(): + x = Symbol('x') + assert asinh(x).series(x, 0, 8) == \ + x - x**3/6 + 3*x**5/40 - 5*x**7/112 + O(x**8) + t5 = asinh(x).taylor_term(5, x) + assert t5 == 3*x**5/40 + assert asinh(x).taylor_term(7, x, t5, 0) == -5*x**7/112 + + +def test_asinh_nseries(): + x = Symbol('x') + # Tests concerning branch points + assert asinh(x + I)._eval_nseries(x, 4, None) == I*pi/2 - \ + sqrt(2)*sqrt(I)*I*sqrt(x) + sqrt(2)*sqrt(I)*x**(S(3)/2)/12 + 3*sqrt(2)*sqrt(I)*I*x**(S(5)/2)/160 - \ + 5*sqrt(2)*sqrt(I)*x**(S(7)/2)/896 + O(x**4) + assert asinh(x - I)._eval_nseries(x, 4, None) == -I*pi/2 + \ + sqrt(2)*I*sqrt(x)*sqrt(-I) + sqrt(2)*x**(S(3)/2)*sqrt(-I)/12 - \ + 3*sqrt(2)*I*x**(S(5)/2)*sqrt(-I)/160 - 5*sqrt(2)*x**(S(7)/2)*sqrt(-I)/896 + O(x**4) + # Tests concerning points lying on branch cuts + assert asinh(x + 2*I)._eval_nseries(x, 4, None, cdir=1) == I*asin(2) - \ + sqrt(3)*I*x/3 + sqrt(3)*x**2/9 + sqrt(3)*I*x**3/18 + O(x**4) + assert asinh(x + 2*I)._eval_nseries(x, 4, None, cdir=-1) == I*pi - I*asin(2) + \ + sqrt(3)*I*x/3 - sqrt(3)*x**2/9 - sqrt(3)*I*x**3/18 + O(x**4) + assert asinh(x - 2*I)._eval_nseries(x, 4, None, cdir=1) == I*asin(2) - I*pi + \ + sqrt(3)*I*x/3 + sqrt(3)*x**2/9 - sqrt(3)*I*x**3/18 + O(x**4) + assert asinh(x - 2*I)._eval_nseries(x, 4, None, cdir=-1) == -I*asin(2) - \ + sqrt(3)*I*x/3 - sqrt(3)*x**2/9 + sqrt(3)*I*x**3/18 + O(x**4) + # Tests concerning re(ndir) == 0 + assert asinh(2*I + I*x - x**2)._eval_nseries(x, 4, None) == I*pi/2 + log(2 - sqrt(3)) + \ + x*(-3 + 2*sqrt(3))/(-6 + 3*sqrt(3)) + x**2*(12 - 36*I + sqrt(3)*(-7 + 21*I))/(-63 + \ + 36*sqrt(3)) + x**3*(-168 + sqrt(3)*(97 - 388*I) + 672*I)/(-1746 + 1008*sqrt(3)) + O(x**4) + + +def test_asinh_fdiff(): + x = Symbol('x') + raises(ArgumentIndexError, lambda: asinh(x).fdiff(2)) + + +def test_acosh(): + x = Symbol('x') + + assert unchanged(acosh, -x) + + #at specific points + assert acosh(1) == 0 + assert acosh(-1) == pi*I + assert acosh(0) == I*pi/2 + assert acosh(S.Half) == I*pi/3 + assert acosh(Rational(-1, 2)) == pi*I*Rational(2, 3) + assert acosh(nan) is nan + + # at infinites + assert acosh(oo) is oo + assert acosh(-oo) is oo + + assert acosh(I*oo) == oo + I*pi/2 + assert acosh(-I*oo) == oo - I*pi/2 + + assert acosh(zoo) is zoo + + assert acosh(I) == log(I*(1 + sqrt(2))) + assert acosh(-I) == log(-I*(1 + sqrt(2))) + assert acosh((sqrt(3) - 1)/(2*sqrt(2))) == pi*I*Rational(5, 12) + assert acosh(-(sqrt(3) - 1)/(2*sqrt(2))) == pi*I*Rational(7, 12) + assert acosh(sqrt(2)/2) == I*pi/4 + assert acosh(-sqrt(2)/2) == I*pi*Rational(3, 4) + assert acosh(sqrt(3)/2) == I*pi/6 + assert acosh(-sqrt(3)/2) == I*pi*Rational(5, 6) + assert acosh(sqrt(2 + sqrt(2))/2) == I*pi/8 + assert acosh(-sqrt(2 + sqrt(2))/2) == I*pi*Rational(7, 8) + assert acosh(sqrt(2 - sqrt(2))/2) == I*pi*Rational(3, 8) + assert acosh(-sqrt(2 - sqrt(2))/2) == I*pi*Rational(5, 8) + assert acosh((1 + sqrt(3))/(2*sqrt(2))) == I*pi/12 + assert acosh(-(1 + sqrt(3))/(2*sqrt(2))) == I*pi*Rational(11, 12) + assert acosh((sqrt(5) + 1)/4) == I*pi/5 + assert acosh(-(sqrt(5) + 1)/4) == I*pi*Rational(4, 5) + + assert str(acosh(5*I).n(6)) == '2.31244 + 1.5708*I' + assert str(acosh(-5*I).n(6)) == '2.31244 - 1.5708*I' + + # inverse composition + assert unchanged(acosh, Symbol('v1')) + + assert acosh(cosh(-3, evaluate=False)) == 3 + assert acosh(cosh(3, evaluate=False)) == 3 + assert acosh(cosh(0, evaluate=False)) == 0 + assert acosh(cosh(I, evaluate=False)) == I + assert acosh(cosh(-I, evaluate=False)) == I + assert acosh(cosh(7*I, evaluate=False)) == -2*I*pi + 7*I + assert acosh(cosh(1 + I)) == 1 + I + assert acosh(cosh(3 - 3*I)) == 3 - 3*I + assert acosh(cosh(-3 + 2*I)) == 3 - 2*I + assert acosh(cosh(-5 - 17*I)) == 5 - 6*I*pi + 17*I + assert acosh(cosh(-21 + 11*I)) == 21 - 11*I + 4*I*pi + assert acosh(cosh(cosh(1) + I)) == cosh(1) + I + assert acosh(1, evaluate=False).is_zero is True + + # Reality + assert acosh(S(2)).is_real is True + assert acosh(S(2)).is_extended_real is True + assert acosh(oo).is_extended_real is True + assert acosh(S(2)).is_finite is True + assert acosh(S(1) / 5).is_real is False + assert (acosh(2) - oo) == -oo + assert acosh(symbols('y', real=True)).is_real is None + + +def test_acosh_rewrite(): + x = Symbol('x') + assert acosh(x).rewrite(log) == log(x + sqrt(x - 1)*sqrt(x + 1)) + assert acosh(x).rewrite(asin) == sqrt(x - 1)*(-asin(x) + pi/2)/sqrt(1 - x) + assert acosh(x).rewrite(asinh) == sqrt(x - 1)*(I*asinh(I*x, evaluate=False) + pi/2)/sqrt(1 - x) + assert acosh(x).rewrite(atanh) == \ + (sqrt(x - 1)*sqrt(x + 1)*atanh(sqrt(x**2 - 1)/x)/sqrt(x**2 - 1) + + pi*sqrt(x - 1)*(-x*sqrt(x**(-2)) + 1)/(2*sqrt(1 - x))) + x = Symbol('x', positive=True) + assert acosh(x).rewrite(atanh) == \ + sqrt(x - 1)*sqrt(x + 1)*atanh(sqrt(x**2 - 1)/x)/sqrt(x**2 - 1) + + +def test_acosh_leading_term(): + x = Symbol('x') + # Tests concerning branch points + assert acosh(x).as_leading_term(x) == I*pi/2 + assert acosh(x + 1).as_leading_term(x) == sqrt(2)*sqrt(x) + assert acosh(x - 1).as_leading_term(x) == I*pi + assert acosh(1/x).as_leading_term(x, cdir=1) == -log(x) + log(2) + assert acosh(1/x).as_leading_term(x, cdir=-1) == -log(x) + log(2) + 2*I*pi + # Tests concerning points lying on branch cuts + assert acosh(I*x - 2).as_leading_term(x, cdir=1) == acosh(-2) + assert acosh(-I*x - 2).as_leading_term(x, cdir=1) == -2*I*pi + acosh(-2) + assert acosh(x**2 - I*x + S(1)/3).as_leading_term(x, cdir=1) == -acosh(S(1)/3) + assert acosh(x**2 - I*x + S(1)/3).as_leading_term(x, cdir=-1) == acosh(S(1)/3) + assert acosh(1/(I*x - 3)).as_leading_term(x, cdir=1) == -acosh(-S(1)/3) + assert acosh(1/(I*x - 3)).as_leading_term(x, cdir=-1) == acosh(-S(1)/3) + # Tests concerning im(ndir) == 0 + assert acosh(-I*x**2 + x - 2).as_leading_term(x, cdir=1) == log(sqrt(3) + 2) - I*pi + assert acosh(-I*x**2 + x - 2).as_leading_term(x, cdir=-1) == log(sqrt(3) + 2) - I*pi + + +def test_acosh_series(): + x = Symbol('x') + assert acosh(x).series(x, 0, 8) == \ + -I*x + pi*I/2 - I*x**3/6 - 3*I*x**5/40 - 5*I*x**7/112 + O(x**8) + t5 = acosh(x).taylor_term(5, x) + assert t5 == - 3*I*x**5/40 + assert acosh(x).taylor_term(7, x, t5, 0) == - 5*I*x**7/112 + + +def test_acosh_nseries(): + x = Symbol('x') + # Tests concerning branch points + assert acosh(x + 1)._eval_nseries(x, 4, None) == sqrt(2)*sqrt(x) - \ + sqrt(2)*x**(S(3)/2)/12 + 3*sqrt(2)*x**(S(5)/2)/160 - 5*sqrt(2)*x**(S(7)/2)/896 + O(x**4) + # Tests concerning points lying on branch cuts + assert acosh(x - 1)._eval_nseries(x, 4, None) == I*pi - \ + sqrt(2)*I*sqrt(x) - sqrt(2)*I*x**(S(3)/2)/12 - 3*sqrt(2)*I*x**(S(5)/2)/160 - \ + 5*sqrt(2)*I*x**(S(7)/2)/896 + O(x**4) + assert acosh(I*x - 2)._eval_nseries(x, 4, None, cdir=1) == acosh(-2) - \ + sqrt(3)*I*x/3 + sqrt(3)*x**2/9 + sqrt(3)*I*x**3/18 + O(x**4) + assert acosh(-I*x - 2)._eval_nseries(x, 4, None, cdir=1) == acosh(-2) - \ + 2*I*pi + sqrt(3)*I*x/3 + sqrt(3)*x**2/9 - sqrt(3)*I*x**3/18 + O(x**4) + assert acosh(1/(I*x - 3))._eval_nseries(x, 4, None, cdir=1) == -acosh(-S(1)/3) + \ + sqrt(2)*x/12 + 17*sqrt(2)*I*x**2/576 - 443*sqrt(2)*x**3/41472 + O(x**4) + assert acosh(1/(I*x - 3))._eval_nseries(x, 4, None, cdir=-1) == acosh(-S(1)/3) - \ + sqrt(2)*x/12 - 17*sqrt(2)*I*x**2/576 + 443*sqrt(2)*x**3/41472 + O(x**4) + # Tests concerning im(ndir) == 0 + assert acosh(-I*x**2 + x - 2)._eval_nseries(x, 4, None) == -I*pi + log(sqrt(3) + 2) + \ + x*(-2*sqrt(3) - 3)/(3*sqrt(3) + 6) + x**2*(-12 + 36*I + sqrt(3)*(-7 + 21*I))/(36*sqrt(3) + \ + 63) + x**3*(-168 + 672*I + sqrt(3)*(-97 + 388*I))/(1008*sqrt(3) + 1746) + O(x**4) + + +def test_acosh_fdiff(): + x = Symbol('x') + raises(ArgumentIndexError, lambda: acosh(x).fdiff(2)) + + +def test_asech(): + x = Symbol('x') + + assert unchanged(asech, -x) + + # values at fixed points + assert asech(1) == 0 + assert asech(-1) == pi*I + assert asech(0) is oo + assert asech(2) == I*pi/3 + assert asech(-2) == 2*I*pi / 3 + assert asech(nan) is nan + + # at infinites + assert asech(oo) == I*pi/2 + assert asech(-oo) == I*pi/2 + assert asech(zoo) == I*AccumBounds(-pi/2, pi/2) + + assert asech(I) == log(1 + sqrt(2)) - I*pi/2 + assert asech(-I) == log(1 + sqrt(2)) + I*pi/2 + assert asech(sqrt(2) - sqrt(6)) == 11*I*pi / 12 + assert asech(sqrt(2 - 2/sqrt(5))) == I*pi / 10 + assert asech(-sqrt(2 - 2/sqrt(5))) == 9*I*pi / 10 + assert asech(2 / sqrt(2 + sqrt(2))) == I*pi / 8 + assert asech(-2 / sqrt(2 + sqrt(2))) == 7*I*pi / 8 + assert asech(sqrt(5) - 1) == I*pi / 5 + assert asech(1 - sqrt(5)) == 4*I*pi / 5 + assert asech(-sqrt(2*(2 + sqrt(2)))) == 5*I*pi / 8 + + # properties + # asech(x) == acosh(1/x) + assert asech(sqrt(2)) == acosh(1/sqrt(2)) + assert asech(2/sqrt(3)) == acosh(sqrt(3)/2) + assert asech(2/sqrt(2 + sqrt(2))) == acosh(sqrt(2 + sqrt(2))/2) + assert asech(2) == acosh(S.Half) + + # reality + assert asech(S(2)).is_real is False + assert asech(-S(1) / 3).is_real is False + assert asech(S(2) / 3).is_finite is True + assert asech(S(0)).is_real is False + assert asech(S(0)).is_extended_real is True + assert asech(symbols('y', real=True)).is_real is None + + # asech(x) == I*acos(1/x) + # (Note: the exact formula is asech(x) == +/- I*acos(1/x)) + assert asech(-sqrt(2)) == I*acos(-1/sqrt(2)) + assert asech(-2/sqrt(3)) == I*acos(-sqrt(3)/2) + assert asech(-S(2)) == I*acos(Rational(-1, 2)) + assert asech(-2/sqrt(2)) == I*acos(-sqrt(2)/2) + + # sech(asech(x)) / x == 1 + assert expand_mul(sech(asech(sqrt(6) - sqrt(2))) / (sqrt(6) - sqrt(2))) == 1 + assert expand_mul(sech(asech(sqrt(6) + sqrt(2))) / (sqrt(6) + sqrt(2))) == 1 + assert (sech(asech(sqrt(2 + 2/sqrt(5)))) / (sqrt(2 + 2/sqrt(5)))).simplify() == 1 + assert (sech(asech(-sqrt(2 + 2/sqrt(5)))) / (-sqrt(2 + 2/sqrt(5)))).simplify() == 1 + assert (sech(asech(sqrt(2*(2 + sqrt(2))))) / (sqrt(2*(2 + sqrt(2))))).simplify() == 1 + assert expand_mul(sech(asech(1 + sqrt(5))) / (1 + sqrt(5))) == 1 + assert expand_mul(sech(asech(-1 - sqrt(5))) / (-1 - sqrt(5))) == 1 + assert expand_mul(sech(asech(-sqrt(6) - sqrt(2))) / (-sqrt(6) - sqrt(2))) == 1 + + # numerical evaluation + assert str(asech(5*I).n(6)) == '0.19869 - 1.5708*I' + assert str(asech(-5*I).n(6)) == '0.19869 + 1.5708*I' + + +def test_asech_leading_term(): + x = Symbol('x') + # Tests concerning branch points + assert asech(x).as_leading_term(x, cdir=1) == -log(x) + log(2) + assert asech(x).as_leading_term(x, cdir=-1) == -log(x) + log(2) + 2*I*pi + assert asech(x + 1).as_leading_term(x, cdir=1) == sqrt(2)*I*sqrt(x) + assert asech(1/x).as_leading_term(x, cdir=1) == I*pi/2 + # Tests concerning points lying on branch cuts + assert asech(x - 1).as_leading_term(x, cdir=1) == I*pi + assert asech(I*x + 3).as_leading_term(x, cdir=1) == -asech(3) + assert asech(-I*x + 3).as_leading_term(x, cdir=1) == asech(3) + assert asech(I*x - 3).as_leading_term(x, cdir=1) == -asech(-3) + assert asech(-I*x - 3).as_leading_term(x, cdir=1) == asech(-3) + assert asech(I*x - S(1)/3).as_leading_term(x, cdir=1) == -2*I*pi + asech(-S(1)/3) + assert asech(I*x - S(1)/3).as_leading_term(x, cdir=-1) == asech(-S(1)/3) + # Tests concerning im(ndir) == 0 + assert asech(-I*x**2 + x - 3).as_leading_term(x, cdir=1) == log(-S(1)/3 + 2*sqrt(2)*I/3) + assert asech(-I*x**2 + x - 3).as_leading_term(x, cdir=-1) == log(-S(1)/3 + 2*sqrt(2)*I/3) + + +def test_asech_series(): + x = Symbol('x') + assert asech(x).series(x, 0, 9, cdir=1) == log(2) - log(x) - x**2/4 - 3*x**4/32 \ + - 5*x**6/96 - 35*x**8/1024 + O(x**9) + assert asech(x).series(x, 0, 9, cdir=-1) == I*pi + log(2) - log(-x) - x**2/4 - \ + 3*x**4/32 - 5*x**6/96 - 35*x**8/1024 + O(x**9) + t6 = asech(x).taylor_term(6, x) + assert t6 == -5*x**6/96 + assert asech(x).taylor_term(8, x, t6, 0) == -35*x**8/1024 + + +def test_asech_nseries(): + x = Symbol('x') + # Tests concerning branch points + assert asech(x + 1)._eval_nseries(x, 4, None) == sqrt(2)*sqrt(-x) + 5*sqrt(2)*(-x)**(S(3)/2)/12 + \ + 43*sqrt(2)*(-x)**(S(5)/2)/160 + 177*sqrt(2)*(-x)**(S(7)/2)/896 + O(x**4) + # Tests concerning points lying on branch cuts + assert asech(x - 1)._eval_nseries(x, 4, None) == I*pi + sqrt(2)*sqrt(x) + \ + 5*sqrt(2)*x**(S(3)/2)/12 + 43*sqrt(2)*x**(S(5)/2)/160 + 177*sqrt(2)*x**(S(7)/2)/896 + O(x**4) + assert asech(I*x + 3)._eval_nseries(x, 4, None) == -asech(3) + sqrt(2)*x/12 - \ + 17*sqrt(2)*I*x**2/576 - 443*sqrt(2)*x**3/41472 + O(x**4) + assert asech(-I*x + 3)._eval_nseries(x, 4, None) == asech(3) + sqrt(2)*x/12 + \ + 17*sqrt(2)*I*x**2/576 - 443*sqrt(2)*x**3/41472 + O(x**4) + assert asech(I*x - 3)._eval_nseries(x, 4, None) == -asech(-3) - sqrt(2)*x/12 - \ + 17*sqrt(2)*I*x**2/576 + 443*sqrt(2)*x**3/41472 + O(x**4) + assert asech(-I*x - 3)._eval_nseries(x, 4, None) == asech(-3) - sqrt(2)*x/12 + \ + 17*sqrt(2)*I*x**2/576 + 443*sqrt(2)*x**3/41472 + O(x**4) + # Tests concerning im(ndir) == 0 + assert asech(-I*x**2 + x - 2)._eval_nseries(x, 3, None) == 2*I*pi/3 + \ + x*(-sqrt(3) + 3*I)/(6*sqrt(3) + 6*I) + x**2*(36 + sqrt(3)*(7 - 12*I) + 21*I)/(72*sqrt(3) - \ + 72*I) + O(x**3) + + +def test_asech_rewrite(): + x = Symbol('x') + assert asech(x).rewrite(log) == log(1/x + sqrt(1/x - 1) * sqrt(1/x + 1)) + assert asech(x).rewrite(acosh) == acosh(1/x) + assert asech(x).rewrite(asinh) == sqrt(-1 + 1/x)*(I*asinh(I/x, evaluate=False) + pi/2)/sqrt(1 - 1/x) + assert asech(x).rewrite(atanh) == \ + sqrt(x + 1)*sqrt(1/(x + 1))*atanh(sqrt(1 - x**2)) + I*pi*(-sqrt(x)*sqrt(1/x) + 1 - I*sqrt(x**2)/(2*sqrt(-x**2)) - I*sqrt(-x)/(2*sqrt(x))) + + +def test_asech_fdiff(): + x = Symbol('x') + raises(ArgumentIndexError, lambda: asech(x).fdiff(2)) + + +def test_acsch(): + x = Symbol('x') + + assert unchanged(acsch, x) + assert acsch(-x) == -acsch(x) + + # values at fixed points + assert acsch(1) == log(1 + sqrt(2)) + assert acsch(-1) == - log(1 + sqrt(2)) + assert acsch(0) is zoo + assert acsch(2) == log((1+sqrt(5))/2) + assert acsch(-2) == - log((1+sqrt(5))/2) + + assert acsch(I) == - I*pi/2 + assert acsch(-I) == I*pi/2 + assert acsch(-I*(sqrt(6) + sqrt(2))) == I*pi / 12 + assert acsch(I*(sqrt(2) + sqrt(6))) == -I*pi / 12 + assert acsch(-I*(1 + sqrt(5))) == I*pi / 10 + assert acsch(I*(1 + sqrt(5))) == -I*pi / 10 + assert acsch(-I*2 / sqrt(2 - sqrt(2))) == I*pi / 8 + assert acsch(I*2 / sqrt(2 - sqrt(2))) == -I*pi / 8 + assert acsch(-I*2) == I*pi / 6 + assert acsch(I*2) == -I*pi / 6 + assert acsch(-I*sqrt(2 + 2/sqrt(5))) == I*pi / 5 + assert acsch(I*sqrt(2 + 2/sqrt(5))) == -I*pi / 5 + assert acsch(-I*sqrt(2)) == I*pi / 4 + assert acsch(I*sqrt(2)) == -I*pi / 4 + assert acsch(-I*(sqrt(5)-1)) == 3*I*pi / 10 + assert acsch(I*(sqrt(5)-1)) == -3*I*pi / 10 + assert acsch(-I*2 / sqrt(3)) == I*pi / 3 + assert acsch(I*2 / sqrt(3)) == -I*pi / 3 + assert acsch(-I*2 / sqrt(2 + sqrt(2))) == 3*I*pi / 8 + assert acsch(I*2 / sqrt(2 + sqrt(2))) == -3*I*pi / 8 + assert acsch(-I*sqrt(2 - 2/sqrt(5))) == 2*I*pi / 5 + assert acsch(I*sqrt(2 - 2/sqrt(5))) == -2*I*pi / 5 + assert acsch(-I*(sqrt(6) - sqrt(2))) == 5*I*pi / 12 + assert acsch(I*(sqrt(6) - sqrt(2))) == -5*I*pi / 12 + assert acsch(nan) is nan + + # properties + # acsch(x) == asinh(1/x) + assert acsch(-I*sqrt(2)) == asinh(I/sqrt(2)) + assert acsch(-I*2 / sqrt(3)) == asinh(I*sqrt(3) / 2) + + # reality + assert acsch(S(2)).is_real is True + assert acsch(S(2)).is_finite is True + assert acsch(S(-2)).is_real is True + assert acsch(S(oo)).is_extended_real is True + assert acsch(-S(oo)).is_real is True + assert (acsch(2) - oo) == -oo + assert acsch(symbols('y', extended_real=True)).is_extended_real is True + + # acsch(x) == -I*asin(I/x) + assert acsch(-I*sqrt(2)) == -I*asin(-1/sqrt(2)) + assert acsch(-I*2 / sqrt(3)) == -I*asin(-sqrt(3)/2) + + # csch(acsch(x)) / x == 1 + assert expand_mul(csch(acsch(-I*(sqrt(6) + sqrt(2)))) / (-I*(sqrt(6) + sqrt(2)))) == 1 + assert expand_mul(csch(acsch(I*(1 + sqrt(5)))) / (I*(1 + sqrt(5)))) == 1 + assert (csch(acsch(I*sqrt(2 - 2/sqrt(5)))) / (I*sqrt(2 - 2/sqrt(5)))).simplify() == 1 + assert (csch(acsch(-I*sqrt(2 - 2/sqrt(5)))) / (-I*sqrt(2 - 2/sqrt(5)))).simplify() == 1 + + # numerical evaluation + assert str(acsch(5*I+1).n(6)) == '0.0391819 - 0.193363*I' + assert str(acsch(-5*I+1).n(6)) == '0.0391819 + 0.193363*I' + + +def test_acsch_infinities(): + assert acsch(oo) == 0 + assert acsch(-oo) == 0 + assert acsch(zoo) == 0 + + +def test_acsch_leading_term(): + x = Symbol('x') + assert acsch(1/x).as_leading_term(x) == x + # Tests concerning branch points + assert acsch(x + I).as_leading_term(x) == -I*pi/2 + assert acsch(x - I).as_leading_term(x) == I*pi/2 + # Tests concerning points lying on branch cuts + assert acsch(x).as_leading_term(x, cdir=1) == -log(x) + log(2) + assert acsch(x).as_leading_term(x, cdir=-1) == log(x) - log(2) - I*pi + assert acsch(x + I/2).as_leading_term(x, cdir=1) == -I*pi - acsch(I/2) + assert acsch(x + I/2).as_leading_term(x, cdir=-1) == acsch(I/2) + assert acsch(x - I/2).as_leading_term(x, cdir=1) == -acsch(I/2) + assert acsch(x - I/2).as_leading_term(x, cdir=-1) == acsch(I/2) + I*pi + # Tests concerning re(ndir) == 0 + assert acsch(I/2 + I*x - x**2).as_leading_term(x, cdir=1) == log(2 - sqrt(3)) - I*pi/2 + assert acsch(I/2 + I*x - x**2).as_leading_term(x, cdir=-1) == log(2 - sqrt(3)) - I*pi/2 + + +def test_acsch_series(): + x = Symbol('x') + assert acsch(x).series(x, 0, 9) == log(2) - log(x) + x**2/4 - 3*x**4/32 \ + + 5*x**6/96 - 35*x**8/1024 + O(x**9) + t4 = acsch(x).taylor_term(4, x) + assert t4 == -3*x**4/32 + assert acsch(x).taylor_term(6, x, t4, 0) == 5*x**6/96 + + +def test_acsch_nseries(): + x = Symbol('x') + # Tests concerning branch points + assert acsch(x + I)._eval_nseries(x, 4, None) == -I*pi/2 + \ + sqrt(2)*I*sqrt(x)*sqrt(-I) - 5*x**(S(3)/2)*(1 - I)/12 - \ + 43*sqrt(2)*I*x**(S(5)/2)*sqrt(-I)/160 + 177*x**(S(7)/2)*(1 - I)/896 + O(x**4) + assert acsch(x - I)._eval_nseries(x, 4, None) == I*pi/2 - \ + sqrt(2)*sqrt(I)*I*sqrt(x) - 5*x**(S(3)/2)*(1 + I)/12 + \ + 43*sqrt(2)*sqrt(I)*I*x**(S(5)/2)/160 + 177*x**(S(7)/2)*(1 + I)/896 + O(x**4) + # Tests concerning points lying on branch cuts + assert acsch(x + I/2)._eval_nseries(x, 4, None, cdir=1) == -acsch(I/2) - \ + I*pi + 4*sqrt(3)*I*x/3 - 8*sqrt(3)*x**2/9 - 16*sqrt(3)*I*x**3/9 + O(x**4) + assert acsch(x + I/2)._eval_nseries(x, 4, None, cdir=-1) == acsch(I/2) - \ + 4*sqrt(3)*I*x/3 + 8*sqrt(3)*x**2/9 + 16*sqrt(3)*I*x**3/9 + O(x**4) + assert acsch(x - I/2)._eval_nseries(x, 4, None, cdir=1) == -acsch(I/2) - \ + 4*sqrt(3)*I*x/3 - 8*sqrt(3)*x**2/9 + 16*sqrt(3)*I*x**3/9 + O(x**4) + assert acsch(x - I/2)._eval_nseries(x, 4, None, cdir=-1) == I*pi + \ + acsch(I/2) + 4*sqrt(3)*I*x/3 + 8*sqrt(3)*x**2/9 - 16*sqrt(3)*I*x**3/9 + O(x**4) + # Tests concerning re(ndir) == 0 + assert acsch(I/2 + I*x - x**2)._eval_nseries(x, 4, None) == -I*pi/2 + \ + log(2 - sqrt(3)) + x*(12 - 8*sqrt(3))/(-6 + 3*sqrt(3)) + x**2*(-96 + \ + sqrt(3)*(56 - 84*I) + 144*I)/(-63 + 36*sqrt(3)) + x**3*(2688 - 2688*I + \ + sqrt(3)*(-1552 + 1552*I))/(-873 + 504*sqrt(3)) + O(x**4) + + +def test_acsch_rewrite(): + x = Symbol('x') + assert acsch(x).rewrite(log) == log(1/x + sqrt(1/x**2 + 1)) + assert acsch(x).rewrite(asinh) == asinh(1/x) + assert acsch(x).rewrite(atanh) == (sqrt(-x**2)*(-sqrt(-(x**2 + 1)**2) + *atanh(sqrt(x**2 + 1))/(x**2 + 1) + + pi/2)/x) + + +def test_acsch_fdiff(): + x = Symbol('x') + raises(ArgumentIndexError, lambda: acsch(x).fdiff(2)) + + +def test_atanh(): + x = Symbol('x') + + # at specific points + assert atanh(0) == 0 + assert atanh(I) == I*pi/4 + assert atanh(-I) == -I*pi/4 + assert atanh(1) is oo + assert atanh(-1) is -oo + assert atanh(nan) is nan + + # at infinites + assert atanh(oo) == -I*pi/2 + assert atanh(-oo) == I*pi/2 + + assert atanh(I*oo) == I*pi/2 + assert atanh(-I*oo) == -I*pi/2 + + assert atanh(zoo) == I*AccumBounds(-pi/2, pi/2) + + # properties + assert atanh(-x) == -atanh(x) + + # reality + assert atanh(S(2)).is_real is False + assert atanh(S(-1)/5).is_real is True + assert atanh(symbols('y', extended_real=True)).is_real is None + assert atanh(S(1)).is_real is False + assert atanh(S(1)).is_extended_real is True + assert atanh(S(-1)).is_real is False + + # special values + assert atanh(I/sqrt(3)) == I*pi/6 + assert atanh(-I/sqrt(3)) == -I*pi/6 + assert atanh(I*sqrt(3)) == I*pi/3 + assert atanh(-I*sqrt(3)) == -I*pi/3 + assert atanh(I*(1 + sqrt(2))) == pi*I*Rational(3, 8) + assert atanh(I*(sqrt(2) - 1)) == pi*I/8 + assert atanh(I*(1 - sqrt(2))) == -pi*I/8 + assert atanh(-I*(1 + sqrt(2))) == pi*I*Rational(-3, 8) + assert atanh(I*sqrt(5 + 2*sqrt(5))) == I*pi*Rational(2, 5) + assert atanh(-I*sqrt(5 + 2*sqrt(5))) == I*pi*Rational(-2, 5) + assert atanh(I*(2 - sqrt(3))) == pi*I/12 + assert atanh(I*(sqrt(3) - 2)) == -pi*I/12 + assert atanh(oo) == -I*pi/2 + + # Symmetry + assert atanh(Rational(-1, 2)) == -atanh(S.Half) + + # inverse composition + assert unchanged(atanh, tanh(Symbol('v1'))) + + assert atanh(tanh(-5, evaluate=False)) == -5 + assert atanh(tanh(0, evaluate=False)) == 0 + assert atanh(tanh(7, evaluate=False)) == 7 + assert atanh(tanh(I, evaluate=False)) == I + assert atanh(tanh(-I, evaluate=False)) == -I + assert atanh(tanh(-11*I, evaluate=False)) == -11*I + 4*I*pi + assert atanh(tanh(3 + I)) == 3 + I + assert atanh(tanh(4 + 5*I)) == 4 - 2*I*pi + 5*I + assert atanh(tanh(pi/2)) == pi/2 + assert atanh(tanh(pi)) == pi + assert atanh(tanh(-3 + 7*I)) == -3 - 2*I*pi + 7*I + assert atanh(tanh(9 - I*2/3)) == 9 - I*2/3 + assert atanh(tanh(-32 - 123*I)) == -32 - 123*I + 39*I*pi + + +def test_atanh_rewrite(): + x = Symbol('x') + assert atanh(x).rewrite(log) == (log(1 + x) - log(1 - x)) / 2 + assert atanh(x).rewrite(asinh) == \ + pi*x/(2*sqrt(-x**2)) - sqrt(-x)*sqrt(1 - x**2)*sqrt(1/(x**2 - 1))*asinh(sqrt(1/(x**2 - 1)))/sqrt(x) + + +def test_atanh_leading_term(): + x = Symbol('x') + assert atanh(x).as_leading_term(x) == x + # Tests concerning branch points + assert atanh(x + 1).as_leading_term(x, cdir=1) == -log(x)/2 + log(2)/2 - I*pi/2 + assert atanh(x + 1).as_leading_term(x, cdir=-1) == -log(x)/2 + log(2)/2 + I*pi/2 + assert atanh(x - 1).as_leading_term(x, cdir=1) == log(x)/2 - log(2)/2 + assert atanh(x - 1).as_leading_term(x, cdir=-1) == log(x)/2 - log(2)/2 + assert atanh(1/x).as_leading_term(x, cdir=1) == -I*pi/2 + assert atanh(1/x).as_leading_term(x, cdir=-1) == I*pi/2 + # Tests concerning points lying on branch cuts + assert atanh(I*x + 2).as_leading_term(x, cdir=1) == atanh(2) + I*pi + assert atanh(-I*x + 2).as_leading_term(x, cdir=1) == atanh(2) + assert atanh(I*x - 2).as_leading_term(x, cdir=1) == -atanh(2) + assert atanh(-I*x - 2).as_leading_term(x, cdir=1) == -I*pi - atanh(2) + # Tests concerning im(ndir) == 0 + assert atanh(-I*x**2 + x - 2).as_leading_term(x, cdir=1) == -log(3)/2 - I*pi/2 + assert atanh(-I*x**2 + x - 2).as_leading_term(x, cdir=-1) == -log(3)/2 - I*pi/2 + + +def test_atanh_series(): + x = Symbol('x') + assert atanh(x).series(x, 0, 10) == \ + x + x**3/3 + x**5/5 + x**7/7 + x**9/9 + O(x**10) + + +def test_atanh_nseries(): + x = Symbol('x') + # Tests concerning branch points + assert atanh(x + 1)._eval_nseries(x, 4, None, cdir=1) == -I*pi/2 + log(2)/2 - \ + log(x)/2 + x/4 - x**2/16 + x**3/48 + O(x**4) + assert atanh(x + 1)._eval_nseries(x, 4, None, cdir=-1) == I*pi/2 + log(2)/2 - \ + log(x)/2 + x/4 - x**2/16 + x**3/48 + O(x**4) + assert atanh(x - 1)._eval_nseries(x, 4, None, cdir=1) == -log(2)/2 + log(x)/2 + \ + x/4 + x**2/16 + x**3/48 + O(x**4) + assert atanh(x - 1)._eval_nseries(x, 4, None, cdir=-1) == -log(2)/2 + log(x)/2 + \ + x/4 + x**2/16 + x**3/48 + O(x**4) + # Tests concerning points lying on branch cuts + assert atanh(I*x + 2)._eval_nseries(x, 4, None, cdir=1) == I*pi + atanh(2) - \ + I*x/3 - 2*x**2/9 + 13*I*x**3/81 + O(x**4) + assert atanh(I*x + 2)._eval_nseries(x, 4, None, cdir=-1) == atanh(2) - I*x/3 - \ + 2*x**2/9 + 13*I*x**3/81 + O(x**4) + assert atanh(I*x - 2)._eval_nseries(x, 4, None, cdir=1) == -atanh(2) - I*x/3 + \ + 2*x**2/9 + 13*I*x**3/81 + O(x**4) + assert atanh(I*x - 2)._eval_nseries(x, 4, None, cdir=-1) == -atanh(2) - I*pi - \ + I*x/3 + 2*x**2/9 + 13*I*x**3/81 + O(x**4) + # Tests concerning im(ndir) == 0 + assert atanh(-I*x**2 + x - 2)._eval_nseries(x, 4, None) == -I*pi/2 - log(3)/2 - x/3 + \ + x**2*(-S(1)/4 + I/2) + x**2*(S(1)/36 - I/6) + x**3*(-S(1)/6 + I/2) + x**3*(S(1)/162 - I/18) + O(x**4) + + +def test_atanh_fdiff(): + x = Symbol('x') + raises(ArgumentIndexError, lambda: atanh(x).fdiff(2)) + + +def test_acoth(): + x = Symbol('x') + + #at specific points + assert acoth(0) == I*pi/2 + assert acoth(I) == -I*pi/4 + assert acoth(-I) == I*pi/4 + assert acoth(1) is oo + assert acoth(-1) is -oo + assert acoth(nan) is nan + + # at infinites + assert acoth(oo) == 0 + assert acoth(-oo) == 0 + assert acoth(I*oo) == 0 + assert acoth(-I*oo) == 0 + assert acoth(zoo) == 0 + + #properties + assert acoth(-x) == -acoth(x) + + assert acoth(I/sqrt(3)) == -I*pi/3 + assert acoth(-I/sqrt(3)) == I*pi/3 + assert acoth(I*sqrt(3)) == -I*pi/6 + assert acoth(-I*sqrt(3)) == I*pi/6 + assert acoth(I*(1 + sqrt(2))) == -pi*I/8 + assert acoth(-I*(sqrt(2) + 1)) == pi*I/8 + assert acoth(I*(1 - sqrt(2))) == pi*I*Rational(3, 8) + assert acoth(I*(sqrt(2) - 1)) == pi*I*Rational(-3, 8) + assert acoth(I*sqrt(5 + 2*sqrt(5))) == -I*pi/10 + assert acoth(-I*sqrt(5 + 2*sqrt(5))) == I*pi/10 + assert acoth(I*(2 + sqrt(3))) == -pi*I/12 + assert acoth(-I*(2 + sqrt(3))) == pi*I/12 + assert acoth(I*(2 - sqrt(3))) == pi*I*Rational(-5, 12) + assert acoth(I*(sqrt(3) - 2)) == pi*I*Rational(5, 12) + + # reality + assert acoth(S(2)).is_real is True + assert acoth(S(2)).is_finite is True + assert acoth(S(2)).is_extended_real is True + assert acoth(S(-2)).is_real is True + assert acoth(S(1)).is_real is False + assert acoth(S(1)).is_extended_real is True + assert acoth(S(-1)).is_real is False + assert acoth(symbols('y', real=True)).is_real is None + + # Symmetry + assert acoth(Rational(-1, 2)) == -acoth(S.Half) + + +def test_acoth_rewrite(): + x = Symbol('x') + assert acoth(x).rewrite(log) == (log(1 + 1/x) - log(1 - 1/x)) / 2 + assert acoth(x).rewrite(atanh) == atanh(1/x) + assert acoth(x).rewrite(asinh) == \ + x*sqrt(x**(-2))*asinh(sqrt(1/(x**2 - 1))) + I*pi*(sqrt((x - 1)/x)*sqrt(x/(x - 1)) - sqrt(x/(x + 1))*sqrt(1 + 1/x))/2 + + +def test_acoth_leading_term(): + x = Symbol('x') + # Tests concerning branch points + assert acoth(x + 1).as_leading_term(x, cdir=1) == -log(x)/2 + log(2)/2 + assert acoth(x + 1).as_leading_term(x, cdir=-1) == -log(x)/2 + log(2)/2 + assert acoth(x - 1).as_leading_term(x, cdir=1) == log(x)/2 - log(2)/2 + I*pi/2 + assert acoth(x - 1).as_leading_term(x, cdir=-1) == log(x)/2 - log(2)/2 - I*pi/2 + # Tests concerning points lying on branch cuts + assert acoth(x).as_leading_term(x, cdir=-1) == I*pi/2 + assert acoth(x).as_leading_term(x, cdir=1) == -I*pi/2 + assert acoth(I*x + 1/2).as_leading_term(x, cdir=1) == acoth(1/2) + assert acoth(-I*x + 1/2).as_leading_term(x, cdir=1) == acoth(1/2) + I*pi + assert acoth(I*x - 1/2).as_leading_term(x, cdir=1) == -I*pi - acoth(1/2) + assert acoth(-I*x - 1/2).as_leading_term(x, cdir=1) == -acoth(1/2) + # Tests concerning im(ndir) == 0 + assert acoth(-I*x**2 - x - S(1)/2).as_leading_term(x, cdir=1) == -log(3)/2 + I*pi/2 + assert acoth(-I*x**2 - x - S(1)/2).as_leading_term(x, cdir=-1) == -log(3)/2 + I*pi/2 + + +def test_acoth_series(): + x = Symbol('x') + assert acoth(x).series(x, 0, 10) == \ + -I*pi/2 + x + x**3/3 + x**5/5 + x**7/7 + x**9/9 + O(x**10) + + +def test_acoth_nseries(): + x = Symbol('x') + # Tests concerning branch points + assert acoth(x + 1)._eval_nseries(x, 4, None) == log(2)/2 - log(x)/2 + x/4 - \ + x**2/16 + x**3/48 + O(x**4) + assert acoth(x - 1)._eval_nseries(x, 4, None, cdir=1) == I*pi/2 - log(2)/2 + \ + log(x)/2 + x/4 + x**2/16 + x**3/48 + O(x**4) + assert acoth(x - 1)._eval_nseries(x, 4, None, cdir=-1) == -I*pi/2 - log(2)/2 + \ + log(x)/2 + x/4 + x**2/16 + x**3/48 + O(x**4) + # Tests concerning points lying on branch cuts + assert acoth(I*x + S(1)/2)._eval_nseries(x, 4, None, cdir=1) == acoth(S(1)/2) + \ + 4*I*x/3 - 8*x**2/9 - 112*I*x**3/81 + O(x**4) + assert acoth(I*x + S(1)/2)._eval_nseries(x, 4, None, cdir=-1) == I*pi + \ + acoth(S(1)/2) + 4*I*x/3 - 8*x**2/9 - 112*I*x**3/81 + O(x**4) + assert acoth(I*x - S(1)/2)._eval_nseries(x, 4, None, cdir=1) == -acoth(S(1)/2) - \ + I*pi + 4*I*x/3 + 8*x**2/9 - 112*I*x**3/81 + O(x**4) + assert acoth(I*x - S(1)/2)._eval_nseries(x, 4, None, cdir=-1) == -acoth(S(1)/2) + \ + 4*I*x/3 + 8*x**2/9 - 112*I*x**3/81 + O(x**4) + # Tests concerning im(ndir) == 0 + assert acoth(-I*x**2 - x - S(1)/2)._eval_nseries(x, 4, None) == I*pi/2 - log(3)/2 - \ + 4*x/3 + x**2*(-S(8)/9 + 2*I/3) - 2*I*x**2 + x**3*(S(104)/81 - 16*I/9) - 8*x**3/3 + O(x**4) + + +def test_acoth_fdiff(): + x = Symbol('x') + raises(ArgumentIndexError, lambda: acoth(x).fdiff(2)) + + +def test_inverses(): + x = Symbol('x') + assert sinh(x).inverse() == asinh + raises(AttributeError, lambda: cosh(x).inverse()) + assert tanh(x).inverse() == atanh + assert coth(x).inverse() == acoth + assert asinh(x).inverse() == sinh + assert acosh(x).inverse() == cosh + assert atanh(x).inverse() == tanh + assert acoth(x).inverse() == coth + assert asech(x).inverse() == sech + assert acsch(x).inverse() == csch + + +def test_leading_term(): + x = Symbol('x') + assert cosh(x).as_leading_term(x) == 1 + assert coth(x).as_leading_term(x) == 1/x + for func in [sinh, tanh]: + assert func(x).as_leading_term(x) == x + for func in [sinh, cosh, tanh, coth]: + for ar in (1/x, S.Half): + eq = func(ar) + assert eq.as_leading_term(x) == eq + for func in [csch, sech]: + eq = func(S.Half) + assert eq.as_leading_term(x) == eq + + +def test_complex(): + a, b = symbols('a,b', real=True) + z = a + b*I + for func in [sinh, cosh, tanh, coth, sech, csch]: + assert func(z).conjugate() == func(a - b*I) + for deep in [True, False]: + assert sinh(z).expand( + complex=True, deep=deep) == sinh(a)*cos(b) + I*cosh(a)*sin(b) + assert cosh(z).expand( + complex=True, deep=deep) == cosh(a)*cos(b) + I*sinh(a)*sin(b) + assert tanh(z).expand(complex=True, deep=deep) == sinh(a)*cosh( + a)/(cos(b)**2 + sinh(a)**2) + I*sin(b)*cos(b)/(cos(b)**2 + sinh(a)**2) + assert coth(z).expand(complex=True, deep=deep) == sinh(a)*cosh( + a)/(sin(b)**2 + sinh(a)**2) - I*sin(b)*cos(b)/(sin(b)**2 + sinh(a)**2) + assert csch(z).expand(complex=True, deep=deep) == cos(b) * sinh(a) / (sin(b)**2\ + *cosh(a)**2 + cos(b)**2 * sinh(a)**2) - I*sin(b) * cosh(a) / (sin(b)**2\ + *cosh(a)**2 + cos(b)**2 * sinh(a)**2) + assert sech(z).expand(complex=True, deep=deep) == cos(b) * cosh(a) / (sin(b)**2\ + *sinh(a)**2 + cos(b)**2 * cosh(a)**2) - I*sin(b) * sinh(a) / (sin(b)**2\ + *sinh(a)**2 + cos(b)**2 * cosh(a)**2) + + +def test_complex_2899(): + a, b = symbols('a,b', real=True) + for deep in [True, False]: + for func in [sinh, cosh, tanh, coth]: + assert func(a).expand(complex=True, deep=deep) == func(a) + + +def test_simplifications(): + x = Symbol('x') + assert sinh(asinh(x)) == x + assert sinh(acosh(x)) == sqrt(x - 1) * sqrt(x + 1) + assert sinh(atanh(x)) == x/sqrt(1 - x**2) + assert sinh(acoth(x)) == 1/(sqrt(x - 1) * sqrt(x + 1)) + + assert cosh(asinh(x)) == sqrt(1 + x**2) + assert cosh(acosh(x)) == x + assert cosh(atanh(x)) == 1/sqrt(1 - x**2) + assert cosh(acoth(x)) == x/(sqrt(x - 1) * sqrt(x + 1)) + + assert tanh(asinh(x)) == x/sqrt(1 + x**2) + assert tanh(acosh(x)) == sqrt(x - 1) * sqrt(x + 1) / x + assert tanh(atanh(x)) == x + assert tanh(acoth(x)) == 1/x + + assert coth(asinh(x)) == sqrt(1 + x**2)/x + assert coth(acosh(x)) == x/(sqrt(x - 1) * sqrt(x + 1)) + assert coth(atanh(x)) == 1/x + assert coth(acoth(x)) == x + + assert csch(asinh(x)) == 1/x + assert csch(acosh(x)) == 1/(sqrt(x - 1) * sqrt(x + 1)) + assert csch(atanh(x)) == sqrt(1 - x**2)/x + assert csch(acoth(x)) == sqrt(x - 1) * sqrt(x + 1) + + assert sech(asinh(x)) == 1/sqrt(1 + x**2) + assert sech(acosh(x)) == 1/x + assert sech(atanh(x)) == sqrt(1 - x**2) + assert sech(acoth(x)) == sqrt(x - 1) * sqrt(x + 1)/x + + +def test_issue_4136(): + assert cosh(asinh(Integer(3)/2)) == sqrt(Integer(13)/4) + + +def test_sinh_rewrite(): + x = Symbol('x') + assert sinh(x).rewrite(exp) == (exp(x) - exp(-x))/2 \ + == sinh(x).rewrite('tractable') + assert sinh(x).rewrite(cosh) == -I*cosh(x + I*pi/2) + tanh_half = tanh(S.Half*x) + assert sinh(x).rewrite(tanh) == 2*tanh_half/(1 - tanh_half**2) + coth_half = coth(S.Half*x) + assert sinh(x).rewrite(coth) == 2*coth_half/(coth_half**2 - 1) + + +def test_cosh_rewrite(): + x = Symbol('x') + assert cosh(x).rewrite(exp) == (exp(x) + exp(-x))/2 \ + == cosh(x).rewrite('tractable') + assert cosh(x).rewrite(sinh) == -I*sinh(x + I*pi/2, evaluate=False) + tanh_half = tanh(S.Half*x)**2 + assert cosh(x).rewrite(tanh) == (1 + tanh_half)/(1 - tanh_half) + coth_half = coth(S.Half*x)**2 + assert cosh(x).rewrite(coth) == (coth_half + 1)/(coth_half - 1) + + +def test_tanh_rewrite(): + x = Symbol('x') + assert tanh(x).rewrite(exp) == (exp(x) - exp(-x))/(exp(x) + exp(-x)) \ + == tanh(x).rewrite('tractable') + assert tanh(x).rewrite(sinh) == I*sinh(x)/sinh(I*pi/2 - x, evaluate=False) + assert tanh(x).rewrite(cosh) == I*cosh(I*pi/2 - x, evaluate=False)/cosh(x) + assert tanh(x).rewrite(coth) == 1/coth(x) + + +def test_coth_rewrite(): + x = Symbol('x') + assert coth(x).rewrite(exp) == (exp(x) + exp(-x))/(exp(x) - exp(-x)) \ + == coth(x).rewrite('tractable') + assert coth(x).rewrite(sinh) == -I*sinh(I*pi/2 - x, evaluate=False)/sinh(x) + assert coth(x).rewrite(cosh) == -I*cosh(x)/cosh(I*pi/2 - x, evaluate=False) + assert coth(x).rewrite(tanh) == 1/tanh(x) + + +def test_csch_rewrite(): + x = Symbol('x') + assert csch(x).rewrite(exp) == 1 / (exp(x)/2 - exp(-x)/2) \ + == csch(x).rewrite('tractable') + assert csch(x).rewrite(cosh) == I/cosh(x + I*pi/2, evaluate=False) + tanh_half = tanh(S.Half*x) + assert csch(x).rewrite(tanh) == (1 - tanh_half**2)/(2*tanh_half) + coth_half = coth(S.Half*x) + assert csch(x).rewrite(coth) == (coth_half**2 - 1)/(2*coth_half) + + +def test_sech_rewrite(): + x = Symbol('x') + assert sech(x).rewrite(exp) == 1 / (exp(x)/2 + exp(-x)/2) \ + == sech(x).rewrite('tractable') + assert sech(x).rewrite(sinh) == I/sinh(x + I*pi/2, evaluate=False) + tanh_half = tanh(S.Half*x)**2 + assert sech(x).rewrite(tanh) == (1 - tanh_half)/(1 + tanh_half) + coth_half = coth(S.Half*x)**2 + assert sech(x).rewrite(coth) == (coth_half - 1)/(coth_half + 1) + + +def test_derivs(): + x = Symbol('x') + assert coth(x).diff(x) == -sinh(x)**(-2) + assert sinh(x).diff(x) == cosh(x) + assert cosh(x).diff(x) == sinh(x) + assert tanh(x).diff(x) == -tanh(x)**2 + 1 + assert csch(x).diff(x) == -coth(x)*csch(x) + assert sech(x).diff(x) == -tanh(x)*sech(x) + assert acoth(x).diff(x) == 1/(-x**2 + 1) + assert asinh(x).diff(x) == 1/sqrt(x**2 + 1) + assert acosh(x).diff(x) == 1/(sqrt(x - 1)*sqrt(x + 1)) + assert acosh(x).diff(x) == acosh(x).rewrite(log).diff(x).together() + assert atanh(x).diff(x) == 1/(-x**2 + 1) + assert asech(x).diff(x) == -1/(x*sqrt(1 - x**2)) + assert acsch(x).diff(x) == -1/(x**2*sqrt(1 + x**(-2))) + + +def test_sinh_expansion(): + x, y = symbols('x,y') + assert sinh(x+y).expand(trig=True) == sinh(x)*cosh(y) + cosh(x)*sinh(y) + assert sinh(2*x).expand(trig=True) == 2*sinh(x)*cosh(x) + assert sinh(3*x).expand(trig=True).expand() == \ + sinh(x)**3 + 3*sinh(x)*cosh(x)**2 + + +def test_cosh_expansion(): + x, y = symbols('x,y') + assert cosh(x+y).expand(trig=True) == cosh(x)*cosh(y) + sinh(x)*sinh(y) + assert cosh(2*x).expand(trig=True) == cosh(x)**2 + sinh(x)**2 + assert cosh(3*x).expand(trig=True).expand() == \ + 3*sinh(x)**2*cosh(x) + cosh(x)**3 + +def test_cosh_positive(): + # See issue 11721 + # cosh(x) is positive for real values of x + k = symbols('k', real=True) + n = symbols('n', integer=True) + + assert cosh(k, evaluate=False).is_positive is True + assert cosh(k + 2*n*pi*I, evaluate=False).is_positive is True + assert cosh(I*pi/4, evaluate=False).is_positive is True + assert cosh(3*I*pi/4, evaluate=False).is_positive is False + +def test_cosh_nonnegative(): + k = symbols('k', real=True) + n = symbols('n', integer=True) + + assert cosh(k, evaluate=False).is_nonnegative is True + assert cosh(k + 2*n*pi*I, evaluate=False).is_nonnegative is True + assert cosh(I*pi/4, evaluate=False).is_nonnegative is True + assert cosh(3*I*pi/4, evaluate=False).is_nonnegative is False + assert cosh(S.Zero, evaluate=False).is_nonnegative is True + +def test_real_assumptions(): + z = Symbol('z', real=False) + assert sinh(z).is_real is None + assert cosh(z).is_real is None + assert tanh(z).is_real is None + assert sech(z).is_real is None + assert csch(z).is_real is None + assert coth(z).is_real is None + +def test_sign_assumptions(): + p = Symbol('p', positive=True) + n = Symbol('n', negative=True) + assert sinh(n).is_negative is True + assert sinh(p).is_positive is True + assert cosh(n).is_positive is True + assert cosh(p).is_positive is True + assert tanh(n).is_negative is True + assert tanh(p).is_positive is True + assert csch(n).is_negative is True + assert csch(p).is_positive is True + assert sech(n).is_positive is True + assert sech(p).is_positive is True + assert coth(n).is_negative is True + assert coth(p).is_positive is True + + +def test_issue_25847(): + x = Symbol('x') + + #atanh + assert atanh(sin(x)/x).as_leading_term(x) == atanh(sin(x)/x) + raises(PoleError, lambda: atanh(exp(1/x)).as_leading_term(x)) + + #asinh + assert asinh(sin(x)/x).as_leading_term(x) == log(1 + sqrt(2)) + raises(PoleError, lambda: asinh(exp(1/x)).as_leading_term(x)) + + #acosh + assert acosh(sin(x)/x).as_leading_term(x) == 0 + raises(PoleError, lambda: acosh(exp(1/x)).as_leading_term(x)) + + #acoth + assert acoth(sin(x)/x).as_leading_term(x) == acoth(sin(x)/x) + raises(PoleError, lambda: acoth(exp(1/x)).as_leading_term(x)) + + #asech + assert asech(sinh(x)/x).as_leading_term(x) == 0 + raises(PoleError, lambda: asech(exp(1/x)).as_leading_term(x)) + + #acsch + assert acsch(sin(x)/x).as_leading_term(x) == log(1 + sqrt(2)) + raises(PoleError, lambda: acsch(exp(1/x)).as_leading_term(x)) + + +def test_issue_25175(): + x = Symbol('x') + g1 = 2*acosh(1 + 2*x/3) - acosh(S(5)/3 - S(8)/3/(x + 4)) + g2 = 2*log(sqrt((x + 4)/3)*(sqrt(x + 3)+sqrt(x))**2/(2*sqrt(x + 3) + sqrt(x))) + assert (g1 - g2).series(x) == O(x**6) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/test_integers.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/test_integers.py new file mode 100644 index 0000000000000000000000000000000000000000..a48ad2ac24c4a857d57b2f24e3308ac90078a9b1 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/test_integers.py @@ -0,0 +1,688 @@ +from sympy.calculus.accumulationbounds import AccumBounds +from sympy.core.numbers import (E, Float, I, Rational, Integer, nan, oo, pi, zoo) +from sympy.core.relational import (Eq, Ge, Gt, Le, Lt, Ne) +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.combinatorial.factorials import factorial +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.integers import (ceiling, floor, frac) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import sin, cos, tan, asin +from sympy.polys.rootoftools import RootOf, CRootOf +from sympy import Integers +from sympy.sets.sets import Interval +from sympy.sets.fancysets import ImageSet +from sympy.core.function import Lambda + +from sympy.core.expr import unchanged +from sympy.testing.pytest import XFAIL, raises + +x = Symbol('x') +i = Symbol('i', imaginary=True) +y = Symbol('y', real=True) +k, n = symbols('k,n', integer=True) +b = Symbol('b', real=True, noninteger=True) +m = Symbol('m', positive=True) + + +def test_floor(): + + assert floor(nan) is nan + + assert floor(oo) is oo + assert floor(-oo) is -oo + assert floor(zoo) is zoo + + assert floor(0) == 0 + + assert floor(1) == 1 + assert floor(-1) == -1 + + assert floor(I*log(asin(5)/abs(asin(5)))) == 0 + assert floor(-I*log(asin(7)/abs(asin(7)))) == -2 + + assert floor(E) == 2 + assert floor(-E) == -3 + + assert floor(2*E) == 5 + assert floor(-2*E) == -6 + + assert floor(pi) == 3 + assert floor(-pi) == -4 + + assert floor(S.Half) == 0 + assert floor(Rational(-1, 2)) == -1 + + assert floor(Rational(7, 3)) == 2 + assert floor(Rational(-7, 3)) == -3 + assert floor(-Rational(7, 3)) == -3 + + assert floor(Float(17.0)) == 17 + assert floor(-Float(17.0)) == -17 + + assert floor(Float(7.69)) == 7 + assert floor(-Float(7.69)) == -8 + + assert floor(1/(m+1)) == S.Zero + assert floor((m+2)/(m+1)) == S.One + assert floor(-1/(m+1)) == S.NegativeOne + assert floor((m+2)/(-m-1)) == Integer(-2) + + assert floor(I) == I + assert floor(-I) == -I + e = floor(i) + assert e.func is floor and e.args[0] == i + + assert floor(oo*I) == oo*I + assert floor(-oo*I) == -oo*I + assert floor(exp(I*pi/4)*oo) == exp(I*pi/4)*oo + + assert floor(2*I) == 2*I + assert floor(-2*I) == -2*I + + assert floor(I/2) == 0 + assert floor(-I/2) == -I + + assert floor(E + 17) == 19 + assert floor(pi + 2) == 5 + + assert floor(E + pi) == 5 + assert floor(I + pi) == 3 + I + + assert floor(floor(pi)) == 3 + assert floor(floor(y)) == floor(y) + assert floor(floor(x)) == floor(x) + + assert unchanged(floor, x) + assert unchanged(floor, 2*x) + assert unchanged(floor, k*x) + + assert floor(k) == k + assert floor(2*k) == 2*k + assert floor(k*n) == k*n + + assert unchanged(floor, k/2) + + assert unchanged(floor, x + y) + + assert floor(x + 3) == floor(x) + 3 + assert floor(x + k) == floor(x) + k + + assert floor(y + 3) == floor(y) + 3 + assert floor(y + k) == floor(y) + k + + assert floor(3 + I*y + pi) == 6 + floor(y)*I + + assert floor(k + n) == k + n + + assert unchanged(floor, x*I) + assert floor(k*I) == k*I + + assert floor(Rational(23, 10) - E*I) == 2 - 3*I + + assert floor(sin(1)) == 0 + assert floor(sin(-1)) == -1 + + assert floor(exp(2)) == 7 + + assert floor(log(8)/log(2)) != 2 + assert int(floor(log(8)/log(2)).evalf(chop=True)) == 3 + + assert floor(factorial(50)/exp(1)) == \ + 11188719610782480504630258070757734324011354208865721592720336800 + + assert (floor(y) < y).is_Relational + assert (floor(y) <= y) == True + assert (floor(y) > y) == False + assert (floor(y) >= y).is_Relational + assert (floor(x) <= x).is_Relational # x could be non-real + assert (floor(x) > x).is_Relational + assert (floor(x) <= y).is_Relational # arg is not same as rhs + assert (floor(x) > y).is_Relational + assert (floor(y) <= oo) == True + assert (floor(y) < oo) == True + assert (floor(y) >= -oo) == True + assert (floor(y) > -oo) == True + assert (floor(b) < b) == True + assert (floor(b) <= b) == True + assert (floor(b) > b) == False + assert (floor(b) >= b) == False + + assert floor(y).rewrite(frac) == y - frac(y) + assert floor(y).rewrite(ceiling) == -ceiling(-y) + assert floor(y).rewrite(frac).subs(y, -pi) == floor(-pi) + assert floor(y).rewrite(frac).subs(y, E) == floor(E) + assert floor(y).rewrite(ceiling).subs(y, E) == -ceiling(-E) + assert floor(y).rewrite(ceiling).subs(y, -pi) == -ceiling(pi) + + assert Eq(floor(y), y - frac(y)) + assert Eq(floor(y), -ceiling(-y)) + + neg = Symbol('neg', negative=True) + nn = Symbol('nn', nonnegative=True) + pos = Symbol('pos', positive=True) + np = Symbol('np', nonpositive=True) + + assert (floor(neg) < 0) == True + assert (floor(neg) <= 0) == True + assert (floor(neg) > 0) == False + assert (floor(neg) >= 0) == False + assert (floor(neg) <= -1) == True + assert (floor(neg) >= -3) == (neg >= -3) + assert (floor(neg) < 5) == (neg < 5) + + assert (floor(nn) < 0) == False + assert (floor(nn) >= 0) == True + + assert (floor(pos) < 0) == False + assert (floor(pos) <= 0) == (pos < 1) + assert (floor(pos) > 0) == (pos >= 1) + assert (floor(pos) >= 0) == True + assert (floor(pos) >= 3) == (pos >= 3) + + assert (floor(np) <= 0) == True + assert (floor(np) > 0) == False + + assert floor(neg).is_negative == True + assert floor(neg).is_nonnegative == False + assert floor(nn).is_negative == False + assert floor(nn).is_nonnegative == True + assert floor(pos).is_negative == False + assert floor(pos).is_nonnegative == True + assert floor(np).is_negative is None + assert floor(np).is_nonnegative is None + + assert (floor(7, evaluate=False) >= 7) == True + assert (floor(7, evaluate=False) > 7) == False + assert (floor(7, evaluate=False) <= 7) == True + assert (floor(7, evaluate=False) < 7) == False + + assert (floor(7, evaluate=False) >= 6) == True + assert (floor(7, evaluate=False) > 6) == True + assert (floor(7, evaluate=False) <= 6) == False + assert (floor(7, evaluate=False) < 6) == False + + assert (floor(7, evaluate=False) >= 8) == False + assert (floor(7, evaluate=False) > 8) == False + assert (floor(7, evaluate=False) <= 8) == True + assert (floor(7, evaluate=False) < 8) == True + + assert (floor(x) <= 5.5) == Le(floor(x), 5.5, evaluate=False) + assert (floor(x) >= -3.2) == Ge(floor(x), -3.2, evaluate=False) + assert (floor(x) < 2.9) == Lt(floor(x), 2.9, evaluate=False) + assert (floor(x) > -1.7) == Gt(floor(x), -1.7, evaluate=False) + + assert (floor(y) <= 5.5) == (y < 6) + assert (floor(y) >= -3.2) == (y >= -3) + assert (floor(y) < 2.9) == (y < 3) + assert (floor(y) > -1.7) == (y >= -1) + + assert (floor(y) <= n) == (y < n + 1) + assert (floor(y) >= n) == (y >= n) + assert (floor(y) < n) == (y < n) + assert (floor(y) > n) == (y >= n + 1) + + assert floor(RootOf(x**3 - 27*x, 2)) == 5 + + +def test_ceiling(): + + assert ceiling(nan) is nan + + assert ceiling(oo) is oo + assert ceiling(-oo) is -oo + assert ceiling(zoo) is zoo + + assert ceiling(0) == 0 + + assert ceiling(1) == 1 + assert ceiling(-1) == -1 + + assert ceiling(I*log(asin(5)/abs(asin(5)))) == 1 + assert ceiling(-I*log(asin(7)/abs(asin(7)))) == -1 + + assert ceiling(E) == 3 + assert ceiling(-E) == -2 + + assert ceiling(2*E) == 6 + assert ceiling(-2*E) == -5 + + assert ceiling(pi) == 4 + assert ceiling(-pi) == -3 + + assert ceiling(S.Half) == 1 + assert ceiling(Rational(-1, 2)) == 0 + + assert ceiling(Rational(7, 3)) == 3 + assert ceiling(-Rational(7, 3)) == -2 + + assert ceiling(Float(17.0)) == 17 + assert ceiling(-Float(17.0)) == -17 + + assert ceiling(Float(7.69)) == 8 + assert ceiling(-Float(7.69)) == -7 + + assert ceiling(1/(m+1)) == S.One + assert ceiling((m+2)/(m+1)) == Integer(2) + assert ceiling(-1/(m+1)) == S.Zero + assert ceiling((m+2)/(-m-1)) == S.NegativeOne + + assert ceiling(I) == I + assert ceiling(-I) == -I + e = ceiling(i) + assert e.func is ceiling and e.args[0] == i + + assert ceiling(oo*I) == oo*I + assert ceiling(-oo*I) == -oo*I + assert ceiling(exp(I*pi/4)*oo) == exp(I*pi/4)*oo + + assert ceiling(2*I) == 2*I + assert ceiling(-2*I) == -2*I + + assert ceiling(I/2) == I + assert ceiling(-I/2) == 0 + + assert ceiling(E + 17) == 20 + assert ceiling(pi + 2) == 6 + + assert ceiling(E + pi) == 6 + assert ceiling(I + pi) == I + 4 + + assert ceiling(ceiling(pi)) == 4 + assert ceiling(ceiling(y)) == ceiling(y) + assert ceiling(ceiling(x)) == ceiling(x) + + assert unchanged(ceiling, x) + assert unchanged(ceiling, 2*x) + assert unchanged(ceiling, k*x) + + assert ceiling(k) == k + assert ceiling(2*k) == 2*k + assert ceiling(k*n) == k*n + + assert unchanged(ceiling, k/2) + + assert unchanged(ceiling, x + y) + + assert ceiling(x + 3) == ceiling(x) + 3 + assert ceiling(x + 3.0) == ceiling(x) + 3 + assert ceiling(x + 3.0*I) == ceiling(x) + 3*I + assert ceiling(x + k) == ceiling(x) + k + + assert ceiling(y + 3) == ceiling(y) + 3 + assert ceiling(y + k) == ceiling(y) + k + + assert ceiling(3 + pi + y*I) == 7 + ceiling(y)*I + + assert ceiling(k + n) == k + n + + assert unchanged(ceiling, x*I) + assert ceiling(k*I) == k*I + + assert ceiling(Rational(23, 10) - E*I) == 3 - 2*I + + assert ceiling(sin(1)) == 1 + assert ceiling(sin(-1)) == 0 + + assert ceiling(exp(2)) == 8 + + assert ceiling(-log(8)/log(2)) != -2 + assert int(ceiling(-log(8)/log(2)).evalf(chop=True)) == -3 + + assert ceiling(factorial(50)/exp(1)) == \ + 11188719610782480504630258070757734324011354208865721592720336801 + + assert (ceiling(y) >= y) == True + assert (ceiling(y) > y).is_Relational + assert (ceiling(y) < y) == False + assert (ceiling(y) <= y).is_Relational + assert (ceiling(x) >= x).is_Relational # x could be non-real + assert (ceiling(x) < x).is_Relational + assert (ceiling(x) >= y).is_Relational # arg is not same as rhs + assert (ceiling(x) < y).is_Relational + assert (ceiling(y) >= -oo) == True + assert (ceiling(y) > -oo) == True + assert (ceiling(y) <= oo) == True + assert (ceiling(y) < oo) == True + assert (ceiling(b) < b) == False + assert (ceiling(b) <= b) == False + assert (ceiling(b) > b) == True + assert (ceiling(b) >= b) == True + + assert ceiling(y).rewrite(floor) == -floor(-y) + assert ceiling(y).rewrite(frac) == y + frac(-y) + assert ceiling(y).rewrite(floor).subs(y, -pi) == -floor(pi) + assert ceiling(y).rewrite(floor).subs(y, E) == -floor(-E) + assert ceiling(y).rewrite(frac).subs(y, pi) == ceiling(pi) + assert ceiling(y).rewrite(frac).subs(y, -E) == ceiling(-E) + + assert Eq(ceiling(y), y + frac(-y)) + assert Eq(ceiling(y), -floor(-y)) + + neg = Symbol('neg', negative=True) + nn = Symbol('nn', nonnegative=True) + pos = Symbol('pos', positive=True) + np = Symbol('np', nonpositive=True) + + assert (ceiling(neg) <= 0) == True + assert (ceiling(neg) < 0) == (neg <= -1) + assert (ceiling(neg) > 0) == False + assert (ceiling(neg) >= 0) == (neg > -1) + assert (ceiling(neg) > -3) == (neg > -3) + assert (ceiling(neg) <= 10) == (neg <= 10) + + assert (ceiling(nn) < 0) == False + assert (ceiling(nn) >= 0) == True + + assert (ceiling(pos) < 0) == False + assert (ceiling(pos) <= 0) == False + assert (ceiling(pos) > 0) == True + assert (ceiling(pos) >= 0) == True + assert (ceiling(pos) >= 1) == True + assert (ceiling(pos) > 5) == (pos > 5) + + assert (ceiling(np) <= 0) == True + assert (ceiling(np) > 0) == False + + assert ceiling(neg).is_positive == False + assert ceiling(neg).is_nonpositive == True + assert ceiling(nn).is_positive is None + assert ceiling(nn).is_nonpositive is None + assert ceiling(pos).is_positive == True + assert ceiling(pos).is_nonpositive == False + assert ceiling(np).is_positive == False + assert ceiling(np).is_nonpositive == True + + assert (ceiling(7, evaluate=False) >= 7) == True + assert (ceiling(7, evaluate=False) > 7) == False + assert (ceiling(7, evaluate=False) <= 7) == True + assert (ceiling(7, evaluate=False) < 7) == False + + assert (ceiling(7, evaluate=False) >= 6) == True + assert (ceiling(7, evaluate=False) > 6) == True + assert (ceiling(7, evaluate=False) <= 6) == False + assert (ceiling(7, evaluate=False) < 6) == False + + assert (ceiling(7, evaluate=False) >= 8) == False + assert (ceiling(7, evaluate=False) > 8) == False + assert (ceiling(7, evaluate=False) <= 8) == True + assert (ceiling(7, evaluate=False) < 8) == True + + assert (ceiling(x) <= 5.5) == Le(ceiling(x), 5.5, evaluate=False) + assert (ceiling(x) >= -3.2) == Ge(ceiling(x), -3.2, evaluate=False) + assert (ceiling(x) < 2.9) == Lt(ceiling(x), 2.9, evaluate=False) + assert (ceiling(x) > -1.7) == Gt(ceiling(x), -1.7, evaluate=False) + + assert (ceiling(y) <= 5.5) == (y <= 5) + assert (ceiling(y) >= -3.2) == (y > -4) + assert (ceiling(y) < 2.9) == (y <= 2) + assert (ceiling(y) > -1.7) == (y > -2) + + assert (ceiling(y) <= n) == (y <= n) + assert (ceiling(y) >= n) == (y > n - 1) + assert (ceiling(y) < n) == (y <= n - 1) + assert (ceiling(y) > n) == (y > n) + + assert ceiling(RootOf(x**3 - 27*x, 2)) == 6 + s = ImageSet(Lambda(n, n + (CRootOf(x**5 - x**2 + 1, 0))), Integers) + f = CRootOf(x**5 - x**2 + 1, 0) + s = ImageSet(Lambda(n, n + f), Integers) + assert s.intersect(Interval(-10, 10)) == {i + f for i in range(-9, 11)} + + +def test_frac(): + assert isinstance(frac(x), frac) + assert frac(oo) == AccumBounds(0, 1) + assert frac(-oo) == AccumBounds(0, 1) + assert frac(zoo) is nan + + assert frac(n) == 0 + assert frac(nan) is nan + assert frac(Rational(4, 3)) == Rational(1, 3) + assert frac(-Rational(4, 3)) == Rational(2, 3) + assert frac(Rational(-4, 3)) == Rational(2, 3) + + r = Symbol('r', real=True) + assert frac(I*r) == I*frac(r) + assert frac(1 + I*r) == I*frac(r) + assert frac(0.5 + I*r) == 0.5 + I*frac(r) + assert frac(n + I*r) == I*frac(r) + assert frac(n + I*k) == 0 + assert unchanged(frac, x + I*x) + assert frac(x + I*n) == frac(x) + + assert frac(x).rewrite(floor) == x - floor(x) + assert frac(x).rewrite(ceiling) == x + ceiling(-x) + assert frac(y).rewrite(floor).subs(y, pi) == frac(pi) + assert frac(y).rewrite(floor).subs(y, -E) == frac(-E) + assert frac(y).rewrite(ceiling).subs(y, -pi) == frac(-pi) + assert frac(y).rewrite(ceiling).subs(y, E) == frac(E) + + assert Eq(frac(y), y - floor(y)) + assert Eq(frac(y), y + ceiling(-y)) + + r = Symbol('r', real=True) + p_i = Symbol('p_i', integer=True, positive=True) + n_i = Symbol('p_i', integer=True, negative=True) + np_i = Symbol('np_i', integer=True, nonpositive=True) + nn_i = Symbol('nn_i', integer=True, nonnegative=True) + p_r = Symbol('p_r', positive=True) + n_r = Symbol('n_r', negative=True) + np_r = Symbol('np_r', real=True, nonpositive=True) + nn_r = Symbol('nn_r', real=True, nonnegative=True) + + # Real frac argument, integer rhs + assert frac(r) <= p_i + assert not frac(r) <= n_i + assert (frac(r) <= np_i).has(Le) + assert (frac(r) <= nn_i).has(Le) + assert frac(r) < p_i + assert not frac(r) < n_i + assert not frac(r) < np_i + assert (frac(r) < nn_i).has(Lt) + assert not frac(r) >= p_i + assert frac(r) >= n_i + assert frac(r) >= np_i + assert (frac(r) >= nn_i).has(Ge) + assert not frac(r) > p_i + assert frac(r) > n_i + assert (frac(r) > np_i).has(Gt) + assert (frac(r) > nn_i).has(Gt) + + assert not Eq(frac(r), p_i) + assert not Eq(frac(r), n_i) + assert Eq(frac(r), np_i).has(Eq) + assert Eq(frac(r), nn_i).has(Eq) + + assert Ne(frac(r), p_i) + assert Ne(frac(r), n_i) + assert Ne(frac(r), np_i).has(Ne) + assert Ne(frac(r), nn_i).has(Ne) + + + # Real frac argument, real rhs + assert (frac(r) <= p_r).has(Le) + assert not frac(r) <= n_r + assert (frac(r) <= np_r).has(Le) + assert (frac(r) <= nn_r).has(Le) + assert (frac(r) < p_r).has(Lt) + assert not frac(r) < n_r + assert not frac(r) < np_r + assert (frac(r) < nn_r).has(Lt) + assert (frac(r) >= p_r).has(Ge) + assert frac(r) >= n_r + assert frac(r) >= np_r + assert (frac(r) >= nn_r).has(Ge) + assert (frac(r) > p_r).has(Gt) + assert frac(r) > n_r + assert (frac(r) > np_r).has(Gt) + assert (frac(r) > nn_r).has(Gt) + + assert not Eq(frac(r), n_r) + assert Eq(frac(r), p_r).has(Eq) + assert Eq(frac(r), np_r).has(Eq) + assert Eq(frac(r), nn_r).has(Eq) + + assert Ne(frac(r), p_r).has(Ne) + assert Ne(frac(r), n_r) + assert Ne(frac(r), np_r).has(Ne) + assert Ne(frac(r), nn_r).has(Ne) + + # Real frac argument, +/- oo rhs + assert frac(r) < oo + assert frac(r) <= oo + assert not frac(r) > oo + assert not frac(r) >= oo + + assert not frac(r) < -oo + assert not frac(r) <= -oo + assert frac(r) > -oo + assert frac(r) >= -oo + + assert frac(r) < 1 + assert frac(r) <= 1 + assert not frac(r) > 1 + assert not frac(r) >= 1 + + assert not frac(r) < 0 + assert (frac(r) <= 0).has(Le) + assert (frac(r) > 0).has(Gt) + assert frac(r) >= 0 + + # Some test for numbers + assert frac(r) <= sqrt(2) + assert (frac(r) <= sqrt(3) - sqrt(2)).has(Le) + assert not frac(r) <= sqrt(2) - sqrt(3) + assert not frac(r) >= sqrt(2) + assert (frac(r) >= sqrt(3) - sqrt(2)).has(Ge) + assert frac(r) >= sqrt(2) - sqrt(3) + + assert not Eq(frac(r), sqrt(2)) + assert Eq(frac(r), sqrt(3) - sqrt(2)).has(Eq) + assert not Eq(frac(r), sqrt(2) - sqrt(3)) + assert Ne(frac(r), sqrt(2)) + assert Ne(frac(r), sqrt(3) - sqrt(2)).has(Ne) + assert Ne(frac(r), sqrt(2) - sqrt(3)) + + assert frac(p_i, evaluate=False).is_zero + assert frac(p_i, evaluate=False).is_finite + assert frac(p_i, evaluate=False).is_integer + assert frac(p_i, evaluate=False).is_real + assert frac(r).is_finite + assert frac(r).is_real + assert frac(r).is_zero is None + assert frac(r).is_integer is None + + assert frac(oo).is_finite + assert frac(oo).is_real + + +def test_series(): + x, y = symbols('x,y') + assert floor(x).nseries(x, y, 100) == floor(y) + assert ceiling(x).nseries(x, y, 100) == ceiling(y) + assert floor(x).nseries(x, pi, 100) == 3 + assert ceiling(x).nseries(x, pi, 100) == 4 + assert floor(x).nseries(x, 0, 100) == 0 + assert ceiling(x).nseries(x, 0, 100) == 1 + assert floor(-x).nseries(x, 0, 100) == -1 + assert ceiling(-x).nseries(x, 0, 100) == 0 + + +def test_issue_14355(): + # This test checks the leading term and series for the floor and ceil + # function when arg0 evaluates to S.NaN. + assert floor((x**3 + x)/(x**2 - x)).as_leading_term(x, cdir = 1) == -2 + assert floor((x**3 + x)/(x**2 - x)).as_leading_term(x, cdir = -1) == -1 + assert floor((cos(x) - 1)/x).as_leading_term(x, cdir = 1) == -1 + assert floor((cos(x) - 1)/x).as_leading_term(x, cdir = -1) == 0 + assert floor(sin(x)/x).as_leading_term(x, cdir = 1) == 0 + assert floor(sin(x)/x).as_leading_term(x, cdir = -1) == 0 + assert floor(-tan(x)/x).as_leading_term(x, cdir = 1) == -2 + assert floor(-tan(x)/x).as_leading_term(x, cdir = -1) == -2 + assert floor(sin(x)/x/3).as_leading_term(x, cdir = 1) == 0 + assert floor(sin(x)/x/3).as_leading_term(x, cdir = -1) == 0 + assert ceiling((x**3 + x)/(x**2 - x)).as_leading_term(x, cdir = 1) == -1 + assert ceiling((x**3 + x)/(x**2 - x)).as_leading_term(x, cdir = -1) == 0 + assert ceiling((cos(x) - 1)/x).as_leading_term(x, cdir = 1) == 0 + assert ceiling((cos(x) - 1)/x).as_leading_term(x, cdir = -1) == 1 + assert ceiling(sin(x)/x).as_leading_term(x, cdir = 1) == 1 + assert ceiling(sin(x)/x).as_leading_term(x, cdir = -1) == 1 + assert ceiling(-tan(x)/x).as_leading_term(x, cdir = 1) == -1 + assert ceiling(-tan(x)/x).as_leading_term(x, cdir = 1) == -1 + assert ceiling(sin(x)/x/3).as_leading_term(x, cdir = 1) == 1 + assert ceiling(sin(x)/x/3).as_leading_term(x, cdir = -1) == 1 + # test for series + assert floor(sin(x)/x).series(x, 0, 100, cdir = 1) == 0 + assert floor(sin(x)/x).series(x, 0, 100, cdir = 1) == 0 + assert floor((x**3 + x)/(x**2 - x)).series(x, 0, 100, cdir = 1) == -2 + assert floor((x**3 + x)/(x**2 - x)).series(x, 0, 100, cdir = -1) == -1 + assert ceiling(sin(x)/x).series(x, 0, 100, cdir = 1) == 1 + assert ceiling(sin(x)/x).series(x, 0, 100, cdir = -1) == 1 + assert ceiling((x**3 + x)/(x**2 - x)).series(x, 0, 100, cdir = 1) == -1 + assert ceiling((x**3 + x)/(x**2 - x)).series(x, 0, 100, cdir = -1) == 0 + + +def test_frac_leading_term(): + assert frac(x).as_leading_term(x) == x + assert frac(x).as_leading_term(x, cdir = 1) == x + assert frac(x).as_leading_term(x, cdir = -1) == 1 + assert frac(x + S.Half).as_leading_term(x, cdir = 1) == S.Half + assert frac(x + S.Half).as_leading_term(x, cdir = -1) == S.Half + assert frac(-2*x + 1).as_leading_term(x, cdir = 1) == S.One + assert frac(-2*x + 1).as_leading_term(x, cdir = -1) == -2*x + assert frac(sin(x) + 5).as_leading_term(x, cdir = 1) == x + assert frac(sin(x) + 5).as_leading_term(x, cdir = -1) == S.One + assert frac(sin(x**2) + 5).as_leading_term(x, cdir = 1) == x**2 + assert frac(sin(x**2) + 5).as_leading_term(x, cdir = -1) == x**2 + + +@XFAIL +def test_issue_4149(): + assert floor(3 + pi*I + y*I) == 3 + floor(pi + y)*I + assert floor(3*I + pi*I + y*I) == floor(3 + pi + y)*I + assert floor(3 + E + pi*I + y*I) == 5 + floor(pi + y)*I + + +def test_issue_21651(): + k = Symbol('k', positive=True, integer=True) + exp = 2*2**(-k) + assert isinstance(floor(exp), floor) + + +def test_issue_11207(): + assert floor(floor(x)) == floor(x) + assert floor(ceiling(x)) == ceiling(x) + assert ceiling(floor(x)) == floor(x) + assert ceiling(ceiling(x)) == ceiling(x) + + +def test_nested_floor_ceiling(): + assert floor(-floor(ceiling(x**3)/y)) == -floor(ceiling(x**3)/y) + assert ceiling(-floor(ceiling(x**3)/y)) == -floor(ceiling(x**3)/y) + assert floor(ceiling(-floor(x**Rational(7, 2)/y))) == -floor(x**Rational(7, 2)/y) + assert -ceiling(-ceiling(floor(x)/y)) == ceiling(floor(x)/y) + +def test_issue_18689(): + assert floor(floor(floor(x)) + 3) == floor(x) + 3 + assert ceiling(ceiling(ceiling(x)) + 1) == ceiling(x) + 1 + assert ceiling(ceiling(floor(x)) + 3) == floor(x) + 3 + +def test_issue_18421(): + assert floor(float(0)) is S.Zero + assert ceiling(float(0)) is S.Zero + +def test_issue_25230(): + a = Symbol('a', real = True) + b = Symbol('b', positive = True) + c = Symbol('c', negative = True) + raises(NotImplementedError, lambda: floor(x/a).as_leading_term(x, cdir = 1)) + raises(NotImplementedError, lambda: ceiling(x/a).as_leading_term(x, cdir = 1)) + assert floor(x/b).as_leading_term(x, cdir = 1) == 0 + assert floor(x/b).as_leading_term(x, cdir = -1) == -1 + assert floor(x/c).as_leading_term(x, cdir = 1) == -1 + assert floor(x/c).as_leading_term(x, cdir = -1) == 0 + assert ceiling(x/b).as_leading_term(x, cdir = 1) == 1 + assert ceiling(x/b).as_leading_term(x, cdir = -1) == 0 + assert ceiling(x/c).as_leading_term(x, cdir = 1) == 0 + assert ceiling(x/c).as_leading_term(x, cdir = -1) == 1 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/test_interface.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/test_interface.py new file mode 100644 index 0000000000000000000000000000000000000000..6ae2f78b50bea24c64079066076971e315660d69 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/test_interface.py @@ -0,0 +1,82 @@ +# This test file tests the SymPy function interface, that people use to create +# their own new functions. It should be as easy as possible. +# +# We test that it works with both Function and DefinedFunction. New code should +# use DefinedFunction because it has better type inference. Old code still +# using Function should continue to work though. +from sympy.core.function import Function, DefinedFunction +from sympy.core.sympify import sympify +from sympy.functions.elementary.hyperbolic import tanh +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.series.limits import limit +from sympy.abc import x + + +def test_function_series1(): + """Create our new "sin" function.""" + + for F in [Function, DefinedFunction]: + + class my_function(F): + + def fdiff(self, argindex=1): + return cos(self.args[0]) + + @classmethod + def eval(cls, arg): + arg = sympify(arg) + if arg == 0: + return sympify(0) + + #Test that the taylor series is correct + assert my_function(x).series(x, 0, 10) == sin(x).series(x, 0, 10) + assert limit(my_function(x)/x, x, 0) == 1 + + +def test_function_series2(): + """Create our new "cos" function.""" + + for F in [Function, DefinedFunction]: + + class my_function2(F): + + def fdiff(self, argindex=1): + return -sin(self.args[0]) + + @classmethod + def eval(cls, arg): + arg = sympify(arg) + if arg == 0: + return sympify(1) + + #Test that the taylor series is correct + assert my_function2(x).series(x, 0, 10) == cos(x).series(x, 0, 10) + + +def test_function_series3(): + """ + Test our easy "tanh" function. + + This test tests two things: + * that the Function interface works as expected and it's easy to use + * that the general algorithm for the series expansion works even when the + derivative is defined recursively in terms of the original function, + since tanh(x).diff(x) == 1-tanh(x)**2 + """ + + for F in [Function, DefinedFunction]: + + class mytanh(F): + + def fdiff(self, argindex=1): + return 1 - mytanh(self.args[0])**2 + + @classmethod + def eval(cls, arg): + arg = sympify(arg) + if arg == 0: + return sympify(0) + + e = tanh(x) + f = mytanh(x) + assert e.series(x, 0, 6) == f.series(x, 0, 6) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/test_miscellaneous.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/test_miscellaneous.py new file mode 100644 index 0000000000000000000000000000000000000000..374c4fb50eaae54a9884015c124c245385e1761e --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/test_miscellaneous.py @@ -0,0 +1,504 @@ +import itertools as it + +from sympy.core.expr import unchanged +from sympy.core.function import Function +from sympy.core.numbers import I, oo, Rational +from sympy.core.power import Pow +from sympy.core.singleton import S +from sympy.core.symbol import Symbol +from sympy.external import import_module +from sympy.functions.elementary.exponential import log +from sympy.functions.elementary.integers import floor, ceiling +from sympy.functions.elementary.miscellaneous import (sqrt, cbrt, root, Min, + Max, real_root, Rem) +from sympy.functions.elementary.trigonometric import cos, sin +from sympy.functions.special.delta_functions import Heaviside + +from sympy.utilities.lambdify import lambdify +from sympy.testing.pytest import raises, skip, ignore_warnings + +def test_Min(): + from sympy.abc import x, y, z + n = Symbol('n', negative=True) + n_ = Symbol('n_', negative=True) + nn = Symbol('nn', nonnegative=True) + nn_ = Symbol('nn_', nonnegative=True) + p = Symbol('p', positive=True) + p_ = Symbol('p_', positive=True) + np = Symbol('np', nonpositive=True) + np_ = Symbol('np_', nonpositive=True) + r = Symbol('r', real=True) + + assert Min(5, 4) == 4 + assert Min(-oo, -oo) is -oo + assert Min(-oo, n) is -oo + assert Min(n, -oo) is -oo + assert Min(-oo, np) is -oo + assert Min(np, -oo) is -oo + assert Min(-oo, 0) is -oo + assert Min(0, -oo) is -oo + assert Min(-oo, nn) is -oo + assert Min(nn, -oo) is -oo + assert Min(-oo, p) is -oo + assert Min(p, -oo) is -oo + assert Min(-oo, oo) is -oo + assert Min(oo, -oo) is -oo + assert Min(n, n) == n + assert unchanged(Min, n, np) + assert Min(np, n) == Min(n, np) + assert Min(n, 0) == n + assert Min(0, n) == n + assert Min(n, nn) == n + assert Min(nn, n) == n + assert Min(n, p) == n + assert Min(p, n) == n + assert Min(n, oo) == n + assert Min(oo, n) == n + assert Min(np, np) == np + assert Min(np, 0) == np + assert Min(0, np) == np + assert Min(np, nn) == np + assert Min(nn, np) == np + assert Min(np, p) == np + assert Min(p, np) == np + assert Min(np, oo) == np + assert Min(oo, np) == np + assert Min(0, 0) == 0 + assert Min(0, nn) == 0 + assert Min(nn, 0) == 0 + assert Min(0, p) == 0 + assert Min(p, 0) == 0 + assert Min(0, oo) == 0 + assert Min(oo, 0) == 0 + assert Min(nn, nn) == nn + assert unchanged(Min, nn, p) + assert Min(p, nn) == Min(nn, p) + assert Min(nn, oo) == nn + assert Min(oo, nn) == nn + assert Min(p, p) == p + assert Min(p, oo) == p + assert Min(oo, p) == p + assert Min(oo, oo) is oo + + assert Min(n, n_).func is Min + assert Min(nn, nn_).func is Min + assert Min(np, np_).func is Min + assert Min(p, p_).func is Min + + # lists + assert Min() is S.Infinity + assert Min(x) == x + assert Min(x, y) == Min(y, x) + assert Min(x, y, z) == Min(z, y, x) + assert Min(x, Min(y, z)) == Min(z, y, x) + assert Min(x, Max(y, -oo)) == Min(x, y) + assert Min(p, oo, n, p, p, p_) == n + assert Min(p_, n_, p) == n_ + assert Min(n, oo, -7, p, p, 2) == Min(n, -7) + assert Min(2, x, p, n, oo, n_, p, 2, -2, -2) == Min(-2, x, n, n_) + assert Min(0, x, 1, y) == Min(0, x, y) + assert Min(1000, 100, -100, x, p, n) == Min(n, x, -100) + assert unchanged(Min, sin(x), cos(x)) + assert Min(sin(x), cos(x)) == Min(cos(x), sin(x)) + assert Min(cos(x), sin(x)).subs(x, 1) == cos(1) + assert Min(cos(x), sin(x)).subs(x, S.Half) == sin(S.Half) + raises(ValueError, lambda: Min(cos(x), sin(x)).subs(x, I)) + raises(ValueError, lambda: Min(I)) + raises(ValueError, lambda: Min(I, x)) + raises(ValueError, lambda: Min(S.ComplexInfinity, x)) + + assert Min(1, x).diff(x) == Heaviside(1 - x) + assert Min(x, 1).diff(x) == Heaviside(1 - x) + assert Min(0, -x, 1 - 2*x).diff(x) == -Heaviside(x + Min(0, -2*x + 1)) \ + - 2*Heaviside(2*x + Min(0, -x) - 1) + + # issue 7619 + f = Function('f') + assert Min(1, 2*Min(f(1), 2)) # doesn't fail + + # issue 7233 + e = Min(0, x) + assert e.n().args == (0, x) + + # issue 8643 + m = Min(n, p_, n_, r) + assert m.is_positive is False + assert m.is_nonnegative is False + assert m.is_negative is True + + m = Min(p, p_) + assert m.is_positive is True + assert m.is_nonnegative is True + assert m.is_negative is False + + m = Min(p, nn_, p_) + assert m.is_positive is None + assert m.is_nonnegative is True + assert m.is_negative is False + + m = Min(nn, p, r) + assert m.is_positive is None + assert m.is_nonnegative is None + assert m.is_negative is None + + +def test_Max(): + from sympy.abc import x, y, z + n = Symbol('n', negative=True) + n_ = Symbol('n_', negative=True) + nn = Symbol('nn', nonnegative=True) + p = Symbol('p', positive=True) + p_ = Symbol('p_', positive=True) + r = Symbol('r', real=True) + + assert Max(5, 4) == 5 + + # lists + + assert Max() is S.NegativeInfinity + assert Max(x) == x + assert Max(x, y) == Max(y, x) + assert Max(x, y, z) == Max(z, y, x) + assert Max(x, Max(y, z)) == Max(z, y, x) + assert Max(x, Min(y, oo)) == Max(x, y) + assert Max(n, -oo, n_, p, 2) == Max(p, 2) + assert Max(n, -oo, n_, p) == p + assert Max(2, x, p, n, -oo, S.NegativeInfinity, n_, p, 2) == Max(2, x, p) + assert Max(0, x, 1, y) == Max(1, x, y) + assert Max(r, r + 1, r - 1) == 1 + r + assert Max(1000, 100, -100, x, p, n) == Max(p, x, 1000) + assert Max(cos(x), sin(x)) == Max(sin(x), cos(x)) + assert Max(cos(x), sin(x)).subs(x, 1) == sin(1) + assert Max(cos(x), sin(x)).subs(x, S.Half) == cos(S.Half) + raises(ValueError, lambda: Max(cos(x), sin(x)).subs(x, I)) + raises(ValueError, lambda: Max(I)) + raises(ValueError, lambda: Max(I, x)) + raises(ValueError, lambda: Max(S.ComplexInfinity, 1)) + assert Max(n, -oo, n_, p, 2) == Max(p, 2) + assert Max(n, -oo, n_, p, 1000) == Max(p, 1000) + + assert Max(1, x).diff(x) == Heaviside(x - 1) + assert Max(x, 1).diff(x) == Heaviside(x - 1) + assert Max(x**2, 1 + x, 1).diff(x) == \ + 2*x*Heaviside(x**2 - Max(1, x + 1)) \ + + Heaviside(x - Max(1, x**2) + 1) + + e = Max(0, x) + assert e.n().args == (0, x) + + # issue 8643 + m = Max(p, p_, n, r) + assert m.is_positive is True + assert m.is_nonnegative is True + assert m.is_negative is False + + m = Max(n, n_) + assert m.is_positive is False + assert m.is_nonnegative is False + assert m.is_negative is True + + m = Max(n, n_, r) + assert m.is_positive is None + assert m.is_nonnegative is None + assert m.is_negative is None + + m = Max(n, nn, r) + assert m.is_positive is None + assert m.is_nonnegative is True + assert m.is_negative is False + + +def test_minmax_assumptions(): + r = Symbol('r', real=True) + a = Symbol('a', real=True, algebraic=True) + t = Symbol('t', real=True, transcendental=True) + q = Symbol('q', rational=True) + p = Symbol('p', irrational=True) + n = Symbol('n', rational=True, integer=False) + i = Symbol('i', integer=True) + o = Symbol('o', odd=True) + e = Symbol('e', even=True) + k = Symbol('k', prime=True) + reals = [r, a, t, q, p, n, i, o, e, k] + + for ext in (Max, Min): + for x, y in it.product(reals, repeat=2): + + # Must be real + assert ext(x, y).is_real + + # Algebraic? + if x.is_algebraic and y.is_algebraic: + assert ext(x, y).is_algebraic + elif x.is_transcendental and y.is_transcendental: + assert ext(x, y).is_transcendental + else: + assert ext(x, y).is_algebraic is None + + # Rational? + if x.is_rational and y.is_rational: + assert ext(x, y).is_rational + elif x.is_irrational and y.is_irrational: + assert ext(x, y).is_irrational + else: + assert ext(x, y).is_rational is None + + # Integer? + if x.is_integer and y.is_integer: + assert ext(x, y).is_integer + elif x.is_noninteger and y.is_noninteger: + assert ext(x, y).is_noninteger + else: + assert ext(x, y).is_integer is None + + # Odd? + if x.is_odd and y.is_odd: + assert ext(x, y).is_odd + elif x.is_odd is False and y.is_odd is False: + assert ext(x, y).is_odd is False + else: + assert ext(x, y).is_odd is None + + # Even? + if x.is_even and y.is_even: + assert ext(x, y).is_even + elif x.is_even is False and y.is_even is False: + assert ext(x, y).is_even is False + else: + assert ext(x, y).is_even is None + + # Prime? + if x.is_prime and y.is_prime: + assert ext(x, y).is_prime + elif x.is_prime is False and y.is_prime is False: + assert ext(x, y).is_prime is False + else: + assert ext(x, y).is_prime is None + + +def test_issue_8413(): + x = Symbol('x', real=True) + # we can't evaluate in general because non-reals are not + # comparable: Min(floor(3.2 + I), 3.2 + I) -> ValueError + assert Min(floor(x), x) == floor(x) + assert Min(ceiling(x), x) == x + assert Max(floor(x), x) == x + assert Max(ceiling(x), x) == ceiling(x) + + +def test_root(): + from sympy.abc import x + n = Symbol('n', integer=True) + k = Symbol('k', integer=True) + + assert root(2, 2) == sqrt(2) + assert root(2, 1) == 2 + assert root(2, 3) == 2**Rational(1, 3) + assert root(2, 3) == cbrt(2) + assert root(2, -5) == 2**Rational(4, 5)/2 + + assert root(-2, 1) == -2 + + assert root(-2, 2) == sqrt(2)*I + assert root(-2, 1) == -2 + + assert root(x, 2) == sqrt(x) + assert root(x, 1) == x + assert root(x, 3) == x**Rational(1, 3) + assert root(x, 3) == cbrt(x) + assert root(x, -5) == x**Rational(-1, 5) + + assert root(x, n) == x**(1/n) + assert root(x, -n) == x**(-1/n) + + assert root(x, n, k) == (-1)**(2*k/n)*x**(1/n) + + +def test_real_root(): + assert real_root(-8, 3) == -2 + assert real_root(-16, 4) == root(-16, 4) + r = root(-7, 4) + assert real_root(r) == r + r1 = root(-1, 3) + r2 = r1**2 + r3 = root(-1, 4) + assert real_root(r1 + r2 + r3) == -1 + r2 + r3 + assert real_root(root(-2, 3)) == -root(2, 3) + assert real_root(-8., 3) == -2.0 + x = Symbol('x') + n = Symbol('n') + g = real_root(x, n) + assert g.subs({"x": -8, "n": 3}) == -2 + assert g.subs({"x": 8, "n": 3}) == 2 + # give principle root if there is no real root -- if this is not desired + # then maybe a Root class is needed to raise an error instead + assert g.subs({"x": I, "n": 3}) == cbrt(I) + assert g.subs({"x": -8, "n": 2}) == sqrt(-8) + assert g.subs({"x": I, "n": 2}) == sqrt(I) + + +def test_issue_11463(): + numpy = import_module('numpy') + if not numpy: + skip("numpy not installed.") + x = Symbol('x') + f = lambdify(x, real_root((log(x/(x-2))), 3), 'numpy') + # numpy.select evaluates all options before considering conditions, + # so it raises a warning about root of negative number which does + # not affect the outcome. This warning is suppressed here + with ignore_warnings(RuntimeWarning): + assert f(numpy.array(-1)) < -1 + + +def test_rewrite_MaxMin_as_Heaviside(): + from sympy.abc import x + assert Max(0, x).rewrite(Heaviside) == x*Heaviside(x) + assert Max(3, x).rewrite(Heaviside) == x*Heaviside(x - 3) + \ + 3*Heaviside(-x + 3) + assert Max(0, x+2, 2*x).rewrite(Heaviside) == \ + 2*x*Heaviside(2*x)*Heaviside(x - 2) + \ + (x + 2)*Heaviside(-x + 2)*Heaviside(x + 2) + + assert Min(0, x).rewrite(Heaviside) == x*Heaviside(-x) + assert Min(3, x).rewrite(Heaviside) == x*Heaviside(-x + 3) + \ + 3*Heaviside(x - 3) + assert Min(x, -x, -2).rewrite(Heaviside) == \ + x*Heaviside(-2*x)*Heaviside(-x - 2) - \ + x*Heaviside(2*x)*Heaviside(x - 2) \ + - 2*Heaviside(-x + 2)*Heaviside(x + 2) + + +def test_rewrite_MaxMin_as_Piecewise(): + from sympy.core.symbol import symbols + from sympy.functions.elementary.piecewise import Piecewise + x, y, z, a, b = symbols('x y z a b', real=True) + vx, vy, va = symbols('vx vy va') + assert Max(a, b).rewrite(Piecewise) == Piecewise((a, a >= b), (b, True)) + assert Max(x, y, z).rewrite(Piecewise) == Piecewise((x, (x >= y) & (x >= z)), (y, y >= z), (z, True)) + assert Max(x, y, a, b).rewrite(Piecewise) == Piecewise((a, (a >= b) & (a >= x) & (a >= y)), + (b, (b >= x) & (b >= y)), (x, x >= y), (y, True)) + assert Min(a, b).rewrite(Piecewise) == Piecewise((a, a <= b), (b, True)) + assert Min(x, y, z).rewrite(Piecewise) == Piecewise((x, (x <= y) & (x <= z)), (y, y <= z), (z, True)) + assert Min(x, y, a, b).rewrite(Piecewise) == Piecewise((a, (a <= b) & (a <= x) & (a <= y)), + (b, (b <= x) & (b <= y)), (x, x <= y), (y, True)) + + # Piecewise rewriting of Min/Max does also takes place for not explicitly real arguments + assert Max(vx, vy).rewrite(Piecewise) == Piecewise((vx, vx >= vy), (vy, True)) + assert Min(va, vx, vy).rewrite(Piecewise) == Piecewise((va, (va <= vx) & (va <= vy)), (vx, vx <= vy), (vy, True)) + + +def test_issue_11099(): + from sympy.abc import x, y + # some fixed value tests + fixed_test_data = {x: -2, y: 3} + assert Min(x, y).evalf(subs=fixed_test_data) == \ + Min(x, y).subs(fixed_test_data).evalf() + assert Max(x, y).evalf(subs=fixed_test_data) == \ + Max(x, y).subs(fixed_test_data).evalf() + # randomly generate some test data + from sympy.core.random import randint + for i in range(20): + random_test_data = {x: randint(-100, 100), y: randint(-100, 100)} + assert Min(x, y).evalf(subs=random_test_data) == \ + Min(x, y).subs(random_test_data).evalf() + assert Max(x, y).evalf(subs=random_test_data) == \ + Max(x, y).subs(random_test_data).evalf() + + +def test_issue_12638(): + from sympy.abc import a, b, c + assert Min(a, b, c, Max(a, b)) == Min(a, b, c) + assert Min(a, b, Max(a, b, c)) == Min(a, b) + assert Min(a, b, Max(a, c)) == Min(a, b) + +def test_issue_21399(): + from sympy.abc import a, b, c + assert Max(Min(a, b), Min(a, b, c)) == Min(a, b) + + +def test_instantiation_evaluation(): + from sympy.abc import v, w, x, y, z + assert Min(1, Max(2, x)) == 1 + assert Max(3, Min(2, x)) == 3 + assert Min(Max(x, y), Max(x, z)) == Max(x, Min(y, z)) + assert set(Min(Max(w, x), Max(y, z)).args) == { + Max(w, x), Max(y, z)} + assert Min(Max(x, y), Max(x, z), w) == Min( + w, Max(x, Min(y, z))) + A, B = Min, Max + for i in range(2): + assert A(x, B(x, y)) == x + assert A(x, B(y, A(x, w, z))) == A(x, B(y, A(w, z))) + A, B = B, A + assert Min(w, Max(x, y), Max(v, x, z)) == Min( + w, Max(x, Min(y, Max(v, z)))) + +def test_rewrite_as_Abs(): + from itertools import permutations + from sympy.functions.elementary.complexes import Abs + from sympy.abc import x, y, z, w + def test(e): + free = e.free_symbols + a = e.rewrite(Abs) + assert not a.has(Min, Max) + for i in permutations(range(len(free))): + reps = dict(zip(free, i)) + assert a.xreplace(reps) == e.xreplace(reps) + test(Min(x, y)) + test(Max(x, y)) + test(Min(x, y, z)) + test(Min(Max(w, x), Max(y, z))) + +def test_issue_14000(): + assert isinstance(sqrt(4, evaluate=False), Pow) == True + assert isinstance(cbrt(3.5, evaluate=False), Pow) == True + assert isinstance(root(16, 4, evaluate=False), Pow) == True + + assert sqrt(4, evaluate=False) == Pow(4, S.Half, evaluate=False) + assert cbrt(3.5, evaluate=False) == Pow(3.5, Rational(1, 3), evaluate=False) + assert root(4, 2, evaluate=False) == Pow(4, S.Half, evaluate=False) + + assert root(16, 4, 2, evaluate=False).has(Pow) == True + assert real_root(-8, 3, evaluate=False).has(Pow) == True + +def test_issue_6899(): + from sympy.core.function import Lambda + x = Symbol('x') + eqn = Lambda(x, x) + assert eqn.func(*eqn.args) == eqn + +def test_Rem(): + from sympy.abc import x, y + assert Rem(5, 3) == 2 + assert Rem(-5, 3) == -2 + assert Rem(5, -3) == 2 + assert Rem(-5, -3) == -2 + assert Rem(x**3, y) == Rem(x**3, y) + assert Rem(Rem(-5, 3) + 3, 3) == 1 + + +def test_minmax_no_evaluate(): + from sympy import evaluate + p = Symbol('p', positive=True) + + assert Max(1, 3) == 3 + assert Max(1, 3).args == () + assert Max(0, p) == p + assert Max(0, p).args == () + assert Min(0, p) == 0 + assert Min(0, p).args == () + + assert Max(1, 3, evaluate=False) != 3 + assert Max(1, 3, evaluate=False).args == (1, 3) + assert Max(0, p, evaluate=False) != p + assert Max(0, p, evaluate=False).args == (0, p) + assert Min(0, p, evaluate=False) != 0 + assert Min(0, p, evaluate=False).args == (0, p) + + with evaluate(False): + assert Max(1, 3) != 3 + assert Max(1, 3).args == (1, 3) + assert Max(0, p) != p + assert Max(0, p).args == (0, p) + assert Min(0, p) != 0 + assert Min(0, p).args == (0, p) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/test_piecewise.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/test_piecewise.py new file mode 100644 index 0000000000000000000000000000000000000000..7d0728095578b49480a1334857a1c237012d2534 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/test_piecewise.py @@ -0,0 +1,1639 @@ +from sympy.concrete.summations import Sum +from sympy.core.add import Add +from sympy.core.basic import Basic +from sympy.core.containers import Tuple +from sympy.core.expr import unchanged +from sympy.core.function import (Function, diff, expand) +from sympy.core.mul import Mul +from sympy.core.mod import Mod +from sympy.core.numbers import (Float, I, Rational, oo, pi, zoo) +from sympy.core.relational import (Eq, Ge, Gt, Ne) +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.combinatorial.factorials import factorial +from sympy.functions.elementary.complexes import (Abs, adjoint, arg, conjugate, im, re, transpose) +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.miscellaneous import (Max, Min, sqrt) +from sympy.functions.elementary.piecewise import (Piecewise, + piecewise_fold, piecewise_exclusive, Undefined, ExprCondPair) +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.functions.special.delta_functions import (DiracDelta, Heaviside) +from sympy.functions.special.tensor_functions import KroneckerDelta +from sympy.integrals.integrals import (Integral, integrate) +from sympy.logic.boolalg import (And, ITE, Not, Or) +from sympy.matrices.expressions.matexpr import MatrixSymbol +from sympy.printing import srepr +from sympy.sets.contains import Contains +from sympy.sets.sets import Interval +from sympy.solvers.solvers import solve +from sympy.testing.pytest import raises, slow +from sympy.utilities.lambdify import lambdify + +a, b, c, d, x, y = symbols('a:d, x, y') +z = symbols('z', nonzero=True) + + +def test_piecewise1(): + + # Test canonicalization + assert Piecewise((x, x < 1.)).has(1.0) # doesn't get changed to x < 1 + assert unchanged(Piecewise, ExprCondPair(x, x < 1), ExprCondPair(0, True)) + assert Piecewise((x, x < 1), (0, True)) == Piecewise(ExprCondPair(x, x < 1), + ExprCondPair(0, True)) + assert Piecewise((x, x < 1), (0, True), (1, True)) == \ + Piecewise((x, x < 1), (0, True)) + assert Piecewise((x, x < 1), (0, False), (-1, 1 > 2)) == \ + Piecewise((x, x < 1)) + assert Piecewise((x, x < 1), (0, x < 1), (0, True)) == \ + Piecewise((x, x < 1), (0, True)) + assert Piecewise((x, x < 1), (0, x < 2), (0, True)) == \ + Piecewise((x, x < 1), (0, True)) + assert Piecewise((x, x < 1), (x, x < 2), (0, True)) == \ + Piecewise((x, Or(x < 1, x < 2)), (0, True)) + assert Piecewise((x, x < 1), (x, x < 2), (x, True)) == x + assert Piecewise((x, True)) == x + # Explicitly constructed empty Piecewise not accepted + raises(TypeError, lambda: Piecewise()) + # False condition is never retained + assert Piecewise((2*x, x < 0), (x, False)) == \ + Piecewise((2*x, x < 0), (x, False), evaluate=False) == \ + Piecewise((2*x, x < 0)) + assert Piecewise((x, False)) == Undefined + raises(TypeError, lambda: Piecewise(x)) + assert Piecewise((x, 1)) == x # 1 and 0 are accepted as True/False + raises(TypeError, lambda: Piecewise((x, 2))) + raises(TypeError, lambda: Piecewise((x, x**2))) + raises(TypeError, lambda: Piecewise(([1], True))) + assert Piecewise(((1, 2), True)) == Tuple(1, 2) + cond = (Piecewise((1, x < 0), (2, True)) < y) + assert Piecewise((1, cond) + ) == Piecewise((1, ITE(x < 0, y > 1, y > 2))) + + assert Piecewise((1, x > 0), (2, And(x <= 0, x > -1)) + ) == Piecewise((1, x > 0), (2, x > -1)) + assert Piecewise((1, x <= 0), (2, (x < 0) & (x > -1)) + ) == Piecewise((1, x <= 0)) + + # test for supporting Contains in Piecewise + pwise = Piecewise( + (1, And(x <= 6, x > 1, Contains(x, S.Integers))), + (0, True)) + assert pwise.subs(x, pi) == 0 + assert pwise.subs(x, 2) == 1 + assert pwise.subs(x, 7) == 0 + + # Test subs + p = Piecewise((-1, x < -1), (x**2, x < 0), (log(x), x >= 0)) + p_x2 = Piecewise((-1, x**2 < -1), (x**4, x**2 < 0), (log(x**2), x**2 >= 0)) + assert p.subs(x, x**2) == p_x2 + assert p.subs(x, -5) == -1 + assert p.subs(x, -1) == 1 + assert p.subs(x, 1) == log(1) + + # More subs tests + p2 = Piecewise((1, x < pi), (-1, x < 2*pi), (0, x > 2*pi)) + p3 = Piecewise((1, Eq(x, 0)), (1/x, True)) + p4 = Piecewise((1, Eq(x, 0)), (2, 1/x>2)) + assert p2.subs(x, 2) == 1 + assert p2.subs(x, 4) == -1 + assert p2.subs(x, 10) == 0 + assert p3.subs(x, 0.0) == 1 + assert p4.subs(x, 0.0) == 1 + + + f, g, h = symbols('f,g,h', cls=Function) + pf = Piecewise((f(x), x < -1), (f(x) + h(x) + 2, x <= 1)) + pg = Piecewise((g(x), x < -1), (g(x) + h(x) + 2, x <= 1)) + assert pg.subs(g, f) == pf + + assert Piecewise((1, Eq(x, 0)), (0, True)).subs(x, 0) == 1 + assert Piecewise((1, Eq(x, 0)), (0, True)).subs(x, 1) == 0 + assert Piecewise((1, Eq(x, y)), (0, True)).subs(x, y) == 1 + assert Piecewise((1, Eq(x, z)), (0, True)).subs(x, z) == 1 + assert Piecewise((1, Eq(exp(x), cos(z))), (0, True)).subs(x, z) == \ + Piecewise((1, Eq(exp(z), cos(z))), (0, True)) + + p5 = Piecewise( (0, Eq(cos(x) + y, 0)), (1, True)) + assert p5.subs(y, 0) == Piecewise( (0, Eq(cos(x), 0)), (1, True)) + + assert Piecewise((-1, y < 1), (0, x < 0), (1, Eq(x, 0)), (2, True) + ).subs(x, 1) == Piecewise((-1, y < 1), (2, True)) + assert Piecewise((1, Eq(x**2, -1)), (2, x < 0)).subs(x, I) == 1 + + p6 = Piecewise((x, x > 0)) + n = symbols('n', negative=True) + assert p6.subs(x, n) == Undefined + + # Test evalf + assert p.evalf() == Piecewise((-1.0, x < -1), (x**2, x < 0), (log(x), True)) + assert p.evalf(subs={x: -2}) == -1.0 + assert p.evalf(subs={x: -1}) == 1.0 + assert p.evalf(subs={x: 1}) == log(1) + assert p6.evalf(subs={x: -5}) == Undefined + + # Test doit + f_int = Piecewise((Integral(x, (x, 0, 1)), x < 1)) + assert f_int.doit() == Piecewise( (S.Half, x < 1) ) + + # Test differentiation + f = x + fp = x*p + dp = Piecewise((0, x < -1), (2*x, x < 0), (1/x, x >= 0)) + fp_dx = x*dp + p + assert diff(p, x) == dp + assert diff(f*p, x) == fp_dx + + # Test simple arithmetic + assert x*p == fp + assert x*p + p == p + x*p + assert p + f == f + p + assert p + dp == dp + p + assert p - dp == -(dp - p) + + # Test power + dp2 = Piecewise((0, x < -1), (4*x**2, x < 0), (1/x**2, x >= 0)) + assert dp**2 == dp2 + + # Test _eval_interval + f1 = x*y + 2 + f2 = x*y**2 + 3 + peval = Piecewise((f1, x < 0), (f2, x > 0)) + peval_interval = f1.subs( + x, 0) - f1.subs(x, -1) + f2.subs(x, 1) - f2.subs(x, 0) + assert peval._eval_interval(x, 0, 0) == 0 + assert peval._eval_interval(x, -1, 1) == peval_interval + peval2 = Piecewise((f1, x < 0), (f2, True)) + assert peval2._eval_interval(x, 0, 0) == 0 + assert peval2._eval_interval(x, 1, -1) == -peval_interval + assert peval2._eval_interval(x, -1, -2) == f1.subs(x, -2) - f1.subs(x, -1) + assert peval2._eval_interval(x, -1, 1) == peval_interval + assert peval2._eval_interval(x, None, 0) == peval2.subs(x, 0) + assert peval2._eval_interval(x, -1, None) == -peval2.subs(x, -1) + + # Test integration + assert p.integrate() == Piecewise( + (-x, x < -1), + (x**3/3 + Rational(4, 3), x < 0), + (x*log(x) - x + Rational(4, 3), True)) + p = Piecewise((x, x < 1), (x**2, -1 <= x), (x, 3 < x)) + assert integrate(p, (x, -2, 2)) == Rational(5, 6) + assert integrate(p, (x, 2, -2)) == Rational(-5, 6) + p = Piecewise((0, x < 0), (1, x < 1), (0, x < 2), (1, x < 3), (0, True)) + assert integrate(p, (x, -oo, oo)) == 2 + p = Piecewise((x, x < -10), (x**2, x <= -1), (x, 1 < x)) + assert integrate(p, (x, -2, 2)) == Undefined + + # Test commutativity + assert isinstance(p, Piecewise) and p.is_commutative is True + + +def test_piecewise_free_symbols(): + f = Piecewise((x, a < 0), (y, True)) + assert f.free_symbols == {x, y, a} + + +def test_piecewise_integrate1(): + x, y = symbols('x y', real=True) + + f = Piecewise(((x - 2)**2, x >= 0), (1, True)) + assert integrate(f, (x, -2, 2)) == Rational(14, 3) + + g = Piecewise(((x - 5)**5, x >= 4), (f, True)) + assert integrate(g, (x, -2, 2)) == Rational(14, 3) + assert integrate(g, (x, -2, 5)) == Rational(43, 6) + + assert g == Piecewise(((x - 5)**5, x >= 4), (f, x < 4)) + + g = Piecewise(((x - 5)**5, 2 <= x), (f, x < 2)) + assert integrate(g, (x, -2, 2)) == Rational(14, 3) + assert integrate(g, (x, -2, 5)) == Rational(-701, 6) + + assert g == Piecewise(((x - 5)**5, 2 <= x), (f, True)) + + g = Piecewise(((x - 5)**5, 2 <= x), (2*f, True)) + assert integrate(g, (x, -2, 2)) == Rational(28, 3) + assert integrate(g, (x, -2, 5)) == Rational(-673, 6) + + +def test_piecewise_integrate1b(): + g = Piecewise((1, x > 0), (0, Eq(x, 0)), (-1, x < 0)) + assert integrate(g, (x, -1, 1)) == 0 + + g = Piecewise((1, x - y < 0), (0, True)) + assert integrate(g, (y, -oo, 0)) == -Min(0, x) + assert g.subs(x, -3).integrate((y, -oo, 0)) == 3 + assert integrate(g, (y, 0, -oo)) == Min(0, x) + assert integrate(g, (y, 0, oo)) == -Max(0, x) + oo + assert integrate(g, (y, -oo, 42)) == -Min(42, x) + 42 + assert integrate(g, (y, -oo, oo)) == -x + oo + + g = Piecewise((0, x < 0), (x, x <= 1), (1, True)) + gy1 = g.integrate((x, y, 1)) + g1y = g.integrate((x, 1, y)) + for yy in (-1, S.Half, 2): + assert g.integrate((x, yy, 1)) == gy1.subs(y, yy) + assert g.integrate((x, 1, yy)) == g1y.subs(y, yy) + assert gy1 == Piecewise( + (-Min(1, Max(0, y))**2/2 + S.Half, y < 1), + (-y + 1, True)) + assert g1y == Piecewise( + (Min(1, Max(0, y))**2/2 - S.Half, y < 1), + (y - 1, True)) + + +@slow +def test_piecewise_integrate1ca(): + y = symbols('y', real=True) + g = Piecewise( + (1 - x, Interval(0, 1).contains(x)), + (1 + x, Interval(-1, 0).contains(x)), + (0, True) + ) + gy1 = g.integrate((x, y, 1)) + g1y = g.integrate((x, 1, y)) + + assert g.integrate((x, -2, 1)) == gy1.subs(y, -2) + assert g.integrate((x, 1, -2)) == g1y.subs(y, -2) + assert g.integrate((x, 0, 1)) == gy1.subs(y, 0) + assert g.integrate((x, 1, 0)) == g1y.subs(y, 0) + assert g.integrate((x, 2, 1)) == gy1.subs(y, 2) + assert g.integrate((x, 1, 2)) == g1y.subs(y, 2) + assert piecewise_fold(gy1.rewrite(Piecewise) + ).simplify() == Piecewise( + (1, y <= -1), + (-y**2/2 - y + S.Half, y <= 0), + (y**2/2 - y + S.Half, y < 1), + (0, True)) + assert piecewise_fold(g1y.rewrite(Piecewise) + ).simplify() == Piecewise( + (-1, y <= -1), + (y**2/2 + y - S.Half, y <= 0), + (-y**2/2 + y - S.Half, y < 1), + (0, True)) + assert gy1 == Piecewise( + ( + -Min(1, Max(-1, y))**2/2 - Min(1, Max(-1, y)) + + Min(1, Max(0, y))**2 + S.Half, y < 1), + (0, True) + ) + assert g1y == Piecewise( + ( + Min(1, Max(-1, y))**2/2 + Min(1, Max(-1, y)) - + Min(1, Max(0, y))**2 - S.Half, y < 1), + (0, True)) + + +@slow +def test_piecewise_integrate1cb(): + y = symbols('y', real=True) + g = Piecewise( + (0, Or(x <= -1, x >= 1)), + (1 - x, x > 0), + (1 + x, True) + ) + gy1 = g.integrate((x, y, 1)) + g1y = g.integrate((x, 1, y)) + + assert g.integrate((x, -2, 1)) == gy1.subs(y, -2) + assert g.integrate((x, 1, -2)) == g1y.subs(y, -2) + assert g.integrate((x, 0, 1)) == gy1.subs(y, 0) + assert g.integrate((x, 1, 0)) == g1y.subs(y, 0) + assert g.integrate((x, 2, 1)) == gy1.subs(y, 2) + assert g.integrate((x, 1, 2)) == g1y.subs(y, 2) + + assert piecewise_fold(gy1.rewrite(Piecewise) + ).simplify() == Piecewise( + (1, y <= -1), + (-y**2/2 - y + S.Half, y <= 0), + (y**2/2 - y + S.Half, y < 1), + (0, True)) + assert piecewise_fold(g1y.rewrite(Piecewise) + ).simplify() == Piecewise( + (-1, y <= -1), + (y**2/2 + y - S.Half, y <= 0), + (-y**2/2 + y - S.Half, y < 1), + (0, True)) + + # g1y and gy1 should simplify if the condition that y < 1 + # is applied, e.g. Min(1, Max(-1, y)) --> Max(-1, y) + assert gy1 == Piecewise( + ( + -Min(1, Max(-1, y))**2/2 - Min(1, Max(-1, y)) + + Min(1, Max(0, y))**2 + S.Half, y < 1), + (0, True) + ) + assert g1y == Piecewise( + ( + Min(1, Max(-1, y))**2/2 + Min(1, Max(-1, y)) - + Min(1, Max(0, y))**2 - S.Half, y < 1), + (0, True)) + + +def test_piecewise_integrate2(): + from itertools import permutations + lim = Tuple(x, c, d) + p = Piecewise((1, x < a), (2, x > b), (3, True)) + q = p.integrate(lim) + assert q == Piecewise( + (-c + 2*d - 2*Min(d, Max(a, c)) + Min(d, Max(a, b, c)), c < d), + (-2*c + d + 2*Min(c, Max(a, d)) - Min(c, Max(a, b, d)), True)) + for v in permutations((1, 2, 3, 4)): + r = dict(zip((a, b, c, d), v)) + assert p.subs(r).integrate(lim.subs(r)) == q.subs(r) + + +def test_meijer_bypass(): + # totally bypass meijerg machinery when dealing + # with Piecewise in integrate + assert Piecewise((1, x < 4), (0, True)).integrate((x, oo, 1)) == -3 + + +def test_piecewise_integrate3_inequality_conditions(): + from sympy.utilities.iterables import cartes + lim = (x, 0, 5) + # set below includes two pts below range, 2 pts in range, + # 2 pts above range, and the boundaries + N = (-2, -1, 0, 1, 2, 5, 6, 7) + + p = Piecewise((1, x > a), (2, x > b), (0, True)) + ans = p.integrate(lim) + for i, j in cartes(N, repeat=2): + reps = dict(zip((a, b), (i, j))) + assert ans.subs(reps) == p.subs(reps).integrate(lim) + assert ans.subs(a, 4).subs(b, 1) == 0 + 2*3 + 1 + + p = Piecewise((1, x > a), (2, x < b), (0, True)) + ans = p.integrate(lim) + for i, j in cartes(N, repeat=2): + reps = dict(zip((a, b), (i, j))) + assert ans.subs(reps) == p.subs(reps).integrate(lim) + + # delete old tests that involved c1 and c2 since those + # reduce to the above except that a value of 0 was used + # for two expressions whereas the above uses 3 different + # values + + +@slow +def test_piecewise_integrate4_symbolic_conditions(): + a = Symbol('a', real=True) + b = Symbol('b', real=True) + x = Symbol('x', real=True) + y = Symbol('y', real=True) + p0 = Piecewise((0, Or(x < a, x > b)), (1, True)) + p1 = Piecewise((0, x < a), (0, x > b), (1, True)) + p2 = Piecewise((0, x > b), (0, x < a), (1, True)) + p3 = Piecewise((0, x < a), (1, x < b), (0, True)) + p4 = Piecewise((0, x > b), (1, x > a), (0, True)) + p5 = Piecewise((1, And(a < x, x < b)), (0, True)) + + # check values of a=1, b=3 (and reversed) with values + # of y of 0, 1, 2, 3, 4 + lim = Tuple(x, -oo, y) + for p in (p0, p1, p2, p3, p4, p5): + ans = p.integrate(lim) + for i in range(5): + reps = {a:1, b:3, y:i} + assert ans.subs(reps) == p.subs(reps).integrate(lim.subs(reps)) + reps = {a: 3, b:1, y:i} + assert ans.subs(reps) == p.subs(reps).integrate(lim.subs(reps)) + lim = Tuple(x, y, oo) + for p in (p0, p1, p2, p3, p4, p5): + ans = p.integrate(lim) + for i in range(5): + reps = {a:1, b:3, y:i} + assert ans.subs(reps) == p.subs(reps).integrate(lim.subs(reps)) + reps = {a:3, b:1, y:i} + assert ans.subs(reps) == p.subs(reps).integrate(lim.subs(reps)) + + ans = Piecewise( + (0, x <= Min(a, b)), + (x - Min(a, b), x <= b), + (b - Min(a, b), True)) + for i in (p0, p1, p2, p4): + assert i.integrate(x) == ans + assert p3.integrate(x) == Piecewise( + (0, x < a), + (-a + x, x <= Max(a, b)), + (-a + Max(a, b), True)) + assert p5.integrate(x) == Piecewise( + (0, x <= a), + (-a + x, x <= Max(a, b)), + (-a + Max(a, b), True)) + + p1 = Piecewise((0, x < a), (S.Half, x > b), (1, True)) + p2 = Piecewise((S.Half, x > b), (0, x < a), (1, True)) + p3 = Piecewise((0, x < a), (1, x < b), (S.Half, True)) + p4 = Piecewise((S.Half, x > b), (1, x > a), (0, True)) + p5 = Piecewise((1, And(a < x, x < b)), (S.Half, x > b), (0, True)) + + # check values of a=1, b=3 (and reversed) with values + # of y of 0, 1, 2, 3, 4 + lim = Tuple(x, -oo, y) + for p in (p1, p2, p3, p4, p5): + ans = p.integrate(lim) + for i in range(5): + reps = {a:1, b:3, y:i} + assert ans.subs(reps) == p.subs(reps).integrate(lim.subs(reps)) + reps = {a: 3, b:1, y:i} + assert ans.subs(reps) == p.subs(reps).integrate(lim.subs(reps)) + + +def test_piecewise_integrate5_independent_conditions(): + p = Piecewise((0, Eq(y, 0)), (x*y, True)) + assert integrate(p, (x, 1, 3)) == Piecewise((0, Eq(y, 0)), (4*y, True)) + + +def test_issue_22917(): + p = (Piecewise((0, ITE((x - y > 1) | (2 * x - 2 * y > 1), False, + ITE(x - y > 1, 2 * y - 2 < -1, 2 * x - 2 * y > 1))), + (Piecewise((0, ITE(x - y > 1, True, 2 * x - 2 * y > 1)), + (2 * Piecewise((0, x - y > 1), (y, True)), True)), True)) + + 2 * Piecewise((1, ITE((x - y > 1) | (2 * x - 2 * y > 1), False, + ITE(x - y > 1, 2 * y - 2 < -1, 2 * x - 2 * y > 1))), + (Piecewise((1, ITE(x - y > 1, True, 2 * x - 2 * y > 1)), + (2 * Piecewise((1, x - y > 1), (x, True)), True)), True))) + assert piecewise_fold(p) == Piecewise((2, (x - y > S.Half) | (x - y > 1)), + (2*y + 4, x - y > 1), + (4*x + 2*y, True)) + assert piecewise_fold(p > 1).rewrite(ITE) == ITE((x - y > S.Half) | (x - y > 1), True, + ITE(x - y > 1, 2*y + 4 > 1, 4*x + 2*y > 1)) + + +def test_piecewise_simplify(): + p = Piecewise(((x**2 + 1)/x**2, Eq(x*(1 + x) - x**2, 0)), + ((-1)**x*(-1), True)) + assert p.simplify() == \ + Piecewise((zoo, Eq(x, 0)), ((-1)**(x + 1), True)) + # simplify when there are Eq in conditions + assert Piecewise( + (a, And(Eq(a, 0), Eq(a + b, 0))), (1, True)).simplify( + ) == Piecewise( + (0, And(Eq(a, 0), Eq(b, 0))), (1, True)) + assert Piecewise((2*x*factorial(a)/(factorial(y)*factorial(-y + a)), + Eq(y, 0) & Eq(-y + a, 0)), (2*factorial(a)/(factorial(y)*factorial(-y + + a)), Eq(y, 0) & Eq(-y + a, 1)), (0, True)).simplify( + ) == Piecewise( + (2*x, And(Eq(a, 0), Eq(y, 0))), + (2, And(Eq(a, 1), Eq(y, 0))), + (0, True)) + args = (2, And(Eq(x, 2), Ge(y, 0))), (x, True) + assert Piecewise(*args).simplify() == Piecewise(*args) + args = (1, Eq(x, 0)), (sin(x)/x, True) + assert Piecewise(*args).simplify() == Piecewise(*args) + assert Piecewise((2 + y, And(Eq(x, 2), Eq(y, 0))), (x, True) + ).simplify() == x + # check that x or f(x) are recognized as being Symbol-like for lhs + args = Tuple((1, Eq(x, 0)), (sin(x) + 1 + x, True)) + ans = x + sin(x) + 1 + f = Function('f') + assert Piecewise(*args).simplify() == ans + assert Piecewise(*args.subs(x, f(x))).simplify() == ans.subs(x, f(x)) + + # issue 18634 + d = Symbol("d", integer=True) + n = Symbol("n", integer=True) + t = Symbol("t", positive=True) + expr = Piecewise((-d + 2*n, Eq(1/t, 1)), (t**(1 - 4*n)*t**(4*n - 1)*(-d + 2*n), True)) + assert expr.simplify() == -d + 2*n + + # issue 22747 + p = Piecewise((0, (t < -2) & (t < -1) & (t < 0)), ((t/2 + 1)*(t + + 1)*(t + 2), (t < -1) & (t < 0)), ((S.Half - t/2)*(1 - t)*(t + 1), + (t < -2) & (t < -1) & (t < 1)), ((t + 1)*(-t*(t/2 + 1) + (S.Half + - t/2)*(1 - t)), (t < -2) & (t < -1) & (t < 0) & (t < 1)), ((t + + 1)*((S.Half - t/2)*(1 - t) + (t/2 + 1)*(t + 2)), (t < -1) & (t < + 1)), ((t + 1)*(-t*(t/2 + 1) + (S.Half - t/2)*(1 - t)), (t < -1) & + (t < 0) & (t < 1)), (0, (t < -2) & (t < -1)), ((t/2 + 1)*(t + + 1)*(t + 2), t < -1), ((t + 1)*(-t*(t/2 + 1) + (S.Half - t/2)*(t + + 1)), (t < 0) & ((t < -2) | (t < 0))), ((S.Half - t/2)*(1 - t)*(t + + 1), (t < 1) & ((t < -2) | (t < 1))), (0, True)) + Piecewise((0, + (t < -1) & (t < 0) & (t < 1)), ((1 - t)*(t/2 + S.Half)*(t + 1), + (t < 0) & (t < 1)), ((1 - t)*(1 - t/2)*(2 - t), (t < -1) & (t < + 0) & (t < 2)), ((1 - t)*((1 - t)*(t/2 + S.Half) + (1 - t/2)*(2 - + t)), (t < -1) & (t < 0) & (t < 1) & (t < 2)), ((1 - t)*((1 - + t/2)*(2 - t) + (t/2 + S.Half)*(t + 1)), (t < 0) & (t < 2)), ((1 - + t)*((1 - t)*(t/2 + S.Half) + (1 - t/2)*(2 - t)), (t < 0) & (t < + 1) & (t < 2)), (0, (t < -1) & (t < 0)), ((1 - t)*(t/2 + + S.Half)*(t + 1), t < 0), ((1 - t)*(t*(1 - t/2) + (1 - t)*(t/2 + + S.Half)), (t < 1) & ((t < -1) | (t < 1))), ((1 - t)*(1 - t/2)*(2 + - t), (t < 2) & ((t < -1) | (t < 2))), (0, True)) + assert p.simplify() == Piecewise( + (0, t < -2), ((t + 1)*(t + 2)**2/2, t < -1), (-3*t**3/2 + - 5*t**2/2 + 1, t < 0), (3*t**3/2 - 5*t**2/2 + 1, t < 1), ((1 - + t)*(t - 2)**2/2, t < 2), (0, True)) + + # coverage + nan = Undefined + assert Piecewise((1, x > 3), (2, x < 2), (3, x > 1)).simplify( + ) == Piecewise((1, x > 3), (2, x < 2), (3, True)) + assert Piecewise((1, x < 2), (2, x < 1), (3, True)).simplify( + ) == Piecewise((1, x < 2), (3, True)) + assert Piecewise((1, x > 2)).simplify() == Piecewise((1, x > 2), + (nan, True)) + assert Piecewise((1, (x >= 2) & (x < oo)) + ).simplify() == Piecewise((1, (x >= 2) & (x < oo)), (nan, True)) + assert Piecewise((1, x < 2), (2, (x > 1) & (x < 3)), (3, True) + ). simplify() == Piecewise((1, x < 2), (2, x < 3), (3, True)) + assert Piecewise((1, x < 2), (2, (x <= 3) & (x > 1)), (3, True) + ).simplify() == Piecewise((1, x < 2), (2, x <= 3), (3, True)) + assert Piecewise((1, x < 2), (2, (x > 2) & (x < 3)), (3, True) + ).simplify() == Piecewise((1, x < 2), (2, (x > 2) & (x < 3)), + (3, True)) + assert Piecewise((1, x < 2), (2, (x >= 1) & (x <= 3)), (3, True) + ).simplify() == Piecewise((1, x < 2), (2, x <= 3), (3, True)) + assert Piecewise((1, x < 1), (2, (x >= 2) & (x <= 3)), (3, True) + ).simplify() == Piecewise((1, x < 1), (2, (x >= 2) & (x <= 3)), + (3, True)) + # https://github.com/sympy/sympy/issues/25603 + assert Piecewise((log(x), (x <= 5) & (x > 3)), (x, True) + ).simplify() == Piecewise((log(x), (x <= 5) & (x > 3)), (x, True)) + + assert Piecewise((1, (x >= 1) & (x < 3)), (2, (x > 2) & (x < 4)) + ).simplify() == Piecewise((1, (x >= 1) & (x < 3)), ( + 2, (x >= 3) & (x < 4)), (nan, True)) + assert Piecewise((1, (x >= 1) & (x <= 3)), (2, (x > 2) & (x < 4)) + ).simplify() == Piecewise((1, (x >= 1) & (x <= 3)), ( + 2, (x > 3) & (x < 4)), (nan, True)) + + # involves a symbolic range so cset.inf fails + L = Symbol('L', nonnegative=True) + p = Piecewise((nan, x <= 0), (0, (x >= 0) & (L > x) & (L - x <= 0)), + (x - L/2, (L > x) & (L - x <= 0)), + (L/2 - x, (x >= 0) & (L > x)), + (0, L > x), (nan, True)) + assert p.simplify() == Piecewise( + (nan, x <= 0), (L/2 - x, L > x), (nan, True)) + assert p.subs(L, y).simplify() == Piecewise( + (nan, x <= 0), (-x + y/2, x < Max(0, y)), (0, x < y), (nan, True)) + + +def test_piecewise_solve(): + abs2 = Piecewise((-x, x <= 0), (x, x > 0)) + f = abs2.subs(x, x - 2) + assert solve(f, x) == [2] + assert solve(f - 1, x) == [1, 3] + + f = Piecewise(((x - 2)**2, x >= 0), (1, True)) + assert solve(f, x) == [2] + + g = Piecewise(((x - 5)**5, x >= 4), (f, True)) + assert solve(g, x) == [2, 5] + + g = Piecewise(((x - 5)**5, x >= 4), (f, x < 4)) + assert solve(g, x) == [2, 5] + + g = Piecewise(((x - 5)**5, x >= 2), (f, x < 2)) + assert solve(g, x) == [5] + + g = Piecewise(((x - 5)**5, x >= 2), (f, True)) + assert solve(g, x) == [5] + + g = Piecewise(((x - 5)**5, x >= 2), (f, True), (10, False)) + assert solve(g, x) == [5] + + g = Piecewise(((x - 5)**5, x >= 2), + (-x + 2, x - 2 <= 0), (x - 2, x - 2 > 0)) + assert solve(g, x) == [5] + + # if no symbol is given the piecewise detection must still work + assert solve(Piecewise((x - 2, x > 2), (2 - x, True)) - 3) == [-1, 5] + + f = Piecewise(((x - 2)**2, x >= 0), (0, True)) + raises(NotImplementedError, lambda: solve(f, x)) + + def nona(ans): + return list(filter(lambda x: x is not S.NaN, ans)) + p = Piecewise((x**2 - 4, x < y), (x - 2, True)) + ans = solve(p, x) + assert nona([i.subs(y, -2) for i in ans]) == [2] + assert nona([i.subs(y, 2) for i in ans]) == [-2, 2] + assert nona([i.subs(y, 3) for i in ans]) == [-2, 2] + assert ans == [ + Piecewise((-2, y > -2), (S.NaN, True)), + Piecewise((2, y <= 2), (S.NaN, True)), + Piecewise((2, y > 2), (S.NaN, True))] + + # issue 6060 + absxm3 = Piecewise( + (x - 3, 0 <= x - 3), + (3 - x, 0 > x - 3) + ) + assert solve(absxm3 - y, x) == [ + Piecewise((-y + 3, -y < 0), (S.NaN, True)), + Piecewise((y + 3, y >= 0), (S.NaN, True))] + p = Symbol('p', positive=True) + assert solve(absxm3 - p, x) == [-p + 3, p + 3] + + # issue 6989 + f = Function('f') + assert solve(Eq(-f(x), Piecewise((1, x > 0), (0, True))), f(x)) == \ + [Piecewise((-1, x > 0), (0, True))] + + # issue 8587 + f = Piecewise((2*x**2, And(0 < x, x < 1)), (2, True)) + assert solve(f - 1) == [1/sqrt(2)] + + +def test_piecewise_fold(): + p = Piecewise((x, x < 1), (1, 1 <= x)) + + assert piecewise_fold(x*p) == Piecewise((x**2, x < 1), (x, 1 <= x)) + assert piecewise_fold(p + p) == Piecewise((2*x, x < 1), (2, 1 <= x)) + assert piecewise_fold(Piecewise((1, x < 0), (2, True)) + + Piecewise((10, x < 0), (-10, True))) == \ + Piecewise((11, x < 0), (-8, True)) + + p1 = Piecewise((0, x < 0), (x, x <= 1), (0, True)) + p2 = Piecewise((0, x < 0), (1 - x, x <= 1), (0, True)) + + p = 4*p1 + 2*p2 + assert integrate( + piecewise_fold(p), (x, -oo, oo)) == integrate(2*x + 2, (x, 0, 1)) + + assert piecewise_fold( + Piecewise((1, y <= 0), (-Piecewise((2, y >= 0)), True) + )) == Piecewise((1, y <= 0), (-2, y >= 0)) + + assert piecewise_fold(Piecewise((x, ITE(x > 0, y < 1, y > 1))) + ) == Piecewise((x, ((x <= 0) | (y < 1)) & ((x > 0) | (y > 1)))) + + a, b = (Piecewise((2, Eq(x, 0)), (0, True)), + Piecewise((x, Eq(-x + y, 0)), (1, Eq(-x + y, 1)), (0, True))) + assert piecewise_fold(Mul(a, b, evaluate=False) + ) == piecewise_fold(Mul(b, a, evaluate=False)) + + +def test_piecewise_fold_piecewise_in_cond(): + p1 = Piecewise((cos(x), x < 0), (0, True)) + p2 = Piecewise((0, Eq(p1, 0)), (p1 / Abs(p1), True)) + assert p2.subs(x, -pi/2) == 0 + assert p2.subs(x, 1) == 0 + assert p2.subs(x, -pi/4) == 1 + p4 = Piecewise((0, Eq(p1, 0)), (1,True)) + ans = piecewise_fold(p4) + for i in range(-1, 1): + assert ans.subs(x, i) == p4.subs(x, i) + + r1 = 1 < Piecewise((1, x < 1), (3, True)) + ans = piecewise_fold(r1) + for i in range(2): + assert ans.subs(x, i) == r1.subs(x, i) + + p5 = Piecewise((1, x < 0), (3, True)) + p6 = Piecewise((1, x < 1), (3, True)) + p7 = Piecewise((1, p5 < p6), (0, True)) + ans = piecewise_fold(p7) + for i in range(-1, 2): + assert ans.subs(x, i) == p7.subs(x, i) + + +def test_piecewise_fold_piecewise_in_cond_2(): + p1 = Piecewise((cos(x), x < 0), (0, True)) + p2 = Piecewise((0, Eq(p1, 0)), (1 / p1, True)) + p3 = Piecewise( + (0, (x >= 0) | Eq(cos(x), 0)), + (1/cos(x), x < 0), + (zoo, True)) # redundant b/c all x are already covered + assert(piecewise_fold(p2) == p3) + + +def test_piecewise_fold_expand(): + p1 = Piecewise((1, Interval(0, 1, False, True).contains(x)), (0, True)) + + p2 = piecewise_fold(expand((1 - x)*p1)) + cond = ((x >= 0) & (x < 1)) + assert piecewise_fold(expand((1 - x)*p1), evaluate=False + ) == Piecewise((1 - x, cond), (-x, cond), (1, cond), (0, True), evaluate=False) + assert piecewise_fold(expand((1 - x)*p1), evaluate=None + ) == Piecewise((1 - x, cond), (0, True)) + assert p2 == Piecewise((1 - x, cond), (0, True)) + assert p2 == expand(piecewise_fold((1 - x)*p1)) + + +def test_piecewise_duplicate(): + p = Piecewise((x, x < -10), (x**2, x <= -1), (x, 1 < x)) + assert p == Piecewise(*p.args) + + +def test_doit(): + p1 = Piecewise((x, x < 1), (x**2, -1 <= x), (x, 3 < x)) + p2 = Piecewise((x, x < 1), (Integral(2 * x), -1 <= x), (x, 3 < x)) + assert p2.doit() == p1 + assert p2.doit(deep=False) == p2 + # issue 17165 + p1 = Sum(y**x, (x, -1, oo)).doit() + assert p1.doit() == p1 + + +def test_piecewise_interval(): + p1 = Piecewise((x, Interval(0, 1).contains(x)), (0, True)) + assert p1.subs(x, -0.5) == 0 + assert p1.subs(x, 0.5) == 0.5 + assert p1.diff(x) == Piecewise((1, Interval(0, 1).contains(x)), (0, True)) + assert integrate(p1, x) == Piecewise( + (0, x <= 0), + (x**2/2, x <= 1), + (S.Half, True)) + + +def test_piecewise_exclusive(): + p = Piecewise((0, x < 0), (S.Half, x <= 0), (1, True)) + assert piecewise_exclusive(p) == Piecewise((0, x < 0), (S.Half, Eq(x, 0)), + (1, x > 0), evaluate=False) + assert piecewise_exclusive(p + 2) == Piecewise((0, x < 0), (S.Half, Eq(x, 0)), + (1, x > 0), evaluate=False) + 2 + assert piecewise_exclusive(Piecewise((1, y <= 0), + (-Piecewise((2, y >= 0)), True))) == \ + Piecewise((1, y <= 0), + (-Piecewise((2, y >= 0), + (S.NaN, y < 0), evaluate=False), y > 0), evaluate=False) + assert piecewise_exclusive(Piecewise((1, x > y))) == Piecewise((1, x > y), + (S.NaN, x <= y), + evaluate=False) + assert piecewise_exclusive(Piecewise((1, x > y)), + skip_nan=True) == Piecewise((1, x > y)) + + xr, yr = symbols('xr, yr', real=True) + + p1 = Piecewise((1, xr < 0), (2, True), evaluate=False) + p1x = Piecewise((1, xr < 0), (2, xr >= 0), evaluate=False) + + p2 = Piecewise((p1, yr < 0), (3, True), evaluate=False) + p2x = Piecewise((p1, yr < 0), (3, yr >= 0), evaluate=False) + p2xx = Piecewise((p1x, yr < 0), (3, yr >= 0), evaluate=False) + + assert piecewise_exclusive(p2) == p2xx + assert piecewise_exclusive(p2, deep=False) == p2x + + +def test_piecewise_collapse(): + assert Piecewise((x, True)) == x + a = x < 1 + assert Piecewise((x, a), (x + 1, a)) == Piecewise((x, a)) + assert Piecewise((x, a), (x + 1, a.reversed)) == Piecewise((x, a)) + b = x < 5 + def canonical(i): + if isinstance(i, Piecewise): + return Piecewise(*i.args) + return i + for args in [ + ((1, a), (Piecewise((2, a), (3, b)), b)), + ((1, a), (Piecewise((2, a), (3, b.reversed)), b)), + ((1, a), (Piecewise((2, a), (3, b)), b), (4, True)), + ((1, a), (Piecewise((2, a), (3, b), (4, True)), b)), + ((1, a), (Piecewise((2, a), (3, b), (4, True)), b), (5, True))]: + for i in (0, 2, 10): + assert canonical( + Piecewise(*args, evaluate=False).subs(x, i) + ) == canonical(Piecewise(*args).subs(x, i)) + r1, r2, r3, r4 = symbols('r1:5') + a = x < r1 + b = x < r2 + c = x < r3 + d = x < r4 + assert Piecewise((1, a), (Piecewise( + (2, a), (3, b), (4, c)), b), (5, c) + ) == Piecewise((1, a), (3, b), (5, c)) + assert Piecewise((1, a), (Piecewise( + (2, a), (3, b), (4, c), (6, True)), c), (5, d) + ) == Piecewise((1, a), (Piecewise( + (3, b), (4, c)), c), (5, d)) + assert Piecewise((1, Or(a, d)), (Piecewise( + (2, d), (3, b), (4, c)), b), (5, c) + ) == Piecewise((1, Or(a, d)), (Piecewise( + (2, d), (3, b)), b), (5, c)) + assert Piecewise((1, c), (2, ~c), (3, S.true) + ) == Piecewise((1, c), (2, S.true)) + assert Piecewise((1, c), (2, And(~c, b)), (3,True) + ) == Piecewise((1, c), (2, b), (3, True)) + assert Piecewise((1, c), (2, Or(~c, b)), (3,True) + ).subs(dict(zip((r1, r2, r3, r4, x), (1, 2, 3, 4, 3.5)))) == 2 + assert Piecewise((1, c), (2, ~c)) == Piecewise((1, c), (2, True)) + + +def test_piecewise_lambdify(): + p = Piecewise( + (x**2, x < 0), + (x, Interval(0, 1, False, True).contains(x)), + (2 - x, x >= 1), + (0, True) + ) + + f = lambdify(x, p) + assert f(-2.0) == 4.0 + assert f(0.0) == 0.0 + assert f(0.5) == 0.5 + assert f(2.0) == 0.0 + + +def test_piecewise_series(): + from sympy.series.order import O + p1 = Piecewise((sin(x), x < 0), (cos(x), x > 0)) + p2 = Piecewise((x + O(x**2), x < 0), (1 + O(x**2), x > 0)) + assert p1.nseries(x, n=2) == p2 + + +def test_piecewise_as_leading_term(): + p1 = Piecewise((1/x, x > 1), (0, True)) + p2 = Piecewise((x, x > 1), (0, True)) + p3 = Piecewise((1/x, x > 1), (x, True)) + p4 = Piecewise((x, x > 1), (1/x, True)) + p5 = Piecewise((1/x, x > 1), (x, True)) + p6 = Piecewise((1/x, x < 1), (x, True)) + p7 = Piecewise((x, x < 1), (1/x, True)) + p8 = Piecewise((x, x > 1), (1/x, True)) + assert p1.as_leading_term(x) == 0 + assert p2.as_leading_term(x) == 0 + assert p3.as_leading_term(x) == x + assert p4.as_leading_term(x) == 1/x + assert p5.as_leading_term(x) == x + assert p6.as_leading_term(x) == 1/x + assert p7.as_leading_term(x) == x + assert p8.as_leading_term(x) == 1/x + + +def test_piecewise_complex(): + p1 = Piecewise((2, x < 0), (1, 0 <= x)) + p2 = Piecewise((2*I, x < 0), (I, 0 <= x)) + p3 = Piecewise((I*x, x > 1), (1 + I, True)) + p4 = Piecewise((-I*conjugate(x), x > 1), (1 - I, True)) + + assert conjugate(p1) == p1 + assert conjugate(p2) == piecewise_fold(-p2) + assert conjugate(p3) == p4 + + assert p1.is_imaginary is False + assert p1.is_real is True + assert p2.is_imaginary is True + assert p2.is_real is False + assert p3.is_imaginary is None + assert p3.is_real is None + + assert p1.as_real_imag() == (p1, 0) + assert p2.as_real_imag() == (0, -I*p2) + + +def test_conjugate_transpose(): + A, B = symbols("A B", commutative=False) + p = Piecewise((A*B**2, x > 0), (A**2*B, True)) + assert p.adjoint() == \ + Piecewise((adjoint(A*B**2), x > 0), (adjoint(A**2*B), True)) + assert p.conjugate() == \ + Piecewise((conjugate(A*B**2), x > 0), (conjugate(A**2*B), True)) + assert p.transpose() == \ + Piecewise((transpose(A*B**2), x > 0), (transpose(A**2*B), True)) + + +def test_piecewise_evaluate(): + assert Piecewise((x, True)) == x + assert Piecewise((x, True), evaluate=True) == x + assert Piecewise((1, Eq(1, x))).args == ((1, Eq(x, 1)),) + assert Piecewise((1, Eq(1, x)), evaluate=False).args == ( + (1, Eq(1, x)),) + # like the additive and multiplicative identities that + # cannot be kept in Add/Mul, we also do not keep a single True + p = Piecewise((x, True), evaluate=False) + assert p == x + + +def test_as_expr_set_pairs(): + assert Piecewise((x, x > 0), (-x, x <= 0)).as_expr_set_pairs() == \ + [(x, Interval(0, oo, True, True)), (-x, Interval(-oo, 0))] + + assert Piecewise(((x - 2)**2, x >= 0), (0, True)).as_expr_set_pairs() == \ + [((x - 2)**2, Interval(0, oo)), (0, Interval(-oo, 0, True, True))] + + +def test_S_srepr_is_identity(): + p = Piecewise((10, Eq(x, 0)), (12, True)) + q = S(srepr(p)) + assert p == q + + +def test_issue_12587(): + # sort holes into intervals + p = Piecewise((1, x > 4), (2, Not((x <= 3) & (x > -1))), (3, True)) + assert p.integrate((x, -5, 5)) == 23 + p = Piecewise((1, x > 1), (2, x < y), (3, True)) + lim = x, -3, 3 + ans = p.integrate(lim) + for i in range(-1, 3): + assert ans.subs(y, i) == p.subs(y, i).integrate(lim) + + +def test_issue_11045(): + assert integrate(1/(x*sqrt(x**2 - 1)), (x, 1, 2)) == pi/3 + + # handle And with Or arguments + assert Piecewise((1, And(Or(x < 1, x > 3), x < 2)), (0, True) + ).integrate((x, 0, 3)) == 1 + + # hidden false + assert Piecewise((1, x > 1), (2, x > x + 1), (3, True) + ).integrate((x, 0, 3)) == 5 + # targetcond is Eq + assert Piecewise((1, x > 1), (2, Eq(1, x)), (3, True) + ).integrate((x, 0, 4)) == 6 + # And has Relational needing to be solved + assert Piecewise((1, And(2*x > x + 1, x < 2)), (0, True) + ).integrate((x, 0, 3)) == 1 + # Or has Relational needing to be solved + assert Piecewise((1, Or(2*x > x + 2, x < 1)), (0, True) + ).integrate((x, 0, 3)) == 2 + # ignore hidden false (handled in canonicalization) + assert Piecewise((1, x > 1), (2, x > x + 1), (3, True) + ).integrate((x, 0, 3)) == 5 + # watch for hidden True Piecewise + assert Piecewise((2, Eq(1 - x, x*(1/x - 1))), (0, True) + ).integrate((x, 0, 3)) == 6 + + # overlapping conditions of targetcond are recognized and ignored; + # the condition x > 3 will be pre-empted by the first condition + assert Piecewise((1, Or(x < 1, x > 2)), (2, x > 3), (3, True) + ).integrate((x, 0, 4)) == 6 + + # convert Ne to Or + assert Piecewise((1, Ne(x, 0)), (2, True) + ).integrate((x, -1, 1)) == 2 + + # no default but well defined + assert Piecewise((x, (x > 1) & (x < 3)), (1, (x < 4)) + ).integrate((x, 1, 4)) == 5 + + p = Piecewise((x, (x > 1) & (x < 3)), (1, (x < 4))) + nan = Undefined + i = p.integrate((x, 1, y)) + assert i == Piecewise( + (y - 1, y < 1), + (Min(3, y)**2/2 - Min(3, y) + Min(4, y) - S.Half, + y <= Min(4, y)), + (nan, True)) + assert p.integrate((x, 1, -1)) == i.subs(y, -1) + assert p.integrate((x, 1, 4)) == 5 + assert p.integrate((x, 1, 5)) is nan + + # handle Not + p = Piecewise((1, x > 1), (2, Not(And(x > 1, x< 3))), (3, True)) + assert p.integrate((x, 0, 3)) == 4 + + # handle updating of int_expr when there is overlap + p = Piecewise( + (1, And(5 > x, x > 1)), + (2, Or(x < 3, x > 7)), + (4, x < 8)) + assert p.integrate((x, 0, 10)) == 20 + + # And with Eq arg handling + assert Piecewise((1, x < 1), (2, And(Eq(x, 3), x > 1)) + ).integrate((x, 0, 3)) is S.NaN + assert Piecewise((1, x < 1), (2, And(Eq(x, 3), x > 1)), (3, True) + ).integrate((x, 0, 3)) == 7 + assert Piecewise((1, x < 0), (2, And(Eq(x, 3), x < 1)), (3, True) + ).integrate((x, -1, 1)) == 4 + # middle condition doesn't matter: it's a zero width interval + assert Piecewise((1, x < 1), (2, Eq(x, 3) & (y < x)), (3, True) + ).integrate((x, 0, 3)) == 7 + + +def test_holes(): + nan = Undefined + assert Piecewise((1, x < 2)).integrate(x) == Piecewise( + (x, x < 2), (nan, True)) + assert Piecewise((1, And(x > 1, x < 2))).integrate(x) == Piecewise( + (nan, x < 1), (x, x < 2), (nan, True)) + assert Piecewise((1, And(x > 1, x < 2))).integrate((x, 0, 3)) is nan + assert Piecewise((1, And(x > 0, x < 4))).integrate((x, 1, 3)) == 2 + + # this also tests that the integrate method is used on non-Piecwise + # arguments in _eval_integral + A, B = symbols("A B") + a, b = symbols('a b', real=True) + assert Piecewise((A, And(x < 0, a < 1)), (B, Or(x < 1, a > 2)) + ).integrate(x) == Piecewise( + (B*x, (a > 2)), + (Piecewise((A*x, x < 0), (B*x, x < 1), (nan, True)), a < 1), + (Piecewise((B*x, x < 1), (nan, True)), True)) + + +def test_issue_11922(): + def f(x): + return Piecewise((0, x < -1), (1 - x**2, x < 1), (0, True)) + autocorr = lambda k: ( + f(x) * f(x + k)).integrate((x, -1, 1)) + assert autocorr(1.9) > 0 + k = symbols('k') + good_autocorr = lambda k: ( + (1 - x**2) * f(x + k)).integrate((x, -1, 1)) + a = good_autocorr(k) + assert a.subs(k, 3) == 0 + k = symbols('k', positive=True) + a = good_autocorr(k) + assert a.subs(k, 3) == 0 + assert Piecewise((0, x < 1), (10, (x >= 1)) + ).integrate() == Piecewise((0, x < 1), (10*x - 10, True)) + + +def test_issue_5227(): + f = 0.0032513612725229*Piecewise((0, x < -80.8461538461539), + (-0.0160799238820171*x + 1.33215984776403, x < 2), + (Piecewise((0.3, x > 123), (0.7, True)) + + Piecewise((0.4, x > 2), (0.6, True)), x <= + 123), (-0.00817409766454352*x + 2.10541401273885, x < + 380.571428571429), (0, True)) + i = integrate(f, (x, -oo, oo)) + assert i == Integral(f, (x, -oo, oo)).doit() + assert str(i) == '1.00195081676351' + assert Piecewise((1, x - y < 0), (0, True) + ).integrate(y) == Piecewise((0, y <= x), (-x + y, True)) + + +def test_issue_10137(): + a = Symbol('a', real=True) + b = Symbol('b', real=True) + x = Symbol('x', real=True) + y = Symbol('y', real=True) + p0 = Piecewise((0, Or(x < a, x > b)), (1, True)) + p1 = Piecewise((0, Or(a > x, b < x)), (1, True)) + assert integrate(p0, (x, y, oo)) == integrate(p1, (x, y, oo)) + p3 = Piecewise((1, And(0 < x, x < a)), (0, True)) + p4 = Piecewise((1, And(a > x, x > 0)), (0, True)) + ip3 = integrate(p3, x) + assert ip3 == Piecewise( + (0, x <= 0), + (x, x <= Max(0, a)), + (Max(0, a), True)) + ip4 = integrate(p4, x) + assert ip4 == ip3 + assert p3.integrate((x, 2, 4)) == Min(4, Max(2, a)) - 2 + assert p4.integrate((x, 2, 4)) == Min(4, Max(2, a)) - 2 + + +def test_stackoverflow_43852159(): + f = lambda x: Piecewise((1, (x >= -1) & (x <= 1)), (0, True)) + Conv = lambda x: integrate(f(x - y)*f(y), (y, -oo, +oo)) + cx = Conv(x) + assert cx.subs(x, -1.5) == cx.subs(x, 1.5) + assert cx.subs(x, 3) == 0 + assert piecewise_fold(f(x - y)*f(y)) == Piecewise( + (1, (y >= -1) & (y <= 1) & (x - y >= -1) & (x - y <= 1)), + (0, True)) + + +def test_issue_12557(): + ''' + # 3200 seconds to compute the fourier part of issue + import sympy as sym + x,y,z,t = sym.symbols('x y z t') + k = sym.symbols("k", integer=True) + fourier = sym.fourier_series(sym.cos(k*x)*sym.sqrt(x**2), + (x, -sym.pi, sym.pi)) + assert fourier == FourierSeries( + sqrt(x**2)*cos(k*x), (x, -pi, pi), (Piecewise((pi**2, + Eq(k, 0)), (2*(-1)**k/k**2 - 2/k**2, True))/(2*pi), + SeqFormula(Piecewise((pi**2, (Eq(_n, 0) & Eq(k, 0)) | (Eq(_n, 0) & + Eq(_n, k) & Eq(k, 0)) | (Eq(_n, 0) & Eq(k, 0) & Eq(_n, -k)) | (Eq(_n, + 0) & Eq(_n, k) & Eq(k, 0) & Eq(_n, -k))), (pi**2/2, Eq(_n, k) | Eq(_n, + -k) | (Eq(_n, 0) & Eq(_n, k)) | (Eq(_n, k) & Eq(k, 0)) | (Eq(_n, 0) & + Eq(_n, -k)) | (Eq(_n, k) & Eq(_n, -k)) | (Eq(k, 0) & Eq(_n, -k)) | + (Eq(_n, 0) & Eq(_n, k) & Eq(_n, -k)) | (Eq(_n, k) & Eq(k, 0) & Eq(_n, + -k))), ((-1)**k*pi**2*_n**3*sin(pi*_n)/(pi*_n**4 - 2*pi*_n**2*k**2 + + pi*k**4) - (-1)**k*pi**2*_n**3*sin(pi*_n)/(-pi*_n**4 + 2*pi*_n**2*k**2 + - pi*k**4) + (-1)**k*pi*_n**2*cos(pi*_n)/(pi*_n**4 - 2*pi*_n**2*k**2 + + pi*k**4) - (-1)**k*pi*_n**2*cos(pi*_n)/(-pi*_n**4 + 2*pi*_n**2*k**2 - + pi*k**4) - (-1)**k*pi**2*_n*k**2*sin(pi*_n)/(pi*_n**4 - + 2*pi*_n**2*k**2 + pi*k**4) + + (-1)**k*pi**2*_n*k**2*sin(pi*_n)/(-pi*_n**4 + 2*pi*_n**2*k**2 - + pi*k**4) + (-1)**k*pi*k**2*cos(pi*_n)/(pi*_n**4 - 2*pi*_n**2*k**2 + + pi*k**4) - (-1)**k*pi*k**2*cos(pi*_n)/(-pi*_n**4 + 2*pi*_n**2*k**2 - + pi*k**4) - (2*_n**2 + 2*k**2)/(_n**4 - 2*_n**2*k**2 + k**4), + True))*cos(_n*x)/pi, (_n, 1, oo)), SeqFormula(0, (_k, 1, oo)))) + ''' + x = symbols("x", real=True) + k = symbols('k', integer=True, finite=True) + abs2 = lambda x: Piecewise((-x, x <= 0), (x, x > 0)) + assert integrate(abs2(x), (x, -pi, pi)) == pi**2 + func = cos(k*x)*sqrt(x**2) + assert integrate(func, (x, -pi, pi)) == Piecewise( + (2*(-1)**k/k**2 - 2/k**2, Ne(k, 0)), (pi**2, True)) + +def test_issue_6900(): + from itertools import permutations + t0, t1, T, t = symbols('t0, t1 T t') + f = Piecewise((0, t < t0), (x, And(t0 <= t, t < t1)), (0, t >= t1)) + g = f.integrate(t) + assert g == Piecewise( + (0, t <= t0), + (t*x - t0*x, t <= Max(t0, t1)), + (-t0*x + x*Max(t0, t1), True)) + for i in permutations(range(2)): + reps = dict(zip((t0,t1), i)) + for tt in range(-1,3): + assert (g.xreplace(reps).subs(t,tt) == + f.xreplace(reps).integrate(t).subs(t,tt)) + lim = Tuple(t, t0, T) + g = f.integrate(lim) + ans = Piecewise( + (-t0*x + x*Min(T, Max(t0, t1)), T > t0), + (0, True)) + for i in permutations(range(3)): + reps = dict(zip((t0,t1,T), i)) + tru = f.xreplace(reps).integrate(lim.xreplace(reps)) + assert tru == ans.xreplace(reps) + assert g == ans + + +def test_issue_10122(): + assert solve(abs(x) + abs(x - 1) - 1 > 0, x + ) == Or(And(-oo < x, x < S.Zero), And(S.One < x, x < oo)) + + +def test_issue_4313(): + u = Piecewise((0, x <= 0), (1, x >= a), (x/a, True)) + e = (u - u.subs(x, y))**2/(x - y)**2 + M = Max(0, a) + assert integrate(e, x).expand() == Piecewise( + (Piecewise( + (0, x <= 0), + (-y**2/(a**2*x - a**2*y) + x/a**2 - 2*y*log(-y)/a**2 + + 2*y*log(x - y)/a**2 - y/a**2, x <= M), + (-y**2/(-a**2*y + a**2*M) + 1/(-y + M) - + 1/(x - y) - 2*y*log(-y)/a**2 + 2*y*log(-y + + M)/a**2 - y/a**2 + M/a**2, True)), + ((a <= y) & (y <= 0)) | ((y <= 0) & (y > -oo))), + (Piecewise( + (-1/(x - y), x <= 0), + (-a**2/(a**2*x - a**2*y) + 2*a*y/(a**2*x - a**2*y) - + y**2/(a**2*x - a**2*y) + 2*log(-y)/a - 2*log(x - y)/a + + 2/a + x/a**2 - 2*y*log(-y)/a**2 + 2*y*log(x - y)/a**2 - + y/a**2, x <= M), + (-a**2/(-a**2*y + a**2*M) + 2*a*y/(-a**2*y + + a**2*M) - y**2/(-a**2*y + a**2*M) + + 2*log(-y)/a - 2*log(-y + M)/a + 2/a - + 2*y*log(-y)/a**2 + 2*y*log(-y + M)/a**2 - + y/a**2 + M/a**2, True)), + a <= y), + (Piecewise( + (-y**2/(a**2*x - a**2*y), x <= 0), + (x/a**2 + y/a**2, x <= M), + (a**2/(-a**2*y + a**2*M) - + a**2/(a**2*x - a**2*y) - 2*a*y/(-a**2*y + a**2*M) + + 2*a*y/(a**2*x - a**2*y) + y**2/(-a**2*y + a**2*M) - + y**2/(a**2*x - a**2*y) + y/a**2 + M/a**2, True)), + True)) + + +def test__intervals(): + assert Piecewise((x + 2, Eq(x, 3)))._intervals(x) == (True, []) + assert Piecewise( + (1, x > x + 1), + (Piecewise((1, x < x + 1)), 2*x < 2*x + 1), + (1, True))._intervals(x) == (True, [(-oo, oo, 1, 1)]) + assert Piecewise((1, Ne(x, I)), (0, True))._intervals(x) == (True, + [(-oo, oo, 1, 0)]) + assert Piecewise((-cos(x), sin(x) >= 0), (cos(x), True) + )._intervals(x) == (True, + [(0, pi, -cos(x), 0), (-oo, oo, cos(x), 1)]) + # the following tests that duplicates are removed and that non-Eq + # generated zero-width intervals are removed + assert Piecewise((1, Abs(x**(-2)) > 1), (0, True) + )._intervals(x) == (True, + [(-1, 0, 1, 0), (0, 1, 1, 0), (-oo, oo, 0, 1)]) + + +def test_containment(): + a, b, c, d, e = [1, 2, 3, 4, 5] + p = (Piecewise((d, x > 1), (e, True))* + Piecewise((a, Abs(x - 1) < 1), (b, Abs(x - 2) < 2), (c, True))) + assert p.integrate(x).diff(x) == Piecewise( + (c*e, x <= 0), + (a*e, x <= 1), + (a*d, x < 2), # this is what we want to get right + (b*d, x < 4), + (c*d, True)) + + +def test_piecewise_with_DiracDelta(): + d1 = DiracDelta(x - 1) + assert integrate(d1, (x, -oo, oo)) == 1 + assert integrate(d1, (x, 0, 2)) == 1 + assert Piecewise((d1, Eq(x, 2)), (0, True)).integrate(x) == 0 + assert Piecewise((d1, x < 2), (0, True)).integrate(x) == Piecewise( + (Heaviside(x - 1), x < 2), (1, True)) + # TODO raise error if function is discontinuous at limit of + # integration, e.g. integrate(d1, (x, -2, 1)) or Piecewise( + # (d1, Eq(x, 1) + + +def test_issue_10258(): + assert Piecewise((0, x < 1), (1, True)).is_zero is None + assert Piecewise((-1, x < 1), (1, True)).is_zero is False + a = Symbol('a', zero=True) + assert Piecewise((0, x < 1), (a, True)).is_zero + assert Piecewise((1, x < 1), (a, x < 3)).is_zero is None + a = Symbol('a') + assert Piecewise((0, x < 1), (a, True)).is_zero is None + assert Piecewise((0, x < 1), (1, True)).is_nonzero is None + assert Piecewise((1, x < 1), (2, True)).is_nonzero + assert Piecewise((0, x < 1), (oo, True)).is_finite is None + assert Piecewise((0, x < 1), (1, True)).is_finite + b = Basic() + assert Piecewise((b, x < 1)).is_finite is None + + # 10258 + c = Piecewise((1, x < 0), (2, True)) < 3 + assert c != True + assert piecewise_fold(c) == True + + +def test_issue_10087(): + a, b = Piecewise((x, x > 1), (2, True)), Piecewise((x, x > 3), (3, True)) + m = a*b + f = piecewise_fold(m) + for i in (0, 2, 4): + assert m.subs(x, i) == f.subs(x, i) + m = a + b + f = piecewise_fold(m) + for i in (0, 2, 4): + assert m.subs(x, i) == f.subs(x, i) + + +def test_issue_8919(): + c = symbols('c:5') + x = symbols("x") + f1 = Piecewise((c[1], x < 1), (c[2], True)) + f2 = Piecewise((c[3], x < Rational(1, 3)), (c[4], True)) + assert integrate(f1*f2, (x, 0, 2) + ) == c[1]*c[3]/3 + 2*c[1]*c[4]/3 + c[2]*c[4] + f1 = Piecewise((0, x < 1), (2, True)) + f2 = Piecewise((3, x < 2), (0, True)) + assert integrate(f1*f2, (x, 0, 3)) == 6 + + y = symbols("y", positive=True) + a, b, c, x, z = symbols("a,b,c,x,z", real=True) + I = Integral(Piecewise( + (0, (x >= y) | (x < 0) | (b > c)), + (a, True)), (x, 0, z)) + ans = I.doit() + assert ans == Piecewise((0, b > c), (a*Min(y, z) - a*Min(0, z), True)) + for cond in (True, False): + for yy in range(1, 3): + for zz in range(-yy, 0, yy): + reps = [(b > c, cond), (y, yy), (z, zz)] + assert ans.subs(reps) == I.subs(reps).doit() + + +def test_unevaluated_integrals(): + f = Function('f') + p = Piecewise((1, Eq(f(x) - 1, 0)), (2, x - 10 < 0), (0, True)) + assert p.integrate(x) == Integral(p, x) + assert p.integrate((x, 0, 5)) == Integral(p, (x, 0, 5)) + # test it by replacing f(x) with x%2 which will not + # affect the answer: the integrand is essentially 2 over + # the domain of integration + assert Integral(p, (x, 0, 5)).subs(f(x), x%2).n() == 10.0 + + # this is a test of using _solve_inequality when + # solve_univariate_inequality fails + assert p.integrate(y) == Piecewise( + (y, Eq(f(x), 1) | ((x < 10) & Eq(f(x), 1))), + (2*y, (x > -oo) & (x < 10)), (0, True)) + + +def test_conditions_as_alternate_booleans(): + a, b, c = symbols('a:c') + assert Piecewise((x, Piecewise((y < 1, x > 0), (y > 1, True))) + ) == Piecewise((x, ITE(x > 0, y < 1, y > 1))) + + +def test_Piecewise_rewrite_as_ITE(): + a, b, c, d = symbols('a:d') + + def _ITE(*args): + return Piecewise(*args).rewrite(ITE) + + assert _ITE((a, x < 1), (b, x >= 1)) == ITE(x < 1, a, b) + assert _ITE((a, x < 1), (b, x < oo)) == ITE(x < 1, a, b) + assert _ITE((a, x < 1), (b, Or(y < 1, x < oo)), (c, y > 0) + ) == ITE(x < 1, a, b) + assert _ITE((a, x < 1), (b, True)) == ITE(x < 1, a, b) + assert _ITE((a, x < 1), (b, x < 2), (c, True) + ) == ITE(x < 1, a, ITE(x < 2, b, c)) + assert _ITE((a, x < 1), (b, y < 2), (c, True) + ) == ITE(x < 1, a, ITE(y < 2, b, c)) + assert _ITE((a, x < 1), (b, x < oo), (c, y < 1) + ) == ITE(x < 1, a, b) + assert _ITE((a, x < 1), (c, y < 1), (b, x < oo), (d, True) + ) == ITE(x < 1, a, ITE(y < 1, c, b)) + assert _ITE((a, x < 0), (b, Or(x < oo, y < 1)) + ) == ITE(x < 0, a, b) + raises(TypeError, lambda: _ITE((x + 1, x < 1), (x, True))) + # if `a` in the following were replaced with y then the coverage + # is complete but something other than as_set would need to be + # used to detect this + raises(NotImplementedError, lambda: _ITE((x, x < y), (y, x >= a))) + raises(ValueError, lambda: _ITE((a, x < 2), (b, x > 3))) + + +def test_Piecewise_replace_relational_27538(): + x, y = symbols('x, y') + p1 = Piecewise( + (0, Eq(x, True)), + (1, True), + ) + p2 = p1.xreplace({x: y < 1}) + assert p2.subs(y, 0) == 0 + assert p2.subs(y, 1) == 1 + + +def test_issue_14052(): + assert integrate(abs(sin(x)), (x, 0, 2*pi)) == 4 + + +def test_issue_14240(): + assert piecewise_fold( + Piecewise((1, a), (2, b), (4, True)) + + Piecewise((8, a), (16, True)) + ) == Piecewise((9, a), (18, b), (20, True)) + assert piecewise_fold( + Piecewise((2, a), (3, b), (5, True)) * + Piecewise((7, a), (11, True)) + ) == Piecewise((14, a), (33, b), (55, True)) + # these will hang if naive folding is used + assert piecewise_fold(Add(*[ + Piecewise((i, a), (0, True)) for i in range(40)]) + ) == Piecewise((780, a), (0, True)) + assert piecewise_fold(Mul(*[ + Piecewise((i, a), (0, True)) for i in range(1, 41)]) + ) == Piecewise((factorial(40), a), (0, True)) + + +def test_issue_14787(): + x = Symbol('x') + f = Piecewise((x, x < 1), ((S(58) / 7), True)) + assert str(f.evalf()) == "Piecewise((x, x < 1), (8.28571428571429, True))" + +def test_issue_21481(): + b, e = symbols('b e') + C = Piecewise( + (2, + ((b > 1) & (e > 0)) | + ((b > 0) & (b < 1) & (e < 0)) | + ((e >= 2) & (b < -1) & Eq(Mod(e, 2), 0)) | + ((e <= -2) & (b > -1) & (b < 0) & Eq(Mod(e, 2), 0))), + (S.Half, + ((b > 1) & (e < 0)) | + ((b > 0) & (e > 0) & (b < 1)) | + ((e <= -2) & (b < -1) & Eq(Mod(e, 2), 0)) | + ((e >= 2) & (b > -1) & (b < 0) & Eq(Mod(e, 2), 0))), + (-S.Half, + Eq(Mod(e, 2), 1) & + (((e <= -1) & (b < -1)) | ((e >= 1) & (b > -1) & (b < 0)))), + (-2, + ((e >= 1) & (b < -1) & Eq(Mod(e, 2), 1)) | + ((e <= -1) & (b > -1) & (b < 0) & Eq(Mod(e, 2), 1))) + ) + A = Piecewise( + (1, Eq(b, 1) | Eq(e, 0) | (Eq(b, -1) & Eq(Mod(e, 2), 0))), + (0, Eq(b, 0) & (e > 0)), + (-1, Eq(b, -1) & Eq(Mod(e, 2), 1)), + (C, Eq(im(b), 0) & Eq(im(e), 0)) + ) + + B = piecewise_fold(A) + sa = A.simplify() + sb = B.simplify() + v = (-2, -1, -S.Half, 0, S.Half, 1, 2) + for i in v: + for j in v: + r = {b:i, e:j} + ok = [k.xreplace(r) for k in (A, B, sa, sb)] + assert len(set(ok)) == 1 + + +def test_issue_8458(): + x, y = symbols('x y') + # Original issue + p1 = Piecewise((0, Eq(x, 0)), (sin(x), True)) + assert p1.simplify() == sin(x) + # Slightly larger variant + p2 = Piecewise((x, Eq(x, 0)), (4*x + (y-2)**4, Eq(x, 0) & Eq(x+y, 2)), (sin(x), True)) + assert p2.simplify() == sin(x) + # Test for problem highlighted during review + p3 = Piecewise((x+1, Eq(x, -1)), (4*x + (y-2)**4, Eq(x, 0) & Eq(x+y, 2)), (sin(x), True)) + assert p3.simplify() == Piecewise((0, Eq(x, -1)), (sin(x), True)) + + +def test_issue_16417(): + z = Symbol('z') + assert unchanged(Piecewise, (1, Or(Eq(im(z), 0), Gt(re(z), 0))), (2, True)) + + x = Symbol('x') + assert unchanged(Piecewise, (S.Pi, re(x) < 0), + (0, Or(re(x) > 0, Ne(im(x), 0))), + (S.NaN, True)) + r = Symbol('r', real=True) + p = Piecewise((S.Pi, re(r) < 0), + (0, Or(re(r) > 0, Ne(im(r), 0))), + (S.NaN, True)) + assert p == Piecewise((S.Pi, r < 0), + (0, r > 0), + (S.NaN, True), evaluate=False) + # Does not work since imaginary != 0... + #i = Symbol('i', imaginary=True) + #p = Piecewise((S.Pi, re(i) < 0), + # (0, Or(re(i) > 0, Ne(im(i), 0))), + # (S.NaN, True)) + #assert p == Piecewise((0, Ne(im(i), 0)), + # (S.NaN, True), evaluate=False) + i = I*r + p = Piecewise((S.Pi, re(i) < 0), + (0, Or(re(i) > 0, Ne(im(i), 0))), + (S.NaN, True)) + assert p == Piecewise((0, Ne(im(i), 0)), + (S.NaN, True), evaluate=False) + assert p == Piecewise((0, Ne(r, 0)), + (S.NaN, True), evaluate=False) + + +def test_eval_rewrite_as_KroneckerDelta(): + x, y, z, n, t, m = symbols('x y z n t m') + K = KroneckerDelta + f = lambda p: expand(p.rewrite(K)) + + p1 = Piecewise((0, Eq(x, y)), (1, True)) + assert f(p1) == 1 - K(x, y) + + p2 = Piecewise((x, Eq(y,0)), (z, Eq(t,0)), (n, True)) + assert f(p2) == n*K(0, t)*K(0, y) - n*K(0, t) - n*K(0, y) + n + \ + x*K(0, y) - z*K(0, t)*K(0, y) + z*K(0, t) + + p3 = Piecewise((1, Ne(x, y)), (0, True)) + assert f(p3) == 1 - K(x, y) + + p4 = Piecewise((1, Eq(x, 3)), (4, True), (5, True)) + assert f(p4) == 4 - 3*K(3, x) + + p5 = Piecewise((3, Ne(x, 2)), (4, Eq(y, 2)), (5, True)) + assert f(p5) == -K(2, x)*K(2, y) + 2*K(2, x) + 3 + + p6 = Piecewise((0, Ne(x, 1) & Ne(y, 4)), (1, True)) + assert f(p6) == -K(1, x)*K(4, y) + K(1, x) + K(4, y) + + p7 = Piecewise((2, Eq(y, 3) & Ne(x, 2)), (1, True)) + assert f(p7) == -K(2, x)*K(3, y) + K(3, y) + 1 + + p8 = Piecewise((4, Eq(x, 3) & Ne(y, 2)), (1, True)) + assert f(p8) == -3*K(2, y)*K(3, x) + 3*K(3, x) + 1 + + p9 = Piecewise((6, Eq(x, 4) & Eq(y, 1)), (1, True)) + assert f(p9) == 5 * K(1, y) * K(4, x) + 1 + + p10 = Piecewise((4, Ne(x, -4) | Ne(y, 1)), (1, True)) + assert f(p10) == -3 * K(-4, x) * K(1, y) + 4 + + p11 = Piecewise((1, Eq(y, 2) | Ne(x, -3)), (2, True)) + assert f(p11) == -K(-3, x)*K(2, y) + K(-3, x) + 1 + + p12 = Piecewise((-1, Eq(x, 1) | Ne(y, 3)), (1, True)) + assert f(p12) == -2*K(1, x)*K(3, y) + 2*K(3, y) - 1 + + p13 = Piecewise((3, Eq(x, 2) | Eq(y, 4)), (1, True)) + assert f(p13) == -2*K(2, x)*K(4, y) + 2*K(2, x) + 2*K(4, y) + 1 + + p14 = Piecewise((1, Ne(x, 0) | Ne(y, 1)), (3, True)) + assert f(p14) == 2 * K(0, x) * K(1, y) + 1 + + p15 = Piecewise((2, Eq(x, 3) | Ne(y, 2)), (3, Eq(x, 4) & Eq(y, 5)), (1, True)) + assert f(p15) == -2*K(2, y)*K(3, x)*K(4, x)*K(5, y) + K(2, y)*K(3, x) + \ + 2*K(2, y)*K(4, x)*K(5, y) - K(2, y) + 2 + + p16 = Piecewise((0, Ne(m, n)), (1, True))*Piecewise((0, Ne(n, t)), (1, True))\ + *Piecewise((0, Ne(n, x)), (1, True)) - Piecewise((0, Ne(t, x)), (1, True)) + assert f(p16) == K(m, n)*K(n, t)*K(n, x) - K(t, x) + + p17 = Piecewise((0, Ne(t, x) & (Ne(m, n) | Ne(n, t) | Ne(n, x))), + (1, Ne(t, x)), (-1, Ne(m, n) | Ne(n, t) | Ne(n, x)), (0, True)) + assert f(p17) == K(m, n)*K(n, t)*K(n, x) - K(t, x) + + p18 = Piecewise((-4, Eq(y, 1) | (Eq(x, -5) & Eq(x, z))), (4, True)) + assert f(p18) == 8*K(-5, x)*K(1, y)*K(x, z) - 8*K(-5, x)*K(x, z) - 8*K(1, y) + 4 + + p19 = Piecewise((0, x > 2), (1, True)) + assert f(p19) == p19 + + p20 = Piecewise((0, And(x < 2, x > -5)), (1, True)) + assert f(p20) == p20 + + p21 = Piecewise((0, Or(x > 1, x < 0)), (1, True)) + assert f(p21) == p21 + + p22 = Piecewise((0, ~((Eq(y, -1) | Ne(x, 0)) & (Ne(x, 1) | Ne(y, -1)))), (1, True)) + assert f(p22) == K(-1, y)*K(0, x) - K(-1, y)*K(1, x) - K(0, x) + 1 + + +@slow +def test_identical_conds_issue(): + from sympy.stats import Uniform, density + u1 = Uniform('u1', 0, 1) + u2 = Uniform('u2', 0, 1) + # Result is quite big, so not really important here (and should ideally be + # simpler). Should not give an exception though. + density(u1 + u2) + + +def test_issue_7370(): + f = Piecewise((1, x <= 2400)) + v = integrate(f, (x, 0, Float("252.4", 30))) + assert str(v) == '252.400000000000000000000000000' + + +def test_issue_14933(): + x = Symbol('x') + y = Symbol('y') + + inp = MatrixSymbol('inp', 1, 1) + rep_dict = {y: inp[0, 0], x: inp[0, 0]} + + p = Piecewise((1, ITE(y > 0, x < 0, True))) + assert p.xreplace(rep_dict) == Piecewise((1, ITE(inp[0, 0] > 0, inp[0, 0] < 0, True))) + + +def test_issue_16715(): + raises(NotImplementedError, lambda: Piecewise((x, x<0), (0, y>1)).as_expr_set_pairs()) + + +def test_issue_20360(): + t, tau = symbols("t tau", real=True) + n = symbols("n", integer=True) + lam = pi * (n - S.Half) + eq = integrate(exp(lam * tau), (tau, 0, t)) + assert eq.simplify() == (2*exp(pi*t*(2*n - 1)/2) - 2)/(pi*(2*n - 1)) + + +def test_piecewise_eval(): + # XXX these tests might need modification if this + # simplification is moved out of eval and into + # boolalg or Piecewise simplification functions + f = lambda x: x.args[0].cond + # unsimplified + assert f(Piecewise((x, (x > -oo) & (x < 3))) + ) == ((x > -oo) & (x < 3)) + assert f(Piecewise((x, (x > -oo) & (x < oo))) + ) == ((x > -oo) & (x < oo)) + assert f(Piecewise((x, (x > -3) & (x < 3))) + ) == ((x > -3) & (x < 3)) + assert f(Piecewise((x, (x > -3) & (x < oo))) + ) == ((x > -3) & (x < oo)) + assert f(Piecewise((x, (x <= 3) & (x > -oo))) + ) == ((x <= 3) & (x > -oo)) + assert f(Piecewise((x, (x <= 3) & (x > -3))) + ) == ((x <= 3) & (x > -3)) + assert f(Piecewise((x, (x >= -3) & (x < 3))) + ) == ((x >= -3) & (x < 3)) + assert f(Piecewise((x, (x >= -3) & (x < oo))) + ) == ((x >= -3) & (x < oo)) + assert f(Piecewise((x, (x >= -3) & (x <= 3))) + ) == ((x >= -3) & (x <= 3)) + # could simplify by keeping only the first + # arg of result + assert f(Piecewise((x, (x <= oo) & (x > -oo))) + ) == (x > -oo) & (x <= oo) + assert f(Piecewise((x, (x <= oo) & (x > -3))) + ) == (x > -3) & (x <= oo) + assert f(Piecewise((x, (x >= -oo) & (x < 3))) + ) == (x < 3) & (x >= -oo) + assert f(Piecewise((x, (x >= -oo) & (x < oo))) + ) == (x < oo) & (x >= -oo) + assert f(Piecewise((x, (x >= -oo) & (x <= 3))) + ) == (x <= 3) & (x >= -oo) + assert f(Piecewise((x, (x >= -oo) & (x <= oo))) + ) == (x <= oo) & (x >= -oo) # but cannot be True unless x is real + assert f(Piecewise((x, (x >= -3) & (x <= oo))) + ) == (x >= -3) & (x <= oo) + assert f(Piecewise((x, (Abs(arg(a)) <= 1) | (Abs(arg(a)) < 1))) + ) == (Abs(arg(a)) <= 1) | (Abs(arg(a)) < 1) + + +def test_issue_22533(): + x = Symbol('x', real=True) + f = Piecewise((-1 / x, x <= 0), (1 / x, True)) + assert integrate(f, x) == Piecewise((-log(x), x <= 0), (log(x), True)) + + +def test_issue_24072(): + assert Piecewise((1, x > 1), (2, x <= 1), (3, x <= 1) + ) == Piecewise((1, x > 1), (2, True)) + + +def test_piecewise__eval_is_meromorphic(): + """ Issue 24127: Tests eval_is_meromorphic auxiliary method """ + x = symbols('x', real=True) + f = Piecewise((1, x < 0), (sqrt(1 - x), True)) + assert f.is_meromorphic(x, I) is None + assert f.is_meromorphic(x, -1) == True + assert f.is_meromorphic(x, 0) == None + assert f.is_meromorphic(x, 1) == False + assert f.is_meromorphic(x, 2) == True + assert f.is_meromorphic(x, Symbol('a')) == None + assert f.is_meromorphic(x, Symbol('a', real=True)) == None diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/test_trigonometric.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/test_trigonometric.py new file mode 100644 index 0000000000000000000000000000000000000000..815f424093aac72ee3a078d8ce62e5c195a625dc --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/tests/test_trigonometric.py @@ -0,0 +1,2236 @@ +from sympy.calculus.accumulationbounds import AccumBounds +from sympy.core.add import Add +from sympy.core.function import (Lambda, diff) +from sympy.core.mod import Mod +from sympy.core.mul import Mul +from sympy.core.numbers import (E, Float, I, Rational, nan, oo, pi, zoo) +from sympy.core.power import Pow +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.elementary.complexes import (arg, conjugate, im, re) +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.hyperbolic import (acoth, asinh, atanh, cosh, coth, sinh, tanh) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (acos, acot, acsc, asec, asin, atan, atan2, + cos, cot, csc, sec, sin, sinc, tan) +from sympy.functions.special.bessel import (besselj, jn) +from sympy.functions.special.delta_functions import Heaviside +from sympy.matrices.dense import Matrix +from sympy.polys.polytools import (cancel, gcd) +from sympy.series.limits import limit +from sympy.series.order import O +from sympy.series.series import series +from sympy.sets.fancysets import ImageSet +from sympy.sets.sets import (FiniteSet, Interval) +from sympy.simplify.simplify import simplify +from sympy.core.expr import unchanged +from sympy.core.function import ArgumentIndexError, PoleError +from sympy.core.relational import Ne, Eq +from sympy.functions.elementary.piecewise import Piecewise +from sympy.sets.setexpr import SetExpr +from sympy.testing.pytest import XFAIL, slow, raises + + +x, y, z = symbols('x y z') +r = Symbol('r', real=True) +k, m = symbols('k m', integer=True) +p = Symbol('p', positive=True) +n = Symbol('n', negative=True) +np = Symbol('p', nonpositive=True) +nn = Symbol('n', nonnegative=True) +nz = Symbol('nz', nonzero=True) +ep = Symbol('ep', extended_positive=True) +en = Symbol('en', extended_negative=True) +enp = Symbol('ep', extended_nonpositive=True) +enn = Symbol('en', extended_nonnegative=True) +enz = Symbol('enz', extended_nonzero=True) +a = Symbol('a', algebraic=True) +na = Symbol('na', nonzero=True, algebraic=True) + + +def test_sin(): + x, y = symbols('x y') + z = symbols('z', imaginary=True) + + assert sin.nargs == FiniteSet(1) + assert sin(nan) is nan + assert sin(zoo) is nan + + assert sin(oo) == AccumBounds(-1, 1) + assert sin(oo) - sin(oo) == AccumBounds(-2, 2) + assert sin(oo*I) == oo*I + assert sin(-oo*I) == -oo*I + assert 0*sin(oo) is S.Zero + assert 0/sin(oo) is S.Zero + assert 0 + sin(oo) == AccumBounds(-1, 1) + assert 5 + sin(oo) == AccumBounds(4, 6) + + assert sin(0) == 0 + + assert sin(z*I) == I*sinh(z) + assert sin(asin(x)) == x + assert sin(atan(x)) == x / sqrt(1 + x**2) + assert sin(acos(x)) == sqrt(1 - x**2) + assert sin(acot(x)) == 1 / (sqrt(1 + 1 / x**2) * x) + assert sin(acsc(x)) == 1 / x + assert sin(asec(x)) == sqrt(1 - 1 / x**2) + assert sin(atan2(y, x)) == y / sqrt(x**2 + y**2) + + assert sin(pi*I) == sinh(pi)*I + assert sin(-pi*I) == -sinh(pi)*I + assert sin(-2*I) == -sinh(2)*I + + assert sin(pi) == 0 + assert sin(-pi) == 0 + assert sin(2*pi) == 0 + assert sin(-2*pi) == 0 + assert sin(-3*10**73*pi) == 0 + assert sin(7*10**103*pi) == 0 + + assert sin(pi/2) == 1 + assert sin(-pi/2) == -1 + assert sin(pi*Rational(5, 2)) == 1 + assert sin(pi*Rational(7, 2)) == -1 + + ne = symbols('ne', integer=True, even=False) + e = symbols('e', even=True) + assert sin(pi*ne/2) == (-1)**(ne/2 - S.Half) + assert sin(pi*k/2).func == sin + assert sin(pi*e/2) == 0 + assert sin(pi*k) == 0 + assert sin(pi*k).subs(k, 3) == sin(pi*k/2).subs(k, 6) # issue 8298 + + assert sin(pi/3) == S.Half*sqrt(3) + assert sin(pi*Rational(-2, 3)) == Rational(-1, 2)*sqrt(3) + + assert sin(pi/4) == S.Half*sqrt(2) + assert sin(-pi/4) == Rational(-1, 2)*sqrt(2) + assert sin(pi*Rational(17, 4)) == S.Half*sqrt(2) + assert sin(pi*Rational(-3, 4)) == Rational(-1, 2)*sqrt(2) + + assert sin(pi/6) == S.Half + assert sin(-pi/6) == Rational(-1, 2) + assert sin(pi*Rational(7, 6)) == Rational(-1, 2) + assert sin(pi*Rational(-5, 6)) == Rational(-1, 2) + + assert sin(pi*Rational(1, 5)) == sqrt((5 - sqrt(5)) / 8) + assert sin(pi*Rational(2, 5)) == sqrt((5 + sqrt(5)) / 8) + assert sin(pi*Rational(3, 5)) == sin(pi*Rational(2, 5)) + assert sin(pi*Rational(4, 5)) == sin(pi*Rational(1, 5)) + assert sin(pi*Rational(6, 5)) == -sin(pi*Rational(1, 5)) + assert sin(pi*Rational(8, 5)) == -sin(pi*Rational(2, 5)) + + assert sin(pi*Rational(-1273, 5)) == -sin(pi*Rational(2, 5)) + + assert sin(pi/8) == sqrt((2 - sqrt(2))/4) + + assert sin(pi/10) == Rational(-1, 4) + sqrt(5)/4 + + assert sin(pi/12) == -sqrt(2)/4 + sqrt(6)/4 + assert sin(pi*Rational(5, 12)) == sqrt(2)/4 + sqrt(6)/4 + assert sin(pi*Rational(-7, 12)) == -sqrt(2)/4 - sqrt(6)/4 + assert sin(pi*Rational(-11, 12)) == sqrt(2)/4 - sqrt(6)/4 + + assert sin(pi*Rational(104, 105)) == sin(pi/105) + assert sin(pi*Rational(106, 105)) == -sin(pi/105) + + assert sin(pi*Rational(-104, 105)) == -sin(pi/105) + assert sin(pi*Rational(-106, 105)) == sin(pi/105) + + assert sin(x*I) == sinh(x)*I + + assert sin(k*pi) == 0 + assert sin(17*k*pi) == 0 + assert sin(2*k*pi + 4) == sin(4) + assert sin(2*k*pi + m*pi + 1) == (-1)**(m + 2*k)*sin(1) + + assert sin(k*pi*I) == sinh(k*pi)*I + + assert sin(r).is_real is True + + assert sin(0, evaluate=False).is_algebraic + assert sin(a).is_algebraic is None + assert sin(na).is_algebraic is False + q = Symbol('q', rational=True) + assert sin(pi*q).is_algebraic + qn = Symbol('qn', rational=True, nonzero=True) + assert sin(qn).is_rational is False + assert sin(q).is_rational is None # issue 8653 + + assert isinstance(sin( re(x) - im(y)), sin) is True + assert isinstance(sin(-re(x) + im(y)), sin) is False + + assert sin(SetExpr(Interval(0, 1))) == SetExpr(ImageSet(Lambda(x, sin(x)), + Interval(0, 1))) + + for d in list(range(1, 22)) + [60, 85]: + for n in range(d*2 + 1): + x = n*pi/d + e = abs( float(sin(x)) - sin(float(x)) ) + assert e < 1e-12 + + assert sin(0, evaluate=False).is_zero is True + assert sin(k*pi, evaluate=False).is_zero is True + + assert sin(Add(1, -1, evaluate=False), evaluate=False).is_zero is True + + +def test_sin_cos(): + for d in [1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 24, 30, 40, 60, 120]: # list is not exhaustive... + for n in range(-2*d, d*2): + x = n*pi/d + assert sin(x + pi/2) == cos(x), "fails for %d*pi/%d" % (n, d) + assert sin(x - pi/2) == -cos(x), "fails for %d*pi/%d" % (n, d) + assert sin(x) == cos(x - pi/2), "fails for %d*pi/%d" % (n, d) + assert -sin(x) == cos(x + pi/2), "fails for %d*pi/%d" % (n, d) + + +def test_sin_series(): + assert sin(x).series(x, 0, 9) == \ + x - x**3/6 + x**5/120 - x**7/5040 + O(x**9) + + +def test_sin_rewrite(): + assert sin(x).rewrite(exp) == -I*(exp(I*x) - exp(-I*x))/2 + assert sin(x).rewrite(tan) == 2*tan(x/2)/(1 + tan(x/2)**2) + assert sin(x).rewrite(cot) == \ + Piecewise((0, Eq(im(x), 0) & Eq(Mod(x, pi), 0)), + (2*cot(x/2)/(cot(x/2)**2 + 1), True)) + assert sin(sinh(x)).rewrite( + exp).subs(x, 3).n() == sin(x).rewrite(exp).subs(x, sinh(3)).n() + assert sin(cosh(x)).rewrite( + exp).subs(x, 3).n() == sin(x).rewrite(exp).subs(x, cosh(3)).n() + assert sin(tanh(x)).rewrite( + exp).subs(x, 3).n() == sin(x).rewrite(exp).subs(x, tanh(3)).n() + assert sin(coth(x)).rewrite( + exp).subs(x, 3).n() == sin(x).rewrite(exp).subs(x, coth(3)).n() + assert sin(sin(x)).rewrite( + exp).subs(x, 3).n() == sin(x).rewrite(exp).subs(x, sin(3)).n() + assert sin(cos(x)).rewrite( + exp).subs(x, 3).n() == sin(x).rewrite(exp).subs(x, cos(3)).n() + assert sin(tan(x)).rewrite( + exp).subs(x, 3).n() == sin(x).rewrite(exp).subs(x, tan(3)).n() + assert sin(cot(x)).rewrite( + exp).subs(x, 3).n() == sin(x).rewrite(exp).subs(x, cot(3)).n() + assert sin(log(x)).rewrite(Pow) == I*x**-I / 2 - I*x**I /2 + assert sin(x).rewrite(csc) == 1/csc(x) + assert sin(x).rewrite(cos) == cos(x - pi / 2, evaluate=False) + assert sin(x).rewrite(sec) == 1 / sec(x - pi / 2, evaluate=False) + assert sin(cos(x)).rewrite(Pow) == sin(cos(x)) + assert sin(x).rewrite(besselj) == sqrt(pi*x/2)*besselj(S.Half, x) + assert sin(x).rewrite(besselj).subs(x, 0) == sin(0) + + +def _test_extrig(f, i, e): + from sympy.core.function import expand_trig + assert unchanged(f, i) + assert expand_trig(f(i)) == f(i) + # testing directly instead of with .expand(trig=True) + # because the other expansions undo the unevaluated Mul + assert expand_trig(f(Mul(i, 1, evaluate=False))) == e + assert abs(f(i) - e).n() < 1e-10 + + +def test_sin_expansion(): + # Note: these formulas are not unique. The ones here come from the + # Chebyshev formulas. + assert sin(x + y).expand(trig=True) == sin(x)*cos(y) + cos(x)*sin(y) + assert sin(x - y).expand(trig=True) == sin(x)*cos(y) - cos(x)*sin(y) + assert sin(y - x).expand(trig=True) == cos(x)*sin(y) - sin(x)*cos(y) + assert sin(2*x).expand(trig=True) == 2*sin(x)*cos(x) + assert sin(3*x).expand(trig=True) == -4*sin(x)**3 + 3*sin(x) + assert sin(4*x).expand(trig=True) == -8*sin(x)**3*cos(x) + 4*sin(x)*cos(x) + assert sin(2*pi/17).expand(trig=True) == sin(2*pi/17, evaluate=False) + assert sin(x+pi/17).expand(trig=True) == sin(pi/17)*cos(x) + cos(pi/17)*sin(x) + _test_extrig(sin, 2, 2*sin(1)*cos(1)) + _test_extrig(sin, 3, -4*sin(1)**3 + 3*sin(1)) + + +def test_sin_AccumBounds(): + assert sin(AccumBounds(-oo, oo)) == AccumBounds(-1, 1) + assert sin(AccumBounds(0, oo)) == AccumBounds(-1, 1) + assert sin(AccumBounds(-oo, 0)) == AccumBounds(-1, 1) + assert sin(AccumBounds(0, 2*S.Pi)) == AccumBounds(-1, 1) + assert sin(AccumBounds(0, S.Pi*Rational(3, 4))) == AccumBounds(0, 1) + assert sin(AccumBounds(S.Pi*Rational(3, 4), S.Pi*Rational(7, 4))) == AccumBounds(-1, sin(S.Pi*Rational(3, 4))) + assert sin(AccumBounds(S.Pi/4, S.Pi/3)) == AccumBounds(sin(S.Pi/4), sin(S.Pi/3)) + assert sin(AccumBounds(S.Pi*Rational(3, 4), S.Pi*Rational(5, 6))) == AccumBounds(sin(S.Pi*Rational(5, 6)), sin(S.Pi*Rational(3, 4))) + + +def test_sin_fdiff(): + assert sin(x).fdiff() == cos(x) + raises(ArgumentIndexError, lambda: sin(x).fdiff(2)) + + +def test_trig_symmetry(): + assert sin(-x) == -sin(x) + assert cos(-x) == cos(x) + assert tan(-x) == -tan(x) + assert cot(-x) == -cot(x) + assert sin(x + pi) == -sin(x) + assert sin(x + 2*pi) == sin(x) + assert sin(x + 3*pi) == -sin(x) + assert sin(x + 4*pi) == sin(x) + assert sin(x - 5*pi) == -sin(x) + assert cos(x + pi) == -cos(x) + assert cos(x + 2*pi) == cos(x) + assert cos(x + 3*pi) == -cos(x) + assert cos(x + 4*pi) == cos(x) + assert cos(x - 5*pi) == -cos(x) + assert tan(x + pi) == tan(x) + assert tan(x - 3*pi) == tan(x) + assert cot(x + pi) == cot(x) + assert cot(x - 3*pi) == cot(x) + assert sin(pi/2 - x) == cos(x) + assert sin(pi*Rational(3, 2) - x) == -cos(x) + assert sin(pi*Rational(5, 2) - x) == cos(x) + assert cos(pi/2 - x) == sin(x) + assert cos(pi*Rational(3, 2) - x) == -sin(x) + assert cos(pi*Rational(5, 2) - x) == sin(x) + assert tan(pi/2 - x) == cot(x) + assert tan(pi*Rational(3, 2) - x) == cot(x) + assert tan(pi*Rational(5, 2) - x) == cot(x) + assert cot(pi/2 - x) == tan(x) + assert cot(pi*Rational(3, 2) - x) == tan(x) + assert cot(pi*Rational(5, 2) - x) == tan(x) + assert sin(pi/2 + x) == cos(x) + assert cos(pi/2 + x) == -sin(x) + assert tan(pi/2 + x) == -cot(x) + assert cot(pi/2 + x) == -tan(x) + + +def test_cos(): + x, y = symbols('x y') + + assert cos.nargs == FiniteSet(1) + assert cos(nan) is nan + + assert cos(oo) == AccumBounds(-1, 1) + assert cos(oo) - cos(oo) == AccumBounds(-2, 2) + assert cos(oo*I) is oo + assert cos(-oo*I) is oo + assert cos(zoo) is nan + + assert cos(0) == 1 + + assert cos(acos(x)) == x + assert cos(atan(x)) == 1 / sqrt(1 + x**2) + assert cos(asin(x)) == sqrt(1 - x**2) + assert cos(acot(x)) == 1 / sqrt(1 + 1 / x**2) + assert cos(acsc(x)) == sqrt(1 - 1 / x**2) + assert cos(asec(x)) == 1 / x + assert cos(atan2(y, x)) == x / sqrt(x**2 + y**2) + + assert cos(pi*I) == cosh(pi) + assert cos(-pi*I) == cosh(pi) + assert cos(-2*I) == cosh(2) + + assert cos(pi/2) == 0 + assert cos(-pi/2) == 0 + assert cos(pi/2) == 0 + assert cos(-pi/2) == 0 + assert cos((-3*10**73 + 1)*pi/2) == 0 + assert cos((7*10**103 + 1)*pi/2) == 0 + + n = symbols('n', integer=True, even=False) + e = symbols('e', even=True) + assert cos(pi*n/2) == 0 + assert cos(pi*e/2) == (-1)**(e/2) + + assert cos(pi) == -1 + assert cos(-pi) == -1 + assert cos(2*pi) == 1 + assert cos(5*pi) == -1 + assert cos(8*pi) == 1 + + assert cos(pi/3) == S.Half + assert cos(pi*Rational(-2, 3)) == Rational(-1, 2) + + assert cos(pi/4) == S.Half*sqrt(2) + assert cos(-pi/4) == S.Half*sqrt(2) + assert cos(pi*Rational(11, 4)) == Rational(-1, 2)*sqrt(2) + assert cos(pi*Rational(-3, 4)) == Rational(-1, 2)*sqrt(2) + + assert cos(pi/6) == S.Half*sqrt(3) + assert cos(-pi/6) == S.Half*sqrt(3) + assert cos(pi*Rational(7, 6)) == Rational(-1, 2)*sqrt(3) + assert cos(pi*Rational(-5, 6)) == Rational(-1, 2)*sqrt(3) + + assert cos(pi*Rational(1, 5)) == (sqrt(5) + 1)/4 + assert cos(pi*Rational(2, 5)) == (sqrt(5) - 1)/4 + assert cos(pi*Rational(3, 5)) == -cos(pi*Rational(2, 5)) + assert cos(pi*Rational(4, 5)) == -cos(pi*Rational(1, 5)) + assert cos(pi*Rational(6, 5)) == -cos(pi*Rational(1, 5)) + assert cos(pi*Rational(8, 5)) == cos(pi*Rational(2, 5)) + + assert cos(pi*Rational(-1273, 5)) == -cos(pi*Rational(2, 5)) + + assert cos(pi/8) == sqrt((2 + sqrt(2))/4) + + assert cos(pi/12) == sqrt(2)/4 + sqrt(6)/4 + assert cos(pi*Rational(5, 12)) == -sqrt(2)/4 + sqrt(6)/4 + assert cos(pi*Rational(7, 12)) == sqrt(2)/4 - sqrt(6)/4 + assert cos(pi*Rational(11, 12)) == -sqrt(2)/4 - sqrt(6)/4 + + assert cos(pi*Rational(104, 105)) == -cos(pi/105) + assert cos(pi*Rational(106, 105)) == -cos(pi/105) + + assert cos(pi*Rational(-104, 105)) == -cos(pi/105) + assert cos(pi*Rational(-106, 105)) == -cos(pi/105) + + assert cos(x*I) == cosh(x) + assert cos(k*pi*I) == cosh(k*pi) + + assert cos(r).is_real is True + + assert cos(0, evaluate=False).is_algebraic + assert cos(a).is_algebraic is None + assert cos(na).is_algebraic is False + q = Symbol('q', rational=True) + assert cos(pi*q).is_algebraic + assert cos(pi*Rational(2, 7)).is_algebraic + + assert cos(k*pi) == (-1)**k + assert cos(2*k*pi) == 1 + assert cos(0, evaluate=False).is_zero is False + assert cos(Rational(1, 2)).is_zero is False + # The following test will return None as the result, but really it should + # be True even if it is not always possible to resolve an assumptions query. + assert cos(asin(-1, evaluate=False), evaluate=False).is_zero is None + for d in list(range(1, 22)) + [60, 85]: + for n in range(2*d + 1): + x = n*pi/d + e = abs( float(cos(x)) - cos(float(x)) ) + assert e < 1e-12 + + +def test_issue_6190(): + c = Float('123456789012345678901234567890.25', '') + for cls in [sin, cos, tan, cot]: + assert cls(c*pi) == cls(pi/4) + assert cls(4.125*pi) == cls(pi/8) + assert cls(4.7*pi) == cls((4.7 % 2)*pi) + + +def test_cos_series(): + assert cos(x).series(x, 0, 9) == \ + 1 - x**2/2 + x**4/24 - x**6/720 + x**8/40320 + O(x**9) + + +def test_cos_rewrite(): + assert cos(x).rewrite(exp) == exp(I*x)/2 + exp(-I*x)/2 + assert cos(x).rewrite(tan) == (1 - tan(x/2)**2)/(1 + tan(x/2)**2) + assert cos(x).rewrite(cot) == \ + Piecewise((1, Eq(im(x), 0) & Eq(Mod(x, 2*pi), 0)), + ((cot(x/2)**2 - 1)/(cot(x/2)**2 + 1), True)) + assert cos(sinh(x)).rewrite( + exp).subs(x, 3).n() == cos(x).rewrite(exp).subs(x, sinh(3)).n() + assert cos(cosh(x)).rewrite( + exp).subs(x, 3).n() == cos(x).rewrite(exp).subs(x, cosh(3)).n() + assert cos(tanh(x)).rewrite( + exp).subs(x, 3).n() == cos(x).rewrite(exp).subs(x, tanh(3)).n() + assert cos(coth(x)).rewrite( + exp).subs(x, 3).n() == cos(x).rewrite(exp).subs(x, coth(3)).n() + assert cos(sin(x)).rewrite( + exp).subs(x, 3).n() == cos(x).rewrite(exp).subs(x, sin(3)).n() + assert cos(cos(x)).rewrite( + exp).subs(x, 3).n() == cos(x).rewrite(exp).subs(x, cos(3)).n() + assert cos(tan(x)).rewrite( + exp).subs(x, 3).n() == cos(x).rewrite(exp).subs(x, tan(3)).n() + assert cos(cot(x)).rewrite( + exp).subs(x, 3).n() == cos(x).rewrite(exp).subs(x, cot(3)).n() + assert cos(log(x)).rewrite(Pow) == x**I/2 + x**-I/2 + assert cos(x).rewrite(sec) == 1/sec(x) + assert cos(x).rewrite(sin) == sin(x + pi/2, evaluate=False) + assert cos(x).rewrite(csc) == 1/csc(-x + pi/2, evaluate=False) + assert cos(sin(x)).rewrite(Pow) == cos(sin(x)) + assert cos(x).rewrite(besselj) == Piecewise( + (sqrt(pi*x/2)*besselj(-S.Half, x), Ne(x, 0)), + (1, True) + ) + assert cos(x).rewrite(besselj).subs(x, 0) == cos(0) + + +def test_cos_expansion(): + assert cos(x + y).expand(trig=True) == cos(x)*cos(y) - sin(x)*sin(y) + assert cos(x - y).expand(trig=True) == cos(x)*cos(y) + sin(x)*sin(y) + assert cos(y - x).expand(trig=True) == cos(x)*cos(y) + sin(x)*sin(y) + assert cos(2*x).expand(trig=True) == 2*cos(x)**2 - 1 + assert cos(3*x).expand(trig=True) == 4*cos(x)**3 - 3*cos(x) + assert cos(4*x).expand(trig=True) == 8*cos(x)**4 - 8*cos(x)**2 + 1 + assert cos(2*pi/17).expand(trig=True) == cos(2*pi/17, evaluate=False) + assert cos(x+pi/17).expand(trig=True) == cos(pi/17)*cos(x) - sin(pi/17)*sin(x) + _test_extrig(cos, 2, 2*cos(1)**2 - 1) + _test_extrig(cos, 3, 4*cos(1)**3 - 3*cos(1)) + + +def test_cos_AccumBounds(): + assert cos(AccumBounds(-oo, oo)) == AccumBounds(-1, 1) + assert cos(AccumBounds(0, oo)) == AccumBounds(-1, 1) + assert cos(AccumBounds(-oo, 0)) == AccumBounds(-1, 1) + assert cos(AccumBounds(0, 2*S.Pi)) == AccumBounds(-1, 1) + assert cos(AccumBounds(-S.Pi/3, S.Pi/4)) == AccumBounds(cos(-S.Pi/3), 1) + assert cos(AccumBounds(S.Pi*Rational(3, 4), S.Pi*Rational(5, 4))) == AccumBounds(-1, cos(S.Pi*Rational(3, 4))) + assert cos(AccumBounds(S.Pi*Rational(5, 4), S.Pi*Rational(4, 3))) == AccumBounds(cos(S.Pi*Rational(5, 4)), cos(S.Pi*Rational(4, 3))) + assert cos(AccumBounds(S.Pi/4, S.Pi/3)) == AccumBounds(cos(S.Pi/3), cos(S.Pi/4)) + + +def test_cos_fdiff(): + assert cos(x).fdiff() == -sin(x) + raises(ArgumentIndexError, lambda: cos(x).fdiff(2)) + + +def test_tan(): + assert tan(nan) is nan + + assert tan(zoo) is nan + assert tan(oo) == AccumBounds(-oo, oo) + assert tan(oo) - tan(oo) == AccumBounds(-oo, oo) + assert tan.nargs == FiniteSet(1) + assert tan(oo*I) == I + assert tan(-oo*I) == -I + + assert tan(0) == 0 + + assert tan(atan(x)) == x + assert tan(asin(x)) == x / sqrt(1 - x**2) + assert tan(acos(x)) == sqrt(1 - x**2) / x + assert tan(acot(x)) == 1 / x + assert tan(acsc(x)) == 1 / (sqrt(1 - 1 / x**2) * x) + assert tan(asec(x)) == sqrt(1 - 1 / x**2) * x + assert tan(atan2(y, x)) == y/x + + assert tan(pi*I) == tanh(pi)*I + assert tan(-pi*I) == -tanh(pi)*I + assert tan(-2*I) == -tanh(2)*I + + assert tan(pi) == 0 + assert tan(-pi) == 0 + assert tan(2*pi) == 0 + assert tan(-2*pi) == 0 + assert tan(-3*10**73*pi) == 0 + + assert tan(pi/2) is zoo + assert tan(pi*Rational(3, 2)) is zoo + + assert tan(pi/3) == sqrt(3) + assert tan(pi*Rational(-2, 3)) == sqrt(3) + + assert tan(pi/4) is S.One + assert tan(-pi/4) is S.NegativeOne + assert tan(pi*Rational(17, 4)) is S.One + assert tan(pi*Rational(-3, 4)) is S.One + + assert tan(pi/5) == sqrt(5 - 2*sqrt(5)) + assert tan(pi*Rational(2, 5)) == sqrt(5 + 2*sqrt(5)) + assert tan(pi*Rational(18, 5)) == -sqrt(5 + 2*sqrt(5)) + assert tan(pi*Rational(-16, 5)) == -sqrt(5 - 2*sqrt(5)) + + assert tan(pi/6) == 1/sqrt(3) + assert tan(-pi/6) == -1/sqrt(3) + assert tan(pi*Rational(7, 6)) == 1/sqrt(3) + assert tan(pi*Rational(-5, 6)) == 1/sqrt(3) + + assert tan(pi/8) == -1 + sqrt(2) + assert tan(pi*Rational(3, 8)) == 1 + sqrt(2) # issue 15959 + assert tan(pi*Rational(5, 8)) == -1 - sqrt(2) + assert tan(pi*Rational(7, 8)) == 1 - sqrt(2) + + assert tan(pi/10) == sqrt(1 - 2*sqrt(5)/5) + assert tan(pi*Rational(3, 10)) == sqrt(1 + 2*sqrt(5)/5) + assert tan(pi*Rational(17, 10)) == -sqrt(1 + 2*sqrt(5)/5) + assert tan(pi*Rational(-31, 10)) == -sqrt(1 - 2*sqrt(5)/5) + + assert tan(pi/12) == -sqrt(3) + 2 + assert tan(pi*Rational(5, 12)) == sqrt(3) + 2 + assert tan(pi*Rational(7, 12)) == -sqrt(3) - 2 + assert tan(pi*Rational(11, 12)) == sqrt(3) - 2 + + assert tan(pi/24).radsimp() == -2 - sqrt(3) + sqrt(2) + sqrt(6) + assert tan(pi*Rational(5, 24)).radsimp() == -2 + sqrt(3) - sqrt(2) + sqrt(6) + assert tan(pi*Rational(7, 24)).radsimp() == 2 - sqrt(3) - sqrt(2) + sqrt(6) + assert tan(pi*Rational(11, 24)).radsimp() == 2 + sqrt(3) + sqrt(2) + sqrt(6) + assert tan(pi*Rational(13, 24)).radsimp() == -2 - sqrt(3) - sqrt(2) - sqrt(6) + assert tan(pi*Rational(17, 24)).radsimp() == -2 + sqrt(3) + sqrt(2) - sqrt(6) + assert tan(pi*Rational(19, 24)).radsimp() == 2 - sqrt(3) + sqrt(2) - sqrt(6) + assert tan(pi*Rational(23, 24)).radsimp() == 2 + sqrt(3) - sqrt(2) - sqrt(6) + + assert tan(x*I) == tanh(x)*I + + assert tan(k*pi) == 0 + assert tan(17*k*pi) == 0 + + assert tan(k*pi*I) == tanh(k*pi)*I + + assert tan(r).is_real is None + assert tan(r).is_extended_real is True + + assert tan(0, evaluate=False).is_algebraic + assert tan(a).is_algebraic is None + assert tan(na).is_algebraic is False + + assert tan(pi*Rational(10, 7)) == tan(pi*Rational(3, 7)) + assert tan(pi*Rational(11, 7)) == -tan(pi*Rational(3, 7)) + assert tan(pi*Rational(-11, 7)) == tan(pi*Rational(3, 7)) + + assert tan(pi*Rational(15, 14)) == tan(pi/14) + assert tan(pi*Rational(-15, 14)) == -tan(pi/14) + + assert tan(r).is_finite is None + assert tan(I*r).is_finite is True + + # https://github.com/sympy/sympy/issues/21177 + f = tan(pi*(x + S(3)/2))/(3*x) + assert f.as_leading_term(x) == -1/(3*pi*x**2) + + +def test_tan_series(): + assert tan(x).series(x, 0, 9) == \ + x + x**3/3 + 2*x**5/15 + 17*x**7/315 + O(x**9) + + +def test_tan_rewrite(): + neg_exp, pos_exp = exp(-x*I), exp(x*I) + assert tan(x).rewrite(exp) == I*(neg_exp - pos_exp)/(neg_exp + pos_exp) + assert tan(x).rewrite(sin) == 2*sin(x)**2/sin(2*x) + assert tan(x).rewrite(cos) == cos(x - S.Pi/2, evaluate=False)/cos(x) + assert tan(x).rewrite(cot) == 1/cot(x) + assert tan(sinh(x)).rewrite(exp).subs(x, 3).n() == tan(x).rewrite(exp).subs(x, sinh(3)).n() + assert tan(cosh(x)).rewrite(exp).subs(x, 3).n() == tan(x).rewrite(exp).subs(x, cosh(3)).n() + assert tan(tanh(x)).rewrite(exp).subs(x, 3).n() == tan(x).rewrite(exp).subs(x, tanh(3)).n() + assert tan(coth(x)).rewrite(exp).subs(x, 3).n() == tan(x).rewrite(exp).subs(x, coth(3)).n() + assert tan(sin(x)).rewrite(exp).subs(x, 3).n() == tan(x).rewrite(exp).subs(x, sin(3)).n() + assert tan(cos(x)).rewrite(exp).subs(x, 3).n() == tan(x).rewrite(exp).subs(x, cos(3)).n() + assert tan(tan(x)).rewrite(exp).subs(x, 3).n() == tan(x).rewrite(exp).subs(x, tan(3)).n() + assert tan(cot(x)).rewrite(exp).subs(x, 3).n() == tan(x).rewrite(exp).subs(x, cot(3)).n() + assert tan(log(x)).rewrite(Pow) == I*(x**-I - x**I)/(x**-I + x**I) + assert tan(x).rewrite(sec) == sec(x)/sec(x - pi/2, evaluate=False) + assert tan(x).rewrite(csc) == csc(-x + pi/2, evaluate=False)/csc(x) + assert tan(sin(x)).rewrite(Pow) == tan(sin(x)) + assert tan(pi*Rational(2, 5), evaluate=False).rewrite(sqrt) == sqrt(sqrt(5)/8 + + Rational(5, 8))/(Rational(-1, 4) + sqrt(5)/4) + assert tan(x).rewrite(besselj) == besselj(S.Half, x)/besselj(-S.Half, x) + assert tan(x).rewrite(besselj).subs(x, 0) == tan(0) + + +@slow +def test_tan_rewrite_slow(): + assert 0 == (cos(pi/34)*tan(pi/34) - sin(pi/34)).rewrite(pow) + assert 0 == (cos(pi/17)*tan(pi/17) - sin(pi/17)).rewrite(pow) + assert tan(pi/19).rewrite(pow) == tan(pi/19) + assert tan(pi*Rational(8, 19)).rewrite(sqrt) == tan(pi*Rational(8, 19)) + assert tan(pi*Rational(2, 5), evaluate=False).rewrite(sqrt) == sqrt(sqrt(5)/8 + + Rational(5, 8))/(Rational(-1, 4) + sqrt(5)/4) + + +def test_tan_subs(): + assert tan(x).subs(tan(x), y) == y + assert tan(x).subs(x, y) == tan(y) + assert tan(x).subs(x, S.Pi/2) is zoo + assert tan(x).subs(x, S.Pi*Rational(3, 2)) is zoo + + +def test_tan_expansion(): + assert tan(x + y).expand(trig=True) == ((tan(x) + tan(y))/(1 - tan(x)*tan(y))).expand() + assert tan(x - y).expand(trig=True) == ((tan(x) - tan(y))/(1 + tan(x)*tan(y))).expand() + assert tan(x + y + z).expand(trig=True) == ( + (tan(x) + tan(y) + tan(z) - tan(x)*tan(y)*tan(z))/ + (1 - tan(x)*tan(y) - tan(x)*tan(z) - tan(y)*tan(z))).expand() + assert 0 == tan(2*x).expand(trig=True).rewrite(tan).subs([(tan(x), Rational(1, 7))])*24 - 7 + assert 0 == tan(3*x).expand(trig=True).rewrite(tan).subs([(tan(x), Rational(1, 5))])*55 - 37 + assert 0 == tan(4*x - pi/4).expand(trig=True).rewrite(tan).subs([(tan(x), Rational(1, 5))])*239 - 1 + _test_extrig(tan, 2, 2*tan(1)/(1 - tan(1)**2)) + _test_extrig(tan, 3, (-tan(1)**3 + 3*tan(1))/(1 - 3*tan(1)**2)) + + +def test_tan_AccumBounds(): + assert tan(AccumBounds(-oo, oo)) == AccumBounds(-oo, oo) + assert tan(AccumBounds(S.Pi/3, S.Pi*Rational(2, 3))) == AccumBounds(-oo, oo) + assert tan(AccumBounds(S.Pi/6, S.Pi/3)) == AccumBounds(tan(S.Pi/6), tan(S.Pi/3)) + + +def test_tan_fdiff(): + assert tan(x).fdiff() == tan(x)**2 + 1 + raises(ArgumentIndexError, lambda: tan(x).fdiff(2)) + + +def test_cot(): + assert cot(nan) is nan + + assert cot.nargs == FiniteSet(1) + assert cot(oo*I) == -I + assert cot(-oo*I) == I + assert cot(zoo) is nan + + assert cot(0) is zoo + assert cot(2*pi) is zoo + + assert cot(acot(x)) == x + assert cot(atan(x)) == 1 / x + assert cot(asin(x)) == sqrt(1 - x**2) / x + assert cot(acos(x)) == x / sqrt(1 - x**2) + assert cot(acsc(x)) == sqrt(1 - 1 / x**2) * x + assert cot(asec(x)) == 1 / (sqrt(1 - 1 / x**2) * x) + assert cot(atan2(y, x)) == x/y + + assert cot(pi*I) == -coth(pi)*I + assert cot(-pi*I) == coth(pi)*I + assert cot(-2*I) == coth(2)*I + + assert cot(pi) == cot(2*pi) == cot(3*pi) + assert cot(-pi) == cot(-2*pi) == cot(-3*pi) + + assert cot(pi/2) == 0 + assert cot(-pi/2) == 0 + assert cot(pi*Rational(5, 2)) == 0 + assert cot(pi*Rational(7, 2)) == 0 + + assert cot(pi/3) == 1/sqrt(3) + assert cot(pi*Rational(-2, 3)) == 1/sqrt(3) + + assert cot(pi/4) is S.One + assert cot(-pi/4) is S.NegativeOne + assert cot(pi*Rational(17, 4)) is S.One + assert cot(pi*Rational(-3, 4)) is S.One + + assert cot(pi/6) == sqrt(3) + assert cot(-pi/6) == -sqrt(3) + assert cot(pi*Rational(7, 6)) == sqrt(3) + assert cot(pi*Rational(-5, 6)) == sqrt(3) + + assert cot(pi/8) == 1 + sqrt(2) + assert cot(pi*Rational(3, 8)) == -1 + sqrt(2) + assert cot(pi*Rational(5, 8)) == 1 - sqrt(2) + assert cot(pi*Rational(7, 8)) == -1 - sqrt(2) + + assert cot(pi/12) == sqrt(3) + 2 + assert cot(pi*Rational(5, 12)) == -sqrt(3) + 2 + assert cot(pi*Rational(7, 12)) == sqrt(3) - 2 + assert cot(pi*Rational(11, 12)) == -sqrt(3) - 2 + + assert cot(pi/24).radsimp() == sqrt(2) + sqrt(3) + 2 + sqrt(6) + assert cot(pi*Rational(5, 24)).radsimp() == -sqrt(2) - sqrt(3) + 2 + sqrt(6) + assert cot(pi*Rational(7, 24)).radsimp() == -sqrt(2) + sqrt(3) - 2 + sqrt(6) + assert cot(pi*Rational(11, 24)).radsimp() == sqrt(2) - sqrt(3) - 2 + sqrt(6) + assert cot(pi*Rational(13, 24)).radsimp() == -sqrt(2) + sqrt(3) + 2 - sqrt(6) + assert cot(pi*Rational(17, 24)).radsimp() == sqrt(2) - sqrt(3) + 2 - sqrt(6) + assert cot(pi*Rational(19, 24)).radsimp() == sqrt(2) + sqrt(3) - 2 - sqrt(6) + assert cot(pi*Rational(23, 24)).radsimp() == -sqrt(2) - sqrt(3) - 2 - sqrt(6) + + assert cot(x*I) == -coth(x)*I + assert cot(k*pi*I) == -coth(k*pi)*I + + assert cot(r).is_real is None + assert cot(r).is_extended_real is True + + assert cot(a).is_algebraic is None + assert cot(na).is_algebraic is False + + assert cot(pi*Rational(10, 7)) == cot(pi*Rational(3, 7)) + assert cot(pi*Rational(11, 7)) == -cot(pi*Rational(3, 7)) + assert cot(pi*Rational(-11, 7)) == cot(pi*Rational(3, 7)) + + assert cot(pi*Rational(39, 34)) == cot(pi*Rational(5, 34)) + assert cot(pi*Rational(-41, 34)) == -cot(pi*Rational(7, 34)) + + assert cot(x).is_finite is None + assert cot(r).is_finite is None + i = Symbol('i', imaginary=True) + assert cot(i).is_finite is True + + assert cot(x).subs(x, 3*pi) is zoo + + # https://github.com/sympy/sympy/issues/21177 + f = cot(pi*(x + 4))/(3*x) + assert f.as_leading_term(x) == 1/(3*pi*x**2) + + +def test_tan_cot_sin_cos_evalf(): + assert abs((tan(pi*Rational(8, 15))*cos(pi*Rational(8, 15))/sin(pi*Rational(8, 15)) - 1).evalf()) < 1e-14 + assert abs((cot(pi*Rational(4, 15))*sin(pi*Rational(4, 15))/cos(pi*Rational(4, 15)) - 1).evalf()) < 1e-14 + +@XFAIL +def test_tan_cot_sin_cos_ratsimp(): + assert 1 == (tan(pi*Rational(8, 15))*cos(pi*Rational(8, 15))/sin(pi*Rational(8, 15))).ratsimp() + assert 1 == (cot(pi*Rational(4, 15))*sin(pi*Rational(4, 15))/cos(pi*Rational(4, 15))).ratsimp() + + +def test_cot_series(): + assert cot(x).series(x, 0, 9) == \ + 1/x - x/3 - x**3/45 - 2*x**5/945 - x**7/4725 + O(x**9) + # issue 6210 + assert cot(x**4 + x**5).series(x, 0, 1) == \ + x**(-4) - 1/x**3 + x**(-2) - 1/x + 1 + O(x) + assert cot(pi*(1-x)).series(x, 0, 3) == -1/(pi*x) + pi*x/3 + O(x**3) + assert cot(x).taylor_term(0, x) == 1/x + assert cot(x).taylor_term(2, x) is S.Zero + assert cot(x).taylor_term(3, x) == -x**3/45 + + +def test_cot_rewrite(): + neg_exp, pos_exp = exp(-x*I), exp(x*I) + assert cot(x).rewrite(exp) == I*(pos_exp + neg_exp)/(pos_exp - neg_exp) + assert cot(x).rewrite(sin) == sin(2*x)/(2*(sin(x)**2)) + assert cot(x).rewrite(cos) == cos(x)/cos(x - pi/2, evaluate=False) + assert cot(x).rewrite(tan) == 1/tan(x) + def check(func): + z = cot(func(x)).rewrite(exp) - cot(x).rewrite(exp).subs(x, func(x)) + assert z.rewrite(exp).expand() == 0 + check(sinh) + check(cosh) + check(tanh) + check(coth) + check(sin) + check(cos) + check(tan) + assert cot(log(x)).rewrite(Pow) == -I*(x**-I + x**I)/(x**-I - x**I) + assert cot(x).rewrite(sec) == sec(x - pi / 2, evaluate=False) / sec(x) + assert cot(x).rewrite(csc) == csc(x) / csc(- x + pi / 2, evaluate=False) + assert cot(sin(x)).rewrite(Pow) == cot(sin(x)) + assert cot(pi*Rational(2, 5), evaluate=False).rewrite(sqrt) == (Rational(-1, 4) + sqrt(5)/4)/\ + sqrt(sqrt(5)/8 + Rational(5, 8)) + assert cot(x).rewrite(besselj) == besselj(-S.Half, x)/besselj(S.Half, x) + assert cot(x).rewrite(besselj).subs(x, 0) == cot(0) + + +@slow +def test_cot_rewrite_slow(): + assert cot(pi*Rational(4, 34)).rewrite(pow).ratsimp() == \ + (cos(pi*Rational(4, 34))/sin(pi*Rational(4, 34))).rewrite(pow).ratsimp() + assert cot(pi*Rational(4, 17)).rewrite(pow) == \ + (cos(pi*Rational(4, 17))/sin(pi*Rational(4, 17))).rewrite(pow) + assert cot(pi/19).rewrite(pow) == cot(pi/19) + assert cot(pi/19).rewrite(sqrt) == cot(pi/19) + assert cot(pi*Rational(2, 5), evaluate=False).rewrite(sqrt) == \ + (Rational(-1, 4) + sqrt(5)/4) / sqrt(sqrt(5)/8 + Rational(5, 8)) + + +def test_cot_subs(): + assert cot(x).subs(cot(x), y) == y + assert cot(x).subs(x, y) == cot(y) + assert cot(x).subs(x, 0) is zoo + assert cot(x).subs(x, S.Pi) is zoo + + +def test_cot_expansion(): + assert cot(x + y).expand(trig=True).together() == ( + (cot(x)*cot(y) - 1)/(cot(x) + cot(y))) + assert cot(x - y).expand(trig=True).together() == ( + cot(x)*cot(-y) - 1)/(cot(x) + cot(-y)) + assert cot(x + y + z).expand(trig=True).together() == ( + (cot(x)*cot(y)*cot(z) - cot(x) - cot(y) - cot(z))/ + (-1 + cot(x)*cot(y) + cot(x)*cot(z) + cot(y)*cot(z))) + assert cot(3*x).expand(trig=True).together() == ( + (cot(x)**2 - 3)*cot(x)/(3*cot(x)**2 - 1)) + assert cot(2*x).expand(trig=True) == cot(x)/2 - 1/(2*cot(x)) + assert cot(3*x).expand(trig=True).together() == ( + cot(x)**2 - 3)*cot(x)/(3*cot(x)**2 - 1) + assert cot(4*x - pi/4).expand(trig=True).cancel() == ( + -tan(x)**4 + 4*tan(x)**3 + 6*tan(x)**2 - 4*tan(x) - 1 + )/(tan(x)**4 + 4*tan(x)**3 - 6*tan(x)**2 - 4*tan(x) + 1) + _test_extrig(cot, 2, (-1 + cot(1)**2)/(2*cot(1))) + _test_extrig(cot, 3, (-3*cot(1) + cot(1)**3)/(-1 + 3*cot(1)**2)) + + +def test_cot_AccumBounds(): + assert cot(AccumBounds(-oo, oo)) == AccumBounds(-oo, oo) + assert cot(AccumBounds(-S.Pi/3, S.Pi/3)) == AccumBounds(-oo, oo) + assert cot(AccumBounds(S.Pi/6, S.Pi/3)) == AccumBounds(cot(S.Pi/3), cot(S.Pi/6)) + + +def test_cot_fdiff(): + assert cot(x).fdiff() == -cot(x)**2 - 1 + raises(ArgumentIndexError, lambda: cot(x).fdiff(2)) + + +def test_sinc(): + assert isinstance(sinc(x), sinc) + + s = Symbol('s', zero=True) + assert sinc(s) is S.One + assert sinc(S.Infinity) is S.Zero + assert sinc(S.NegativeInfinity) is S.Zero + assert sinc(S.NaN) is S.NaN + assert sinc(S.ComplexInfinity) is S.NaN + + n = Symbol('n', integer=True, nonzero=True) + assert sinc(n*pi) is S.Zero + assert sinc(-n*pi) is S.Zero + assert sinc(pi/2) == 2 / pi + assert sinc(-pi/2) == 2 / pi + assert sinc(pi*Rational(5, 2)) == 2 / (5*pi) + assert sinc(pi*Rational(7, 2)) == -2 / (7*pi) + + assert sinc(-x) == sinc(x) + + assert sinc(x).diff(x) == cos(x)/x - sin(x)/x**2 + assert sinc(x).diff(x) == (sin(x)/x).diff(x) + assert sinc(x).diff(x, x) == (-sin(x) - 2*cos(x)/x + 2*sin(x)/x**2)/x + assert sinc(x).diff(x, x) == (sin(x)/x).diff(x, x) + assert limit(sinc(x).diff(x), x, 0) == 0 + assert limit(sinc(x).diff(x, x), x, 0) == -S(1)/3 + + # https://github.com/sympy/sympy/issues/11402 + # + # assert sinc(x).diff(x) == Piecewise(((x*cos(x) - sin(x)) / x**2, Ne(x, 0)), (0, True)) + # + # assert sinc(x).diff(x).equals(sinc(x).rewrite(sin).diff(x)) + # + # assert sinc(x).diff(x).subs(x, 0) is S.Zero + + assert sinc(x).series() == 1 - x**2/6 + x**4/120 + O(x**6) + + assert sinc(x).rewrite(jn) == jn(0, x) + assert sinc(x).rewrite(sin) == Piecewise((sin(x)/x, Ne(x, 0)), (1, True)) + assert sinc(pi, evaluate=False).is_zero is True + assert sinc(0, evaluate=False).is_zero is False + assert sinc(n*pi, evaluate=False).is_zero is True + assert sinc(x).is_zero is None + xr = Symbol('xr', real=True, nonzero=True) + assert sinc(x).is_real is None + assert sinc(xr).is_real is True + assert sinc(I*xr).is_real is True + assert sinc(I*100).is_real is True + assert sinc(x).is_finite is None + assert sinc(xr).is_finite is True + + +def test_asin(): + assert asin(nan) is nan + + assert asin.nargs == FiniteSet(1) + assert asin(oo) == -I*oo + assert asin(-oo) == I*oo + assert asin(zoo) is zoo + + # Note: asin(-x) = - asin(x) + assert asin(0) == 0 + assert asin(1) == pi/2 + assert asin(-1) == -pi/2 + assert asin(sqrt(3)/2) == pi/3 + assert asin(-sqrt(3)/2) == -pi/3 + assert asin(sqrt(2)/2) == pi/4 + assert asin(-sqrt(2)/2) == -pi/4 + assert asin(sqrt((5 - sqrt(5))/8)) == pi/5 + assert asin(-sqrt((5 - sqrt(5))/8)) == -pi/5 + assert asin(S.Half) == pi/6 + assert asin(Rational(-1, 2)) == -pi/6 + assert asin((sqrt(2 - sqrt(2)))/2) == pi/8 + assert asin(-(sqrt(2 - sqrt(2)))/2) == -pi/8 + assert asin((sqrt(5) - 1)/4) == pi/10 + assert asin(-(sqrt(5) - 1)/4) == -pi/10 + assert asin((sqrt(3) - 1)/sqrt(2**3)) == pi/12 + assert asin(-(sqrt(3) - 1)/sqrt(2**3)) == -pi/12 + + # check round-trip for exact values: + for d in [5, 6, 8, 10, 12]: + for n in range(-(d//2), d//2 + 1): + if gcd(n, d) == 1: + assert asin(sin(n*pi/d)) == n*pi/d + + assert asin(x).diff(x) == 1/sqrt(1 - x**2) + + assert asin(0.2, evaluate=False).is_real is True + assert asin(-2).is_real is False + assert asin(r).is_real is None + + assert asin(-2*I) == -I*asinh(2) + + assert asin(Rational(1, 7), evaluate=False).is_positive is True + assert asin(Rational(-1, 7), evaluate=False).is_positive is False + assert asin(p).is_positive is None + assert asin(sin(Rational(7, 2))) == Rational(-7, 2) + pi + assert asin(sin(Rational(-7, 4))) == Rational(7, 4) - pi + assert unchanged(asin, cos(x)) + + +def test_asin_series(): + assert asin(x).series(x, 0, 9) == \ + x + x**3/6 + 3*x**5/40 + 5*x**7/112 + O(x**9) + t5 = asin(x).taylor_term(5, x) + assert t5 == 3*x**5/40 + assert asin(x).taylor_term(7, x, t5, 0) == 5*x**7/112 + + +def test_asin_leading_term(): + assert asin(x).as_leading_term(x) == x + # Tests concerning branch points + assert asin(x + 1).as_leading_term(x) == pi/2 + assert asin(x - 1).as_leading_term(x) == -pi/2 + assert asin(1/x).as_leading_term(x, cdir=1) == I*log(x) + pi/2 - I*log(2) + assert asin(1/x).as_leading_term(x, cdir=-1) == -I*log(x) - 3*pi/2 + I*log(2) + # Tests concerning points lying on branch cuts + assert asin(I*x + 2).as_leading_term(x, cdir=1) == pi - asin(2) + assert asin(-I*x + 2).as_leading_term(x, cdir=1) == asin(2) + assert asin(I*x - 2).as_leading_term(x, cdir=1) == -asin(2) + assert asin(-I*x - 2).as_leading_term(x, cdir=1) == -pi + asin(2) + # Tests concerning im(ndir) == 0 + assert asin(-I*x**2 + x - 2).as_leading_term(x, cdir=1) == -pi/2 + I*log(2 - sqrt(3)) + assert asin(-I*x**2 + x - 2).as_leading_term(x, cdir=-1) == -pi/2 + I*log(2 - sqrt(3)) + + +def test_asin_rewrite(): + assert asin(x).rewrite(log) == -I*log(I*x + sqrt(1 - x**2)) + assert asin(x).rewrite(atan) == 2*atan(x/(1 + sqrt(1 - x**2))) + assert asin(x).rewrite(acos) == S.Pi/2 - acos(x) + assert asin(x).rewrite(acot) == 2*acot((sqrt(-x**2 + 1) + 1)/x) + assert asin(x).rewrite(asec) == -asec(1/x) + pi/2 + assert asin(x).rewrite(acsc) == acsc(1/x) + + +def test_asin_fdiff(): + assert asin(x).fdiff() == 1/sqrt(1 - x**2) + raises(ArgumentIndexError, lambda: asin(x).fdiff(2)) + + +def test_acos(): + assert acos(nan) is nan + assert acos(zoo) is zoo + + assert acos.nargs == FiniteSet(1) + assert acos(oo) == I*oo + assert acos(-oo) == -I*oo + + # Note: acos(-x) = pi - acos(x) + assert acos(0) == pi/2 + assert acos(S.Half) == pi/3 + assert acos(Rational(-1, 2)) == pi*Rational(2, 3) + assert acos(1) == 0 + assert acos(-1) == pi + assert acos(sqrt(2)/2) == pi/4 + assert acos(-sqrt(2)/2) == pi*Rational(3, 4) + + # check round-trip for exact values: + for d in range(5, 13): + for num in range(d): + if gcd(num, d) == 1: + assert acos(cos(num*pi/d)) == num*pi/d + assert acos(-cos(num*pi/d)) == pi - num*pi/d + assert acos(sin(num*pi/d)) == pi/2 - asin(sin(num*pi/d)) + assert acos(-sin(num*pi/d)) == pi/2 - asin(-sin(num*pi/d)) + + assert acos(2*I) == pi/2 - asin(2*I) + + assert acos(x).diff(x) == -1/sqrt(1 - x**2) + + assert acos(0.2).is_real is True + assert acos(-2).is_real is False + assert acos(r).is_real is None + + assert acos(Rational(1, 7), evaluate=False).is_positive is True + assert acos(Rational(-1, 7), evaluate=False).is_positive is True + assert acos(Rational(3, 2), evaluate=False).is_positive is False + assert acos(p).is_positive is None + + assert acos(2 + p).conjugate() != acos(10 + p) + assert acos(-3 + n).conjugate() != acos(-3 + n) + assert acos(Rational(1, 3)).conjugate() == acos(Rational(1, 3)) + assert acos(Rational(-1, 3)).conjugate() == acos(Rational(-1, 3)) + assert acos(p + n*I).conjugate() == acos(p - n*I) + assert acos(z).conjugate() != acos(conjugate(z)) + + +def test_acos_leading_term(): + assert acos(x).as_leading_term(x) == pi/2 + # Tests concerning branch points + assert acos(x + 1).as_leading_term(x) == sqrt(2)*sqrt(-x) + assert acos(x - 1).as_leading_term(x) == pi + assert acos(1/x).as_leading_term(x, cdir=1) == -I*log(x) + I*log(2) + assert acos(1/x).as_leading_term(x, cdir=-1) == I*log(x) + 2*pi - I*log(2) + # Tests concerning points lying on branch cuts + assert acos(I*x + 2).as_leading_term(x, cdir=1) == -acos(2) + assert acos(-I*x + 2).as_leading_term(x, cdir=1) == acos(2) + assert acos(I*x - 2).as_leading_term(x, cdir=1) == acos(-2) + assert acos(-I*x - 2).as_leading_term(x, cdir=1) == 2*pi - acos(-2) + # Tests concerning im(ndir) == 0 + assert acos(-I*x**2 + x - 2).as_leading_term(x, cdir=1) == pi + I*log(sqrt(3) + 2) + assert acos(-I*x**2 + x - 2).as_leading_term(x, cdir=-1) == pi + I*log(sqrt(3) + 2) + + +def test_acos_series(): + assert acos(x).series(x, 0, 8) == \ + pi/2 - x - x**3/6 - 3*x**5/40 - 5*x**7/112 + O(x**8) + assert acos(x).series(x, 0, 8) == pi/2 - asin(x).series(x, 0, 8) + t5 = acos(x).taylor_term(5, x) + assert t5 == -3*x**5/40 + assert acos(x).taylor_term(7, x, t5, 0) == -5*x**7/112 + assert acos(x).taylor_term(0, x) == pi/2 + assert acos(x).taylor_term(2, x) is S.Zero + + +def test_acos_rewrite(): + assert acos(x).rewrite(log) == pi/2 + I*log(I*x + sqrt(1 - x**2)) + assert acos(x).rewrite(atan) == pi*(-x*sqrt(x**(-2)) + 1)/2 + atan(sqrt(1 - x**2)/x) + assert acos(0).rewrite(atan) == S.Pi/2 + assert acos(0.5).rewrite(atan) == acos(0.5).rewrite(log) + assert acos(x).rewrite(asin) == S.Pi/2 - asin(x) + assert acos(x).rewrite(acot) == -2*acot((sqrt(-x**2 + 1) + 1)/x) + pi/2 + assert acos(x).rewrite(asec) == asec(1/x) + assert acos(x).rewrite(acsc) == -acsc(1/x) + pi/2 + + +def test_acos_fdiff(): + assert acos(x).fdiff() == -1/sqrt(1 - x**2) + raises(ArgumentIndexError, lambda: acos(x).fdiff(2)) + + +def test_atan(): + assert atan(nan) is nan + + assert atan.nargs == FiniteSet(1) + assert atan(oo) == pi/2 + assert atan(-oo) == -pi/2 + assert atan(zoo) == AccumBounds(-pi/2, pi/2) + + assert atan(0) == 0 + assert atan(1) == pi/4 + assert atan(sqrt(3)) == pi/3 + assert atan(-(1 + sqrt(2))) == pi*Rational(-3, 8) + assert atan(sqrt(5 - 2 * sqrt(5))) == pi/5 + assert atan(-sqrt(1 - 2 * sqrt(5)/ 5)) == -pi/10 + assert atan(sqrt(1 + 2 * sqrt(5) / 5)) == pi*Rational(3, 10) + assert atan(-2 + sqrt(3)) == -pi/12 + assert atan(2 + sqrt(3)) == pi*Rational(5, 12) + assert atan(-2 - sqrt(3)) == pi*Rational(-5, 12) + + # check round-trip for exact values: + for d in [5, 6, 8, 10, 12]: + for num in range(-(d//2), d//2 + 1): + if gcd(num, d) == 1: + assert atan(tan(num*pi/d)) == num*pi/d + + assert atan(oo) == pi/2 + assert atan(x).diff(x) == 1/(1 + x**2) + + assert atan(r).is_real is True + + assert atan(-2*I) == -I*atanh(2) + assert unchanged(atan, cot(x)) + assert atan(cot(Rational(1, 4))) == Rational(-1, 4) + pi/2 + assert acot(Rational(1, 4)).is_rational is False + + for s in (x, p, n, np, nn, nz, ep, en, enp, enn, enz): + if s.is_real or s.is_extended_real is None: + assert s.is_nonzero is atan(s).is_nonzero + assert s.is_positive is atan(s).is_positive + assert s.is_negative is atan(s).is_negative + assert s.is_nonpositive is atan(s).is_nonpositive + assert s.is_nonnegative is atan(s).is_nonnegative + else: + assert s.is_extended_nonzero is atan(s).is_nonzero + assert s.is_extended_positive is atan(s).is_positive + assert s.is_extended_negative is atan(s).is_negative + assert s.is_extended_nonpositive is atan(s).is_nonpositive + assert s.is_extended_nonnegative is atan(s).is_nonnegative + assert s.is_extended_nonzero is atan(s).is_extended_nonzero + assert s.is_extended_positive is atan(s).is_extended_positive + assert s.is_extended_negative is atan(s).is_extended_negative + assert s.is_extended_nonpositive is atan(s).is_extended_nonpositive + assert s.is_extended_nonnegative is atan(s).is_extended_nonnegative + + +def test_atan_rewrite(): + assert atan(x).rewrite(log) == I*(log(1 - I*x)-log(1 + I*x))/2 + assert atan(x).rewrite(asin) == (-asin(1/sqrt(x**2 + 1)) + pi/2)*sqrt(x**2)/x + assert atan(x).rewrite(acos) == sqrt(x**2)*acos(1/sqrt(x**2 + 1))/x + assert atan(x).rewrite(acot) == acot(1/x) + assert atan(x).rewrite(asec) == sqrt(x**2)*asec(sqrt(x**2 + 1))/x + assert atan(x).rewrite(acsc) == (-acsc(sqrt(x**2 + 1)) + pi/2)*sqrt(x**2)/x + + assert atan(-5*I).evalf() == atan(x).rewrite(log).evalf(subs={x:-5*I}) + assert atan(5*I).evalf() == atan(x).rewrite(log).evalf(subs={x:5*I}) + + +def test_atan_fdiff(): + assert atan(x).fdiff() == 1/(x**2 + 1) + raises(ArgumentIndexError, lambda: atan(x).fdiff(2)) + + +def test_atan_leading_term(): + assert atan(x).as_leading_term(x) == x + assert atan(1/x).as_leading_term(x, cdir=1) == pi/2 + assert atan(1/x).as_leading_term(x, cdir=-1) == -pi/2 + # Tests concerning branch points + assert atan(x + I).as_leading_term(x, cdir=1) == -I*log(x)/2 + pi/4 + I*log(2)/2 + assert atan(x + I).as_leading_term(x, cdir=-1) == -I*log(x)/2 - 3*pi/4 + I*log(2)/2 + assert atan(x - I).as_leading_term(x, cdir=1) == I*log(x)/2 + pi/4 - I*log(2)/2 + assert atan(x - I).as_leading_term(x, cdir=-1) == I*log(x)/2 + pi/4 - I*log(2)/2 + # Tests concerning points lying on branch cuts + assert atan(x + 2*I).as_leading_term(x, cdir=1) == I*atanh(2) + assert atan(x + 2*I).as_leading_term(x, cdir=-1) == -pi + I*atanh(2) + assert atan(x - 2*I).as_leading_term(x, cdir=1) == pi - I*atanh(2) + assert atan(x - 2*I).as_leading_term(x, cdir=-1) == -I*atanh(2) + # Tests concerning re(ndir) == 0 + assert atan(2*I - I*x - x**2).as_leading_term(x, cdir=1) == -pi/2 + I*log(3)/2 + assert atan(2*I - I*x - x**2).as_leading_term(x, cdir=-1) == -pi/2 + I*log(3)/2 + + +def test_atan2(): + assert atan2.nargs == FiniteSet(2) + assert atan2(0, 0) is S.NaN + assert atan2(0, 1) == 0 + assert atan2(1, 1) == pi/4 + assert atan2(1, 0) == pi/2 + assert atan2(1, -1) == pi*Rational(3, 4) + assert atan2(0, -1) == pi + assert atan2(-1, -1) == pi*Rational(-3, 4) + assert atan2(-1, 0) == -pi/2 + assert atan2(-1, 1) == -pi/4 + i = symbols('i', imaginary=True) + r = symbols('r', real=True) + eq = atan2(r, i) + ans = -I*log((i + I*r)/sqrt(i**2 + r**2)) + reps = ((r, 2), (i, I)) + assert eq.subs(reps) == ans.subs(reps) + + x = Symbol('x', negative=True) + y = Symbol('y', negative=True) + assert atan2(y, x) == atan(y/x) - pi + y = Symbol('y', nonnegative=True) + assert atan2(y, x) == atan(y/x) + pi + y = Symbol('y') + assert atan2(y, x) == atan2(y, x, evaluate=False) + + u = Symbol("u", positive=True) + assert atan2(0, u) == 0 + u = Symbol("u", negative=True) + assert atan2(0, u) == pi + + assert atan2(y, oo) == 0 + assert atan2(y, -oo)== 2*pi*Heaviside(re(y), S.Half) - pi + + assert atan2(y, x).rewrite(log) == -I*log((x + I*y)/sqrt(x**2 + y**2)) + assert atan2(0, 0) is S.NaN + + ex = atan2(y, x) - arg(x + I*y) + assert ex.subs({x:2, y:3}).rewrite(arg) == 0 + assert ex.subs({x:2, y:3*I}).rewrite(arg) == -pi - I*log(sqrt(5)*I/5) + assert ex.subs({x:2*I, y:3}).rewrite(arg) == -pi/2 - I*log(sqrt(5)*I) + assert ex.subs({x:2*I, y:3*I}).rewrite(arg) == -pi + atan(Rational(2, 3)) + atan(Rational(3, 2)) + i = symbols('i', imaginary=True) + r = symbols('r', real=True) + e = atan2(i, r) + rewrite = e.rewrite(arg) + reps = {i: I, r: -2} + assert rewrite == -I*log(abs(I*i + r)/sqrt(abs(i**2 + r**2))) + arg((I*i + r)/sqrt(i**2 + r**2)) + assert (e - rewrite).subs(reps).equals(0) + + assert atan2(0, x).rewrite(atan) == Piecewise((pi, re(x) < 0), + (0, Ne(x, 0)), + (nan, True)) + assert atan2(0, r).rewrite(atan) == Piecewise((pi, r < 0), (0, Ne(r, 0)), (S.NaN, True)) + assert atan2(0, i),rewrite(atan) == 0 + assert atan2(0, r + i).rewrite(atan) == Piecewise((pi, r < 0), (0, True)) + + assert atan2(y, x).rewrite(atan) == Piecewise( + (2*atan(y/(x + sqrt(x**2 + y**2))), Ne(y, 0)), + (pi, re(x) < 0), + (0, (re(x) > 0) | Ne(im(x), 0)), + (nan, True)) + assert conjugate(atan2(x, y)) == atan2(conjugate(x), conjugate(y)) + + assert diff(atan2(y, x), x) == -y/(x**2 + y**2) + assert diff(atan2(y, x), y) == x/(x**2 + y**2) + + assert simplify(diff(atan2(y, x).rewrite(log), x)) == -y/(x**2 + y**2) + assert simplify(diff(atan2(y, x).rewrite(log), y)) == x/(x**2 + y**2) + + assert str(atan2(1, 2).evalf(5)) == '0.46365' + raises(ArgumentIndexError, lambda: atan2(x, y).fdiff(3)) + +def test_issue_17461(): + class A(Symbol): + is_extended_real = True + + def _eval_evalf(self, prec): + return Float(5.0) + + x = A('X') + y = A('Y') + assert abs(atan2(x, y).evalf() - 0.785398163397448) <= 1e-10 + +def test_acot(): + assert acot(nan) is nan + + assert acot.nargs == FiniteSet(1) + assert acot(-oo) == 0 + assert acot(oo) == 0 + assert acot(zoo) == 0 + assert acot(1) == pi/4 + assert acot(0) == pi/2 + assert acot(sqrt(3)/3) == pi/3 + assert acot(1/sqrt(3)) == pi/3 + assert acot(-1/sqrt(3)) == -pi/3 + assert acot(x).diff(x) == -1/(1 + x**2) + + assert acot(r).is_extended_real is True + + assert acot(I*pi) == -I*acoth(pi) + assert acot(-2*I) == I*acoth(2) + assert acot(x).is_positive is None + assert acot(n).is_positive is False + assert acot(p).is_positive is True + assert acot(I).is_positive is False + assert acot(Rational(1, 4)).is_rational is False + assert unchanged(acot, cot(x)) + assert unchanged(acot, tan(x)) + assert acot(cot(Rational(1, 4))) == Rational(1, 4) + assert acot(tan(Rational(-1, 4))) == Rational(1, 4) - pi/2 + + +def test_acot_rewrite(): + assert acot(x).rewrite(log) == I*(log(1 - I/x)-log(1 + I/x))/2 + assert acot(x).rewrite(asin) == x*(-asin(sqrt(-x**2)/sqrt(-x**2 - 1)) + pi/2)*sqrt(x**(-2)) + assert acot(x).rewrite(acos) == x*sqrt(x**(-2))*acos(sqrt(-x**2)/sqrt(-x**2 - 1)) + assert acot(x).rewrite(atan) == atan(1/x) + assert acot(x).rewrite(asec) == x*sqrt(x**(-2))*asec(sqrt((x**2 + 1)/x**2)) + assert acot(x).rewrite(acsc) == x*(-acsc(sqrt((x**2 + 1)/x**2)) + pi/2)*sqrt(x**(-2)) + + assert acot(-I/5).evalf() == acot(x).rewrite(log).evalf(subs={x:-I/5}) + assert acot(I/5).evalf() == acot(x).rewrite(log).evalf(subs={x:I/5}) + + +def test_acot_fdiff(): + assert acot(x).fdiff() == -1/(x**2 + 1) + raises(ArgumentIndexError, lambda: acot(x).fdiff(2)) + +def test_acot_leading_term(): + assert acot(1/x).as_leading_term(x) == x + # Tests concerning branch points + assert acot(x + I).as_leading_term(x, cdir=1) == I*log(x)/2 + pi/4 - I*log(2)/2 + assert acot(x + I).as_leading_term(x, cdir=-1) == I*log(x)/2 + pi/4 - I*log(2)/2 + assert acot(x - I).as_leading_term(x, cdir=1) == -I*log(x)/2 + pi/4 + I*log(2)/2 + assert acot(x - I).as_leading_term(x, cdir=-1) == -I*log(x)/2 - 3*pi/4 + I*log(2)/2 + # Tests concerning points lying on branch cuts + assert acot(x).as_leading_term(x, cdir=1) == pi/2 + assert acot(x).as_leading_term(x, cdir=-1) == -pi/2 + assert acot(x + I/2).as_leading_term(x, cdir=1) == pi - I*acoth(S(1)/2) + assert acot(x + I/2).as_leading_term(x, cdir=-1) == -I*acoth(S(1)/2) + assert acot(x - I/2).as_leading_term(x, cdir=1) == I*acoth(S(1)/2) + assert acot(x - I/2).as_leading_term(x, cdir=-1) == -pi + I*acoth(S(1)/2) + # Tests concerning re(ndir) == 0 + assert acot(I/2 - I*x - x**2).as_leading_term(x, cdir=1) == -pi/2 - I*log(3)/2 + assert acot(I/2 - I*x - x**2).as_leading_term(x, cdir=-1) == -pi/2 - I*log(3)/2 + + +def test_attributes(): + assert sin(x).args == (x,) + + +def test_sincos_rewrite(): + assert sin(pi/2 - x) == cos(x) + assert sin(pi - x) == sin(x) + assert cos(pi/2 - x) == sin(x) + assert cos(pi - x) == -cos(x) + + +def _check_even_rewrite(func, arg): + """Checks that the expr has been rewritten using f(-x) -> f(x) + arg : -x + """ + return func(arg).args[0] == -arg + + +def _check_odd_rewrite(func, arg): + """Checks that the expr has been rewritten using f(-x) -> -f(x) + arg : -x + """ + return func(arg).func.is_Mul + + +def _check_no_rewrite(func, arg): + """Checks that the expr is not rewritten""" + return func(arg).args[0] == arg + + +def test_evenodd_rewrite(): + a = cos(2) # negative + b = sin(1) # positive + even = [cos] + odd = [sin, tan, cot, asin, atan, acot] + with_minus = [-1, -2**1024 * E, -pi/105, -x*y, -x - y] + for func in even: + for expr in with_minus: + assert _check_even_rewrite(func, expr) + assert _check_no_rewrite(func, a*b) + assert func( + x - y) == func(y - x) # it doesn't matter which form is canonical + for func in odd: + for expr in with_minus: + assert _check_odd_rewrite(func, expr) + assert _check_no_rewrite(func, a*b) + assert func( + x - y) == -func(y - x) # it doesn't matter which form is canonical + + +def test_as_leading_term_issue_5272(): + assert sin(x).as_leading_term(x) == x + assert cos(x).as_leading_term(x) == 1 + assert tan(x).as_leading_term(x) == x + assert cot(x).as_leading_term(x) == 1/x + + +def test_leading_terms(): + assert sin(1/x).as_leading_term(x) == AccumBounds(-1, 1) + assert sin(S.Half).as_leading_term(x) == sin(S.Half) + assert cos(1/x).as_leading_term(x) == AccumBounds(-1, 1) + assert cos(S.Half).as_leading_term(x) == cos(S.Half) + assert sec(1/x).as_leading_term(x) == AccumBounds(S.NegativeInfinity, S.Infinity) + assert csc(1/x).as_leading_term(x) == AccumBounds(S.NegativeInfinity, S.Infinity) + assert tan(1/x).as_leading_term(x) == AccumBounds(S.NegativeInfinity, S.Infinity) + assert cot(1/x).as_leading_term(x) == AccumBounds(S.NegativeInfinity, S.Infinity) + + # https://github.com/sympy/sympy/issues/21038 + f = sin(pi*(x + 4))/(3*x) + assert f.as_leading_term(x) == pi/3 + + +def test_atan2_expansion(): + assert cancel(atan2(x**2, x + 1).diff(x) - atan(x**2/(x + 1)).diff(x)) == 0 + assert cancel(atan(y/x).series(y, 0, 5) - atan2(y, x).series(y, 0, 5) + + atan2(0, x) - atan(0)) == O(y**5) + assert cancel(atan(y/x).series(x, 1, 4) - atan2(y, x).series(x, 1, 4) + + atan2(y, 1) - atan(y)) == O((x - 1)**4, (x, 1)) + assert cancel(atan((y + x)/x).series(x, 1, 3) - atan2(y + x, x).series(x, 1, 3) + + atan2(1 + y, 1) - atan(1 + y)) == O((x - 1)**3, (x, 1)) + assert Matrix([atan2(y, x)]).jacobian([y, x]) == \ + Matrix([[x/(y**2 + x**2), -y/(y**2 + x**2)]]) + + +def test_aseries(): + def t(n, v, d, e): + assert abs( + n(1/v).evalf() - n(1/x).series(x, dir=d).removeO().subs(x, v)) < e + t(atan, 0.1, '+', 1e-5) + t(atan, -0.1, '-', 1e-5) + t(acot, 0.1, '+', 1e-5) + t(acot, -0.1, '-', 1e-5) + + +def test_issue_4420(): + i = Symbol('i', integer=True) + e = Symbol('e', even=True) + o = Symbol('o', odd=True) + + # unknown parity for variable + assert cos(4*i*pi) == 1 + assert sin(4*i*pi) == 0 + assert tan(4*i*pi) == 0 + assert cot(4*i*pi) is zoo + + assert cos(3*i*pi) == cos(pi*i) # +/-1 + assert sin(3*i*pi) == 0 + assert tan(3*i*pi) == 0 + assert cot(3*i*pi) is zoo + + assert cos(4.0*i*pi) == 1 + assert sin(4.0*i*pi) == 0 + assert tan(4.0*i*pi) == 0 + assert cot(4.0*i*pi) is zoo + + assert cos(3.0*i*pi) == cos(pi*i) # +/-1 + assert sin(3.0*i*pi) == 0 + assert tan(3.0*i*pi) == 0 + assert cot(3.0*i*pi) is zoo + + assert cos(4.5*i*pi) == cos(0.5*pi*i) + assert sin(4.5*i*pi) == sin(0.5*pi*i) + assert tan(4.5*i*pi) == tan(0.5*pi*i) + assert cot(4.5*i*pi) == cot(0.5*pi*i) + + # parity of variable is known + assert cos(4*e*pi) == 1 + assert sin(4*e*pi) == 0 + assert tan(4*e*pi) == 0 + assert cot(4*e*pi) is zoo + + assert cos(3*e*pi) == 1 + assert sin(3*e*pi) == 0 + assert tan(3*e*pi) == 0 + assert cot(3*e*pi) is zoo + + assert cos(4.0*e*pi) == 1 + assert sin(4.0*e*pi) == 0 + assert tan(4.0*e*pi) == 0 + assert cot(4.0*e*pi) is zoo + + assert cos(3.0*e*pi) == 1 + assert sin(3.0*e*pi) == 0 + assert tan(3.0*e*pi) == 0 + assert cot(3.0*e*pi) is zoo + + assert cos(4.5*e*pi) == cos(0.5*pi*e) + assert sin(4.5*e*pi) == sin(0.5*pi*e) + assert tan(4.5*e*pi) == tan(0.5*pi*e) + assert cot(4.5*e*pi) == cot(0.5*pi*e) + + assert cos(4*o*pi) == 1 + assert sin(4*o*pi) == 0 + assert tan(4*o*pi) == 0 + assert cot(4*o*pi) is zoo + + assert cos(3*o*pi) == -1 + assert sin(3*o*pi) == 0 + assert tan(3*o*pi) == 0 + assert cot(3*o*pi) is zoo + + assert cos(4.0*o*pi) == 1 + assert sin(4.0*o*pi) == 0 + assert tan(4.0*o*pi) == 0 + assert cot(4.0*o*pi) is zoo + + assert cos(3.0*o*pi) == -1 + assert sin(3.0*o*pi) == 0 + assert tan(3.0*o*pi) == 0 + assert cot(3.0*o*pi) is zoo + + assert cos(4.5*o*pi) == cos(0.5*pi*o) + assert sin(4.5*o*pi) == sin(0.5*pi*o) + assert tan(4.5*o*pi) == tan(0.5*pi*o) + assert cot(4.5*o*pi) == cot(0.5*pi*o) + + # x could be imaginary + assert cos(4*x*pi) == cos(4*pi*x) + assert sin(4*x*pi) == sin(4*pi*x) + assert tan(4*x*pi) == tan(4*pi*x) + assert cot(4*x*pi) == cot(4*pi*x) + + assert cos(3*x*pi) == cos(3*pi*x) + assert sin(3*x*pi) == sin(3*pi*x) + assert tan(3*x*pi) == tan(3*pi*x) + assert cot(3*x*pi) == cot(3*pi*x) + + assert cos(4.0*x*pi) == cos(4.0*pi*x) + assert sin(4.0*x*pi) == sin(4.0*pi*x) + assert tan(4.0*x*pi) == tan(4.0*pi*x) + assert cot(4.0*x*pi) == cot(4.0*pi*x) + + assert cos(3.0*x*pi) == cos(3.0*pi*x) + assert sin(3.0*x*pi) == sin(3.0*pi*x) + assert tan(3.0*x*pi) == tan(3.0*pi*x) + assert cot(3.0*x*pi) == cot(3.0*pi*x) + + assert cos(4.5*x*pi) == cos(4.5*pi*x) + assert sin(4.5*x*pi) == sin(4.5*pi*x) + assert tan(4.5*x*pi) == tan(4.5*pi*x) + assert cot(4.5*x*pi) == cot(4.5*pi*x) + + +def test_inverses(): + raises(AttributeError, lambda: sin(x).inverse()) + raises(AttributeError, lambda: cos(x).inverse()) + assert tan(x).inverse() == atan + assert cot(x).inverse() == acot + raises(AttributeError, lambda: csc(x).inverse()) + raises(AttributeError, lambda: sec(x).inverse()) + assert asin(x).inverse() == sin + assert acos(x).inverse() == cos + assert atan(x).inverse() == tan + assert acot(x).inverse() == cot + + +def test_real_imag(): + a, b = symbols('a b', real=True) + z = a + b*I + for deep in [True, False]: + assert sin( + z).as_real_imag(deep=deep) == (sin(a)*cosh(b), cos(a)*sinh(b)) + assert cos( + z).as_real_imag(deep=deep) == (cos(a)*cosh(b), -sin(a)*sinh(b)) + assert tan(z).as_real_imag(deep=deep) == (sin(2*a)/(cos(2*a) + + cosh(2*b)), sinh(2*b)/(cos(2*a) + cosh(2*b))) + assert cot(z).as_real_imag(deep=deep) == (-sin(2*a)/(cos(2*a) - + cosh(2*b)), sinh(2*b)/(cos(2*a) - cosh(2*b))) + assert sin(a).as_real_imag(deep=deep) == (sin(a), 0) + assert cos(a).as_real_imag(deep=deep) == (cos(a), 0) + assert tan(a).as_real_imag(deep=deep) == (tan(a), 0) + assert cot(a).as_real_imag(deep=deep) == (cot(a), 0) + + +@slow +def test_sincos_rewrite_sqrt(): + # equivalent to testing rewrite(pow) + for p in [1, 3, 5, 17]: + for t in [1, 8]: + n = t*p + # The vertices `exp(i*pi/n)` of a regular `n`-gon can + # be expressed by means of nested square roots if and + # only if `n` is a product of Fermat primes, `p`, and + # powers of 2, `t'. The code aims to check all vertices + # not belonging to an `m`-gon for `m < n`(`gcd(i, n) == 1`). + # For large `n` this makes the test too slow, therefore + # the vertices are limited to those of index `i < 10`. + for i in range(1, min((n + 1)//2 + 1, 10)): + if 1 == gcd(i, n): + x = i*pi/n + s1 = sin(x).rewrite(sqrt) + c1 = cos(x).rewrite(sqrt) + assert not s1.has(cos, sin), "fails for %d*pi/%d" % (i, n) + assert not c1.has(cos, sin), "fails for %d*pi/%d" % (i, n) + assert 1e-3 > abs(sin(x.evalf(5)) - s1.evalf(2)), "fails for %d*pi/%d" % (i, n) + assert 1e-3 > abs(cos(x.evalf(5)) - c1.evalf(2)), "fails for %d*pi/%d" % (i, n) + assert cos(pi/14).rewrite(sqrt) == sqrt(cos(pi/7)/2 + S.Half) + assert cos(pi*Rational(-15, 2)/11, evaluate=False).rewrite( + sqrt) == -sqrt(-cos(pi*Rational(4, 11))/2 + S.Half) + assert cos(Mul(2, pi, S.Half, evaluate=False), evaluate=False).rewrite( + sqrt) == -1 + e = cos(pi/3/17) # don't use pi/15 since that is caught at instantiation + a = ( + -3*sqrt(-sqrt(17) + 17)*sqrt(sqrt(17) + 17)/64 - + 3*sqrt(34)*sqrt(sqrt(17) + 17)/128 - sqrt(sqrt(17) + + 17)*sqrt(-8*sqrt(2)*sqrt(sqrt(17) + 17) - sqrt(2)*sqrt(-sqrt(17) + 17) + + sqrt(34)*sqrt(-sqrt(17) + 17) + 6*sqrt(17) + 34)/64 - sqrt(-sqrt(17) + + 17)*sqrt(-8*sqrt(2)*sqrt(sqrt(17) + 17) - sqrt(2)*sqrt(-sqrt(17) + + 17) + sqrt(34)*sqrt(-sqrt(17) + 17) + 6*sqrt(17) + 34)/128 - Rational(1, 32) + + sqrt(2)*sqrt(-8*sqrt(2)*sqrt(sqrt(17) + 17) - sqrt(2)*sqrt(-sqrt(17) + + 17) + sqrt(34)*sqrt(-sqrt(17) + 17) + 6*sqrt(17) + 34)/64 + + 3*sqrt(2)*sqrt(sqrt(17) + 17)/128 + sqrt(34)*sqrt(-sqrt(17) + 17)/128 + + 13*sqrt(2)*sqrt(-sqrt(17) + 17)/128 + sqrt(17)*sqrt(-sqrt(17) + + 17)*sqrt(-8*sqrt(2)*sqrt(sqrt(17) + 17) - sqrt(2)*sqrt(-sqrt(17) + 17) + + sqrt(34)*sqrt(-sqrt(17) + 17) + 6*sqrt(17) + 34)/128 + 5*sqrt(17)/32 + + sqrt(3)*sqrt(-sqrt(2)*sqrt(sqrt(17) + 17)*sqrt(sqrt(17)/32 + + sqrt(2)*sqrt(-sqrt(17) + 17)/32 + + sqrt(2)*sqrt(-8*sqrt(2)*sqrt(sqrt(17) + 17) - sqrt(2)*sqrt(-sqrt(17) + + 17) + sqrt(34)*sqrt(-sqrt(17) + 17) + 6*sqrt(17) + 34)/32 + Rational(15, 32))/8 - + 5*sqrt(2)*sqrt(sqrt(17)/32 + sqrt(2)*sqrt(-sqrt(17) + 17)/32 + + sqrt(2)*sqrt(-8*sqrt(2)*sqrt(sqrt(17) + 17) - sqrt(2)*sqrt(-sqrt(17) + + 17) + sqrt(34)*sqrt(-sqrt(17) + 17) + 6*sqrt(17) + 34)/32 + + Rational(15, 32))*sqrt(-8*sqrt(2)*sqrt(sqrt(17) + 17) - sqrt(2)*sqrt(-sqrt(17) + + 17) + sqrt(34)*sqrt(-sqrt(17) + 17) + 6*sqrt(17) + 34)/64 - + 3*sqrt(2)*sqrt(-sqrt(17) + 17)*sqrt(sqrt(17)/32 + + sqrt(2)*sqrt(-sqrt(17) + 17)/32 + + sqrt(2)*sqrt(-8*sqrt(2)*sqrt(sqrt(17) + 17) - sqrt(2)*sqrt(-sqrt(17) + + 17) + sqrt(34)*sqrt(-sqrt(17) + 17) + 6*sqrt(17) + 34)/32 + Rational(15, 32))/32 + + sqrt(34)*sqrt(sqrt(17)/32 + sqrt(2)*sqrt(-sqrt(17) + 17)/32 + + sqrt(2)*sqrt(-8*sqrt(2)*sqrt(sqrt(17) + 17) - sqrt(2)*sqrt(-sqrt(17) + + 17) + sqrt(34)*sqrt(-sqrt(17) + 17) + 6*sqrt(17) + 34)/32 + + Rational(15, 32))*sqrt(-8*sqrt(2)*sqrt(sqrt(17) + 17) - sqrt(2)*sqrt(-sqrt(17) + + 17) + sqrt(34)*sqrt(-sqrt(17) + 17) + 6*sqrt(17) + 34)/64 + + sqrt(sqrt(17)/32 + sqrt(2)*sqrt(-sqrt(17) + 17)/32 + + sqrt(2)*sqrt(-8*sqrt(2)*sqrt(sqrt(17) + 17) - sqrt(2)*sqrt(-sqrt(17) + + 17) + sqrt(34)*sqrt(-sqrt(17) + 17) + 6*sqrt(17) + 34)/32 + Rational(15, 32))/2 + + S.Half + sqrt(-sqrt(17) + 17)*sqrt(sqrt(17)/32 + sqrt(2)*sqrt(-sqrt(17) + + 17)/32 + sqrt(2)*sqrt(-8*sqrt(2)*sqrt(sqrt(17) + 17) - + sqrt(2)*sqrt(-sqrt(17) + 17) + sqrt(34)*sqrt(-sqrt(17) + 17) + + 6*sqrt(17) + 34)/32 + Rational(15, 32))*sqrt(-8*sqrt(2)*sqrt(sqrt(17) + 17) - + sqrt(2)*sqrt(-sqrt(17) + 17) + sqrt(34)*sqrt(-sqrt(17) + 17) + + 6*sqrt(17) + 34)/32 + sqrt(34)*sqrt(-sqrt(17) + 17)*sqrt(sqrt(17)/32 + + sqrt(2)*sqrt(-sqrt(17) + 17)/32 + + sqrt(2)*sqrt(-8*sqrt(2)*sqrt(sqrt(17) + 17) - sqrt(2)*sqrt(-sqrt(17) + + 17) + sqrt(34)*sqrt(-sqrt(17) + 17) + 6*sqrt(17) + 34)/32 + + Rational(15, 32))/32)/2) + assert e.rewrite(sqrt) == a + assert e.n() == a.n() + # coverage of fermatCoords: multiplicity > 1; the following could be + # different but that portion of the code should be tested in some way + assert cos(pi/9/17).rewrite(sqrt) == \ + sin(pi/9)*sin(pi*Rational(2, 17)) + cos(pi/9)*cos(pi*Rational(2, 17)) + + +@slow +def test_sincos_rewrite_sqrt_257(): + assert cos(pi/257).rewrite(sqrt).evalf(64) == cos(pi/257).evalf(64) + + +@slow +def test_tancot_rewrite_sqrt(): + # equivalent to testing rewrite(pow) + for p in [1, 3, 5, 17]: + for t in [1, 8]: + n = t*p + for i in range(1, min((n + 1)//2 + 1, 10)): + if 1 == gcd(i, n): + x = i*pi/n + if 2*i != n and 3*i != 2*n: + t1 = tan(x).rewrite(sqrt) + assert not t1.has(cot, tan), "fails for %d*pi/%d" % (i, n) + assert 1e-3 > abs( tan(x.evalf(7)) - t1.evalf(4) ), "fails for %d*pi/%d" % (i, n) + if i != 0 and i != n: + c1 = cot(x).rewrite(sqrt) + assert not c1.has(cot, tan), "fails for %d*pi/%d" % (i, n) + assert 1e-3 > abs( cot(x.evalf(7)) - c1.evalf(4) ), "fails for %d*pi/%d" % (i, n) + + +def test_sec(): + x = symbols('x', real=True) + z = symbols('z') + + assert sec.nargs == FiniteSet(1) + + assert sec(zoo) is nan + assert sec(0) == 1 + assert sec(pi) == -1 + assert sec(pi/2) is zoo + assert sec(-pi/2) is zoo + assert sec(pi/6) == 2*sqrt(3)/3 + assert sec(pi/3) == 2 + assert sec(pi*Rational(5, 2)) is zoo + assert sec(pi*Rational(9, 7)) == -sec(pi*Rational(2, 7)) + assert sec(pi*Rational(3, 4)) == -sqrt(2) # issue 8421 + assert sec(I) == 1/cosh(1) + assert sec(x*I) == 1/cosh(x) + assert sec(-x) == sec(x) + + assert sec(asec(x)) == x + + assert sec(z).conjugate() == sec(conjugate(z)) + + assert (sec(z).as_real_imag() == + (cos(re(z))*cosh(im(z))/(sin(re(z))**2*sinh(im(z))**2 + + cos(re(z))**2*cosh(im(z))**2), + sin(re(z))*sinh(im(z))/(sin(re(z))**2*sinh(im(z))**2 + + cos(re(z))**2*cosh(im(z))**2))) + + assert sec(x).expand(trig=True) == 1/cos(x) + assert sec(2*x).expand(trig=True) == 1/(2*cos(x)**2 - 1) + + assert sec(x).is_extended_real == True + assert sec(z).is_real == None + + assert sec(a).is_algebraic is None + assert sec(na).is_algebraic is False + + assert sec(x).as_leading_term() == sec(x) + + assert sec(0, evaluate=False).is_finite == True + assert sec(x).is_finite == None + assert sec(pi/2, evaluate=False).is_finite == False + + assert series(sec(x), x, x0=0, n=6) == 1 + x**2/2 + 5*x**4/24 + O(x**6) + + # https://github.com/sympy/sympy/issues/7166 + assert series(sqrt(sec(x))) == 1 + x**2/4 + 7*x**4/96 + O(x**6) + + # https://github.com/sympy/sympy/issues/7167 + assert (series(sqrt(sec(x)), x, x0=pi*3/2, n=4) == + 1/sqrt(x - pi*Rational(3, 2)) + (x - pi*Rational(3, 2))**Rational(3, 2)/12 + + (x - pi*Rational(3, 2))**Rational(7, 2)/160 + O((x - pi*Rational(3, 2))**4, (x, pi*Rational(3, 2)))) + + assert sec(x).diff(x) == tan(x)*sec(x) + + # Taylor Term checks + assert sec(z).taylor_term(4, z) == 5*z**4/24 + assert sec(z).taylor_term(6, z) == 61*z**6/720 + assert sec(z).taylor_term(5, z) == 0 + + +def test_sec_rewrite(): + assert sec(x).rewrite(exp) == 1/(exp(I*x)/2 + exp(-I*x)/2) + assert sec(x).rewrite(cos) == 1/cos(x) + assert sec(x).rewrite(tan) == (tan(x/2)**2 + 1)/(-tan(x/2)**2 + 1) + assert sec(x).rewrite(pow) == sec(x) + assert sec(x).rewrite(sqrt) == sec(x) + assert sec(z).rewrite(cot) == (cot(z/2)**2 + 1)/(cot(z/2)**2 - 1) + assert sec(x).rewrite(sin) == 1 / sin(x + pi / 2, evaluate=False) + assert sec(x).rewrite(tan) == (tan(x / 2)**2 + 1) / (-tan(x / 2)**2 + 1) + assert sec(x).rewrite(csc) == csc(-x + pi/2, evaluate=False) + assert sec(x).rewrite(besselj) == Piecewise( + (sqrt(2)/(sqrt(pi*x)*besselj(-S.Half, x)), Ne(x, 0)), + (1, True) + ) + assert sec(x).rewrite(besselj).subs(x, 0) == sec(0) + + +def test_sec_fdiff(): + assert sec(x).fdiff() == tan(x)*sec(x) + raises(ArgumentIndexError, lambda: sec(x).fdiff(2)) + + +def test_csc(): + x = symbols('x', real=True) + z = symbols('z') + + # https://github.com/sympy/sympy/issues/6707 + cosecant = csc('x') + alternate = 1/sin('x') + assert cosecant.equals(alternate) == True + assert alternate.equals(cosecant) == True + + assert csc.nargs == FiniteSet(1) + + assert csc(0) is zoo + assert csc(pi) is zoo + assert csc(zoo) is nan + + assert csc(pi/2) == 1 + assert csc(-pi/2) == -1 + assert csc(pi/6) == 2 + assert csc(pi/3) == 2*sqrt(3)/3 + assert csc(pi*Rational(5, 2)) == 1 + assert csc(pi*Rational(9, 7)) == -csc(pi*Rational(2, 7)) + assert csc(pi*Rational(3, 4)) == sqrt(2) # issue 8421 + assert csc(I) == -I/sinh(1) + assert csc(x*I) == -I/sinh(x) + assert csc(-x) == -csc(x) + + assert csc(acsc(x)) == x + + assert csc(z).conjugate() == csc(conjugate(z)) + + assert (csc(z).as_real_imag() == + (sin(re(z))*cosh(im(z))/(sin(re(z))**2*cosh(im(z))**2 + + cos(re(z))**2*sinh(im(z))**2), + -cos(re(z))*sinh(im(z))/(sin(re(z))**2*cosh(im(z))**2 + + cos(re(z))**2*sinh(im(z))**2))) + + assert csc(x).expand(trig=True) == 1/sin(x) + assert csc(2*x).expand(trig=True) == 1/(2*sin(x)*cos(x)) + + assert csc(x).is_extended_real == True + assert csc(z).is_real == None + + assert csc(a).is_algebraic is None + assert csc(na).is_algebraic is False + + assert csc(x).as_leading_term() == csc(x) + + assert csc(0, evaluate=False).is_finite == False + assert csc(x).is_finite == None + assert csc(pi/2, evaluate=False).is_finite == True + + assert series(csc(x), x, x0=pi/2, n=6) == \ + 1 + (x - pi/2)**2/2 + 5*(x - pi/2)**4/24 + O((x - pi/2)**6, (x, pi/2)) + assert series(csc(x), x, x0=0, n=6) == \ + 1/x + x/6 + 7*x**3/360 + 31*x**5/15120 + O(x**6) + + assert csc(x).diff(x) == -cot(x)*csc(x) + + assert csc(x).taylor_term(2, x) == 0 + assert csc(x).taylor_term(3, x) == 7*x**3/360 + assert csc(x).taylor_term(5, x) == 31*x**5/15120 + raises(ArgumentIndexError, lambda: csc(x).fdiff(2)) + + +def test_asec(): + z = Symbol('z', zero=True) + assert asec(z) is zoo + assert asec(nan) is nan + assert asec(1) == 0 + assert asec(-1) == pi + assert asec(oo) == pi/2 + assert asec(-oo) == pi/2 + assert asec(zoo) == pi/2 + + assert asec(sec(pi*Rational(13, 4))) == pi*Rational(3, 4) + assert asec(1 + sqrt(5)) == pi*Rational(2, 5) + assert asec(2/sqrt(3)) == pi/6 + assert asec(sqrt(4 - 2*sqrt(2))) == pi/8 + assert asec(-sqrt(4 + 2*sqrt(2))) == pi*Rational(5, 8) + assert asec(sqrt(2 + 2*sqrt(5)/5)) == pi*Rational(3, 10) + assert asec(-sqrt(2 + 2*sqrt(5)/5)) == pi*Rational(7, 10) + assert asec(sqrt(2) - sqrt(6)) == pi*Rational(11, 12) + + for d in [3, 4, 6]: + for num in range(d): + if gcd(num, d) == 1: + assert asec(sec(num*pi/d)) == num*pi/d + assert asec(-sec(num*pi/d)) == pi - num*pi/d + assert asec(csc(num*pi/d)) == pi/2 - acsc(csc(num*pi/d)) + assert asec(-csc(num*pi/d)) == pi/2 - acsc(-csc(num*pi/d)) + + assert asec(x).diff(x) == 1/(x**2*sqrt(1 - 1/x**2)) + + assert asec(x).rewrite(log) == I*log(sqrt(1 - 1/x**2) + I/x) + pi/2 + assert asec(x).rewrite(asin) == -asin(1/x) + pi/2 + assert asec(x).rewrite(acos) == acos(1/x) + assert asec(x).rewrite(atan) == \ + pi*(1 - sqrt(x**2)/x)/2 + sqrt(x**2)*atan(sqrt(x**2 - 1))/x + assert asec(x).rewrite(acot) == \ + pi*(1 - sqrt(x**2)/x)/2 + sqrt(x**2)*acot(1/sqrt(x**2 - 1))/x + assert asec(x).rewrite(acsc) == -acsc(x) + pi/2 + raises(ArgumentIndexError, lambda: asec(x).fdiff(2)) + + +def test_asec_is_real(): + assert asec(S.Half).is_real is False + n = Symbol('n', positive=True, integer=True) + assert asec(n).is_extended_real is True + assert asec(x).is_real is None + assert asec(r).is_real is None + t = Symbol('t', real=False, finite=True) + assert asec(t).is_real is False + + +def test_asec_leading_term(): + assert asec(1/x).as_leading_term(x) == pi/2 + # Tests concerning branch points + assert asec(x + 1).as_leading_term(x) == sqrt(2)*sqrt(x) + assert asec(x - 1).as_leading_term(x) == pi + # Tests concerning points lying on branch cuts + assert asec(x).as_leading_term(x, cdir=1) == -I*log(x) + I*log(2) + assert asec(x).as_leading_term(x, cdir=-1) == I*log(x) + 2*pi - I*log(2) + assert asec(I*x + 1/2).as_leading_term(x, cdir=1) == asec(1/2) + assert asec(-I*x + 1/2).as_leading_term(x, cdir=1) == -asec(1/2) + assert asec(I*x - 1/2).as_leading_term(x, cdir=1) == 2*pi - asec(-1/2) + assert asec(-I*x - 1/2).as_leading_term(x, cdir=1) == asec(-1/2) + # Tests concerning im(ndir) == 0 + assert asec(-I*x**2 + x - S(1)/2).as_leading_term(x, cdir=1) == pi + I*log(2 - sqrt(3)) + assert asec(-I*x**2 + x - S(1)/2).as_leading_term(x, cdir=-1) == pi + I*log(2 - sqrt(3)) + + +def test_asec_series(): + assert asec(x).series(x, 0, 9) == \ + I*log(2) - I*log(x) - I*x**2/4 - 3*I*x**4/32 \ + - 5*I*x**6/96 - 35*I*x**8/1024 + O(x**9) + t4 = asec(x).taylor_term(4, x) + assert t4 == -3*I*x**4/32 + assert asec(x).taylor_term(6, x, t4, 0) == -5*I*x**6/96 + + +def test_acsc(): + assert acsc(nan) is nan + assert acsc(1) == pi/2 + assert acsc(-1) == -pi/2 + assert acsc(oo) == 0 + assert acsc(-oo) == 0 + assert acsc(zoo) == 0 + assert acsc(0) is zoo + + assert acsc(csc(3)) == -3 + pi + assert acsc(csc(4)) == -4 + pi + assert acsc(csc(6)) == 6 - 2*pi + assert unchanged(acsc, csc(x)) + assert unchanged(acsc, sec(x)) + + assert acsc(2/sqrt(3)) == pi/3 + assert acsc(csc(pi*Rational(13, 4))) == -pi/4 + assert acsc(sqrt(2 + 2*sqrt(5)/5)) == pi/5 + assert acsc(-sqrt(2 + 2*sqrt(5)/5)) == -pi/5 + assert acsc(-2) == -pi/6 + assert acsc(-sqrt(4 + 2*sqrt(2))) == -pi/8 + assert acsc(sqrt(4 - 2*sqrt(2))) == pi*Rational(3, 8) + assert acsc(1 + sqrt(5)) == pi/10 + assert acsc(sqrt(2) - sqrt(6)) == pi*Rational(-5, 12) + + assert acsc(x).diff(x) == -1/(x**2*sqrt(1 - 1/x**2)) + + assert acsc(x).rewrite(log) == -I*log(sqrt(1 - 1/x**2) + I/x) + assert acsc(x).rewrite(asin) == asin(1/x) + assert acsc(x).rewrite(acos) == -acos(1/x) + pi/2 + assert acsc(x).rewrite(atan) == \ + (-atan(sqrt(x**2 - 1)) + pi/2)*sqrt(x**2)/x + assert acsc(x).rewrite(acot) == (-acot(1/sqrt(x**2 - 1)) + pi/2)*sqrt(x**2)/x + assert acsc(x).rewrite(asec) == -asec(x) + pi/2 + raises(ArgumentIndexError, lambda: acsc(x).fdiff(2)) + + +def test_csc_rewrite(): + assert csc(x).rewrite(pow) == csc(x) + assert csc(x).rewrite(sqrt) == csc(x) + + assert csc(x).rewrite(exp) == 2*I/(exp(I*x) - exp(-I*x)) + assert csc(x).rewrite(sin) == 1/sin(x) + assert csc(x).rewrite(tan) == (tan(x/2)**2 + 1)/(2*tan(x/2)) + assert csc(x).rewrite(cot) == (cot(x/2)**2 + 1)/(2*cot(x/2)) + assert csc(x).rewrite(cos) == 1/cos(x - pi/2, evaluate=False) + assert csc(x).rewrite(sec) == sec(-x + pi/2, evaluate=False) + + # issue 17349 + assert csc(1 - exp(-besselj(I, I))).rewrite(cos) == \ + -1/cos(-pi/2 - 1 + cos(I*besselj(I, I)) + + I*cos(-pi/2 + I*besselj(I, I), evaluate=False), evaluate=False) + assert csc(x).rewrite(besselj) == sqrt(2)/(sqrt(pi*x)*besselj(S.Half, x)) + assert csc(x).rewrite(besselj).subs(x, 0) == csc(0) + + +def test_acsc_leading_term(): + assert acsc(1/x).as_leading_term(x) == x + # Tests concerning branch points + assert acsc(x + 1).as_leading_term(x) == pi/2 + assert acsc(x - 1).as_leading_term(x) == -pi/2 + # Tests concerning points lying on branch cuts + assert acsc(x).as_leading_term(x, cdir=1) == I*log(x) + pi/2 - I*log(2) + assert acsc(x).as_leading_term(x, cdir=-1) == -I*log(x) - 3*pi/2 + I*log(2) + assert acsc(I*x + 1/2).as_leading_term(x, cdir=1) == acsc(1/2) + assert acsc(-I*x + 1/2).as_leading_term(x, cdir=1) == pi - acsc(1/2) + assert acsc(I*x - 1/2).as_leading_term(x, cdir=1) == -pi - acsc(-1/2) + assert acsc(-I*x - 1/2).as_leading_term(x, cdir=1) == -acsc(1/2) + # Tests concerning im(ndir) == 0 + assert acsc(-I*x**2 + x - S(1)/2).as_leading_term(x, cdir=1) == -pi/2 + I*log(sqrt(3) + 2) + assert acsc(-I*x**2 + x - S(1)/2).as_leading_term(x, cdir=-1) == -pi/2 + I*log(sqrt(3) + 2) + + +def test_acsc_series(): + assert acsc(x).series(x, 0, 9) == \ + -I*log(2) + pi/2 + I*log(x) + I*x**2/4 \ + + 3*I*x**4/32 + 5*I*x**6/96 + 35*I*x**8/1024 + O(x**9) + t6 = acsc(x).taylor_term(6, x) + assert t6 == 5*I*x**6/96 + assert acsc(x).taylor_term(8, x, t6, 0) == 35*I*x**8/1024 + + +def test_asin_nseries(): + assert asin(x + 2)._eval_nseries(x, 4, None, I) == -asin(2) + pi + \ + sqrt(3)*I*x/3 - sqrt(3)*I*x**2/9 + sqrt(3)*I*x**3/18 + O(x**4) + assert asin(x + 2)._eval_nseries(x, 4, None, -I) == asin(2) - \ + sqrt(3)*I*x/3 + sqrt(3)*I*x**2/9 - sqrt(3)*I*x**3/18 + O(x**4) + assert asin(x - 2)._eval_nseries(x, 4, None, I) == -asin(2) - \ + sqrt(3)*I*x/3 - sqrt(3)*I*x**2/9 - sqrt(3)*I*x**3/18 + O(x**4) + assert asin(x - 2)._eval_nseries(x, 4, None, -I) == asin(2) - pi + \ + sqrt(3)*I*x/3 + sqrt(3)*I*x**2/9 + sqrt(3)*I*x**3/18 + O(x**4) + # testing nseries for asin at branch points + assert asin(1 + x)._eval_nseries(x, 3, None) == pi/2 - sqrt(2)*sqrt(-x) - \ + sqrt(2)*(-x)**(S(3)/2)/12 - 3*sqrt(2)*(-x)**(S(5)/2)/160 + O(x**3) + assert asin(-1 + x)._eval_nseries(x, 3, None) == -pi/2 + sqrt(2)*sqrt(x) + \ + sqrt(2)*x**(S(3)/2)/12 + 3*sqrt(2)*x**(S(5)/2)/160 + O(x**3) + assert asin(exp(x))._eval_nseries(x, 3, None) == pi/2 - sqrt(2)*sqrt(-x) + \ + sqrt(2)*(-x)**(S(3)/2)/6 - sqrt(2)*(-x)**(S(5)/2)/120 + O(x**3) + assert asin(-exp(x))._eval_nseries(x, 3, None) == -pi/2 + sqrt(2)*sqrt(-x) - \ + sqrt(2)*(-x)**(S(3)/2)/6 + sqrt(2)*(-x)**(S(5)/2)/120 + O(x**3) + + +def test_acos_nseries(): + assert acos(x + 2)._eval_nseries(x, 4, None, I) == -acos(2) - sqrt(3)*I*x/3 + \ + sqrt(3)*I*x**2/9 - sqrt(3)*I*x**3/18 + O(x**4) + assert acos(x + 2)._eval_nseries(x, 4, None, -I) == acos(2) + sqrt(3)*I*x/3 - \ + sqrt(3)*I*x**2/9 + sqrt(3)*I*x**3/18 + O(x**4) + assert acos(x - 2)._eval_nseries(x, 4, None, I) == acos(-2) + sqrt(3)*I*x/3 + \ + sqrt(3)*I*x**2/9 + sqrt(3)*I*x**3/18 + O(x**4) + assert acos(x - 2)._eval_nseries(x, 4, None, -I) == -acos(-2) + 2*pi - \ + sqrt(3)*I*x/3 - sqrt(3)*I*x**2/9 - sqrt(3)*I*x**3/18 + O(x**4) + # testing nseries for acos at branch points + assert acos(1 + x)._eval_nseries(x, 3, None) == sqrt(2)*sqrt(-x) + \ + sqrt(2)*(-x)**(S(3)/2)/12 + 3*sqrt(2)*(-x)**(S(5)/2)/160 + O(x**3) + assert acos(-1 + x)._eval_nseries(x, 3, None) == pi - sqrt(2)*sqrt(x) - \ + sqrt(2)*x**(S(3)/2)/12 - 3*sqrt(2)*x**(S(5)/2)/160 + O(x**3) + assert acos(exp(x))._eval_nseries(x, 3, None) == sqrt(2)*sqrt(-x) - \ + sqrt(2)*(-x)**(S(3)/2)/6 + sqrt(2)*(-x)**(S(5)/2)/120 + O(x**3) + assert acos(-exp(x))._eval_nseries(x, 3, None) == pi - sqrt(2)*sqrt(-x) + \ + sqrt(2)*(-x)**(S(3)/2)/6 - sqrt(2)*(-x)**(S(5)/2)/120 + O(x**3) + + +def test_atan_nseries(): + assert atan(x + 2*I)._eval_nseries(x, 4, None, 1) == I*atanh(2) - x/3 - \ + 2*I*x**2/9 + 13*x**3/81 + O(x**4) + assert atan(x + 2*I)._eval_nseries(x, 4, None, -1) == I*atanh(2) - pi - \ + x/3 - 2*I*x**2/9 + 13*x**3/81 + O(x**4) + assert atan(x - 2*I)._eval_nseries(x, 4, None, 1) == -I*atanh(2) + pi - \ + x/3 + 2*I*x**2/9 + 13*x**3/81 + O(x**4) + assert atan(x - 2*I)._eval_nseries(x, 4, None, -1) == -I*atanh(2) - x/3 + \ + 2*I*x**2/9 + 13*x**3/81 + O(x**4) + assert atan(1/x)._eval_nseries(x, 2, None, 1) == pi/2 - x + O(x**2) + assert atan(1/x)._eval_nseries(x, 2, None, -1) == -pi/2 - x + O(x**2) + # testing nseries for atan at branch points + assert atan(x + I)._eval_nseries(x, 4, None) == I*log(2)/2 + pi/4 - \ + I*log(x)/2 + x/4 + I*x**2/16 - x**3/48 + O(x**4) + assert atan(x - I)._eval_nseries(x, 4, None) == -I*log(2)/2 + pi/4 + \ + I*log(x)/2 + x/4 - I*x**2/16 - x**3/48 + O(x**4) + + +def test_acot_nseries(): + assert acot(x + S(1)/2*I)._eval_nseries(x, 4, None, 1) == -I*acoth(S(1)/2) + \ + pi - 4*x/3 + 8*I*x**2/9 + 112*x**3/81 + O(x**4) + assert acot(x + S(1)/2*I)._eval_nseries(x, 4, None, -1) == -I*acoth(S(1)/2) - \ + 4*x/3 + 8*I*x**2/9 + 112*x**3/81 + O(x**4) + assert acot(x - S(1)/2*I)._eval_nseries(x, 4, None, 1) == I*acoth(S(1)/2) - \ + 4*x/3 - 8*I*x**2/9 + 112*x**3/81 + O(x**4) + assert acot(x - S(1)/2*I)._eval_nseries(x, 4, None, -1) == I*acoth(S(1)/2) - \ + pi - 4*x/3 - 8*I*x**2/9 + 112*x**3/81 + O(x**4) + assert acot(x)._eval_nseries(x, 2, None, 1) == pi/2 - x + O(x**2) + assert acot(x)._eval_nseries(x, 2, None, -1) == -pi/2 - x + O(x**2) + # testing nseries for acot at branch points + assert acot(x + I)._eval_nseries(x, 4, None) == -I*log(2)/2 + pi/4 + \ + I*log(x)/2 - x/4 - I*x**2/16 + x**3/48 + O(x**4) + assert acot(x - I)._eval_nseries(x, 4, None) == I*log(2)/2 + pi/4 - \ + I*log(x)/2 - x/4 + I*x**2/16 + x**3/48 + O(x**4) + + +def test_asec_nseries(): + assert asec(x + S(1)/2)._eval_nseries(x, 4, None, I) == asec(S(1)/2) - \ + 4*sqrt(3)*I*x/3 + 8*sqrt(3)*I*x**2/9 - 16*sqrt(3)*I*x**3/9 + O(x**4) + assert asec(x + S(1)/2)._eval_nseries(x, 4, None, -I) == -asec(S(1)/2) + \ + 4*sqrt(3)*I*x/3 - 8*sqrt(3)*I*x**2/9 + 16*sqrt(3)*I*x**3/9 + O(x**4) + assert asec(x - S(1)/2)._eval_nseries(x, 4, None, I) == -asec(-S(1)/2) + \ + 2*pi + 4*sqrt(3)*I*x/3 + 8*sqrt(3)*I*x**2/9 + 16*sqrt(3)*I*x**3/9 + O(x**4) + assert asec(x - S(1)/2)._eval_nseries(x, 4, None, -I) == asec(-S(1)/2) - \ + 4*sqrt(3)*I*x/3 - 8*sqrt(3)*I*x**2/9 - 16*sqrt(3)*I*x**3/9 + O(x**4) + # testing nseries for asec at branch points + assert asec(1 + x)._eval_nseries(x, 3, None) == sqrt(2)*sqrt(x) - \ + 5*sqrt(2)*x**(S(3)/2)/12 + 43*sqrt(2)*x**(S(5)/2)/160 + O(x**3) + assert asec(-1 + x)._eval_nseries(x, 3, None) == pi - sqrt(2)*sqrt(-x) + \ + 5*sqrt(2)*(-x)**(S(3)/2)/12 - 43*sqrt(2)*(-x)**(S(5)/2)/160 + O(x**3) + assert asec(exp(x))._eval_nseries(x, 3, None) == sqrt(2)*sqrt(x) - \ + sqrt(2)*x**(S(3)/2)/6 + sqrt(2)*x**(S(5)/2)/120 + O(x**3) + assert asec(-exp(x))._eval_nseries(x, 3, None) == pi - sqrt(2)*sqrt(x) + \ + sqrt(2)*x**(S(3)/2)/6 - sqrt(2)*x**(S(5)/2)/120 + O(x**3) + + +def test_acsc_nseries(): + assert acsc(x + S(1)/2)._eval_nseries(x, 4, None, I) == acsc(S(1)/2) + \ + 4*sqrt(3)*I*x/3 - 8*sqrt(3)*I*x**2/9 + 16*sqrt(3)*I*x**3/9 + O(x**4) + assert acsc(x + S(1)/2)._eval_nseries(x, 4, None, -I) == -acsc(S(1)/2) + \ + pi - 4*sqrt(3)*I*x/3 + 8*sqrt(3)*I*x**2/9 - 16*sqrt(3)*I*x**3/9 + O(x**4) + assert acsc(x - S(1)/2)._eval_nseries(x, 4, None, I) == acsc(S(1)/2) - pi -\ + 4*sqrt(3)*I*x/3 - 8*sqrt(3)*I*x**2/9 - 16*sqrt(3)*I*x**3/9 + O(x**4) + assert acsc(x - S(1)/2)._eval_nseries(x, 4, None, -I) == -acsc(S(1)/2) + \ + 4*sqrt(3)*I*x/3 + 8*sqrt(3)*I*x**2/9 + 16*sqrt(3)*I*x**3/9 + O(x**4) + # testing nseries for acsc at branch points + assert acsc(1 + x)._eval_nseries(x, 3, None) == pi/2 - sqrt(2)*sqrt(x) + \ + 5*sqrt(2)*x**(S(3)/2)/12 - 43*sqrt(2)*x**(S(5)/2)/160 + O(x**3) + assert acsc(-1 + x)._eval_nseries(x, 3, None) == -pi/2 + sqrt(2)*sqrt(-x) - \ + 5*sqrt(2)*(-x)**(S(3)/2)/12 + 43*sqrt(2)*(-x)**(S(5)/2)/160 + O(x**3) + assert acsc(exp(x))._eval_nseries(x, 3, None) == pi/2 - sqrt(2)*sqrt(x) + \ + sqrt(2)*x**(S(3)/2)/6 - sqrt(2)*x**(S(5)/2)/120 + O(x**3) + assert acsc(-exp(x))._eval_nseries(x, 3, None) == -pi/2 + sqrt(2)*sqrt(x) - \ + sqrt(2)*x**(S(3)/2)/6 + sqrt(2)*x**(S(5)/2)/120 + O(x**3) + + +def test_issue_8653(): + n = Symbol('n', integer=True) + assert sin(n).is_irrational is None + assert cos(n).is_irrational is None + assert tan(n).is_irrational is None + + +def test_issue_9157(): + n = Symbol('n', integer=True, positive=True) + assert atan(n - 1).is_nonnegative is True + + +def test_trig_period(): + x, y = symbols('x, y') + + assert sin(x).period() == 2*pi + assert cos(x).period() == 2*pi + assert tan(x).period() == pi + assert cot(x).period() == pi + assert sec(x).period() == 2*pi + assert csc(x).period() == 2*pi + assert sin(2*x).period() == pi + assert cot(4*x - 6).period() == pi/4 + assert cos((-3)*x).period() == pi*Rational(2, 3) + assert cos(x*y).period(x) == 2*pi/abs(y) + assert sin(3*x*y + 2*pi).period(y) == 2*pi/abs(3*x) + assert tan(3*x).period(y) is S.Zero + raises(NotImplementedError, lambda: sin(x**2).period(x)) + + +def test_issue_7171(): + assert sin(x).rewrite(sqrt) == sin(x) + assert sin(x).rewrite(pow) == sin(x) + + +def test_issue_11864(): + w, k = symbols('w, k', real=True) + F = Piecewise((1, Eq(2*pi*k, 0)), (sin(pi*k)/(pi*k), True)) + soln = Piecewise((1, Eq(2*pi*k, 0)), (sinc(pi*k), True)) + assert F.rewrite(sinc) == soln + +def test_real_assumptions(): + z = Symbol('z', real=False, finite=True) + assert sin(z).is_real is None + assert cos(z).is_real is None + assert tan(z).is_real is False + assert sec(z).is_real is None + assert csc(z).is_real is None + assert cot(z).is_real is False + assert asin(p).is_real is None + assert asin(n).is_real is None + assert asec(p).is_real is None + assert asec(n).is_real is None + assert acos(p).is_real is None + assert acos(n).is_real is None + assert acsc(p).is_real is None + assert acsc(n).is_real is None + assert atan(p).is_positive is True + assert atan(n).is_negative is True + assert acot(p).is_positive is True + assert acot(n).is_negative is True + +def test_issue_14320(): + assert asin(sin(2)) == -2 + pi and (-pi/2 <= -2 + pi <= pi/2) and sin(2) == sin(-2 + pi) + assert asin(cos(2)) == -2 + pi/2 and (-pi/2 <= -2 + pi/2 <= pi/2) and cos(2) == sin(-2 + pi/2) + assert acos(sin(2)) == -pi/2 + 2 and (0 <= -pi/2 + 2 <= pi) and sin(2) == cos(-pi/2 + 2) + assert acos(cos(20)) == -6*pi + 20 and (0 <= -6*pi + 20 <= pi) and cos(20) == cos(-6*pi + 20) + assert acos(cos(30)) == -30 + 10*pi and (0 <= -30 + 10*pi <= pi) and cos(30) == cos(-30 + 10*pi) + + assert atan(tan(17)) == -5*pi + 17 and (-pi/2 < -5*pi + 17 < pi/2) and tan(17) == tan(-5*pi + 17) + assert atan(tan(15)) == -5*pi + 15 and (-pi/2 < -5*pi + 15 < pi/2) and tan(15) == tan(-5*pi + 15) + assert atan(cot(12)) == -12 + pi*Rational(7, 2) and (-pi/2 < -12 + pi*Rational(7, 2) < pi/2) and cot(12) == tan(-12 + pi*Rational(7, 2)) + assert acot(cot(15)) == -5*pi + 15 and (-pi/2 < -5*pi + 15 <= pi/2) and cot(15) == cot(-5*pi + 15) + assert acot(tan(19)) == -19 + pi*Rational(13, 2) and (-pi/2 < -19 + pi*Rational(13, 2) <= pi/2) and tan(19) == cot(-19 + pi*Rational(13, 2)) + + assert asec(sec(11)) == -11 + 4*pi and (0 <= -11 + 4*pi <= pi) and cos(11) == cos(-11 + 4*pi) + assert asec(csc(13)) == -13 + pi*Rational(9, 2) and (0 <= -13 + pi*Rational(9, 2) <= pi) and sin(13) == cos(-13 + pi*Rational(9, 2)) + assert acsc(csc(14)) == -4*pi + 14 and (-pi/2 <= -4*pi + 14 <= pi/2) and sin(14) == sin(-4*pi + 14) + assert acsc(sec(10)) == pi*Rational(-7, 2) + 10 and (-pi/2 <= pi*Rational(-7, 2) + 10 <= pi/2) and cos(10) == sin(pi*Rational(-7, 2) + 10) + +def test_issue_14543(): + assert sec(2*pi + 11) == sec(11) + assert sec(2*pi - 11) == sec(11) + assert sec(pi + 11) == -sec(11) + assert sec(pi - 11) == -sec(11) + + assert csc(2*pi + 17) == csc(17) + assert csc(2*pi - 17) == -csc(17) + assert csc(pi + 17) == -csc(17) + assert csc(pi - 17) == csc(17) + + x = Symbol('x') + assert csc(pi/2 + x) == sec(x) + assert csc(pi/2 - x) == sec(x) + assert csc(pi*Rational(3, 2) + x) == -sec(x) + assert csc(pi*Rational(3, 2) - x) == -sec(x) + + assert sec(pi/2 - x) == csc(x) + assert sec(pi/2 + x) == -csc(x) + assert sec(pi*Rational(3, 2) + x) == csc(x) + assert sec(pi*Rational(3, 2) - x) == -csc(x) + + +def test_as_real_imag(): + # This is for https://github.com/sympy/sympy/issues/17142 + # If it start failing again in irrelevant builds or in the master + # please open up the issue again. + expr = atan(I/(I + I*tan(1))) + assert expr.as_real_imag() == (expr, 0) + + +def test_issue_18746(): + e3 = cos(S.Pi*(x/4 + 1/4)) + assert e3.period() == 8 + + +def test_issue_25833(): + assert limit(atan(x**2), x, oo) == pi/2 + assert limit(atan(x**2 - 1), x, oo) == pi/2 + assert limit(atan(log(2**x)/log(2*x)), x, oo) == pi/2 + + +def test_issue_25847(): + #atan + assert atan(sin(x)/x).as_leading_term(x) == pi/4 + raises(PoleError, lambda: atan(exp(1/x)).as_leading_term(x)) + + #asin + assert asin(sin(x)/x).as_leading_term(x) == pi/2 + raises(PoleError, lambda: asin(exp(1/x)).as_leading_term(x)) + + #acos + assert acos(sin(x)/x).as_leading_term(x) == 0 + raises(PoleError, lambda: acos(exp(1/x)).as_leading_term(x)) + + #acot + assert acot(sin(x)/x).as_leading_term(x) == pi/4 + raises(PoleError, lambda: acot(exp(1/x)).as_leading_term(x)) + + #asec + assert asec(sin(x)/x).as_leading_term(x) == 0 + raises(PoleError, lambda: asec(exp(1/x)).as_leading_term(x)) + + #acsc + assert acsc(sin(x)/x).as_leading_term(x) == pi/2 + raises(PoleError, lambda: acsc(exp(1/x)).as_leading_term(x)) + +def test_issue_23843(): + #atan + assert atan(x + I).series(x, oo) == -16/(5*x**5) - 2*I/x**4 + 4/(3*x**3) + I/x**2 - 1/x + pi/2 + O(x**(-6), (x, oo)) + assert atan(x + I).series(x, -oo) == -16/(5*x**5) - 2*I/x**4 + 4/(3*x**3) + I/x**2 - 1/x - pi/2 + O(x**(-6), (x, -oo)) + assert atan(x - I).series(x, oo) == -16/(5*x**5) + 2*I/x**4 + 4/(3*x**3) - I/x**2 - 1/x + pi/2 + O(x**(-6), (x, oo)) + assert atan(x - I).series(x, -oo) == -16/(5*x**5) + 2*I/x**4 + 4/(3*x**3) - I/x**2 - 1/x - pi/2 + O(x**(-6), (x, -oo)) + + #acot + assert acot(x + I).series(x, oo) == 16/(5*x**5) + 2*I/x**4 - 4/(3*x**3) - I/x**2 + 1/x + O(x**(-6), (x, oo)) + assert acot(x + I).series(x, -oo) == 16/(5*x**5) + 2*I/x**4 - 4/(3*x**3) - I/x**2 + 1/x + O(x**(-6), (x, -oo)) + assert acot(x - I).series(x, oo) == 16/(5*x**5) - 2*I/x**4 - 4/(3*x**3) + I/x**2 + 1/x + O(x**(-6), (x, oo)) + assert acot(x - I).series(x, -oo) == 16/(5*x**5) - 2*I/x**4 - 4/(3*x**3) + I/x**2 + 1/x + O(x**(-6), (x, -oo)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/trigonometric.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/trigonometric.py new file mode 100644 index 0000000000000000000000000000000000000000..24e5db81f17a215f5b344291f0e9bf4752e5317d --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/elementary/trigonometric.py @@ -0,0 +1,3627 @@ +from __future__ import annotations +from sympy.core.add import Add +from sympy.core.cache import cacheit +from sympy.core.expr import Expr +from sympy.core.function import DefinedFunction, ArgumentIndexError, PoleError, expand_mul +from sympy.core.logic import fuzzy_not, fuzzy_or, FuzzyBool, fuzzy_and +from sympy.core.mod import Mod +from sympy.core.numbers import Rational, pi, Integer, Float, equal_valued +from sympy.core.relational import Ne, Eq +from sympy.core.singleton import S +from sympy.core.symbol import Symbol, Dummy +from sympy.core.sympify import sympify +from sympy.functions.combinatorial.factorials import factorial, RisingFactorial +from sympy.functions.combinatorial.numbers import bernoulli, euler +from sympy.functions.elementary.complexes import arg as arg_f, im, re +from sympy.functions.elementary.exponential import log, exp +from sympy.functions.elementary.integers import floor +from sympy.functions.elementary.miscellaneous import sqrt, Min, Max +from sympy.functions.elementary.piecewise import Piecewise +from sympy.functions.elementary._trigonometric_special import ( + cos_table, ipartfrac, fermat_coords) +from sympy.logic.boolalg import And +from sympy.ntheory import factorint +from sympy.polys.specialpolys import symmetric_poly +from sympy.utilities.iterables import numbered_symbols + + +############################################################################### +########################## UTILITIES ########################################## +############################################################################### + + +def _imaginary_unit_as_coefficient(arg): + """ Helper to extract symbolic coefficient for imaginary unit """ + if isinstance(arg, Float): + return None + else: + return arg.as_coefficient(S.ImaginaryUnit) + +############################################################################### +########################## TRIGONOMETRIC FUNCTIONS ############################ +############################################################################### + + +class TrigonometricFunction(DefinedFunction): + """Base class for trigonometric functions. """ + + unbranched = True + _singularities = (S.ComplexInfinity,) + + def _eval_is_rational(self): + s = self.func(*self.args) + if s.func == self.func: + if s.args[0].is_rational and fuzzy_not(s.args[0].is_zero): + return False + else: + return s.is_rational + + def _eval_is_algebraic(self): + s = self.func(*self.args) + if s.func == self.func: + if fuzzy_not(self.args[0].is_zero) and self.args[0].is_algebraic: + return False + pi_coeff = _pi_coeff(self.args[0]) + if pi_coeff is not None and pi_coeff.is_rational: + return True + else: + return s.is_algebraic + + def _eval_expand_complex(self, deep=True, **hints): + re_part, im_part = self.as_real_imag(deep=deep, **hints) + return re_part + im_part*S.ImaginaryUnit + + def _as_real_imag(self, deep=True, **hints): + if self.args[0].is_extended_real: + if deep: + hints['complex'] = False + return (self.args[0].expand(deep, **hints), S.Zero) + else: + return (self.args[0], S.Zero) + if deep: + re, im = self.args[0].expand(deep, **hints).as_real_imag() + else: + re, im = self.args[0].as_real_imag() + return (re, im) + + def _period(self, general_period, symbol=None): + f = expand_mul(self.args[0]) + if symbol is None: + symbol = tuple(f.free_symbols)[0] + + if not f.has(symbol): + return S.Zero + + if f == symbol: + return general_period + + if symbol in f.free_symbols: + if f.is_Mul: + g, h = f.as_independent(symbol) + if h == symbol: + return general_period/abs(g) + + if f.is_Add: + a, h = f.as_independent(symbol) + g, h = h.as_independent(symbol, as_Add=False) + if h == symbol: + return general_period/abs(g) + + raise NotImplementedError("Use the periodicity function instead.") + + +@cacheit +def _table2(): + # If nested sqrt's are worse than un-evaluation + # you can require q to be in (1, 2, 3, 4, 6, 12) + # q <= 12, q=15, q=20, q=24, q=30, q=40, q=60, q=120 return + # expressions with 2 or fewer sqrt nestings. + return { + 12: (3, 4), + 20: (4, 5), + 30: (5, 6), + 15: (6, 10), + 24: (6, 8), + 40: (8, 10), + 60: (20, 30), + 120: (40, 60) + } + + +def _peeloff_pi(arg): + r""" + Split ARG into two parts, a "rest" and a multiple of $\pi$. + This assumes ARG to be an Add. + The multiple of $\pi$ returned in the second position is always a Rational. + + Examples + ======== + + >>> from sympy.functions.elementary.trigonometric import _peeloff_pi + >>> from sympy import pi + >>> from sympy.abc import x, y + >>> _peeloff_pi(x + pi/2) + (x, 1/2) + >>> _peeloff_pi(x + 2*pi/3 + pi*y) + (x + pi*y + pi/6, 1/2) + + """ + pi_coeff = S.Zero + rest_terms = [] + for a in Add.make_args(arg): + K = a.coeff(pi) + if K and K.is_rational: + pi_coeff += K + else: + rest_terms.append(a) + + if pi_coeff is S.Zero: + return arg, S.Zero + + m1 = (pi_coeff % S.Half) + m2 = pi_coeff - m1 + if m2.is_integer or ((2*m2).is_integer and m2.is_even is False): + return Add(*(rest_terms + [m1*pi])), m2 + return arg, S.Zero + + +def _pi_coeff(arg: Expr, cycles: int = 1) -> Expr | None: + r""" + When arg is a Number times $\pi$ (e.g. $3\pi/2$) then return the Number + normalized to be in the range $[0, 2]$, else `None`. + + When an even multiple of $\pi$ is encountered, if it is multiplying + something with known parity then the multiple is returned as 0 otherwise + as 2. + + Examples + ======== + + >>> from sympy.functions.elementary.trigonometric import _pi_coeff + >>> from sympy import pi, Dummy + >>> from sympy.abc import x + >>> _pi_coeff(3*x*pi) + 3*x + >>> _pi_coeff(11*pi/7) + 11/7 + >>> _pi_coeff(-11*pi/7) + 3/7 + >>> _pi_coeff(4*pi) + 0 + >>> _pi_coeff(5*pi) + 1 + >>> _pi_coeff(5.0*pi) + 1 + >>> _pi_coeff(5.5*pi) + 3/2 + >>> _pi_coeff(2 + pi) + + >>> _pi_coeff(2*Dummy(integer=True)*pi) + 2 + >>> _pi_coeff(2*Dummy(even=True)*pi) + 0 + + """ + if arg is pi: + return S.One + elif not arg: + return S.Zero + elif arg.is_Mul: + cx = arg.coeff(pi) + if cx: + c, x = cx.as_coeff_Mul() # pi is not included as coeff + if c.is_Float: + # recast exact binary fractions to Rationals + f = abs(c) % 1 + if f != 0: + p = -int(round(log(f, 2).evalf())) + m = 2**p + cm = c*m + i = int(cm) + if equal_valued(i, cm): + c = Rational(i, m) + cx = c*x + else: + c = Rational(int(c)) + cx = c*x + if x.is_integer: + c2 = c % 2 + if c2 == 1: + return x + elif not c2: + if x.is_even is not None: # known parity + return S.Zero + return Integer(2) + else: + return c2*x + return cx + elif arg.is_zero: + return S.Zero + return None + + +class sin(TrigonometricFunction): + r""" + The sine function. + + Returns the sine of x (measured in radians). + + Explanation + =========== + + This function will evaluate automatically in the + case $x/\pi$ is some rational number [4]_. For example, + if $x$ is a multiple of $\pi$, $\pi/2$, $\pi/3$, $\pi/4$, and $\pi/6$. + + Examples + ======== + + >>> from sympy import sin, pi + >>> from sympy.abc import x + >>> sin(x**2).diff(x) + 2*x*cos(x**2) + >>> sin(1).diff(x) + 0 + >>> sin(pi) + 0 + >>> sin(pi/2) + 1 + >>> sin(pi/6) + 1/2 + >>> sin(pi/12) + -sqrt(2)/4 + sqrt(6)/4 + + + See Also + ======== + + csc, cos, sec, tan, cot + asin, acsc, acos, asec, atan, acot, atan2 + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Trigonometric_functions + .. [2] https://dlmf.nist.gov/4.14 + .. [3] https://functions.wolfram.com/ElementaryFunctions/Sin + .. [4] https://mathworld.wolfram.com/TrigonometryAngles.html + + """ + + def period(self, symbol=None): + return self._period(2*pi, symbol) + + def fdiff(self, argindex=1): + if argindex == 1: + return cos(self.args[0]) + else: + raise ArgumentIndexError(self, argindex) + + @classmethod + def eval(cls, arg): + from sympy.calculus.accumulationbounds import AccumBounds + from sympy.sets.setexpr import SetExpr + if arg.is_Number: + if arg is S.NaN: + return S.NaN + elif arg.is_zero: + return S.Zero + elif arg in (S.Infinity, S.NegativeInfinity): + return AccumBounds(-1, 1) + + if arg is S.ComplexInfinity: + return S.NaN + + if isinstance(arg, AccumBounds): + from sympy.sets.sets import FiniteSet + min, max = arg.min, arg.max + d = floor(min/(2*pi)) + if min is not S.NegativeInfinity: + min = min - d*2*pi + if max is not S.Infinity: + max = max - d*2*pi + if AccumBounds(min, max).intersection(FiniteSet(pi/2, pi*Rational(5, 2))) \ + is not S.EmptySet and \ + AccumBounds(min, max).intersection(FiniteSet(pi*Rational(3, 2), + pi*Rational(7, 2))) is not S.EmptySet: + return AccumBounds(-1, 1) + elif AccumBounds(min, max).intersection(FiniteSet(pi/2, pi*Rational(5, 2))) \ + is not S.EmptySet: + return AccumBounds(Min(sin(min), sin(max)), 1) + elif AccumBounds(min, max).intersection(FiniteSet(pi*Rational(3, 2), pi*Rational(8, 2))) \ + is not S.EmptySet: + return AccumBounds(-1, Max(sin(min), sin(max))) + else: + return AccumBounds(Min(sin(min), sin(max)), + Max(sin(min), sin(max))) + elif isinstance(arg, SetExpr): + return arg._eval_func(cls) + + if arg.could_extract_minus_sign(): + return -cls(-arg) + + i_coeff = _imaginary_unit_as_coefficient(arg) + if i_coeff is not None: + from sympy.functions.elementary.hyperbolic import sinh + return S.ImaginaryUnit*sinh(i_coeff) + + pi_coeff = _pi_coeff(arg) + if pi_coeff is not None: + if pi_coeff.is_integer: + return S.Zero + + if (2*pi_coeff).is_integer: + # is_even-case handled above as then pi_coeff.is_integer, + # so check if known to be not even + if pi_coeff.is_even is False: + return S.NegativeOne**(pi_coeff - S.Half) + + if not pi_coeff.is_Rational: + narg = pi_coeff*pi + if narg != arg: + return cls(narg) + return None + + # https://github.com/sympy/sympy/issues/6048 + # transform a sine to a cosine, to avoid redundant code + if pi_coeff.is_Rational: + x = pi_coeff % 2 + if x > 1: + return -cls((x % 1)*pi) + if 2*x > 1: + return cls((1 - x)*pi) + narg = ((pi_coeff + Rational(3, 2)) % 2)*pi + result = cos(narg) + if not isinstance(result, cos): + return result + if pi_coeff*pi != arg: + return cls(pi_coeff*pi) + return None + + if arg.is_Add: + x, m = _peeloff_pi(arg) + if m: + m = m*pi + return sin(m)*cos(x) + cos(m)*sin(x) + + if arg.is_zero: + return S.Zero + + if isinstance(arg, asin): + return arg.args[0] + + if isinstance(arg, atan): + x = arg.args[0] + return x/sqrt(1 + x**2) + + if isinstance(arg, atan2): + y, x = arg.args + return y/sqrt(x**2 + y**2) + + if isinstance(arg, acos): + x = arg.args[0] + return sqrt(1 - x**2) + + if isinstance(arg, acot): + x = arg.args[0] + return 1/(sqrt(1 + 1/x**2)*x) + + if isinstance(arg, acsc): + x = arg.args[0] + return 1/x + + if isinstance(arg, asec): + x = arg.args[0] + return sqrt(1 - 1/x**2) + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + if n < 0 or n % 2 == 0: + return S.Zero + else: + x = sympify(x) + + if len(previous_terms) > 2: + p = previous_terms[-2] + return -p*x**2/(n*(n - 1)) + else: + return S.NegativeOne**(n//2)*x**n/factorial(n) + + def _eval_nseries(self, x, n, logx, cdir=0): + arg = self.args[0] + if logx is not None: + arg = arg.subs(log(x), logx) + if arg.subs(x, 0).has(S.NaN, S.ComplexInfinity): + raise PoleError("Cannot expand %s around 0" % (self)) + return super()._eval_nseries(x, n=n, logx=logx, cdir=cdir) + + def _eval_rewrite_as_exp(self, arg, **kwargs): + from sympy.functions.elementary.hyperbolic import HyperbolicFunction + I = S.ImaginaryUnit + if isinstance(arg, (TrigonometricFunction, HyperbolicFunction)): + arg = arg.func(arg.args[0]).rewrite(exp) + return (exp(arg*I) - exp(-arg*I))/(2*I) + + def _eval_rewrite_as_Pow(self, arg, **kwargs): + if isinstance(arg, log): + I = S.ImaginaryUnit + x = arg.args[0] + return I*x**-I/2 - I*x**I /2 + + def _eval_rewrite_as_cos(self, arg, **kwargs): + return cos(arg - pi/2, evaluate=False) + + def _eval_rewrite_as_tan(self, arg, **kwargs): + tan_half = tan(S.Half*arg) + return 2*tan_half/(1 + tan_half**2) + + def _eval_rewrite_as_sincos(self, arg, **kwargs): + return sin(arg)*cos(arg)/cos(arg) + + def _eval_rewrite_as_cot(self, arg, **kwargs): + cot_half = cot(S.Half*arg) + return Piecewise((0, And(Eq(im(arg), 0), Eq(Mod(arg, pi), 0))), + (2*cot_half/(1 + cot_half**2), True)) + + def _eval_rewrite_as_pow(self, arg, **kwargs): + return self.rewrite(cos, **kwargs).rewrite(pow, **kwargs) + + def _eval_rewrite_as_sqrt(self, arg, **kwargs): + return self.rewrite(cos, **kwargs).rewrite(sqrt, **kwargs) + + def _eval_rewrite_as_csc(self, arg, **kwargs): + return 1/csc(arg) + + def _eval_rewrite_as_sec(self, arg, **kwargs): + return 1/sec(arg - pi/2, evaluate=False) + + def _eval_rewrite_as_sinc(self, arg, **kwargs): + return arg*sinc(arg) + + def _eval_rewrite_as_besselj(self, arg, **kwargs): + from sympy.functions.special.bessel import besselj + return sqrt(pi*arg/2)*besselj(S.Half, arg) + + def _eval_conjugate(self): + return self.func(self.args[0].conjugate()) + + def as_real_imag(self, deep=True, **hints): + from sympy.functions.elementary.hyperbolic import cosh, sinh + re, im = self._as_real_imag(deep=deep, **hints) + return (sin(re)*cosh(im), cos(re)*sinh(im)) + + def _eval_expand_trig(self, **hints): + from sympy.functions.special.polynomials import chebyshevt, chebyshevu + arg = self.args[0] + x = None + if arg.is_Add: # TODO, implement more if deep stuff here + # TODO: Do this more efficiently for more than two terms + x, y = arg.as_two_terms() + sx = sin(x, evaluate=False)._eval_expand_trig() + sy = sin(y, evaluate=False)._eval_expand_trig() + cx = cos(x, evaluate=False)._eval_expand_trig() + cy = cos(y, evaluate=False)._eval_expand_trig() + return sx*cy + sy*cx + elif arg.is_Mul: + n, x = arg.as_coeff_Mul(rational=True) + if n.is_Integer: # n will be positive because of .eval + # canonicalization + + # See https://mathworld.wolfram.com/Multiple-AngleFormulas.html + if n.is_odd: + return S.NegativeOne**((n - 1)/2)*chebyshevt(n, sin(x)) + else: + return expand_mul(S.NegativeOne**(n/2 - 1)*cos(x)* + chebyshevu(n - 1, sin(x)), deep=False) + return sin(arg) + + def _eval_as_leading_term(self, x, logx, cdir): + from sympy.calculus.accumulationbounds import AccumBounds + arg = self.args[0] + x0 = arg.subs(x, 0).cancel() + n = x0/pi + if n.is_integer: + lt = (arg - n*pi).as_leading_term(x) + return (S.NegativeOne**n)*lt + if x0 is S.ComplexInfinity: + x0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+') + if x0 in [S.Infinity, S.NegativeInfinity]: + return AccumBounds(-1, 1) + return self.func(x0) if x0.is_finite else self + + def _eval_is_extended_real(self): + if self.args[0].is_extended_real: + return True + + def _eval_is_finite(self): + arg = self.args[0] + if arg.is_extended_real: + return True + + def _eval_is_zero(self): + rest, pi_mult = _peeloff_pi(self.args[0]) + if rest.is_zero: + return pi_mult.is_integer + + def _eval_is_complex(self): + if self.args[0].is_extended_real \ + or self.args[0].is_complex: + return True + + +class cos(TrigonometricFunction): + """ + The cosine function. + + Returns the cosine of x (measured in radians). + + Explanation + =========== + + See :func:`sin` for notes about automatic evaluation. + + Examples + ======== + + >>> from sympy import cos, pi + >>> from sympy.abc import x + >>> cos(x**2).diff(x) + -2*x*sin(x**2) + >>> cos(1).diff(x) + 0 + >>> cos(pi) + -1 + >>> cos(pi/2) + 0 + >>> cos(2*pi/3) + -1/2 + >>> cos(pi/12) + sqrt(2)/4 + sqrt(6)/4 + + See Also + ======== + + sin, csc, sec, tan, cot + asin, acsc, acos, asec, atan, acot, atan2 + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Trigonometric_functions + .. [2] https://dlmf.nist.gov/4.14 + .. [3] https://functions.wolfram.com/ElementaryFunctions/Cos + + """ + + def period(self, symbol=None): + return self._period(2*pi, symbol) + + def fdiff(self, argindex=1): + if argindex == 1: + return -sin(self.args[0]) + else: + raise ArgumentIndexError(self, argindex) + + @classmethod + def eval(cls, arg): + from sympy.functions.special.polynomials import chebyshevt + from sympy.calculus.accumulationbounds import AccumBounds + from sympy.sets.setexpr import SetExpr + if arg.is_Number: + if arg is S.NaN: + return S.NaN + elif arg.is_zero: + return S.One + elif arg in (S.Infinity, S.NegativeInfinity): + # In this case it is better to return AccumBounds(-1, 1) + # rather than returning S.NaN, since AccumBounds(-1, 1) + # preserves the information that sin(oo) is between + # -1 and 1, where S.NaN does not do that. + return AccumBounds(-1, 1) + + if arg is S.ComplexInfinity: + return S.NaN + + if isinstance(arg, AccumBounds): + return sin(arg + pi/2) + elif isinstance(arg, SetExpr): + return arg._eval_func(cls) + + if arg.is_extended_real and arg.is_finite is False: + return AccumBounds(-1, 1) + + if arg.could_extract_minus_sign(): + return cls(-arg) + + i_coeff = _imaginary_unit_as_coefficient(arg) + if i_coeff is not None: + from sympy.functions.elementary.hyperbolic import cosh + return cosh(i_coeff) + + pi_coeff = _pi_coeff(arg) + if pi_coeff is not None: + if pi_coeff.is_integer: + return (S.NegativeOne)**pi_coeff + + if (2*pi_coeff).is_integer: + # is_even-case handled above as then pi_coeff.is_integer, + # so check if known to be not even + if pi_coeff.is_even is False: + return S.Zero + + if not pi_coeff.is_Rational: + narg = pi_coeff*pi + if narg != arg: + return cls(narg) + return None + + # cosine formula ##################### + # https://github.com/sympy/sympy/issues/6048 + # explicit calculations are performed for + # cos(k pi/n) for n = 8,10,12,15,20,24,30,40,60,120 + # Some other exact values like cos(k pi/240) can be + # calculated using a partial-fraction decomposition + # by calling cos( X ).rewrite(sqrt) + if pi_coeff.is_Rational: + q = pi_coeff.q + p = pi_coeff.p % (2*q) + if p > q: + narg = (pi_coeff - 1)*pi + return -cls(narg) + if 2*p > q: + narg = (1 - pi_coeff)*pi + return -cls(narg) + + # If nested sqrt's are worse than un-evaluation + # you can require q to be in (1, 2, 3, 4, 6, 12) + # q <= 12, q=15, q=20, q=24, q=30, q=40, q=60, q=120 return + # expressions with 2 or fewer sqrt nestings. + table2 = _table2() + if q in table2: + a, b = table2[q] + a, b = p*pi/a, p*pi/b + nvala, nvalb = cls(a), cls(b) + if None in (nvala, nvalb): + return None + return nvala*nvalb + cls(pi/2 - a)*cls(pi/2 - b) + + if q > 12: + return None + + cst_table_some = { + 3: S.Half, + 5: (sqrt(5) + 1) / 4, + } + if q in cst_table_some: + cts = cst_table_some[pi_coeff.q] + return chebyshevt(pi_coeff.p, cts).expand() + + if 0 == q % 2: + narg = (pi_coeff*2)*pi + nval = cls(narg) + if None == nval: + return None + x = (2*pi_coeff + 1)/2 + sign_cos = (-1)**((-1 if x < 0 else 1)*int(abs(x))) + return sign_cos*sqrt( (1 + nval)/2 ) + return None + + if arg.is_Add: + x, m = _peeloff_pi(arg) + if m: + m = m*pi + return cos(m)*cos(x) - sin(m)*sin(x) + + if arg.is_zero: + return S.One + + if isinstance(arg, acos): + return arg.args[0] + + if isinstance(arg, atan): + x = arg.args[0] + return 1/sqrt(1 + x**2) + + if isinstance(arg, atan2): + y, x = arg.args + return x/sqrt(x**2 + y**2) + + if isinstance(arg, asin): + x = arg.args[0] + return sqrt(1 - x ** 2) + + if isinstance(arg, acot): + x = arg.args[0] + return 1/sqrt(1 + 1/x**2) + + if isinstance(arg, acsc): + x = arg.args[0] + return sqrt(1 - 1/x**2) + + if isinstance(arg, asec): + x = arg.args[0] + return 1/x + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + if n < 0 or n % 2 == 1: + return S.Zero + else: + x = sympify(x) + + if len(previous_terms) > 2: + p = previous_terms[-2] + return -p*x**2/(n*(n - 1)) + else: + return S.NegativeOne**(n//2)*x**n/factorial(n) + + def _eval_nseries(self, x, n, logx, cdir=0): + arg = self.args[0] + if logx is not None: + arg = arg.subs(log(x), logx) + if arg.subs(x, 0).has(S.NaN, S.ComplexInfinity): + raise PoleError("Cannot expand %s around 0" % (self)) + return super()._eval_nseries(x, n=n, logx=logx, cdir=cdir) + + def _eval_rewrite_as_exp(self, arg, **kwargs): + I = S.ImaginaryUnit + from sympy.functions.elementary.hyperbolic import HyperbolicFunction + if isinstance(arg, (TrigonometricFunction, HyperbolicFunction)): + arg = arg.func(arg.args[0]).rewrite(exp, **kwargs) + return (exp(arg*I) + exp(-arg*I))/2 + + def _eval_rewrite_as_Pow(self, arg, **kwargs): + if isinstance(arg, log): + I = S.ImaginaryUnit + x = arg.args[0] + return x**I/2 + x**-I/2 + + def _eval_rewrite_as_sin(self, arg, **kwargs): + return sin(arg + pi/2, evaluate=False) + + def _eval_rewrite_as_tan(self, arg, **kwargs): + tan_half = tan(S.Half*arg)**2 + return (1 - tan_half)/(1 + tan_half) + + def _eval_rewrite_as_sincos(self, arg, **kwargs): + return sin(arg)*cos(arg)/sin(arg) + + def _eval_rewrite_as_cot(self, arg, **kwargs): + cot_half = cot(S.Half*arg)**2 + return Piecewise((1, And(Eq(im(arg), 0), Eq(Mod(arg, 2*pi), 0))), + ((cot_half - 1)/(cot_half + 1), True)) + + def _eval_rewrite_as_pow(self, arg, **kwargs): + return self._eval_rewrite_as_sqrt(arg, **kwargs) + + def _eval_rewrite_as_sqrt(self, arg: Expr, **kwargs): + from sympy.functions.special.polynomials import chebyshevt + + pi_coeff = _pi_coeff(arg) + if pi_coeff is None: + return None + + if isinstance(pi_coeff, Integer): + return None + + if not isinstance(pi_coeff, Rational): + return None + + cst_table_some = cos_table() + + if pi_coeff.q in cst_table_some: + rv = chebyshevt(pi_coeff.p, cst_table_some[pi_coeff.q]()) + if pi_coeff.q < 257: + rv = rv.expand() + return rv + + if not pi_coeff.q % 2: # recursively remove factors of 2 + pico2 = pi_coeff * 2 + nval = cos(pico2 * pi).rewrite(sqrt, **kwargs) + x = (pico2 + 1) / 2 + sign_cos = -1 if int(x) % 2 else 1 + return sign_cos * sqrt((1 + nval) / 2) + + FC = fermat_coords(pi_coeff.q) + if FC: + denoms = FC + else: + denoms = [b**e for b, e in factorint(pi_coeff.q).items()] + + apart = ipartfrac(*denoms) + decomp = (pi_coeff.p * Rational(n, d) for n, d in zip(apart, denoms)) + X = [(x[1], x[0]*pi) for x in zip(decomp, numbered_symbols('z'))] + pcls = cos(sum(x[0] for x in X))._eval_expand_trig().subs(X) + + if not FC or len(FC) == 1: + return pcls + return pcls.rewrite(sqrt, **kwargs) + + def _eval_rewrite_as_sec(self, arg, **kwargs): + return 1/sec(arg) + + def _eval_rewrite_as_csc(self, arg, **kwargs): + return 1/sec(arg).rewrite(csc, **kwargs) + + def _eval_rewrite_as_besselj(self, arg, **kwargs): + from sympy.functions.special.bessel import besselj + return Piecewise( + (sqrt(pi*arg/2)*besselj(-S.Half, arg), Ne(arg, 0)), + (1, True) + ) + + def _eval_conjugate(self): + return self.func(self.args[0].conjugate()) + + def as_real_imag(self, deep=True, **hints): + from sympy.functions.elementary.hyperbolic import cosh, sinh + re, im = self._as_real_imag(deep=deep, **hints) + return (cos(re)*cosh(im), -sin(re)*sinh(im)) + + def _eval_expand_trig(self, **hints): + from sympy.functions.special.polynomials import chebyshevt + arg = self.args[0] + x = None + if arg.is_Add: # TODO: Do this more efficiently for more than two terms + x, y = arg.as_two_terms() + sx = sin(x, evaluate=False)._eval_expand_trig() + sy = sin(y, evaluate=False)._eval_expand_trig() + cx = cos(x, evaluate=False)._eval_expand_trig() + cy = cos(y, evaluate=False)._eval_expand_trig() + return cx*cy - sx*sy + elif arg.is_Mul: + coeff, terms = arg.as_coeff_Mul(rational=True) + if coeff.is_Integer: + return chebyshevt(coeff, cos(terms)) + return cos(arg) + + def _eval_as_leading_term(self, x, logx, cdir): + from sympy.calculus.accumulationbounds import AccumBounds + arg = self.args[0] + x0 = arg.subs(x, 0).cancel() + n = (x0 + pi/2)/pi + if n.is_integer: + lt = (arg - n*pi + pi/2).as_leading_term(x) + return (S.NegativeOne**n)*lt + if x0 is S.ComplexInfinity: + x0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+') + if x0 in [S.Infinity, S.NegativeInfinity]: + return AccumBounds(-1, 1) + return self.func(x0) if x0.is_finite else self + + def _eval_is_extended_real(self): + if self.args[0].is_extended_real: + return True + + def _eval_is_finite(self): + arg = self.args[0] + + if arg.is_extended_real: + return True + + def _eval_is_complex(self): + if self.args[0].is_extended_real \ + or self.args[0].is_complex: + return True + + def _eval_is_zero(self): + rest, pi_mult = _peeloff_pi(self.args[0]) + if rest.is_zero and pi_mult: + return (pi_mult - S.Half).is_integer + + +class tan(TrigonometricFunction): + """ + The tangent function. + + Returns the tangent of x (measured in radians). + + Explanation + =========== + + See :class:`sin` for notes about automatic evaluation. + + Examples + ======== + + >>> from sympy import tan, pi + >>> from sympy.abc import x + >>> tan(x**2).diff(x) + 2*x*(tan(x**2)**2 + 1) + >>> tan(1).diff(x) + 0 + >>> tan(pi/8).expand() + -1 + sqrt(2) + + See Also + ======== + + sin, csc, cos, sec, cot + asin, acsc, acos, asec, atan, acot, atan2 + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Trigonometric_functions + .. [2] https://dlmf.nist.gov/4.14 + .. [3] https://functions.wolfram.com/ElementaryFunctions/Tan + + """ + + def period(self, symbol=None): + return self._period(pi, symbol) + + def fdiff(self, argindex=1): + if argindex == 1: + return S.One + self**2 + else: + raise ArgumentIndexError(self, argindex) + + def inverse(self, argindex=1): + """ + Returns the inverse of this function. + """ + return atan + + @classmethod + def eval(cls, arg): + from sympy.calculus.accumulationbounds import AccumBounds + if arg.is_Number: + if arg is S.NaN: + return S.NaN + elif arg.is_zero: + return S.Zero + elif arg in (S.Infinity, S.NegativeInfinity): + return AccumBounds(S.NegativeInfinity, S.Infinity) + + if arg is S.ComplexInfinity: + return S.NaN + + if isinstance(arg, AccumBounds): + min, max = arg.min, arg.max + d = floor(min/pi) + if min is not S.NegativeInfinity: + min = min - d*pi + if max is not S.Infinity: + max = max - d*pi + from sympy.sets.sets import FiniteSet + if AccumBounds(min, max).intersection(FiniteSet(pi/2, pi*Rational(3, 2))): + return AccumBounds(S.NegativeInfinity, S.Infinity) + else: + return AccumBounds(tan(min), tan(max)) + + if arg.could_extract_minus_sign(): + return -cls(-arg) + + i_coeff = _imaginary_unit_as_coefficient(arg) + if i_coeff is not None: + from sympy.functions.elementary.hyperbolic import tanh + return S.ImaginaryUnit*tanh(i_coeff) + + pi_coeff = _pi_coeff(arg, 2) + if pi_coeff is not None: + if pi_coeff.is_integer: + return S.Zero + + if not pi_coeff.is_Rational: + narg = pi_coeff*pi + if narg != arg: + return cls(narg) + return None + + if pi_coeff.is_Rational: + q = pi_coeff.q + p = pi_coeff.p % q + # ensure simplified results are returned for n*pi/5, n*pi/10 + table10 = { + 1: sqrt(1 - 2*sqrt(5)/5), + 2: sqrt(5 - 2*sqrt(5)), + 3: sqrt(1 + 2*sqrt(5)/5), + 4: sqrt(5 + 2*sqrt(5)) + } + if q in (5, 10): + n = 10*p/q + if n > 5: + n = 10 - n + return -table10[n] + else: + return table10[n] + if not pi_coeff.q % 2: + narg = pi_coeff*pi*2 + cresult, sresult = cos(narg), cos(narg - pi/2) + if not isinstance(cresult, cos) \ + and not isinstance(sresult, cos): + if sresult == 0: + return S.ComplexInfinity + return 1/sresult - cresult/sresult + + table2 = _table2() + if q in table2: + a, b = table2[q] + nvala, nvalb = cls(p*pi/a), cls(p*pi/b) + if None in (nvala, nvalb): + return None + return (nvala - nvalb)/(1 + nvala*nvalb) + narg = ((pi_coeff + S.Half) % 1 - S.Half)*pi + # see cos() to specify which expressions should be + # expanded automatically in terms of radicals + cresult, sresult = cos(narg), cos(narg - pi/2) + if not isinstance(cresult, cos) \ + and not isinstance(sresult, cos): + if cresult == 0: + return S.ComplexInfinity + return (sresult/cresult) + if narg != arg: + return cls(narg) + + if arg.is_Add: + x, m = _peeloff_pi(arg) + if m: + tanm = tan(m*pi) + if tanm is S.ComplexInfinity: + return -cot(x) + else: # tanm == 0 + return tan(x) + + if arg.is_zero: + return S.Zero + + if isinstance(arg, atan): + return arg.args[0] + + if isinstance(arg, atan2): + y, x = arg.args + return y/x + + if isinstance(arg, asin): + x = arg.args[0] + return x/sqrt(1 - x**2) + + if isinstance(arg, acos): + x = arg.args[0] + return sqrt(1 - x**2)/x + + if isinstance(arg, acot): + x = arg.args[0] + return 1/x + + if isinstance(arg, acsc): + x = arg.args[0] + return 1/(sqrt(1 - 1/x**2)*x) + + if isinstance(arg, asec): + x = arg.args[0] + return sqrt(1 - 1/x**2)*x + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + if n < 0 or n % 2 == 0: + return S.Zero + else: + x = sympify(x) + + a, b = ((n - 1)//2), 2**(n + 1) + + B = bernoulli(n + 1) + F = factorial(n + 1) + + return S.NegativeOne**a*b*(b - 1)*B/F*x**n + + def _eval_nseries(self, x, n, logx, cdir=0): + i = self.args[0].limit(x, 0)*2/pi + if i and i.is_Integer: + return self.rewrite(cos)._eval_nseries(x, n=n, logx=logx) + return super()._eval_nseries(x, n=n, logx=logx) + + def _eval_rewrite_as_Pow(self, arg, **kwargs): + if isinstance(arg, log): + I = S.ImaginaryUnit + x = arg.args[0] + return I*(x**-I - x**I)/(x**-I + x**I) + + def _eval_conjugate(self): + return self.func(self.args[0].conjugate()) + + def as_real_imag(self, deep=True, **hints): + re, im = self._as_real_imag(deep=deep, **hints) + if im: + from sympy.functions.elementary.hyperbolic import cosh, sinh + denom = cos(2*re) + cosh(2*im) + return (sin(2*re)/denom, sinh(2*im)/denom) + else: + return (self.func(re), S.Zero) + + def _eval_expand_trig(self, **hints): + arg = self.args[0] + x = None + if arg.is_Add: + n = len(arg.args) + TX = [] + for x in arg.args: + tx = tan(x, evaluate=False)._eval_expand_trig() + TX.append(tx) + + Yg = numbered_symbols('Y') + Y = [ next(Yg) for i in range(n) ] + + p = [0, 0] + for i in range(n + 1): + p[1 - i % 2] += symmetric_poly(i, Y)*(-1)**((i % 4)//2) + return (p[0]/p[1]).subs(list(zip(Y, TX))) + + elif arg.is_Mul: + coeff, terms = arg.as_coeff_Mul(rational=True) + if coeff.is_Integer and coeff > 1: + I = S.ImaginaryUnit + z = Symbol('dummy', real=True) + P = ((1 + I*z)**coeff).expand() + return (im(P)/re(P)).subs([(z, tan(terms))]) + return tan(arg) + + def _eval_rewrite_as_exp(self, arg, **kwargs): + I = S.ImaginaryUnit + from sympy.functions.elementary.hyperbolic import HyperbolicFunction + if isinstance(arg, (TrigonometricFunction, HyperbolicFunction)): + arg = arg.func(arg.args[0]).rewrite(exp) + neg_exp, pos_exp = exp(-arg*I), exp(arg*I) + return I*(neg_exp - pos_exp)/(neg_exp + pos_exp) + + def _eval_rewrite_as_sin(self, x, **kwargs): + return 2*sin(x)**2/sin(2*x) + + def _eval_rewrite_as_cos(self, x, **kwargs): + return cos(x - pi/2, evaluate=False)/cos(x) + + def _eval_rewrite_as_sincos(self, arg, **kwargs): + return sin(arg)/cos(arg) + + def _eval_rewrite_as_cot(self, arg, **kwargs): + return 1/cot(arg) + + def _eval_rewrite_as_sec(self, arg, **kwargs): + sin_in_sec_form = sin(arg).rewrite(sec, **kwargs) + cos_in_sec_form = cos(arg).rewrite(sec, **kwargs) + return sin_in_sec_form/cos_in_sec_form + + def _eval_rewrite_as_csc(self, arg, **kwargs): + sin_in_csc_form = sin(arg).rewrite(csc, **kwargs) + cos_in_csc_form = cos(arg).rewrite(csc, **kwargs) + return sin_in_csc_form/cos_in_csc_form + + def _eval_rewrite_as_pow(self, arg, **kwargs): + y = self.rewrite(cos, **kwargs).rewrite(pow, **kwargs) + if y.has(cos): + return None + return y + + def _eval_rewrite_as_sqrt(self, arg, **kwargs): + y = self.rewrite(cos, **kwargs).rewrite(sqrt, **kwargs) + if y.has(cos): + return None + return y + + def _eval_rewrite_as_besselj(self, arg, **kwargs): + from sympy.functions.special.bessel import besselj + return besselj(S.Half, arg)/besselj(-S.Half, arg) + + def _eval_as_leading_term(self, x, logx, cdir): + from sympy.calculus.accumulationbounds import AccumBounds + from sympy.functions.elementary.complexes import re + arg = self.args[0] + x0 = arg.subs(x, 0).cancel() + n = 2*x0/pi + if n.is_integer: + lt = (arg - n*pi/2).as_leading_term(x) + return lt if n.is_even else -1/lt + if x0 is S.ComplexInfinity: + x0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+') + if x0 in (S.Infinity, S.NegativeInfinity): + return AccumBounds(S.NegativeInfinity, S.Infinity) + return self.func(x0) if x0.is_finite else self + + def _eval_is_extended_real(self): + # FIXME: currently tan(pi/2) return zoo + return self.args[0].is_extended_real + + def _eval_is_real(self): + arg = self.args[0] + if arg.is_real and (arg/pi - S.Half).is_integer is False: + return True + + def _eval_is_finite(self): + arg = self.args[0] + + if arg.is_real and (arg/pi - S.Half).is_integer is False: + return True + + if arg.is_imaginary: + return True + + def _eval_is_zero(self): + rest, pi_mult = _peeloff_pi(self.args[0]) + if rest.is_zero: + return pi_mult.is_integer + + def _eval_is_complex(self): + arg = self.args[0] + + if arg.is_real and (arg/pi - S.Half).is_integer is False: + return True + + +class cot(TrigonometricFunction): + """ + The cotangent function. + + Returns the cotangent of x (measured in radians). + + Explanation + =========== + + See :class:`sin` for notes about automatic evaluation. + + Examples + ======== + + >>> from sympy import cot, pi + >>> from sympy.abc import x + >>> cot(x**2).diff(x) + 2*x*(-cot(x**2)**2 - 1) + >>> cot(1).diff(x) + 0 + >>> cot(pi/12) + sqrt(3) + 2 + + See Also + ======== + + sin, csc, cos, sec, tan + asin, acsc, acos, asec, atan, acot, atan2 + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Trigonometric_functions + .. [2] https://dlmf.nist.gov/4.14 + .. [3] https://functions.wolfram.com/ElementaryFunctions/Cot + + """ + + def period(self, symbol=None): + return self._period(pi, symbol) + + def fdiff(self, argindex=1): + if argindex == 1: + return S.NegativeOne - self**2 + else: + raise ArgumentIndexError(self, argindex) + + def inverse(self, argindex=1): + """ + Returns the inverse of this function. + """ + return acot + + @classmethod + def eval(cls, arg): + from sympy.calculus.accumulationbounds import AccumBounds + if arg.is_Number: + if arg is S.NaN: + return S.NaN + if arg.is_zero: + return S.ComplexInfinity + elif arg in (S.Infinity, S.NegativeInfinity): + return AccumBounds(S.NegativeInfinity, S.Infinity) + + if arg is S.ComplexInfinity: + return S.NaN + + if isinstance(arg, AccumBounds): + return -tan(arg + pi/2) + + if arg.could_extract_minus_sign(): + return -cls(-arg) + + i_coeff = _imaginary_unit_as_coefficient(arg) + if i_coeff is not None: + from sympy.functions.elementary.hyperbolic import coth + return -S.ImaginaryUnit*coth(i_coeff) + + pi_coeff = _pi_coeff(arg, 2) + if pi_coeff is not None: + if pi_coeff.is_integer: + return S.ComplexInfinity + + if not pi_coeff.is_Rational: + narg = pi_coeff*pi + if narg != arg: + return cls(narg) + return None + + if pi_coeff.is_Rational: + if pi_coeff.q in (5, 10): + return tan(pi/2 - arg) + if pi_coeff.q > 2 and not pi_coeff.q % 2: + narg = pi_coeff*pi*2 + cresult, sresult = cos(narg), cos(narg - pi/2) + if not isinstance(cresult, cos) \ + and not isinstance(sresult, cos): + return 1/sresult + cresult/sresult + q = pi_coeff.q + p = pi_coeff.p % q + table2 = _table2() + if q in table2: + a, b = table2[q] + nvala, nvalb = cls(p*pi/a), cls(p*pi/b) + if None in (nvala, nvalb): + return None + return (1 + nvala*nvalb)/(nvalb - nvala) + narg = (((pi_coeff + S.Half) % 1) - S.Half)*pi + # see cos() to specify which expressions should be + # expanded automatically in terms of radicals + cresult, sresult = cos(narg), cos(narg - pi/2) + if not isinstance(cresult, cos) \ + and not isinstance(sresult, cos): + if sresult == 0: + return S.ComplexInfinity + return cresult/sresult + if narg != arg: + return cls(narg) + + if arg.is_Add: + x, m = _peeloff_pi(arg) + if m: + cotm = cot(m*pi) + if cotm is S.ComplexInfinity: + return cot(x) + else: # cotm == 0 + return -tan(x) + + if arg.is_zero: + return S.ComplexInfinity + + if isinstance(arg, acot): + return arg.args[0] + + if isinstance(arg, atan): + x = arg.args[0] + return 1/x + + if isinstance(arg, atan2): + y, x = arg.args + return x/y + + if isinstance(arg, asin): + x = arg.args[0] + return sqrt(1 - x**2)/x + + if isinstance(arg, acos): + x = arg.args[0] + return x/sqrt(1 - x**2) + + if isinstance(arg, acsc): + x = arg.args[0] + return sqrt(1 - 1/x**2)*x + + if isinstance(arg, asec): + x = arg.args[0] + return 1/(sqrt(1 - 1/x**2)*x) + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + if n == 0: + return 1/sympify(x) + elif n < 0 or n % 2 == 0: + return S.Zero + else: + x = sympify(x) + + B = bernoulli(n + 1) + F = factorial(n + 1) + + return S.NegativeOne**((n + 1)//2)*2**(n + 1)*B/F*x**n + + def _eval_nseries(self, x, n, logx, cdir=0): + i = self.args[0].limit(x, 0)/pi + if i and i.is_Integer: + return self.rewrite(cos)._eval_nseries(x, n=n, logx=logx) + return self.rewrite(tan)._eval_nseries(x, n=n, logx=logx) + + def _eval_conjugate(self): + return self.func(self.args[0].conjugate()) + + def as_real_imag(self, deep=True, **hints): + re, im = self._as_real_imag(deep=deep, **hints) + if im: + from sympy.functions.elementary.hyperbolic import cosh, sinh + denom = cos(2*re) - cosh(2*im) + return (-sin(2*re)/denom, sinh(2*im)/denom) + else: + return (self.func(re), S.Zero) + + def _eval_rewrite_as_exp(self, arg, **kwargs): + from sympy.functions.elementary.hyperbolic import HyperbolicFunction + I = S.ImaginaryUnit + if isinstance(arg, (TrigonometricFunction, HyperbolicFunction)): + arg = arg.func(arg.args[0]).rewrite(exp, **kwargs) + neg_exp, pos_exp = exp(-arg*I), exp(arg*I) + return I*(pos_exp + neg_exp)/(pos_exp - neg_exp) + + def _eval_rewrite_as_Pow(self, arg, **kwargs): + if isinstance(arg, log): + I = S.ImaginaryUnit + x = arg.args[0] + return -I*(x**-I + x**I)/(x**-I - x**I) + + def _eval_rewrite_as_sin(self, x, **kwargs): + return sin(2*x)/(2*(sin(x)**2)) + + def _eval_rewrite_as_cos(self, x, **kwargs): + return cos(x)/cos(x - pi/2, evaluate=False) + + def _eval_rewrite_as_sincos(self, arg, **kwargs): + return cos(arg)/sin(arg) + + def _eval_rewrite_as_tan(self, arg, **kwargs): + return 1/tan(arg) + + def _eval_rewrite_as_sec(self, arg, **kwargs): + cos_in_sec_form = cos(arg).rewrite(sec, **kwargs) + sin_in_sec_form = sin(arg).rewrite(sec, **kwargs) + return cos_in_sec_form/sin_in_sec_form + + def _eval_rewrite_as_csc(self, arg, **kwargs): + cos_in_csc_form = cos(arg).rewrite(csc, **kwargs) + sin_in_csc_form = sin(arg).rewrite(csc, **kwargs) + return cos_in_csc_form/sin_in_csc_form + + def _eval_rewrite_as_pow(self, arg, **kwargs): + y = self.rewrite(cos, **kwargs).rewrite(pow, **kwargs) + if y.has(cos): + return None + return y + + def _eval_rewrite_as_sqrt(self, arg, **kwargs): + y = self.rewrite(cos, **kwargs).rewrite(sqrt, **kwargs) + if y.has(cos): + return None + return y + + def _eval_rewrite_as_besselj(self, arg, **kwargs): + from sympy.functions.special.bessel import besselj + return besselj(-S.Half, arg)/besselj(S.Half, arg) + + def _eval_as_leading_term(self, x, logx, cdir): + from sympy.calculus.accumulationbounds import AccumBounds + from sympy.functions.elementary.complexes import re + arg = self.args[0] + x0 = arg.subs(x, 0).cancel() + n = 2*x0/pi + if n.is_integer: + lt = (arg - n*pi/2).as_leading_term(x) + return 1/lt if n.is_even else -lt + if x0 is S.ComplexInfinity: + x0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+') + if x0 in (S.Infinity, S.NegativeInfinity): + return AccumBounds(S.NegativeInfinity, S.Infinity) + return self.func(x0) if x0.is_finite else self + + def _eval_is_extended_real(self): + return self.args[0].is_extended_real + + def _eval_expand_trig(self, **hints): + arg = self.args[0] + x = None + if arg.is_Add: + n = len(arg.args) + CX = [] + for x in arg.args: + cx = cot(x, evaluate=False)._eval_expand_trig() + CX.append(cx) + + Yg = numbered_symbols('Y') + Y = [ next(Yg) for i in range(n) ] + + p = [0, 0] + for i in range(n, -1, -1): + p[(n - i) % 2] += symmetric_poly(i, Y)*(-1)**(((n - i) % 4)//2) + return (p[0]/p[1]).subs(list(zip(Y, CX))) + elif arg.is_Mul: + coeff, terms = arg.as_coeff_Mul(rational=True) + if coeff.is_Integer and coeff > 1: + I = S.ImaginaryUnit + z = Symbol('dummy', real=True) + P = ((z + I)**coeff).expand() + return (re(P)/im(P)).subs([(z, cot(terms))]) + return cot(arg) # XXX sec and csc return 1/cos and 1/sin + + def _eval_is_finite(self): + arg = self.args[0] + if arg.is_real and (arg/pi).is_integer is False: + return True + if arg.is_imaginary: + return True + + def _eval_is_real(self): + arg = self.args[0] + if arg.is_real and (arg/pi).is_integer is False: + return True + + def _eval_is_complex(self): + arg = self.args[0] + if arg.is_real and (arg/pi).is_integer is False: + return True + + def _eval_is_zero(self): + rest, pimult = _peeloff_pi(self.args[0]) + if pimult and rest.is_zero: + return (pimult - S.Half).is_integer + + def _eval_subs(self, old, new): + arg = self.args[0] + argnew = arg.subs(old, new) + if arg != argnew and (argnew/pi).is_integer: + return S.ComplexInfinity + return cot(argnew) + + +class ReciprocalTrigonometricFunction(TrigonometricFunction): + """Base class for reciprocal functions of trigonometric functions. """ + + _reciprocal_of = None # mandatory, to be defined in subclass + _singularities = (S.ComplexInfinity,) + + # _is_even and _is_odd are used for correct evaluation of csc(-x), sec(-x) + # TODO refactor into TrigonometricFunction common parts of + # trigonometric functions eval() like even/odd, func(x+2*k*pi), etc. + + # optional, to be defined in subclasses: + _is_even: FuzzyBool = None + _is_odd: FuzzyBool = None + + @classmethod + def eval(cls, arg): + if arg.could_extract_minus_sign(): + if cls._is_even: + return cls(-arg) + if cls._is_odd: + return -cls(-arg) + + pi_coeff = _pi_coeff(arg) + if (pi_coeff is not None + and not (2*pi_coeff).is_integer + and pi_coeff.is_Rational): + q = pi_coeff.q + p = pi_coeff.p % (2*q) + if p > q: + narg = (pi_coeff - 1)*pi + return -cls(narg) + if 2*p > q: + narg = (1 - pi_coeff)*pi + if cls._is_odd: + return cls(narg) + elif cls._is_even: + return -cls(narg) + + if hasattr(arg, 'inverse') and arg.inverse() == cls: + return arg.args[0] + + t = cls._reciprocal_of.eval(arg) + if t is None: + return t + elif any(isinstance(i, cos) for i in (t, -t)): + return (1/t).rewrite(sec) + elif any(isinstance(i, sin) for i in (t, -t)): + return (1/t).rewrite(csc) + else: + return 1/t + + def _call_reciprocal(self, method_name, *args, **kwargs): + # Calls method_name on _reciprocal_of + o = self._reciprocal_of(self.args[0]) + return getattr(o, method_name)(*args, **kwargs) + + def _calculate_reciprocal(self, method_name, *args, **kwargs): + # If calling method_name on _reciprocal_of returns a value != None + # then return the reciprocal of that value + t = self._call_reciprocal(method_name, *args, **kwargs) + return 1/t if t is not None else t + + def _rewrite_reciprocal(self, method_name, arg): + # Special handling for rewrite functions. If reciprocal rewrite returns + # unmodified expression, then return None + t = self._call_reciprocal(method_name, arg) + if t is not None and t != self._reciprocal_of(arg): + return 1/t + + def _period(self, symbol): + f = expand_mul(self.args[0]) + return self._reciprocal_of(f).period(symbol) + + def fdiff(self, argindex=1): + return -self._calculate_reciprocal("fdiff", argindex)/self**2 + + def _eval_rewrite_as_exp(self, arg, **kwargs): + return self._rewrite_reciprocal("_eval_rewrite_as_exp", arg) + + def _eval_rewrite_as_Pow(self, arg, **kwargs): + return self._rewrite_reciprocal("_eval_rewrite_as_Pow", arg) + + def _eval_rewrite_as_sin(self, arg, **kwargs): + return self._rewrite_reciprocal("_eval_rewrite_as_sin", arg) + + def _eval_rewrite_as_cos(self, arg, **kwargs): + return self._rewrite_reciprocal("_eval_rewrite_as_cos", arg) + + def _eval_rewrite_as_tan(self, arg, **kwargs): + return self._rewrite_reciprocal("_eval_rewrite_as_tan", arg) + + def _eval_rewrite_as_pow(self, arg, **kwargs): + return self._rewrite_reciprocal("_eval_rewrite_as_pow", arg) + + def _eval_rewrite_as_sqrt(self, arg, **kwargs): + return self._rewrite_reciprocal("_eval_rewrite_as_sqrt", arg) + + def _eval_conjugate(self): + return self.func(self.args[0].conjugate()) + + def as_real_imag(self, deep=True, **hints): + return (1/self._reciprocal_of(self.args[0])).as_real_imag(deep, + **hints) + + def _eval_expand_trig(self, **hints): + return self._calculate_reciprocal("_eval_expand_trig", **hints) + + def _eval_is_extended_real(self): + return self._reciprocal_of(self.args[0])._eval_is_extended_real() + + def _eval_as_leading_term(self, x, logx, cdir): + return (1/self._reciprocal_of(self.args[0]))._eval_as_leading_term(x, logx=logx, cdir=cdir) + + def _eval_is_finite(self): + return (1/self._reciprocal_of(self.args[0])).is_finite + + def _eval_nseries(self, x, n, logx, cdir=0): + return (1/self._reciprocal_of(self.args[0]))._eval_nseries(x, n, logx) + + +class sec(ReciprocalTrigonometricFunction): + """ + The secant function. + + Returns the secant of x (measured in radians). + + Explanation + =========== + + See :class:`sin` for notes about automatic evaluation. + + Examples + ======== + + >>> from sympy import sec + >>> from sympy.abc import x + >>> sec(x**2).diff(x) + 2*x*tan(x**2)*sec(x**2) + >>> sec(1).diff(x) + 0 + + See Also + ======== + + sin, csc, cos, tan, cot + asin, acsc, acos, asec, atan, acot, atan2 + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Trigonometric_functions + .. [2] https://dlmf.nist.gov/4.14 + .. [3] https://functions.wolfram.com/ElementaryFunctions/Sec + + """ + + _reciprocal_of = cos + _is_even = True + + def period(self, symbol=None): + return self._period(symbol) + + def _eval_rewrite_as_cot(self, arg, **kwargs): + cot_half_sq = cot(arg/2)**2 + return (cot_half_sq + 1)/(cot_half_sq - 1) + + def _eval_rewrite_as_cos(self, arg, **kwargs): + return (1/cos(arg)) + + def _eval_rewrite_as_sincos(self, arg, **kwargs): + return sin(arg)/(cos(arg)*sin(arg)) + + def _eval_rewrite_as_sin(self, arg, **kwargs): + return (1/cos(arg).rewrite(sin, **kwargs)) + + def _eval_rewrite_as_tan(self, arg, **kwargs): + return (1/cos(arg).rewrite(tan, **kwargs)) + + def _eval_rewrite_as_csc(self, arg, **kwargs): + return csc(pi/2 - arg, evaluate=False) + + def fdiff(self, argindex=1): + if argindex == 1: + return tan(self.args[0])*sec(self.args[0]) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_rewrite_as_besselj(self, arg, **kwargs): + from sympy.functions.special.bessel import besselj + return Piecewise( + (1/(sqrt(pi*arg)/(sqrt(2))*besselj(-S.Half, arg)), Ne(arg, 0)), + (1, True) + ) + + def _eval_is_complex(self): + arg = self.args[0] + + if arg.is_complex and (arg/pi - S.Half).is_integer is False: + return True + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + # Reference Formula: + # https://functions.wolfram.com/ElementaryFunctions/Sec/06/01/02/01/ + if n < 0 or n % 2 == 1: + return S.Zero + else: + x = sympify(x) + k = n//2 + return S.NegativeOne**k*euler(2*k)/factorial(2*k)*x**(2*k) + + def _eval_as_leading_term(self, x, logx, cdir): + from sympy.calculus.accumulationbounds import AccumBounds + from sympy.functions.elementary.complexes import re + arg = self.args[0] + x0 = arg.subs(x, 0).cancel() + n = (x0 + pi/2)/pi + if n.is_integer: + lt = (arg - n*pi + pi/2).as_leading_term(x) + return (S.NegativeOne**n)/lt + if x0 is S.ComplexInfinity: + x0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+') + if x0 in (S.Infinity, S.NegativeInfinity): + return AccumBounds(S.NegativeInfinity, S.Infinity) + return self.func(x0) if x0.is_finite else self + + +class csc(ReciprocalTrigonometricFunction): + """ + The cosecant function. + + Returns the cosecant of x (measured in radians). + + Explanation + =========== + + See :func:`sin` for notes about automatic evaluation. + + Examples + ======== + + >>> from sympy import csc + >>> from sympy.abc import x + >>> csc(x**2).diff(x) + -2*x*cot(x**2)*csc(x**2) + >>> csc(1).diff(x) + 0 + + See Also + ======== + + sin, cos, sec, tan, cot + asin, acsc, acos, asec, atan, acot, atan2 + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Trigonometric_functions + .. [2] https://dlmf.nist.gov/4.14 + .. [3] https://functions.wolfram.com/ElementaryFunctions/Csc + + """ + + _reciprocal_of = sin + _is_odd = True + + def period(self, symbol=None): + return self._period(symbol) + + def _eval_rewrite_as_sin(self, arg, **kwargs): + return (1/sin(arg)) + + def _eval_rewrite_as_sincos(self, arg, **kwargs): + return cos(arg)/(sin(arg)*cos(arg)) + + def _eval_rewrite_as_cot(self, arg, **kwargs): + cot_half = cot(arg/2) + return (1 + cot_half**2)/(2*cot_half) + + def _eval_rewrite_as_cos(self, arg, **kwargs): + return 1/sin(arg).rewrite(cos, **kwargs) + + def _eval_rewrite_as_sec(self, arg, **kwargs): + return sec(pi/2 - arg, evaluate=False) + + def _eval_rewrite_as_tan(self, arg, **kwargs): + return (1/sin(arg).rewrite(tan, **kwargs)) + + def _eval_rewrite_as_besselj(self, arg, **kwargs): + from sympy.functions.special.bessel import besselj + return sqrt(2/pi)*(1/(sqrt(arg)*besselj(S.Half, arg))) + + def fdiff(self, argindex=1): + if argindex == 1: + return -cot(self.args[0])*csc(self.args[0]) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_is_complex(self): + arg = self.args[0] + if arg.is_real and (arg/pi).is_integer is False: + return True + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + if n == 0: + return 1/sympify(x) + elif n < 0 or n % 2 == 0: + return S.Zero + else: + x = sympify(x) + k = n//2 + 1 + return (S.NegativeOne**(k - 1)*2*(2**(2*k - 1) - 1)* + bernoulli(2*k)*x**(2*k - 1)/factorial(2*k)) + + def _eval_as_leading_term(self, x, logx, cdir): + from sympy.calculus.accumulationbounds import AccumBounds + from sympy.functions.elementary.complexes import re + arg = self.args[0] + x0 = arg.subs(x, 0).cancel() + n = x0/pi + if n.is_integer: + lt = (arg - n*pi).as_leading_term(x) + return (S.NegativeOne**n)/lt + if x0 is S.ComplexInfinity: + x0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+') + if x0 in (S.Infinity, S.NegativeInfinity): + return AccumBounds(S.NegativeInfinity, S.Infinity) + return self.func(x0) if x0.is_finite else self + + +class sinc(DefinedFunction): + r""" + Represents an unnormalized sinc function: + + .. math:: + + \operatorname{sinc}(x) = + \begin{cases} + \frac{\sin x}{x} & \qquad x \neq 0 \\ + 1 & \qquad x = 0 + \end{cases} + + Examples + ======== + + >>> from sympy import sinc, oo, jn + >>> from sympy.abc import x + >>> sinc(x) + sinc(x) + + * Automated Evaluation + + >>> sinc(0) + 1 + >>> sinc(oo) + 0 + + * Differentiation + + >>> sinc(x).diff() + cos(x)/x - sin(x)/x**2 + + * Series Expansion + + >>> sinc(x).series() + 1 - x**2/6 + x**4/120 + O(x**6) + + * As zero'th order spherical Bessel Function + + >>> sinc(x).rewrite(jn) + jn(0, x) + + See also + ======== + + sin + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Sinc_function + + """ + _singularities = (S.ComplexInfinity,) + + def fdiff(self, argindex=1): + x = self.args[0] + if argindex == 1: + # We would like to return the Piecewise here, but Piecewise.diff + # currently can't handle removable singularities, meaning things + # like sinc(x).diff(x, 2) give the wrong answer at x = 0. See + # https://github.com/sympy/sympy/issues/11402. + # + # return Piecewise(((x*cos(x) - sin(x))/x**2, Ne(x, S.Zero)), (S.Zero, S.true)) + return cos(x)/x - sin(x)/x**2 + else: + raise ArgumentIndexError(self, argindex) + + @classmethod + def eval(cls, arg): + if arg.is_zero: + return S.One + if arg.is_Number: + if arg in [S.Infinity, S.NegativeInfinity]: + return S.Zero + elif arg is S.NaN: + return S.NaN + + if arg is S.ComplexInfinity: + return S.NaN + + if arg.could_extract_minus_sign(): + return cls(-arg) + + pi_coeff = _pi_coeff(arg) + if pi_coeff is not None: + if pi_coeff.is_integer: + if fuzzy_not(arg.is_zero): + return S.Zero + elif (2*pi_coeff).is_integer: + return S.NegativeOne**(pi_coeff - S.Half)/arg + + def _eval_nseries(self, x, n, logx, cdir=0): + x = self.args[0] + return (sin(x)/x)._eval_nseries(x, n, logx) + + def _eval_rewrite_as_jn(self, arg, **kwargs): + from sympy.functions.special.bessel import jn + return jn(0, arg) + + def _eval_rewrite_as_sin(self, arg, **kwargs): + return Piecewise((sin(arg)/arg, Ne(arg, S.Zero)), (S.One, S.true)) + + def _eval_is_zero(self): + if self.args[0].is_infinite: + return True + rest, pi_mult = _peeloff_pi(self.args[0]) + if rest.is_zero: + return fuzzy_and([pi_mult.is_integer, pi_mult.is_nonzero]) + if rest.is_Number and pi_mult.is_integer: + return False + + def _eval_is_real(self): + if self.args[0].is_extended_real or self.args[0].is_imaginary: + return True + + _eval_is_finite = _eval_is_real + + +############################################################################### +########################### TRIGONOMETRIC INVERSES ############################ +############################################################################### + + +class InverseTrigonometricFunction(DefinedFunction): + """Base class for inverse trigonometric functions.""" + _singularities: tuple[Expr, ...] = (S.One, S.NegativeOne, S.Zero, S.ComplexInfinity) + + @staticmethod + @cacheit + def _asin_table(): + # Only keys with could_extract_minus_sign() == False + # are actually needed. + return { + sqrt(3)/2: pi/3, + sqrt(2)/2: pi/4, + 1/sqrt(2): pi/4, + sqrt((5 - sqrt(5))/8): pi/5, + sqrt(2)*sqrt(5 - sqrt(5))/4: pi/5, + sqrt((5 + sqrt(5))/8): pi*Rational(2, 5), + sqrt(2)*sqrt(5 + sqrt(5))/4: pi*Rational(2, 5), + S.Half: pi/6, + sqrt(2 - sqrt(2))/2: pi/8, + sqrt(S.Half - sqrt(2)/4): pi/8, + sqrt(2 + sqrt(2))/2: pi*Rational(3, 8), + sqrt(S.Half + sqrt(2)/4): pi*Rational(3, 8), + (sqrt(5) - 1)/4: pi/10, + (1 - sqrt(5))/4: -pi/10, + (sqrt(5) + 1)/4: pi*Rational(3, 10), + sqrt(6)/4 - sqrt(2)/4: pi/12, + -sqrt(6)/4 + sqrt(2)/4: -pi/12, + (sqrt(3) - 1)/sqrt(8): pi/12, + (1 - sqrt(3))/sqrt(8): -pi/12, + sqrt(6)/4 + sqrt(2)/4: pi*Rational(5, 12), + (1 + sqrt(3))/sqrt(8): pi*Rational(5, 12) + } + + + @staticmethod + @cacheit + def _atan_table(): + # Only keys with could_extract_minus_sign() == False + # are actually needed. + return { + sqrt(3)/3: pi/6, + 1/sqrt(3): pi/6, + sqrt(3): pi/3, + sqrt(2) - 1: pi/8, + 1 - sqrt(2): -pi/8, + 1 + sqrt(2): pi*Rational(3, 8), + sqrt(5 - 2*sqrt(5)): pi/5, + sqrt(5 + 2*sqrt(5)): pi*Rational(2, 5), + sqrt(1 - 2*sqrt(5)/5): pi/10, + sqrt(1 + 2*sqrt(5)/5): pi*Rational(3, 10), + 2 - sqrt(3): pi/12, + -2 + sqrt(3): -pi/12, + 2 + sqrt(3): pi*Rational(5, 12) + } + + @staticmethod + @cacheit + def _acsc_table(): + # Keys for which could_extract_minus_sign() + # will obviously return True are omitted. + return { + 2*sqrt(3)/3: pi/3, + sqrt(2): pi/4, + sqrt(2 + 2*sqrt(5)/5): pi/5, + 1/sqrt(Rational(5, 8) - sqrt(5)/8): pi/5, + sqrt(2 - 2*sqrt(5)/5): pi*Rational(2, 5), + 1/sqrt(Rational(5, 8) + sqrt(5)/8): pi*Rational(2, 5), + 2: pi/6, + sqrt(4 + 2*sqrt(2)): pi/8, + 2/sqrt(2 - sqrt(2)): pi/8, + sqrt(4 - 2*sqrt(2)): pi*Rational(3, 8), + 2/sqrt(2 + sqrt(2)): pi*Rational(3, 8), + 1 + sqrt(5): pi/10, + sqrt(5) - 1: pi*Rational(3, 10), + -(sqrt(5) - 1): pi*Rational(-3, 10), + sqrt(6) + sqrt(2): pi/12, + sqrt(6) - sqrt(2): pi*Rational(5, 12), + -(sqrt(6) - sqrt(2)): pi*Rational(-5, 12) + } + + +class asin(InverseTrigonometricFunction): + r""" + The inverse sine function. + + Returns the arcsine of x in radians. + + Explanation + =========== + + ``asin(x)`` will evaluate automatically in the cases + $x \in \{\infty, -\infty, 0, 1, -1\}$ and for some instances when the + result is a rational multiple of $\pi$ (see the ``eval`` class method). + + A purely imaginary argument will lead to an asinh expression. + + Examples + ======== + + >>> from sympy import asin, oo + >>> asin(1) + pi/2 + >>> asin(-1) + -pi/2 + >>> asin(-oo) + oo*I + >>> asin(oo) + -oo*I + + See Also + ======== + + sin, csc, cos, sec, tan, cot + acsc, acos, asec, atan, acot, atan2 + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Inverse_trigonometric_functions + .. [2] https://dlmf.nist.gov/4.23 + .. [3] https://functions.wolfram.com/ElementaryFunctions/ArcSin + + """ + + def fdiff(self, argindex=1): + if argindex == 1: + return 1/sqrt(1 - self.args[0]**2) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_is_rational(self): + s = self.func(*self.args) + if s.func == self.func: + if s.args[0].is_rational: + return False + else: + return s.is_rational + + def _eval_is_positive(self): + return self._eval_is_extended_real() and self.args[0].is_positive + + def _eval_is_negative(self): + return self._eval_is_extended_real() and self.args[0].is_negative + + @classmethod + def eval(cls, arg): + if arg.is_Number: + if arg is S.NaN: + return S.NaN + elif arg is S.Infinity: + return S.NegativeInfinity*S.ImaginaryUnit + elif arg is S.NegativeInfinity: + return S.Infinity*S.ImaginaryUnit + elif arg.is_zero: + return S.Zero + elif arg is S.One: + return pi/2 + elif arg is S.NegativeOne: + return -pi/2 + + if arg is S.ComplexInfinity: + return S.ComplexInfinity + + if arg.could_extract_minus_sign(): + return -cls(-arg) + + if arg.is_number: + asin_table = cls._asin_table() + if arg in asin_table: + return asin_table[arg] + + i_coeff = _imaginary_unit_as_coefficient(arg) + if i_coeff is not None: + from sympy.functions.elementary.hyperbolic import asinh + return S.ImaginaryUnit*asinh(i_coeff) + + if arg.is_zero: + return S.Zero + + if isinstance(arg, sin): + ang = arg.args[0] + if ang.is_comparable: + ang %= 2*pi # restrict to [0,2*pi) + if ang > pi: # restrict to (-pi,pi] + ang = pi - ang + + # restrict to [-pi/2,pi/2] + if ang > pi/2: + ang = pi - ang + if ang < -pi/2: + ang = -pi - ang + + return ang + + if isinstance(arg, cos): # acos(x) + asin(x) = pi/2 + ang = arg.args[0] + if ang.is_comparable: + return pi/2 - acos(arg) + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + if n < 0 or n % 2 == 0: + return S.Zero + else: + x = sympify(x) + if len(previous_terms) >= 2 and n > 2: + p = previous_terms[-2] + return p*(n - 2)**2/(n*(n - 1))*x**2 + else: + k = (n - 1) // 2 + R = RisingFactorial(S.Half, k) + F = factorial(k) + return R/F*x**n/n + + def _eval_as_leading_term(self, x, logx, cdir): + arg = self.args[0] + x0 = arg.subs(x, 0).cancel() + if x0 is S.NaN: + return self.func(arg.as_leading_term(x)) + if x0.is_zero: + return arg.as_leading_term(x) + + # Handling branch points + if x0 in (-S.One, S.One, S.ComplexInfinity): + return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir).expand() + # Handling points lying on branch cuts (-oo, -1) U (1, oo) + if (1 - x0**2).is_negative: + ndir = arg.dir(x, cdir if cdir else 1) + if im(ndir).is_negative: + if x0.is_negative: + return -pi - self.func(x0) + elif im(ndir).is_positive: + if x0.is_positive: + return pi - self.func(x0) + else: + return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir).expand() + return self.func(x0) + + def _eval_nseries(self, x, n, logx, cdir=0): # asin + from sympy.series.order import O + arg0 = self.args[0].subs(x, 0) + # Handling branch points + if arg0 is S.One: + t = Dummy('t', positive=True) + ser = asin(S.One - t**2).rewrite(log).nseries(t, 0, 2*n) + arg1 = S.One - self.args[0] + f = arg1.as_leading_term(x) + g = (arg1 - f)/ f + if not g.is_meromorphic(x, 0): # cannot be expanded + return O(1) if n == 0 else pi/2 + O(sqrt(x)) + res1 = sqrt(S.One + g)._eval_nseries(x, n=n, logx=logx) + res = (res1.removeO()*sqrt(f)).expand() + return ser.removeO().subs(t, res).expand().powsimp() + O(x**n, x) + + if arg0 is S.NegativeOne: + t = Dummy('t', positive=True) + ser = asin(S.NegativeOne + t**2).rewrite(log).nseries(t, 0, 2*n) + arg1 = S.One + self.args[0] + f = arg1.as_leading_term(x) + g = (arg1 - f)/ f + if not g.is_meromorphic(x, 0): # cannot be expanded + return O(1) if n == 0 else -pi/2 + O(sqrt(x)) + res1 = sqrt(S.One + g)._eval_nseries(x, n=n, logx=logx) + res = (res1.removeO()*sqrt(f)).expand() + return ser.removeO().subs(t, res).expand().powsimp() + O(x**n, x) + + res = super()._eval_nseries(x, n=n, logx=logx) + if arg0 is S.ComplexInfinity: + return res + # Handling points lying on branch cuts (-oo, -1) U (1, oo) + if (1 - arg0**2).is_negative: + ndir = self.args[0].dir(x, cdir if cdir else 1) + if im(ndir).is_negative: + if arg0.is_negative: + return -pi - res + elif im(ndir).is_positive: + if arg0.is_positive: + return pi - res + else: + return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir) + return res + + def _eval_rewrite_as_acos(self, x, **kwargs): + return pi/2 - acos(x) + + def _eval_rewrite_as_atan(self, x, **kwargs): + return 2*atan(x/(1 + sqrt(1 - x**2))) + + def _eval_rewrite_as_log(self, x, **kwargs): + return -S.ImaginaryUnit*log(S.ImaginaryUnit*x + sqrt(1 - x**2)) + + _eval_rewrite_as_tractable = _eval_rewrite_as_log + + def _eval_rewrite_as_acot(self, arg, **kwargs): + return 2*acot((1 + sqrt(1 - arg**2))/arg) + + def _eval_rewrite_as_asec(self, arg, **kwargs): + return pi/2 - asec(1/arg) + + def _eval_rewrite_as_acsc(self, arg, **kwargs): + return acsc(1/arg) + + def _eval_is_extended_real(self): + x = self.args[0] + return x.is_extended_real and (1 - abs(x)).is_nonnegative + + def inverse(self, argindex=1): + """ + Returns the inverse of this function. + """ + return sin + + +class acos(InverseTrigonometricFunction): + r""" + The inverse cosine function. + + Explanation + =========== + + Returns the arc cosine of x (measured in radians). + + ``acos(x)`` will evaluate automatically in the cases + $x \in \{\infty, -\infty, 0, 1, -1\}$ and for some instances when + the result is a rational multiple of $\pi$ (see the eval class method). + + ``acos(zoo)`` evaluates to ``zoo`` + (see note in :class:`sympy.functions.elementary.trigonometric.asec`) + + A purely imaginary argument will be rewritten to asinh. + + Examples + ======== + + >>> from sympy import acos, oo + >>> acos(1) + 0 + >>> acos(0) + pi/2 + >>> acos(oo) + oo*I + + See Also + ======== + + sin, csc, cos, sec, tan, cot + asin, acsc, asec, atan, acot, atan2 + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Inverse_trigonometric_functions + .. [2] https://dlmf.nist.gov/4.23 + .. [3] https://functions.wolfram.com/ElementaryFunctions/ArcCos + + """ + + def fdiff(self, argindex=1): + if argindex == 1: + return -1/sqrt(1 - self.args[0]**2) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_is_rational(self): + s = self.func(*self.args) + if s.func == self.func: + if s.args[0].is_rational: + return False + else: + return s.is_rational + + @classmethod + def eval(cls, arg): + if arg.is_Number: + if arg is S.NaN: + return S.NaN + elif arg is S.Infinity: + return S.Infinity*S.ImaginaryUnit + elif arg is S.NegativeInfinity: + return S.NegativeInfinity*S.ImaginaryUnit + elif arg.is_zero: + return pi/2 + elif arg is S.One: + return S.Zero + elif arg is S.NegativeOne: + return pi + + if arg is S.ComplexInfinity: + return S.ComplexInfinity + + if arg.is_number: + asin_table = cls._asin_table() + if arg in asin_table: + return pi/2 - asin_table[arg] + elif -arg in asin_table: + return pi/2 + asin_table[-arg] + + i_coeff = _imaginary_unit_as_coefficient(arg) + if i_coeff is not None: + return pi/2 - asin(arg) + + if arg.is_Mul and len(arg.args) == 2 and arg.args[0] == -1: + narg = arg.args[1] + minus = True + else: + narg = arg + minus = False + + if isinstance(narg, cos): + # acos(cos(x)) = x or acos(-cos(x)) = pi - x + ang = narg.args[0] + if ang.is_comparable: + if minus: + ang = pi - ang + ang %= 2*pi # restrict to [0,2*pi) + if ang > pi: # restrict to [0,pi] + ang = 2*pi - ang + return ang + + if isinstance(narg, sin): # acos(x) + asin(x) = pi/2 + ang = narg.args[0] + if ang.is_comparable: + if minus: + return pi/2 + asin(narg) + return pi/2 - asin(narg) + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + if n == 0: + return pi/2 + elif n < 0 or n % 2 == 0: + return S.Zero + else: + x = sympify(x) + if len(previous_terms) >= 2 and n > 2: + p = previous_terms[-2] + return p*(n - 2)**2/(n*(n - 1))*x**2 + else: + k = (n - 1) // 2 + R = RisingFactorial(S.Half, k) + F = factorial(k) + return -R/F*x**n/n + + def _eval_as_leading_term(self, x, logx, cdir): + arg = self.args[0] + x0 = arg.subs(x, 0).cancel() + if x0 is S.NaN: + return self.func(arg.as_leading_term(x)) + # Handling branch points + if x0 == 1: + return sqrt(2)*sqrt((S.One - arg).as_leading_term(x)) + if x0 in (-S.One, S.ComplexInfinity): + return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir) + # Handling points lying on branch cuts (-oo, -1) U (1, oo) + if (1 - x0**2).is_negative: + ndir = arg.dir(x, cdir if cdir else 1) + if im(ndir).is_negative: + if x0.is_negative: + return 2*pi - self.func(x0) + elif im(ndir).is_positive: + if x0.is_positive: + return -self.func(x0) + else: + return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir).expand() + return self.func(x0) + + def _eval_is_extended_real(self): + x = self.args[0] + return x.is_extended_real and (1 - abs(x)).is_nonnegative + + def _eval_is_nonnegative(self): + return self._eval_is_extended_real() + + def _eval_nseries(self, x, n, logx, cdir=0): # acos + from sympy.series.order import O + arg0 = self.args[0].subs(x, 0) + # Handling branch points + if arg0 is S.One: + t = Dummy('t', positive=True) + ser = acos(S.One - t**2).rewrite(log).nseries(t, 0, 2*n) + arg1 = S.One - self.args[0] + f = arg1.as_leading_term(x) + g = (arg1 - f)/ f + if not g.is_meromorphic(x, 0): # cannot be expanded + return O(1) if n == 0 else O(sqrt(x)) + res1 = sqrt(S.One + g)._eval_nseries(x, n=n, logx=logx) + res = (res1.removeO()*sqrt(f)).expand() + return ser.removeO().subs(t, res).expand().powsimp() + O(x**n, x) + + if arg0 is S.NegativeOne: + t = Dummy('t', positive=True) + ser = acos(S.NegativeOne + t**2).rewrite(log).nseries(t, 0, 2*n) + arg1 = S.One + self.args[0] + f = arg1.as_leading_term(x) + g = (arg1 - f)/ f + if not g.is_meromorphic(x, 0): # cannot be expanded + return O(1) if n == 0 else pi + O(sqrt(x)) + res1 = sqrt(S.One + g)._eval_nseries(x, n=n, logx=logx) + res = (res1.removeO()*sqrt(f)).expand() + return ser.removeO().subs(t, res).expand().powsimp() + O(x**n, x) + + res = super()._eval_nseries(x, n=n, logx=logx) + if arg0 is S.ComplexInfinity: + return res + # Handling points lying on branch cuts (-oo, -1) U (1, oo) + if (1 - arg0**2).is_negative: + ndir = self.args[0].dir(x, cdir if cdir else 1) + if im(ndir).is_negative: + if arg0.is_negative: + return 2*pi - res + elif im(ndir).is_positive: + if arg0.is_positive: + return -res + else: + return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir) + return res + + def _eval_rewrite_as_log(self, x, **kwargs): + return pi/2 + S.ImaginaryUnit*\ + log(S.ImaginaryUnit*x + sqrt(1 - x**2)) + + _eval_rewrite_as_tractable = _eval_rewrite_as_log + + def _eval_rewrite_as_asin(self, x, **kwargs): + return pi/2 - asin(x) + + def _eval_rewrite_as_atan(self, x, **kwargs): + return atan(sqrt(1 - x**2)/x) + (pi/2)*(1 - x*sqrt(1/x**2)) + + def inverse(self, argindex=1): + """ + Returns the inverse of this function. + """ + return cos + + def _eval_rewrite_as_acot(self, arg, **kwargs): + return pi/2 - 2*acot((1 + sqrt(1 - arg**2))/arg) + + def _eval_rewrite_as_asec(self, arg, **kwargs): + return asec(1/arg) + + def _eval_rewrite_as_acsc(self, arg, **kwargs): + return pi/2 - acsc(1/arg) + + def _eval_conjugate(self): + z = self.args[0] + r = self.func(self.args[0].conjugate()) + if z.is_extended_real is False: + return r + elif z.is_extended_real and (z + 1).is_nonnegative and (z - 1).is_nonpositive: + return r + + +class atan(InverseTrigonometricFunction): + r""" + The inverse tangent function. + + Returns the arc tangent of x (measured in radians). + + Explanation + =========== + + ``atan(x)`` will evaluate automatically in the cases + $x \in \{\infty, -\infty, 0, 1, -1\}$ and for some instances when the + result is a rational multiple of $\pi$ (see the eval class method). + + Examples + ======== + + >>> from sympy import atan, oo + >>> atan(0) + 0 + >>> atan(1) + pi/4 + >>> atan(oo) + pi/2 + + See Also + ======== + + sin, csc, cos, sec, tan, cot + asin, acsc, acos, asec, acot, atan2 + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Inverse_trigonometric_functions + .. [2] https://dlmf.nist.gov/4.23 + .. [3] https://functions.wolfram.com/ElementaryFunctions/ArcTan + + """ + + args: tuple[Expr] + + _singularities = (S.ImaginaryUnit, -S.ImaginaryUnit) + + def fdiff(self, argindex=1): + if argindex == 1: + return 1/(1 + self.args[0]**2) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_is_rational(self): + s = self.func(*self.args) + if s.func == self.func: + if s.args[0].is_rational: + return False + else: + return s.is_rational + + def _eval_is_positive(self): + return self.args[0].is_extended_positive + + def _eval_is_nonnegative(self): + return self.args[0].is_extended_nonnegative + + def _eval_is_zero(self): + return self.args[0].is_zero + + def _eval_is_real(self): + return self.args[0].is_extended_real + + @classmethod + def eval(cls, arg): + if arg.is_Number: + if arg is S.NaN: + return S.NaN + elif arg is S.Infinity: + return pi/2 + elif arg is S.NegativeInfinity: + return -pi/2 + elif arg.is_zero: + return S.Zero + elif arg is S.One: + return pi/4 + elif arg is S.NegativeOne: + return -pi/4 + + if arg is S.ComplexInfinity: + from sympy.calculus.accumulationbounds import AccumBounds + return AccumBounds(-pi/2, pi/2) + + if arg.could_extract_minus_sign(): + return -cls(-arg) + + if arg.is_number: + atan_table = cls._atan_table() + if arg in atan_table: + return atan_table[arg] + + i_coeff = _imaginary_unit_as_coefficient(arg) + if i_coeff is not None: + from sympy.functions.elementary.hyperbolic import atanh + return S.ImaginaryUnit*atanh(i_coeff) + + if arg.is_zero: + return S.Zero + + if isinstance(arg, tan): + ang = arg.args[0] + if ang.is_comparable: + ang %= pi # restrict to [0,pi) + if ang > pi/2: # restrict to [-pi/2,pi/2] + ang -= pi + + return ang + + if isinstance(arg, cot): # atan(x) + acot(x) = pi/2 + ang = arg.args[0] + if ang.is_comparable: + ang = pi/2 - acot(arg) + if ang > pi/2: # restrict to [-pi/2,pi/2] + ang -= pi + return ang + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + if n < 0 or n % 2 == 0: + return S.Zero + else: + x = sympify(x) + return S.NegativeOne**((n - 1)//2)*x**n/n + + def _eval_as_leading_term(self, x, logx, cdir): + arg = self.args[0] + x0 = arg.subs(x, 0).cancel() + if x0 is S.NaN: + return self.func(arg.as_leading_term(x)) + if x0.is_zero: + return arg.as_leading_term(x) + # Handling branch points + if x0 in (-S.ImaginaryUnit, S.ImaginaryUnit, S.ComplexInfinity): + return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir).expand() + # Handling points lying on branch cuts (-I*oo, -I) U (I, I*oo) + if (1 + x0**2).is_negative: + ndir = arg.dir(x, cdir if cdir else 1) + if re(ndir).is_negative: + if im(x0).is_positive: + return self.func(x0) - pi + elif re(ndir).is_positive: + if im(x0).is_negative: + return self.func(x0) + pi + else: + return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir).expand() + return self.func(x0) + + def _eval_nseries(self, x, n, logx, cdir=0): # atan + arg0 = self.args[0].subs(x, 0) + + # Handling branch points + if arg0 in (S.ImaginaryUnit, S.NegativeOne*S.ImaginaryUnit): + return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir) + + res = super()._eval_nseries(x, n=n, logx=logx) + ndir = self.args[0].dir(x, cdir if cdir else 1) + if arg0 is S.ComplexInfinity: + if re(ndir) > 0: + return res - pi + return res + # Handling points lying on branch cuts (-I*oo, -I) U (I, I*oo) + if (1 + arg0**2).is_negative: + if re(ndir).is_negative: + if im(arg0).is_positive: + return res - pi + elif re(ndir).is_positive: + if im(arg0).is_negative: + return res + pi + else: + return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir) + return res + + def _eval_rewrite_as_log(self, x, **kwargs): + return S.ImaginaryUnit/2*(log(S.One - S.ImaginaryUnit*x) + - log(S.One + S.ImaginaryUnit*x)) + + _eval_rewrite_as_tractable = _eval_rewrite_as_log + + def _eval_aseries(self, n, args0, x, logx): + if args0[0] in [S.Infinity, S.NegativeInfinity]: + return (pi/2 - atan(1/self.args[0]))._eval_nseries(x, n, logx) + else: + return super()._eval_aseries(n, args0, x, logx) + + def inverse(self, argindex=1): + """ + Returns the inverse of this function. + """ + return tan + + def _eval_rewrite_as_asin(self, arg, **kwargs): + return sqrt(arg**2)/arg*(pi/2 - asin(1/sqrt(1 + arg**2))) + + def _eval_rewrite_as_acos(self, arg, **kwargs): + return sqrt(arg**2)/arg*acos(1/sqrt(1 + arg**2)) + + def _eval_rewrite_as_acot(self, arg, **kwargs): + return acot(1/arg) + + def _eval_rewrite_as_asec(self, arg, **kwargs): + return sqrt(arg**2)/arg*asec(sqrt(1 + arg**2)) + + def _eval_rewrite_as_acsc(self, arg, **kwargs): + return sqrt(arg**2)/arg*(pi/2 - acsc(sqrt(1 + arg**2))) + + +class acot(InverseTrigonometricFunction): + r""" + The inverse cotangent function. + + Returns the arc cotangent of x (measured in radians). + + Explanation + =========== + + ``acot(x)`` will evaluate automatically in the cases + $x \in \{\infty, -\infty, \tilde{\infty}, 0, 1, -1\}$ + and for some instances when the result is a rational multiple of $\pi$ + (see the eval class method). + + A purely imaginary argument will lead to an ``acoth`` expression. + + ``acot(x)`` has a branch cut along $(-i, i)$, hence it is discontinuous + at 0. Its range for real $x$ is $(-\frac{\pi}{2}, \frac{\pi}{2}]$. + + Examples + ======== + + >>> from sympy import acot, sqrt + >>> acot(0) + pi/2 + >>> acot(1) + pi/4 + >>> acot(sqrt(3) - 2) + -5*pi/12 + + See Also + ======== + + sin, csc, cos, sec, tan, cot + asin, acsc, acos, asec, atan, atan2 + + References + ========== + + .. [1] https://dlmf.nist.gov/4.23 + .. [2] https://functions.wolfram.com/ElementaryFunctions/ArcCot + + """ + _singularities = (S.ImaginaryUnit, -S.ImaginaryUnit) + + def fdiff(self, argindex=1): + if argindex == 1: + return -1/(1 + self.args[0]**2) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_is_rational(self): + s = self.func(*self.args) + if s.func == self.func: + if s.args[0].is_rational: + return False + else: + return s.is_rational + + def _eval_is_positive(self): + return self.args[0].is_nonnegative + + def _eval_is_negative(self): + return self.args[0].is_negative + + def _eval_is_extended_real(self): + return self.args[0].is_extended_real + + @classmethod + def eval(cls, arg): + if arg.is_Number: + if arg is S.NaN: + return S.NaN + elif arg is S.Infinity: + return S.Zero + elif arg is S.NegativeInfinity: + return S.Zero + elif arg.is_zero: + return pi/ 2 + elif arg is S.One: + return pi/4 + elif arg is S.NegativeOne: + return -pi/4 + + if arg is S.ComplexInfinity: + return S.Zero + + if arg.could_extract_minus_sign(): + return -cls(-arg) + + if arg.is_number: + atan_table = cls._atan_table() + if arg in atan_table: + ang = pi/2 - atan_table[arg] + if ang > pi/2: # restrict to (-pi/2,pi/2] + ang -= pi + return ang + + i_coeff = _imaginary_unit_as_coefficient(arg) + if i_coeff is not None: + from sympy.functions.elementary.hyperbolic import acoth + return -S.ImaginaryUnit*acoth(i_coeff) + + if arg.is_zero: + return pi*S.Half + + if isinstance(arg, cot): + ang = arg.args[0] + if ang.is_comparable: + ang %= pi # restrict to [0,pi) + if ang > pi/2: # restrict to (-pi/2,pi/2] + ang -= pi + return ang + + if isinstance(arg, tan): # atan(x) + acot(x) = pi/2 + ang = arg.args[0] + if ang.is_comparable: + ang = pi/2 - atan(arg) + if ang > pi/2: # restrict to (-pi/2,pi/2] + ang -= pi + return ang + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + if n == 0: + return pi/2 # FIX THIS + elif n < 0 or n % 2 == 0: + return S.Zero + else: + x = sympify(x) + return S.NegativeOne**((n + 1)//2)*x**n/n + + def _eval_as_leading_term(self, x, logx, cdir): + arg = self.args[0] + x0 = arg.subs(x, 0).cancel() + if x0 is S.NaN: + return self.func(arg.as_leading_term(x)) + if x0 is S.ComplexInfinity: + return (1/arg).as_leading_term(x) + # Handling branch points + if x0 in (-S.ImaginaryUnit, S.ImaginaryUnit, S.Zero): + return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir).expand() + # Handling points lying on branch cuts [-I, I] + if x0.is_imaginary and (1 + x0**2).is_positive: + ndir = arg.dir(x, cdir if cdir else 1) + if re(ndir).is_positive: + if im(x0).is_positive: + return self.func(x0) + pi + elif re(ndir).is_negative: + if im(x0).is_negative: + return self.func(x0) - pi + else: + return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir).expand() + return self.func(x0) + + def _eval_nseries(self, x, n, logx, cdir=0): # acot + arg0 = self.args[0].subs(x, 0) + + # Handling branch points + if arg0 in (S.ImaginaryUnit, S.NegativeOne*S.ImaginaryUnit): + return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir) + + res = super()._eval_nseries(x, n=n, logx=logx) + if arg0 is S.ComplexInfinity: + return res + ndir = self.args[0].dir(x, cdir if cdir else 1) + if arg0.is_zero: + if re(ndir) < 0: + return res - pi + return res + # Handling points lying on branch cuts [-I, I] + if arg0.is_imaginary and (1 + arg0**2).is_positive: + if re(ndir).is_positive: + if im(arg0).is_positive: + return res + pi + elif re(ndir).is_negative: + if im(arg0).is_negative: + return res - pi + else: + return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir) + return res + + def _eval_aseries(self, n, args0, x, logx): + if args0[0] in [S.Infinity, S.NegativeInfinity]: + return atan(1/self.args[0])._eval_nseries(x, n, logx) + else: + return super()._eval_aseries(n, args0, x, logx) + + def _eval_rewrite_as_log(self, x, **kwargs): + return S.ImaginaryUnit/2*(log(1 - S.ImaginaryUnit/x) + - log(1 + S.ImaginaryUnit/x)) + + _eval_rewrite_as_tractable = _eval_rewrite_as_log + + def inverse(self, argindex=1): + """ + Returns the inverse of this function. + """ + return cot + + def _eval_rewrite_as_asin(self, arg, **kwargs): + return (arg*sqrt(1/arg**2)* + (pi/2 - asin(sqrt(-arg**2)/sqrt(-arg**2 - 1)))) + + def _eval_rewrite_as_acos(self, arg, **kwargs): + return arg*sqrt(1/arg**2)*acos(sqrt(-arg**2)/sqrt(-arg**2 - 1)) + + def _eval_rewrite_as_atan(self, arg, **kwargs): + return atan(1/arg) + + def _eval_rewrite_as_asec(self, arg, **kwargs): + return arg*sqrt(1/arg**2)*asec(sqrt((1 + arg**2)/arg**2)) + + def _eval_rewrite_as_acsc(self, arg, **kwargs): + return arg*sqrt(1/arg**2)*(pi/2 - acsc(sqrt((1 + arg**2)/arg**2))) + + +class asec(InverseTrigonometricFunction): + r""" + The inverse secant function. + + Returns the arc secant of x (measured in radians). + + Explanation + =========== + + ``asec(x)`` will evaluate automatically in the cases + $x \in \{\infty, -\infty, 0, 1, -1\}$ and for some instances when the + result is a rational multiple of $\pi$ (see the eval class method). + + ``asec(x)`` has branch cut in the interval $[-1, 1]$. For complex arguments, + it can be defined [4]_ as + + .. math:: + \operatorname{sec^{-1}}(z) = -i\frac{\log\left(\sqrt{1 - z^2} + 1\right)}{z} + + At ``x = 0``, for positive branch cut, the limit evaluates to ``zoo``. For + negative branch cut, the limit + + .. math:: + \lim_{z \to 0}-i\frac{\log\left(-\sqrt{1 - z^2} + 1\right)}{z} + + simplifies to :math:`-i\log\left(z/2 + O\left(z^3\right)\right)` which + ultimately evaluates to ``zoo``. + + As ``acos(x) = asec(1/x)``, a similar argument can be given for + ``acos(x)``. + + Examples + ======== + + >>> from sympy import asec, oo + >>> asec(1) + 0 + >>> asec(-1) + pi + >>> asec(0) + zoo + >>> asec(-oo) + pi/2 + + See Also + ======== + + sin, csc, cos, sec, tan, cot + asin, acsc, acos, atan, acot, atan2 + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Inverse_trigonometric_functions + .. [2] https://dlmf.nist.gov/4.23 + .. [3] https://functions.wolfram.com/ElementaryFunctions/ArcSec + .. [4] https://reference.wolfram.com/language/ref/ArcSec.html + + """ + + @classmethod + def eval(cls, arg): + if arg.is_zero: + return S.ComplexInfinity + if arg.is_Number: + if arg is S.NaN: + return S.NaN + elif arg is S.One: + return S.Zero + elif arg is S.NegativeOne: + return pi + if arg in [S.Infinity, S.NegativeInfinity, S.ComplexInfinity]: + return pi/2 + + if arg.is_number: + acsc_table = cls._acsc_table() + if arg in acsc_table: + return pi/2 - acsc_table[arg] + elif -arg in acsc_table: + return pi/2 + acsc_table[-arg] + + if arg.is_infinite: + return pi/2 + + if arg.is_Mul and len(arg.args) == 2 and arg.args[0] == -1: + narg = arg.args[1] + minus = True + else: + narg = arg + minus = False + + if isinstance(narg, sec): + # asec(sec(x)) = x or asec(-sec(x)) = pi - x + ang = narg.args[0] + if ang.is_comparable: + if minus: + ang = pi - ang + ang %= 2*pi # restrict to [0,2*pi) + if ang > pi: # restrict to [0,pi] + ang = 2*pi - ang + return ang + + if isinstance(narg, csc): # asec(x) + acsc(x) = pi/2 + ang = narg.args[0] + if ang.is_comparable: + if minus: + pi/2 + acsc(narg) + return pi/2 - acsc(narg) + + def fdiff(self, argindex=1): + if argindex == 1: + return 1/(self.args[0]**2*sqrt(1 - 1/self.args[0]**2)) + else: + raise ArgumentIndexError(self, argindex) + + def inverse(self, argindex=1): + """ + Returns the inverse of this function. + """ + return sec + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + if n == 0: + return S.ImaginaryUnit*log(2 / x) + elif n < 0 or n % 2 == 1: + return S.Zero + else: + x = sympify(x) + if len(previous_terms) > 2 and n > 2: + p = previous_terms[-2] + return p * ((n - 1)*(n-2)) * x**2/(4 * (n//2)**2) + else: + k = n // 2 + R = RisingFactorial(S.Half, k) * n + F = factorial(k) * n // 2 * n // 2 + return -S.ImaginaryUnit * R / F * x**n / 4 + + def _eval_as_leading_term(self, x, logx, cdir): + arg = self.args[0] + x0 = arg.subs(x, 0).cancel() + if x0 is S.NaN: + return self.func(arg.as_leading_term(x)) + # Handling branch points + if x0 == 1: + return sqrt(2)*sqrt((arg - S.One).as_leading_term(x)) + if x0 in (-S.One, S.Zero): + return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir) + # Handling points lying on branch cuts (-1, 1) + if x0.is_real and (1 - x0**2).is_positive: + ndir = arg.dir(x, cdir if cdir else 1) + if im(ndir).is_negative: + if x0.is_positive: + return -self.func(x0) + elif im(ndir).is_positive: + if x0.is_negative: + return 2*pi - self.func(x0) + else: + return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir).expand() + return self.func(x0) + + def _eval_nseries(self, x, n, logx, cdir=0): # asec + from sympy.series.order import O + arg0 = self.args[0].subs(x, 0) + # Handling branch points + if arg0 is S.One: + t = Dummy('t', positive=True) + ser = asec(S.One + t**2).rewrite(log).nseries(t, 0, 2*n) + arg1 = S.NegativeOne + self.args[0] + f = arg1.as_leading_term(x) + g = (arg1 - f)/ f + res1 = sqrt(S.One + g)._eval_nseries(x, n=n, logx=logx) + res = (res1.removeO()*sqrt(f)).expand() + return ser.removeO().subs(t, res).expand().powsimp() + O(x**n, x) + + if arg0 is S.NegativeOne: + t = Dummy('t', positive=True) + ser = asec(S.NegativeOne - t**2).rewrite(log).nseries(t, 0, 2*n) + arg1 = S.NegativeOne - self.args[0] + f = arg1.as_leading_term(x) + g = (arg1 - f)/ f + res1 = sqrt(S.One + g)._eval_nseries(x, n=n, logx=logx) + res = (res1.removeO()*sqrt(f)).expand() + return ser.removeO().subs(t, res).expand().powsimp() + O(x**n, x) + + res = super()._eval_nseries(x, n=n, logx=logx) + if arg0 is S.ComplexInfinity: + return res + # Handling points lying on branch cuts (-1, 1) + if arg0.is_real and (1 - arg0**2).is_positive: + ndir = self.args[0].dir(x, cdir if cdir else 1) + if im(ndir).is_negative: + if arg0.is_positive: + return -res + elif im(ndir).is_positive: + if arg0.is_negative: + return 2*pi - res + else: + return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir) + return res + + def _eval_is_extended_real(self): + x = self.args[0] + if x.is_extended_real is False: + return False + return fuzzy_or(((x - 1).is_nonnegative, (-x - 1).is_nonnegative)) + + def _eval_rewrite_as_log(self, arg, **kwargs): + return pi/2 + S.ImaginaryUnit*log(S.ImaginaryUnit/arg + sqrt(1 - 1/arg**2)) + + _eval_rewrite_as_tractable = _eval_rewrite_as_log + + def _eval_rewrite_as_asin(self, arg, **kwargs): + return pi/2 - asin(1/arg) + + def _eval_rewrite_as_acos(self, arg, **kwargs): + return acos(1/arg) + + def _eval_rewrite_as_atan(self, x, **kwargs): + sx2x = sqrt(x**2)/x + return pi/2*(1 - sx2x) + sx2x*atan(sqrt(x**2 - 1)) + + def _eval_rewrite_as_acot(self, x, **kwargs): + sx2x = sqrt(x**2)/x + return pi/2*(1 - sx2x) + sx2x*acot(1/sqrt(x**2 - 1)) + + def _eval_rewrite_as_acsc(self, arg, **kwargs): + return pi/2 - acsc(arg) + + +class acsc(InverseTrigonometricFunction): + r""" + The inverse cosecant function. + + Returns the arc cosecant of x (measured in radians). + + Explanation + =========== + + ``acsc(x)`` will evaluate automatically in the cases + $x \in \{\infty, -\infty, 0, 1, -1\}$` and for some instances when the + result is a rational multiple of $\pi$ (see the ``eval`` class method). + + Examples + ======== + + >>> from sympy import acsc, oo + >>> acsc(1) + pi/2 + >>> acsc(-1) + -pi/2 + >>> acsc(oo) + 0 + >>> acsc(-oo) == acsc(oo) + True + >>> acsc(0) + zoo + + See Also + ======== + + sin, csc, cos, sec, tan, cot + asin, acos, asec, atan, acot, atan2 + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Inverse_trigonometric_functions + .. [2] https://dlmf.nist.gov/4.23 + .. [3] https://functions.wolfram.com/ElementaryFunctions/ArcCsc + + """ + + @classmethod + def eval(cls, arg): + if arg.is_zero: + return S.ComplexInfinity + if arg.is_Number: + if arg is S.NaN: + return S.NaN + elif arg is S.One: + return pi/2 + elif arg is S.NegativeOne: + return -pi/2 + if arg in [S.Infinity, S.NegativeInfinity, S.ComplexInfinity]: + return S.Zero + + if arg.could_extract_minus_sign(): + return -cls(-arg) + + if arg.is_infinite: + return S.Zero + + if arg.is_number: + acsc_table = cls._acsc_table() + if arg in acsc_table: + return acsc_table[arg] + + if isinstance(arg, csc): + ang = arg.args[0] + if ang.is_comparable: + ang %= 2*pi # restrict to [0,2*pi) + if ang > pi: # restrict to (-pi,pi] + ang = pi - ang + + # restrict to [-pi/2,pi/2] + if ang > pi/2: + ang = pi - ang + if ang < -pi/2: + ang = -pi - ang + + return ang + + if isinstance(arg, sec): # asec(x) + acsc(x) = pi/2 + ang = arg.args[0] + if ang.is_comparable: + return pi/2 - asec(arg) + + def fdiff(self, argindex=1): + if argindex == 1: + return -1/(self.args[0]**2*sqrt(1 - 1/self.args[0]**2)) + else: + raise ArgumentIndexError(self, argindex) + + def inverse(self, argindex=1): + """ + Returns the inverse of this function. + """ + return csc + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + if n == 0: + return pi/2 - S.ImaginaryUnit*log(2) + S.ImaginaryUnit*log(x) + elif n < 0 or n % 2 == 1: + return S.Zero + else: + x = sympify(x) + if len(previous_terms) > 2 and n > 2: + p = previous_terms[-2] + return p * ((n - 1)*(n-2)) * x**2/(4 * (n//2)**2) + else: + k = n // 2 + R = RisingFactorial(S.Half, k) * n + F = factorial(k) * n // 2 * n // 2 + return S.ImaginaryUnit * R / F * x**n / 4 + + def _eval_as_leading_term(self, x, logx, cdir): + arg = self.args[0] + x0 = arg.subs(x, 0).cancel() + if x0 is S.NaN: + return self.func(arg.as_leading_term(x)) + # Handling branch points + if x0 in (-S.One, S.One, S.Zero): + return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir).expand() + if x0 is S.ComplexInfinity: + return (1/arg).as_leading_term(x) + # Handling points lying on branch cuts (-1, 1) + if x0.is_real and (1 - x0**2).is_positive: + ndir = arg.dir(x, cdir if cdir else 1) + if im(ndir).is_negative: + if x0.is_positive: + return pi - self.func(x0) + elif im(ndir).is_positive: + if x0.is_negative: + return -pi - self.func(x0) + else: + return self.rewrite(log)._eval_as_leading_term(x, logx=logx, cdir=cdir).expand() + return self.func(x0) + + def _eval_nseries(self, x, n, logx, cdir=0): # acsc + from sympy.series.order import O + arg0 = self.args[0].subs(x, 0) + # Handling branch points + if arg0 is S.One: + t = Dummy('t', positive=True) + ser = acsc(S.One + t**2).rewrite(log).nseries(t, 0, 2*n) + arg1 = S.NegativeOne + self.args[0] + f = arg1.as_leading_term(x) + g = (arg1 - f)/ f + res1 = sqrt(S.One + g)._eval_nseries(x, n=n, logx=logx) + res = (res1.removeO()*sqrt(f)).expand() + return ser.removeO().subs(t, res).expand().powsimp() + O(x**n, x) + + if arg0 is S.NegativeOne: + t = Dummy('t', positive=True) + ser = acsc(S.NegativeOne - t**2).rewrite(log).nseries(t, 0, 2*n) + arg1 = S.NegativeOne - self.args[0] + f = arg1.as_leading_term(x) + g = (arg1 - f)/ f + res1 = sqrt(S.One + g)._eval_nseries(x, n=n, logx=logx) + res = (res1.removeO()*sqrt(f)).expand() + return ser.removeO().subs(t, res).expand().powsimp() + O(x**n, x) + + res = super()._eval_nseries(x, n=n, logx=logx) + if arg0 is S.ComplexInfinity: + return res + # Handling points lying on branch cuts (-1, 1) + if arg0.is_real and (1 - arg0**2).is_positive: + ndir = self.args[0].dir(x, cdir if cdir else 1) + if im(ndir).is_negative: + if arg0.is_positive: + return pi - res + elif im(ndir).is_positive: + if arg0.is_negative: + return -pi - res + else: + return self.rewrite(log)._eval_nseries(x, n, logx=logx, cdir=cdir) + return res + + def _eval_rewrite_as_log(self, arg, **kwargs): + return -S.ImaginaryUnit*log(S.ImaginaryUnit/arg + sqrt(1 - 1/arg**2)) + + _eval_rewrite_as_tractable = _eval_rewrite_as_log + + def _eval_rewrite_as_asin(self, arg, **kwargs): + return asin(1/arg) + + def _eval_rewrite_as_acos(self, arg, **kwargs): + return pi/2 - acos(1/arg) + + def _eval_rewrite_as_atan(self, x, **kwargs): + return sqrt(x**2)/x*(pi/2 - atan(sqrt(x**2 - 1))) + + def _eval_rewrite_as_acot(self, arg, **kwargs): + return sqrt(arg**2)/arg*(pi/2 - acot(1/sqrt(arg**2 - 1))) + + def _eval_rewrite_as_asec(self, arg, **kwargs): + return pi/2 - asec(arg) + + +class atan2(InverseTrigonometricFunction): + r""" + The function ``atan2(y, x)`` computes `\operatorname{atan}(y/x)` taking + two arguments `y` and `x`. Signs of both `y` and `x` are considered to + determine the appropriate quadrant of `\operatorname{atan}(y/x)`. + The range is `(-\pi, \pi]`. The complete definition reads as follows: + + .. math:: + + \operatorname{atan2}(y, x) = + \begin{cases} + \arctan\left(\frac y x\right) & \qquad x > 0 \\ + \arctan\left(\frac y x\right) + \pi& \qquad y \ge 0, x < 0 \\ + \arctan\left(\frac y x\right) - \pi& \qquad y < 0, x < 0 \\ + +\frac{\pi}{2} & \qquad y > 0, x = 0 \\ + -\frac{\pi}{2} & \qquad y < 0, x = 0 \\ + \text{undefined} & \qquad y = 0, x = 0 + \end{cases} + + Attention: Note the role reversal of both arguments. The `y`-coordinate + is the first argument and the `x`-coordinate the second. + + If either `x` or `y` is complex: + + .. math:: + + \operatorname{atan2}(y, x) = + -i\log\left(\frac{x + iy}{\sqrt{x^2 + y^2}}\right) + + Examples + ======== + + Going counter-clock wise around the origin we find the + following angles: + + >>> from sympy import atan2 + >>> atan2(0, 1) + 0 + >>> atan2(1, 1) + pi/4 + >>> atan2(1, 0) + pi/2 + >>> atan2(1, -1) + 3*pi/4 + >>> atan2(0, -1) + pi + >>> atan2(-1, -1) + -3*pi/4 + >>> atan2(-1, 0) + -pi/2 + >>> atan2(-1, 1) + -pi/4 + + which are all correct. Compare this to the results of the ordinary + `\operatorname{atan}` function for the point `(x, y) = (-1, 1)` + + >>> from sympy import atan, S + >>> atan(S(1)/-1) + -pi/4 + >>> atan2(1, -1) + 3*pi/4 + + where only the `\operatorname{atan2}` function returns what we expect. + We can differentiate the function with respect to both arguments: + + >>> from sympy import diff + >>> from sympy.abc import x, y + >>> diff(atan2(y, x), x) + -y/(x**2 + y**2) + + >>> diff(atan2(y, x), y) + x/(x**2 + y**2) + + We can express the `\operatorname{atan2}` function in terms of + complex logarithms: + + >>> from sympy import log + >>> atan2(y, x).rewrite(log) + -I*log((x + I*y)/sqrt(x**2 + y**2)) + + and in terms of `\operatorname(atan)`: + + >>> from sympy import atan + >>> atan2(y, x).rewrite(atan) + Piecewise((2*atan(y/(x + sqrt(x**2 + y**2))), Ne(y, 0)), (pi, re(x) < 0), (0, Ne(x, 0)), (nan, True)) + + but note that this form is undefined on the negative real axis. + + See Also + ======== + + sin, csc, cos, sec, tan, cot + asin, acsc, acos, asec, atan, acot + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Inverse_trigonometric_functions + .. [2] https://en.wikipedia.org/wiki/Atan2 + .. [3] https://functions.wolfram.com/ElementaryFunctions/ArcTan2 + + """ + + @classmethod + def eval(cls, y, x): + from sympy.functions.special.delta_functions import Heaviside + if x is S.NegativeInfinity: + if y.is_zero: + # Special case y = 0 because we define Heaviside(0) = 1/2 + return pi + return 2*pi*(Heaviside(re(y))) - pi + elif x is S.Infinity: + return S.Zero + elif x.is_imaginary and y.is_imaginary and x.is_number and y.is_number: + x = im(x) + y = im(y) + + if x.is_extended_real and y.is_extended_real: + if x.is_positive: + return atan(y/x) + elif x.is_negative: + if y.is_negative: + return atan(y/x) - pi + elif y.is_nonnegative: + return atan(y/x) + pi + elif x.is_zero: + if y.is_positive: + return pi/2 + elif y.is_negative: + return -pi/2 + elif y.is_zero: + return S.NaN + if y.is_zero: + if x.is_extended_nonzero: + return pi*(S.One - Heaviside(x)) + if x.is_number: + return Piecewise((pi, re(x) < 0), + (0, Ne(x, 0)), + (S.NaN, True)) + if x.is_number and y.is_number: + return -S.ImaginaryUnit*log( + (x + S.ImaginaryUnit*y)/sqrt(x**2 + y**2)) + + def _eval_rewrite_as_log(self, y, x, **kwargs): + return -S.ImaginaryUnit*log((x + S.ImaginaryUnit*y)/sqrt(x**2 + y**2)) + + def _eval_rewrite_as_atan(self, y, x, **kwargs): + return Piecewise((2*atan(y/(x + sqrt(x**2 + y**2))), Ne(y, 0)), + (pi, re(x) < 0), + (0, Ne(x, 0)), + (S.NaN, True)) + + def _eval_rewrite_as_arg(self, y, x, **kwargs): + if x.is_extended_real and y.is_extended_real: + return arg_f(x + y*S.ImaginaryUnit) + n = x + S.ImaginaryUnit*y + d = x**2 + y**2 + return arg_f(n/sqrt(d)) - S.ImaginaryUnit*log(abs(n)/sqrt(abs(d))) + + def _eval_is_extended_real(self): + return self.args[0].is_extended_real and self.args[1].is_extended_real + + def _eval_conjugate(self): + return self.func(self.args[0].conjugate(), self.args[1].conjugate()) + + def fdiff(self, argindex): + y, x = self.args + if argindex == 1: + # Diff wrt y + return x/(x**2 + y**2) + elif argindex == 2: + # Diff wrt x + return -y/(x**2 + y**2) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_evalf(self, prec): + y, x = self.args + if x.is_extended_real and y.is_extended_real: + return super()._eval_evalf(prec) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..ab52ace36a8dfbe73179dbf4419a54f7fa1af5fa --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__init__.py @@ -0,0 +1 @@ +# Stub __init__.py for the sympy.functions.special package diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7427d07014150ec74392388f87ecb02051460b4a Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/beta_functions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/beta_functions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c60f1d450a149ba8c0bde6e23c7bed24bbf61704 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/beta_functions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/bsplines.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/bsplines.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dfee5321b753e0b20c2ce0fa5520a7707fe81368 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/bsplines.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/delta_functions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/delta_functions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2322288612e187d8350e978267221931304cedd7 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/delta_functions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/elliptic_integrals.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/elliptic_integrals.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..84bb6e95f0bd5fbe41ffc84fa275bfd3c50932ac Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/elliptic_integrals.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/gamma_functions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/gamma_functions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d29ce4c8d79bf87a82016809e497c9bc832acf8d Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/gamma_functions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/hyper.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/hyper.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cef57bcb9015f410d899ba2e80e2cf1ec3ecc4f1 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/hyper.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/mathieu_functions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/mathieu_functions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3312f7c7272024be31844e6caf601ffbeec98ecc Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/mathieu_functions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/polynomials.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/polynomials.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7855cea89ec6a6c81076745c64cab4a4555d6d97 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/polynomials.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/singularity_functions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/singularity_functions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9adc8fa60639f320fa34f2269096edf9248bf107 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/singularity_functions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/spherical_harmonics.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/spherical_harmonics.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1701f56403c1fa7aec2b2ab10217cbf23202f09e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/spherical_harmonics.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/tensor_functions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/tensor_functions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..54b0bb5730fed58d1b070cfcf51209df4a2b81d4 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/tensor_functions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/zeta_functions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/zeta_functions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ca935730f0be6c00f264191aaed0850302aad008 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/__pycache__/zeta_functions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/benchmarks/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/benchmarks/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/benchmarks/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/benchmarks/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d37e9115c131d3b104d41dbb346ba23023777865 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/benchmarks/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/benchmarks/__pycache__/bench_special.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/benchmarks/__pycache__/bench_special.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ec4fb20ca84a513bcff0d5304748f72139b14d8e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/benchmarks/__pycache__/bench_special.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/benchmarks/bench_special.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/benchmarks/bench_special.py new file mode 100644 index 0000000000000000000000000000000000000000..25d7280c2cf31dcbff08065a78847ed03e0ebb05 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/benchmarks/bench_special.py @@ -0,0 +1,8 @@ +from sympy.core.symbol import symbols +from sympy.functions.special.spherical_harmonics import Ynm + +x, y = symbols('x,y') + + +def timeit_Ynm_xy(): + Ynm(1, 1, x, y) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/bessel.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/bessel.py new file mode 100644 index 0000000000000000000000000000000000000000..a24e7dc442d2a5a9bf7047113fd81b36c6b6ba36 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/bessel.py @@ -0,0 +1,2208 @@ +from functools import wraps + +from sympy.core import S +from sympy.core.add import Add +from sympy.core.cache import cacheit +from sympy.core.expr import Expr +from sympy.core.function import DefinedFunction, ArgumentIndexError, _mexpand +from sympy.core.logic import fuzzy_or, fuzzy_not +from sympy.core.numbers import Rational, pi, I +from sympy.core.power import Pow +from sympy.core.symbol import Dummy, uniquely_named_symbol, Wild +from sympy.core.sympify import sympify +from sympy.functions.combinatorial.factorials import factorial, RisingFactorial +from sympy.functions.elementary.trigonometric import sin, cos, csc, cot +from sympy.functions.elementary.integers import ceiling +from sympy.functions.elementary.exponential import exp, log +from sympy.functions.elementary.miscellaneous import cbrt, sqrt, root +from sympy.functions.elementary.complexes import (Abs, re, im, polar_lift, unpolarify) +from sympy.functions.special.gamma_functions import gamma, digamma, uppergamma +from sympy.functions.special.hyper import hyper +from sympy.polys.orthopolys import spherical_bessel_fn + +from mpmath import mp, workprec + +# TODO +# o Scorer functions G1 and G2 +# o Asymptotic expansions +# These are possible, e.g. for fixed order, but since the bessel type +# functions are oscillatory they are not actually tractable at +# infinity, so this is not particularly useful right now. +# o Nicer series expansions. +# o More rewriting. +# o Add solvers to ode.py (or rather add solvers for the hypergeometric equation). + + +class BesselBase(DefinedFunction): + """ + Abstract base class for Bessel-type functions. + + This class is meant to reduce code duplication. + All Bessel-type functions can 1) be differentiated, with the derivatives + expressed in terms of similar functions, and 2) be rewritten in terms + of other Bessel-type functions. + + Here, Bessel-type functions are assumed to have one complex parameter. + + To use this base class, define class attributes ``_a`` and ``_b`` such that + ``2*F_n' = -_a*F_{n+1} + b*F_{n-1}``. + + """ + + @property + def order(self): + """ The order of the Bessel-type function. """ + return self.args[0] + + @property + def argument(self): + """ The argument of the Bessel-type function. """ + return self.args[1] + + @classmethod + def eval(cls, nu, z): + return + + def fdiff(self, argindex=2): + if argindex != 2: + raise ArgumentIndexError(self, argindex) + return (self._b/2 * self.__class__(self.order - 1, self.argument) - + self._a/2 * self.__class__(self.order + 1, self.argument)) + + def _eval_conjugate(self): + z = self.argument + if z.is_extended_negative is False: + return self.__class__(self.order.conjugate(), z.conjugate()) + + def _eval_is_meromorphic(self, x, a): + nu, z = self.order, self.argument + + if nu.has(x): + return False + if not z._eval_is_meromorphic(x, a): + return None + z0 = z.subs(x, a) + if nu.is_integer: + if isinstance(self, (besselj, besseli, hn1, hn2, jn, yn)) or not nu.is_zero: + return fuzzy_not(z0.is_infinite) + return fuzzy_not(fuzzy_or([z0.is_zero, z0.is_infinite])) + + def _eval_expand_func(self, **hints): + nu, z, f = self.order, self.argument, self.__class__ + if nu.is_real: + if (nu - 1).is_positive: + return (-self._a*self._b*f(nu - 2, z)._eval_expand_func() + + 2*self._a*(nu - 1)*f(nu - 1, z)._eval_expand_func()/z) + elif (nu + 1).is_negative: + return (2*self._b*(nu + 1)*f(nu + 1, z)._eval_expand_func()/z - + self._a*self._b*f(nu + 2, z)._eval_expand_func()) + return self + + def _eval_simplify(self, **kwargs): + from sympy.simplify.simplify import besselsimp + return besselsimp(self) + + +class besselj(BesselBase): + r""" + Bessel function of the first kind. + + Explanation + =========== + + The Bessel $J$ function of order $\nu$ is defined to be the function + satisfying Bessel's differential equation + + .. math :: + z^2 \frac{\mathrm{d}^2 w}{\mathrm{d}z^2} + + z \frac{\mathrm{d}w}{\mathrm{d}z} + (z^2 - \nu^2) w = 0, + + with Laurent expansion + + .. math :: + J_\nu(z) = z^\nu \left(\frac{1}{\Gamma(\nu + 1) 2^\nu} + O(z^2) \right), + + if $\nu$ is not a negative integer. If $\nu=-n \in \mathbb{Z}_{<0}$ + *is* a negative integer, then the definition is + + .. math :: + J_{-n}(z) = (-1)^n J_n(z). + + Examples + ======== + + Create a Bessel function object: + + >>> from sympy import besselj, jn + >>> from sympy.abc import z, n + >>> b = besselj(n, z) + + Differentiate it: + + >>> b.diff(z) + besselj(n - 1, z)/2 - besselj(n + 1, z)/2 + + Rewrite in terms of spherical Bessel functions: + + >>> b.rewrite(jn) + sqrt(2)*sqrt(z)*jn(n - 1/2, z)/sqrt(pi) + + Access the parameter and argument: + + >>> b.order + n + >>> b.argument + z + + See Also + ======== + + bessely, besseli, besselk + + References + ========== + + .. [1] Abramowitz, Milton; Stegun, Irene A., eds. (1965), "Chapter 9", + Handbook of Mathematical Functions with Formulas, Graphs, and + Mathematical Tables + .. [2] Luke, Y. L. (1969), The Special Functions and Their + Approximations, Volume 1 + .. [3] https://en.wikipedia.org/wiki/Bessel_function + .. [4] https://functions.wolfram.com/Bessel-TypeFunctions/BesselJ/ + + """ + + _a = S.One + _b = S.One + + @classmethod + def eval(cls, nu, z): + if z.is_zero: + if nu.is_zero: + return S.One + elif (nu.is_integer and nu.is_zero is False) or re(nu).is_positive: + return S.Zero + elif re(nu).is_negative and not (nu.is_integer is True): + return S.ComplexInfinity + elif nu.is_imaginary: + return S.NaN + if z in (S.Infinity, S.NegativeInfinity): + return S.Zero + + if z.could_extract_minus_sign(): + return (z)**nu*(-z)**(-nu)*besselj(nu, -z) + if nu.is_integer: + if nu.could_extract_minus_sign(): + return S.NegativeOne**(-nu)*besselj(-nu, z) + newz = z.extract_multiplicatively(I) + if newz: # NOTE we don't want to change the function if z==0 + return I**(nu)*besseli(nu, newz) + + # branch handling: + if nu.is_integer: + newz = unpolarify(z) + if newz != z: + return besselj(nu, newz) + else: + newz, n = z.extract_branch_factor() + if n != 0: + return exp(2*n*pi*nu*I)*besselj(nu, newz) + nnu = unpolarify(nu) + if nu != nnu: + return besselj(nnu, z) + + def _eval_rewrite_as_besseli(self, nu, z, **kwargs): + return exp(I*pi*nu/2)*besseli(nu, polar_lift(-I)*z) + + def _eval_rewrite_as_bessely(self, nu, z, **kwargs): + if nu.is_integer is False: + return csc(pi*nu)*bessely(-nu, z) - cot(pi*nu)*bessely(nu, z) + + def _eval_rewrite_as_jn(self, nu, z, **kwargs): + return sqrt(2*z/pi)*jn(nu - S.Half, self.argument) + + def _eval_as_leading_term(self, x, logx, cdir): + nu, z = self.args + try: + arg = z.as_leading_term(x) + except NotImplementedError: + return self + c, e = arg.as_coeff_exponent(x) + + if e.is_positive: + return arg**nu/(2**nu*gamma(nu + 1)) + elif e.is_negative: + cdir = 1 if cdir == 0 else cdir + sign = c*cdir**e + if not sign.is_negative: + # Refer Abramowitz and Stegun 1965, p. 364 for more information on + # asymptotic approximation of besselj function. + return sqrt(2)*cos(z - pi*(2*nu + 1)/4)/sqrt(pi*z) + return self + + return super(besselj, self)._eval_as_leading_term(x, logx=logx, cdir=cdir) + + def _eval_is_extended_real(self): + nu, z = self.args + if nu.is_integer and z.is_extended_real: + return True + + def _eval_nseries(self, x, n, logx, cdir=0): + # Refer https://functions.wolfram.com/Bessel-TypeFunctions/BesselJ/06/01/04/01/01/0003/ + # for more information on nseries expansion of besselj function. + from sympy.series.order import Order + nu, z = self.args + + # In case of powers less than 1, number of terms need to be computed + # separately to avoid repeated callings of _eval_nseries with wrong n + try: + _, exp = z.leadterm(x) + except (ValueError, NotImplementedError): + return self + + if exp.is_positive: + newn = ceiling(n/exp) + o = Order(x**n, x) + r = (z/2)._eval_nseries(x, n, logx, cdir).removeO() + if r is S.Zero: + return o + t = (_mexpand(r**2) + o).removeO() + + term = r**nu/gamma(nu + 1) + s = [term] + for k in range(1, (newn + 1)//2): + term *= -t/(k*(nu + k)) + term = (_mexpand(term) + o).removeO() + s.append(term) + return Add(*s) + o + + return super(besselj, self)._eval_nseries(x, n, logx, cdir) + + +class bessely(BesselBase): + r""" + Bessel function of the second kind. + + Explanation + =========== + + The Bessel $Y$ function of order $\nu$ is defined as + + .. math :: + Y_\nu(z) = \lim_{\mu \to \nu} \frac{J_\mu(z) \cos(\pi \mu) + - J_{-\mu}(z)}{\sin(\pi \mu)}, + + where $J_\mu(z)$ is the Bessel function of the first kind. + + It is a solution to Bessel's equation, and linearly independent from + $J_\nu$. + + Examples + ======== + + >>> from sympy import bessely, yn + >>> from sympy.abc import z, n + >>> b = bessely(n, z) + >>> b.diff(z) + bessely(n - 1, z)/2 - bessely(n + 1, z)/2 + >>> b.rewrite(yn) + sqrt(2)*sqrt(z)*yn(n - 1/2, z)/sqrt(pi) + + See Also + ======== + + besselj, besseli, besselk + + References + ========== + + .. [1] https://functions.wolfram.com/Bessel-TypeFunctions/BesselY/ + + """ + + _a = S.One + _b = S.One + + @classmethod + def eval(cls, nu, z): + if z.is_zero: + if nu.is_zero: + return S.NegativeInfinity + elif re(nu).is_zero is False: + return S.ComplexInfinity + elif re(nu).is_zero: + return S.NaN + if z in (S.Infinity, S.NegativeInfinity): + return S.Zero + if z == I*S.Infinity: + return exp(I*pi*(nu + 1)/2) * S.Infinity + if z == I*S.NegativeInfinity: + return exp(-I*pi*(nu + 1)/2) * S.Infinity + + if nu.is_integer: + if nu.could_extract_minus_sign(): + return S.NegativeOne**(-nu)*bessely(-nu, z) + + def _eval_rewrite_as_besselj(self, nu, z, **kwargs): + if nu.is_integer is False: + return csc(pi*nu)*(cos(pi*nu)*besselj(nu, z) - besselj(-nu, z)) + + def _eval_rewrite_as_besseli(self, nu, z, **kwargs): + aj = self._eval_rewrite_as_besselj(*self.args) + if aj: + return aj.rewrite(besseli) + + def _eval_rewrite_as_yn(self, nu, z, **kwargs): + return sqrt(2*z/pi) * yn(nu - S.Half, self.argument) + + def _eval_as_leading_term(self, x, logx, cdir): + nu, z = self.args + try: + arg = z.as_leading_term(x) + except NotImplementedError: + return self + c, e = arg.as_coeff_exponent(x) + + if e.is_positive: + term_one = ((2/pi)*log(z/2)*besselj(nu, z)) + term_two = -(z/2)**(-nu)*factorial(nu - 1)/pi if (nu).is_positive else S.Zero + term_three = -(z/2)**nu/(pi*factorial(nu))*(digamma(nu + 1) - S.EulerGamma) + arg = Add(*[term_one, term_two, term_three]).as_leading_term(x, logx=logx) + return arg + elif e.is_negative: + cdir = 1 if cdir == 0 else cdir + sign = c*cdir**e + if not sign.is_negative: + # Refer Abramowitz and Stegun 1965, p. 364 for more information on + # asymptotic approximation of bessely function. + return sqrt(2)*(-sin(pi*nu/2 - z + pi/4) + 3*cos(pi*nu/2 - z + pi/4)/(8*z))*sqrt(1/z)/sqrt(pi) + return self + + return super(bessely, self)._eval_as_leading_term(x, logx=logx, cdir=cdir) + + def _eval_is_extended_real(self): + nu, z = self.args + if nu.is_integer and z.is_positive: + return True + + def _eval_nseries(self, x, n, logx, cdir=0): + # Refer https://functions.wolfram.com/Bessel-TypeFunctions/BesselY/06/01/04/01/02/0008/ + # for more information on nseries expansion of bessely function. + from sympy.series.order import Order + nu, z = self.args + + # In case of powers less than 1, number of terms need to be computed + # separately to avoid repeated callings of _eval_nseries with wrong n + try: + _, exp = z.leadterm(x) + except (ValueError, NotImplementedError): + return self + + if exp.is_positive and nu.is_integer: + newn = ceiling(n/exp) + bn = besselj(nu, z) + a = ((2/pi)*log(z/2)*bn)._eval_nseries(x, n, logx, cdir) + + b, c = [], [] + o = Order(x**n, x) + r = (z/2)._eval_nseries(x, n, logx, cdir).removeO() + if r is S.Zero: + return o + t = (_mexpand(r**2) + o).removeO() + + if nu > S.Zero: + term = r**(-nu)*factorial(nu - 1)/pi + b.append(term) + for k in range(1, nu): + denom = (nu - k)*k + if denom == S.Zero: + term *= t/k + else: + term *= t/denom + term = (_mexpand(term) + o).removeO() + b.append(term) + + p = r**nu/(pi*factorial(nu)) + term = p*(digamma(nu + 1) - S.EulerGamma) + c.append(term) + for k in range(1, (newn + 1)//2): + p *= -t/(k*(k + nu)) + p = (_mexpand(p) + o).removeO() + term = p*(digamma(k + nu + 1) + digamma(k + 1)) + c.append(term) + return a - Add(*b) - Add(*c) # Order term comes from a + + return super(bessely, self)._eval_nseries(x, n, logx, cdir) + + +class besseli(BesselBase): + r""" + Modified Bessel function of the first kind. + + Explanation + =========== + + The Bessel $I$ function is a solution to the modified Bessel equation + + .. math :: + z^2 \frac{\mathrm{d}^2 w}{\mathrm{d}z^2} + + z \frac{\mathrm{d}w}{\mathrm{d}z} + (z^2 + \nu^2)^2 w = 0. + + It can be defined as + + .. math :: + I_\nu(z) = i^{-\nu} J_\nu(iz), + + where $J_\nu(z)$ is the Bessel function of the first kind. + + Examples + ======== + + >>> from sympy import besseli + >>> from sympy.abc import z, n + >>> besseli(n, z).diff(z) + besseli(n - 1, z)/2 + besseli(n + 1, z)/2 + + See Also + ======== + + besselj, bessely, besselk + + References + ========== + + .. [1] https://functions.wolfram.com/Bessel-TypeFunctions/BesselI/ + + """ + + _a = -S.One + _b = S.One + + @classmethod + def eval(cls, nu, z): + if z.is_zero: + if nu.is_zero: + return S.One + elif (nu.is_integer and nu.is_zero is False) or re(nu).is_positive: + return S.Zero + elif re(nu).is_negative and not (nu.is_integer is True): + return S.ComplexInfinity + elif nu.is_imaginary: + return S.NaN + if im(z) in (S.Infinity, S.NegativeInfinity): + return S.Zero + if z is S.Infinity: + return S.Infinity + if z is S.NegativeInfinity: + return (-1)**nu*S.Infinity + + if z.could_extract_minus_sign(): + return (z)**nu*(-z)**(-nu)*besseli(nu, -z) + if nu.is_integer: + if nu.could_extract_minus_sign(): + return besseli(-nu, z) + newz = z.extract_multiplicatively(I) + if newz: # NOTE we don't want to change the function if z==0 + return I**(-nu)*besselj(nu, -newz) + + # branch handling: + if nu.is_integer: + newz = unpolarify(z) + if newz != z: + return besseli(nu, newz) + else: + newz, n = z.extract_branch_factor() + if n != 0: + return exp(2*n*pi*nu*I)*besseli(nu, newz) + nnu = unpolarify(nu) + if nu != nnu: + return besseli(nnu, z) + + def _eval_rewrite_as_tractable(self, nu, z, limitvar=None, **kwargs): + if z.is_extended_real: + return exp(z)*_besseli(nu, z) + + def _eval_rewrite_as_besselj(self, nu, z, **kwargs): + return exp(-I*pi*nu/2)*besselj(nu, polar_lift(I)*z) + + def _eval_rewrite_as_bessely(self, nu, z, **kwargs): + aj = self._eval_rewrite_as_besselj(*self.args) + if aj: + return aj.rewrite(bessely) + + def _eval_rewrite_as_jn(self, nu, z, **kwargs): + return self._eval_rewrite_as_besselj(*self.args).rewrite(jn) + + def _eval_is_extended_real(self): + nu, z = self.args + if nu.is_integer and z.is_extended_real: + return True + + def _eval_as_leading_term(self, x, logx, cdir): + nu, z = self.args + try: + arg = z.as_leading_term(x) + except NotImplementedError: + return self + c, e = arg.as_coeff_exponent(x) + + if e.is_positive: + return arg**nu/(2**nu*gamma(nu + 1)) + elif e.is_negative: + cdir = 1 if cdir == 0 else cdir + sign = c*cdir**e + if not sign.is_negative: + # Refer Abramowitz and Stegun 1965, p. 377 for more information on + # asymptotic approximation of besseli function. + return exp(z)/sqrt(2*pi*z) + return self + + return super(besseli, self)._eval_as_leading_term(x, logx=logx, cdir=cdir) + + def _eval_nseries(self, x, n, logx, cdir=0): + # Refer https://functions.wolfram.com/Bessel-TypeFunctions/BesselI/06/01/04/01/01/0003/ + # for more information on nseries expansion of besseli function. + from sympy.series.order import Order + nu, z = self.args + + # In case of powers less than 1, number of terms need to be computed + # separately to avoid repeated callings of _eval_nseries with wrong n + try: + _, exp = z.leadterm(x) + except (ValueError, NotImplementedError): + return self + + if exp.is_positive: + newn = ceiling(n/exp) + o = Order(x**n, x) + r = (z/2)._eval_nseries(x, n, logx, cdir).removeO() + if r is S.Zero: + return o + t = (_mexpand(r**2) + o).removeO() + + term = r**nu/gamma(nu + 1) + s = [term] + for k in range(1, (newn + 1)//2): + term *= t/(k*(nu + k)) + term = (_mexpand(term) + o).removeO() + s.append(term) + return Add(*s) + o + + return super(besseli, self)._eval_nseries(x, n, logx, cdir) + + def _eval_aseries(self, n, args0, x, logx): + from sympy.functions.combinatorial.factorials import RisingFactorial + from sympy.series.order import Order + point = args0[1] + + if point in [S.Infinity, S.NegativeInfinity]: + nu, z = self.args + s = [(RisingFactorial(Rational(2*nu - 1, 2), k)*RisingFactorial(Rational(2*nu + 1, 2), k))/\ + ((2)**(k)*z**(Rational(2*k + 1, 2))*factorial(k)) for k in range(n)] + [Order(1/z**(Rational(2*n + 1, 2)), x)] + return exp(z)/sqrt(2*pi) * (Add(*s)) + + return super()._eval_aseries(n, args0, x, logx) + + +class besselk(BesselBase): + r""" + Modified Bessel function of the second kind. + + Explanation + =========== + + The Bessel $K$ function of order $\nu$ is defined as + + .. math :: + K_\nu(z) = \lim_{\mu \to \nu} \frac{\pi}{2} + \frac{I_{-\mu}(z) -I_\mu(z)}{\sin(\pi \mu)}, + + where $I_\mu(z)$ is the modified Bessel function of the first kind. + + It is a solution of the modified Bessel equation, and linearly independent + from $Y_\nu$. + + Examples + ======== + + >>> from sympy import besselk + >>> from sympy.abc import z, n + >>> besselk(n, z).diff(z) + -besselk(n - 1, z)/2 - besselk(n + 1, z)/2 + + See Also + ======== + + besselj, besseli, bessely + + References + ========== + + .. [1] https://functions.wolfram.com/Bessel-TypeFunctions/BesselK/ + + """ + + _a = S.One + _b = -S.One + + @classmethod + def eval(cls, nu, z): + if z.is_zero: + if nu.is_zero: + return S.Infinity + elif re(nu).is_zero is False: + return S.ComplexInfinity + elif re(nu).is_zero: + return S.NaN + if z in (S.Infinity, I*S.Infinity, I*S.NegativeInfinity): + return S.Zero + + if nu.is_integer: + if nu.could_extract_minus_sign(): + return besselk(-nu, z) + + def _eval_rewrite_as_besseli(self, nu, z, **kwargs): + if nu.is_integer is False: + return pi*csc(pi*nu)*(besseli(-nu, z) - besseli(nu, z))/2 + + def _eval_rewrite_as_besselj(self, nu, z, **kwargs): + ai = self._eval_rewrite_as_besseli(*self.args) + if ai: + return ai.rewrite(besselj) + + def _eval_rewrite_as_bessely(self, nu, z, **kwargs): + aj = self._eval_rewrite_as_besselj(*self.args) + if aj: + return aj.rewrite(bessely) + + def _eval_rewrite_as_yn(self, nu, z, **kwargs): + ay = self._eval_rewrite_as_bessely(*self.args) + if ay: + return ay.rewrite(yn) + + def _eval_is_extended_real(self): + nu, z = self.args + if nu.is_integer and z.is_positive: + return True + + def _eval_rewrite_as_tractable(self, nu, z, limitvar=None, **kwargs): + if z.is_extended_real: + return exp(-z)*_besselk(nu, z) + + def _eval_as_leading_term(self, x, logx, cdir): + nu, z = self.args + try: + arg = z.as_leading_term(x) + except NotImplementedError: + return self + _, e = arg.as_coeff_exponent(x) + + if e.is_positive: + if nu.is_zero: + # Equation 9.6.8 of Abramowitz and Stegun (10th ed, 1972). + term = -log(z) - S.EulerGamma + log(2) + elif nu.is_nonzero: + # Equation 9.6.9 of Abramowitz and Stegun (10th ed, 1972). + term = gamma(Abs(nu))*(z/2)**(-Abs(nu))/2 + else: + raise NotImplementedError(f"Cannot proceed without knowing if {nu} is zero or not.") + + return term.as_leading_term(x, logx=logx) + elif e.is_negative: + # Equation 9.7.2 of Abramowitz and Stegun (10th ed, 1972). + return sqrt(pi)*exp(-arg)/sqrt(2*arg) + else: + return self.func(nu, arg) + + def _eval_nseries(self, x, n, logx, cdir=0): + from sympy.series.order import Order + nu, z = self.args + + try: + _, exp = z.leadterm(x) + except (ValueError, NotImplementedError): + return self + + # In case of powers less than 1, number of terms need to be computed + # separately to avoid repeated callings of _eval_nseries with wrong n + if exp.is_positive: + r = (z/2)._eval_nseries(x, n, logx, cdir).removeO() + if r is S.Zero: + return Order(z**(-nu) + z**nu, x) + + o = Order(x**n, x) + if nu.is_integer: + # Reference: https://functions.wolfram.com/Bessel-TypeFunctions/BesselK/06/01/04/01/02/0008/ (only for integer order) + newn = ceiling(n/exp) + bn = besseli(nu, z) + a = ((-1)**(nu - 1)*log(z/2)*bn)._eval_nseries(x, n, logx, cdir) + + b, c = [], [] + t = _mexpand(r**2) + + if nu > S.Zero: + term = r**(-nu)*factorial(nu - 1)/2 + b.append(term) + for k in range(1, nu): + term *= t/((k - nu)*k) + term = (_mexpand(term) + o).removeO() + b.append(term) + + p = r**nu*(-1)**nu/(2*factorial(nu)) + term = p*(digamma(nu + 1) - S.EulerGamma) + c.append(term) + for k in range(1, (newn + 1)//2): + p *= t/(k*(k + nu)) + p = (_mexpand(p) + o).removeO() + term = p*(digamma(k + nu + 1) + digamma(k + 1)) + c.append(term) + return a + Add(*b) + Add(*c) + o + elif nu.is_noninteger: + # Reference: https://functions.wolfram.com/Bessel-TypeFunctions/BesselK/06/01/04/01/01/0003/ + # (only for non-integer order). + # While the expression in the reference above seems correct + # for non-real order as well, it would need some manipulation + # (not implemented) to be written as a power series in x with + # real exponents [e.g. Dunster 1990. "Bessel functions + # of purely imaginary order, with an application to second-order + # linear differential equations having a large parameter". + # SIAM J. Math. Anal. Vol 21, No. 4, pp 995-1018.]. + newn_a = ceiling((n+nu)/exp) + newn_b = ceiling((n-nu)/exp) + + a, b = [], [] + for k in range((newn_a+1)//2): + term = gamma(nu)*r**(2*k-nu)/(2*RisingFactorial(1-nu, k)*factorial(k)) + a.append(_mexpand(term)) + for k in range((newn_b+1)//2): + term = gamma(-nu)*r**(2*k+nu)/(2*RisingFactorial(nu+1, k)*factorial(k)) + b.append(_mexpand(term)) + return Add(*a) + Add(*b) + o + else: + raise NotImplementedError("besselk expansion is only implemented for real order") + + return super(besselk, self)._eval_nseries(x, n, logx, cdir) + + def _eval_aseries(self, n, args0, x, logx): + from sympy.functions.combinatorial.factorials import RisingFactorial + from sympy.series.order import Order + point = args0[1] + + if point in [S.Infinity, S.NegativeInfinity]: + nu, z = self.args + s = [(RisingFactorial(Rational(2*nu - 1, 2), k)*RisingFactorial(Rational(2*nu + 1, 2), k))/\ + ((-2)**(k)*z**(Rational(2*k + 1, 2))*factorial(k)) for k in range(n)] +[Order(1/z**(Rational(2*n + 1, 2)), x)] + return (exp(-z)*sqrt(pi/2))*Add(*s) + + return super()._eval_aseries(n, args0, x, logx) + + +class hankel1(BesselBase): + r""" + Hankel function of the first kind. + + Explanation + =========== + + This function is defined as + + .. math :: + H_\nu^{(1)} = J_\nu(z) + iY_\nu(z), + + where $J_\nu(z)$ is the Bessel function of the first kind, and + $Y_\nu(z)$ is the Bessel function of the second kind. + + It is a solution to Bessel's equation. + + Examples + ======== + + >>> from sympy import hankel1 + >>> from sympy.abc import z, n + >>> hankel1(n, z).diff(z) + hankel1(n - 1, z)/2 - hankel1(n + 1, z)/2 + + See Also + ======== + + hankel2, besselj, bessely + + References + ========== + + .. [1] https://functions.wolfram.com/Bessel-TypeFunctions/HankelH1/ + + """ + + _a = S.One + _b = S.One + + def _eval_conjugate(self): + z = self.argument + if z.is_extended_negative is False: + return hankel2(self.order.conjugate(), z.conjugate()) + + +class hankel2(BesselBase): + r""" + Hankel function of the second kind. + + Explanation + =========== + + This function is defined as + + .. math :: + H_\nu^{(2)} = J_\nu(z) - iY_\nu(z), + + where $J_\nu(z)$ is the Bessel function of the first kind, and + $Y_\nu(z)$ is the Bessel function of the second kind. + + It is a solution to Bessel's equation, and linearly independent from + $H_\nu^{(1)}$. + + Examples + ======== + + >>> from sympy import hankel2 + >>> from sympy.abc import z, n + >>> hankel2(n, z).diff(z) + hankel2(n - 1, z)/2 - hankel2(n + 1, z)/2 + + See Also + ======== + + hankel1, besselj, bessely + + References + ========== + + .. [1] https://functions.wolfram.com/Bessel-TypeFunctions/HankelH2/ + + """ + + _a = S.One + _b = S.One + + def _eval_conjugate(self): + z = self.argument + if z.is_extended_negative is False: + return hankel1(self.order.conjugate(), z.conjugate()) + + +def assume_integer_order(fn): + @wraps(fn) + def g(self, nu, z): + if nu.is_integer: + return fn(self, nu, z) + return g + + +class SphericalBesselBase(BesselBase): + """ + Base class for spherical Bessel functions. + + These are thin wrappers around ordinary Bessel functions, + since spherical Bessel functions differ from the ordinary + ones just by a slight change in order. + + To use this class, define the ``_eval_evalf()`` and ``_expand()`` methods. + + """ + + def _expand(self, **hints): + """ Expand self into a polynomial. Nu is guaranteed to be Integer. """ + raise NotImplementedError('expansion') + + def _eval_expand_func(self, **hints): + if self.order.is_Integer: + return self._expand(**hints) + return self + + def fdiff(self, argindex=2): + if argindex != 2: + raise ArgumentIndexError(self, argindex) + return self.__class__(self.order - 1, self.argument) - \ + self * (self.order + 1)/self.argument + + +def _jn(n, z): + return (spherical_bessel_fn(n, z)*sin(z) + + S.NegativeOne**(n + 1)*spherical_bessel_fn(-n - 1, z)*cos(z)) + + +def _yn(n, z): + # (-1)**(n + 1) * _jn(-n - 1, z) + return (S.NegativeOne**(n + 1) * spherical_bessel_fn(-n - 1, z)*sin(z) - + spherical_bessel_fn(n, z)*cos(z)) + + +class jn(SphericalBesselBase): + r""" + Spherical Bessel function of the first kind. + + Explanation + =========== + + This function is a solution to the spherical Bessel equation + + .. math :: + z^2 \frac{\mathrm{d}^2 w}{\mathrm{d}z^2} + + 2z \frac{\mathrm{d}w}{\mathrm{d}z} + (z^2 - \nu(\nu + 1)) w = 0. + + It can be defined as + + .. math :: + j_\nu(z) = \sqrt{\frac{\pi}{2z}} J_{\nu + \frac{1}{2}}(z), + + where $J_\nu(z)$ is the Bessel function of the first kind. + + The spherical Bessel functions of integral order are + calculated using the formula: + + .. math:: j_n(z) = f_n(z) \sin{z} + (-1)^{n+1} f_{-n-1}(z) \cos{z}, + + where the coefficients $f_n(z)$ are available as + :func:`sympy.polys.orthopolys.spherical_bessel_fn`. + + Examples + ======== + + >>> from sympy import Symbol, jn, sin, cos, expand_func, besselj, bessely + >>> z = Symbol("z") + >>> nu = Symbol("nu", integer=True) + >>> print(expand_func(jn(0, z))) + sin(z)/z + >>> expand_func(jn(1, z)) == sin(z)/z**2 - cos(z)/z + True + >>> expand_func(jn(3, z)) + (-6/z**2 + 15/z**4)*sin(z) + (1/z - 15/z**3)*cos(z) + >>> jn(nu, z).rewrite(besselj) + sqrt(2)*sqrt(pi)*sqrt(1/z)*besselj(nu + 1/2, z)/2 + >>> jn(nu, z).rewrite(bessely) + (-1)**nu*sqrt(2)*sqrt(pi)*sqrt(1/z)*bessely(-nu - 1/2, z)/2 + >>> jn(2, 5.2+0.3j).evalf(20) + 0.099419756723640344491 - 0.054525080242173562897*I + + See Also + ======== + + besselj, bessely, besselk, yn + + References + ========== + + .. [1] https://dlmf.nist.gov/10.47 + + """ + @classmethod + def eval(cls, nu, z): + if z.is_zero: + if nu.is_zero: + return S.One + elif nu.is_integer: + if nu.is_positive: + return S.Zero + else: + return S.ComplexInfinity + if z in (S.NegativeInfinity, S.Infinity): + return S.Zero + + def _eval_rewrite_as_besselj(self, nu, z, **kwargs): + return sqrt(pi/(2*z)) * besselj(nu + S.Half, z) + + def _eval_rewrite_as_bessely(self, nu, z, **kwargs): + return S.NegativeOne**nu * sqrt(pi/(2*z)) * bessely(-nu - S.Half, z) + + def _eval_rewrite_as_yn(self, nu, z, **kwargs): + return S.NegativeOne**(nu) * yn(-nu - 1, z) + + def _expand(self, **hints): + return _jn(self.order, self.argument) + + def _eval_evalf(self, prec): + if self.order.is_Integer: + return self.rewrite(besselj)._eval_evalf(prec) + + +class yn(SphericalBesselBase): + r""" + Spherical Bessel function of the second kind. + + Explanation + =========== + + This function is another solution to the spherical Bessel equation, and + linearly independent from $j_n$. It can be defined as + + .. math :: + y_\nu(z) = \sqrt{\frac{\pi}{2z}} Y_{\nu + \frac{1}{2}}(z), + + where $Y_\nu(z)$ is the Bessel function of the second kind. + + For integral orders $n$, $y_n$ is calculated using the formula: + + .. math:: y_n(z) = (-1)^{n+1} j_{-n-1}(z) + + Examples + ======== + + >>> from sympy import Symbol, yn, sin, cos, expand_func, besselj, bessely + >>> z = Symbol("z") + >>> nu = Symbol("nu", integer=True) + >>> print(expand_func(yn(0, z))) + -cos(z)/z + >>> expand_func(yn(1, z)) == -cos(z)/z**2-sin(z)/z + True + >>> yn(nu, z).rewrite(besselj) + (-1)**(nu + 1)*sqrt(2)*sqrt(pi)*sqrt(1/z)*besselj(-nu - 1/2, z)/2 + >>> yn(nu, z).rewrite(bessely) + sqrt(2)*sqrt(pi)*sqrt(1/z)*bessely(nu + 1/2, z)/2 + >>> yn(2, 5.2+0.3j).evalf(20) + 0.18525034196069722536 + 0.014895573969924817587*I + + See Also + ======== + + besselj, bessely, besselk, jn + + References + ========== + + .. [1] https://dlmf.nist.gov/10.47 + + """ + @assume_integer_order + def _eval_rewrite_as_besselj(self, nu, z, **kwargs): + return S.NegativeOne**(nu+1) * sqrt(pi/(2*z)) * besselj(-nu - S.Half, z) + + @assume_integer_order + def _eval_rewrite_as_bessely(self, nu, z, **kwargs): + return sqrt(pi/(2*z)) * bessely(nu + S.Half, z) + + def _eval_rewrite_as_jn(self, nu, z, **kwargs): + return S.NegativeOne**(nu + 1) * jn(-nu - 1, z) + + def _expand(self, **hints): + return _yn(self.order, self.argument) + + def _eval_evalf(self, prec): + if self.order.is_Integer: + return self.rewrite(bessely)._eval_evalf(prec) + + +class SphericalHankelBase(SphericalBesselBase): + + @assume_integer_order + def _eval_rewrite_as_besselj(self, nu, z, **kwargs): + # jn +- I*yn + # jn as beeselj: sqrt(pi/(2*z)) * besselj(nu + S.Half, z) + # yn as besselj: (-1)**(nu+1) * sqrt(pi/(2*z)) * besselj(-nu - S.Half, z) + hks = self._hankel_kind_sign + return sqrt(pi/(2*z))*(besselj(nu + S.Half, z) + + hks*I*S.NegativeOne**(nu+1)*besselj(-nu - S.Half, z)) + + @assume_integer_order + def _eval_rewrite_as_bessely(self, nu, z, **kwargs): + # jn +- I*yn + # jn as bessely: (-1)**nu * sqrt(pi/(2*z)) * bessely(-nu - S.Half, z) + # yn as bessely: sqrt(pi/(2*z)) * bessely(nu + S.Half, z) + hks = self._hankel_kind_sign + return sqrt(pi/(2*z))*(S.NegativeOne**nu*bessely(-nu - S.Half, z) + + hks*I*bessely(nu + S.Half, z)) + + def _eval_rewrite_as_yn(self, nu, z, **kwargs): + hks = self._hankel_kind_sign + return jn(nu, z).rewrite(yn) + hks*I*yn(nu, z) + + def _eval_rewrite_as_jn(self, nu, z, **kwargs): + hks = self._hankel_kind_sign + return jn(nu, z) + hks*I*yn(nu, z).rewrite(jn) + + def _eval_expand_func(self, **hints): + if self.order.is_Integer: + return self._expand(**hints) + else: + nu = self.order + z = self.argument + hks = self._hankel_kind_sign + return jn(nu, z) + hks*I*yn(nu, z) + + def _expand(self, **hints): + n = self.order + z = self.argument + hks = self._hankel_kind_sign + + # fully expanded version + # return ((fn(n, z) * sin(z) + + # (-1)**(n + 1) * fn(-n - 1, z) * cos(z)) + # jn + # (hks * I * (-1)**(n + 1) * + # (fn(-n - 1, z) * hk * I * sin(z) + + # (-1)**(-n) * fn(n, z) * I * cos(z))) # +-I*yn + # ) + + return (_jn(n, z) + hks*I*_yn(n, z)).expand() + + def _eval_evalf(self, prec): + if self.order.is_Integer: + return self.rewrite(besselj)._eval_evalf(prec) + + +class hn1(SphericalHankelBase): + r""" + Spherical Hankel function of the first kind. + + Explanation + =========== + + This function is defined as + + .. math:: h_\nu^(1)(z) = j_\nu(z) + i y_\nu(z), + + where $j_\nu(z)$ and $y_\nu(z)$ are the spherical + Bessel function of the first and second kinds. + + For integral orders $n$, $h_n^(1)$ is calculated using the formula: + + .. math:: h_n^(1)(z) = j_{n}(z) + i (-1)^{n+1} j_{-n-1}(z) + + Examples + ======== + + >>> from sympy import Symbol, hn1, hankel1, expand_func, yn, jn + >>> z = Symbol("z") + >>> nu = Symbol("nu", integer=True) + >>> print(expand_func(hn1(nu, z))) + jn(nu, z) + I*yn(nu, z) + >>> print(expand_func(hn1(0, z))) + sin(z)/z - I*cos(z)/z + >>> print(expand_func(hn1(1, z))) + -I*sin(z)/z - cos(z)/z + sin(z)/z**2 - I*cos(z)/z**2 + >>> hn1(nu, z).rewrite(jn) + (-1)**(nu + 1)*I*jn(-nu - 1, z) + jn(nu, z) + >>> hn1(nu, z).rewrite(yn) + (-1)**nu*yn(-nu - 1, z) + I*yn(nu, z) + >>> hn1(nu, z).rewrite(hankel1) + sqrt(2)*sqrt(pi)*sqrt(1/z)*hankel1(nu, z)/2 + + See Also + ======== + + hn2, jn, yn, hankel1, hankel2 + + References + ========== + + .. [1] https://dlmf.nist.gov/10.47 + + """ + + _hankel_kind_sign = S.One + + @assume_integer_order + def _eval_rewrite_as_hankel1(self, nu, z, **kwargs): + return sqrt(pi/(2*z))*hankel1(nu, z) + + +class hn2(SphericalHankelBase): + r""" + Spherical Hankel function of the second kind. + + Explanation + =========== + + This function is defined as + + .. math:: h_\nu^(2)(z) = j_\nu(z) - i y_\nu(z), + + where $j_\nu(z)$ and $y_\nu(z)$ are the spherical + Bessel function of the first and second kinds. + + For integral orders $n$, $h_n^(2)$ is calculated using the formula: + + .. math:: h_n^(2)(z) = j_{n} - i (-1)^{n+1} j_{-n-1}(z) + + Examples + ======== + + >>> from sympy import Symbol, hn2, hankel2, expand_func, jn, yn + >>> z = Symbol("z") + >>> nu = Symbol("nu", integer=True) + >>> print(expand_func(hn2(nu, z))) + jn(nu, z) - I*yn(nu, z) + >>> print(expand_func(hn2(0, z))) + sin(z)/z + I*cos(z)/z + >>> print(expand_func(hn2(1, z))) + I*sin(z)/z - cos(z)/z + sin(z)/z**2 + I*cos(z)/z**2 + >>> hn2(nu, z).rewrite(hankel2) + sqrt(2)*sqrt(pi)*sqrt(1/z)*hankel2(nu, z)/2 + >>> hn2(nu, z).rewrite(jn) + -(-1)**(nu + 1)*I*jn(-nu - 1, z) + jn(nu, z) + >>> hn2(nu, z).rewrite(yn) + (-1)**nu*yn(-nu - 1, z) - I*yn(nu, z) + + See Also + ======== + + hn1, jn, yn, hankel1, hankel2 + + References + ========== + + .. [1] https://dlmf.nist.gov/10.47 + + """ + + _hankel_kind_sign = -S.One + + @assume_integer_order + def _eval_rewrite_as_hankel2(self, nu, z, **kwargs): + return sqrt(pi/(2*z))*hankel2(nu, z) + + +def jn_zeros(n, k, method="sympy", dps=15): + """ + Zeros of the spherical Bessel function of the first kind. + + Explanation + =========== + + This returns an array of zeros of $jn$ up to the $k$-th zero. + + * method = "sympy": uses `mpmath.besseljzero + `_ + * method = "scipy": uses the + `SciPy's sph_jn `_ + and + `newton `_ + to find all + roots, which is faster than computing the zeros using a general + numerical solver, but it requires SciPy and only works with low + precision floating point numbers. (The function used with + method="sympy" is a recent addition to mpmath; before that a general + solver was used.) + + Examples + ======== + + >>> from sympy import jn_zeros + >>> jn_zeros(2, 4, dps=5) + [5.7635, 9.095, 12.323, 15.515] + + See Also + ======== + + jn, yn, besselj, besselk, bessely + + Parameters + ========== + + n : integer + order of Bessel function + + k : integer + number of zeros to return + + + """ + from math import pi as math_pi + + if method == "sympy": + from mpmath import besseljzero + from mpmath.libmp.libmpf import dps_to_prec + prec = dps_to_prec(dps) + return [Expr._from_mpmath(besseljzero(S(n + 0.5)._to_mpmath(prec), + int(l)), prec) + for l in range(1, k + 1)] + elif method == "scipy": + from scipy.optimize import newton + try: + from scipy.special import spherical_jn + f = lambda x: spherical_jn(n, x) + except ImportError: + from scipy.special import sph_jn + f = lambda x: sph_jn(n, x)[0][-1] + else: + raise NotImplementedError("Unknown method.") + + def solver(f, x): + if method == "scipy": + root = newton(f, x) + else: + raise NotImplementedError("Unknown method.") + return root + + # we need to approximate the position of the first root: + root = n + math_pi + # determine the first root exactly: + root = solver(f, root) + roots = [root] + for i in range(k - 1): + # estimate the position of the next root using the last root + pi: + root = solver(f, root + math_pi) + roots.append(root) + return roots + + +class AiryBase(DefinedFunction): + """ + Abstract base class for Airy functions. + + This class is meant to reduce code duplication. + + """ + + def _eval_conjugate(self): + return self.func(self.args[0].conjugate()) + + def _eval_is_extended_real(self): + return self.args[0].is_extended_real + + def as_real_imag(self, deep=True, **hints): + z = self.args[0] + zc = z.conjugate() + f = self.func + u = (f(z)+f(zc))/2 + v = I*(f(zc)-f(z))/2 + return u, v + + def _eval_expand_complex(self, deep=True, **hints): + re_part, im_part = self.as_real_imag(deep=deep, **hints) + return re_part + im_part*I + + +class airyai(AiryBase): + r""" + The Airy function $\operatorname{Ai}$ of the first kind. + + Explanation + =========== + + The Airy function $\operatorname{Ai}(z)$ is defined to be the function + satisfying Airy's differential equation + + .. math:: + \frac{\mathrm{d}^2 w(z)}{\mathrm{d}z^2} - z w(z) = 0. + + Equivalently, for real $z$ + + .. math:: + \operatorname{Ai}(z) := \frac{1}{\pi} + \int_0^\infty \cos\left(\frac{t^3}{3} + z t\right) \mathrm{d}t. + + Examples + ======== + + Create an Airy function object: + + >>> from sympy import airyai + >>> from sympy.abc import z + + >>> airyai(z) + airyai(z) + + Several special values are known: + + >>> airyai(0) + 3**(1/3)/(3*gamma(2/3)) + >>> from sympy import oo + >>> airyai(oo) + 0 + >>> airyai(-oo) + 0 + + The Airy function obeys the mirror symmetry: + + >>> from sympy import conjugate + >>> conjugate(airyai(z)) + airyai(conjugate(z)) + + Differentiation with respect to $z$ is supported: + + >>> from sympy import diff + >>> diff(airyai(z), z) + airyaiprime(z) + >>> diff(airyai(z), z, 2) + z*airyai(z) + + Series expansion is also supported: + + >>> from sympy import series + >>> series(airyai(z), z, 0, 3) + 3**(5/6)*gamma(1/3)/(6*pi) - 3**(1/6)*z*gamma(2/3)/(2*pi) + O(z**3) + + We can numerically evaluate the Airy function to arbitrary precision + on the whole complex plane: + + >>> airyai(-2).evalf(50) + 0.22740742820168557599192443603787379946077222541710 + + Rewrite $\operatorname{Ai}(z)$ in terms of hypergeometric functions: + + >>> from sympy import hyper + >>> airyai(z).rewrite(hyper) + -3**(2/3)*z*hyper((), (4/3,), z**3/9)/(3*gamma(1/3)) + 3**(1/3)*hyper((), (2/3,), z**3/9)/(3*gamma(2/3)) + + See Also + ======== + + airybi: Airy function of the second kind. + airyaiprime: Derivative of the Airy function of the first kind. + airybiprime: Derivative of the Airy function of the second kind. + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Airy_function + .. [2] https://dlmf.nist.gov/9 + .. [3] https://encyclopediaofmath.org/wiki/Airy_functions + .. [4] https://mathworld.wolfram.com/AiryFunctions.html + + """ + + nargs = 1 + unbranched = True + + @classmethod + def eval(cls, arg): + if arg.is_Number: + if arg is S.NaN: + return S.NaN + elif arg is S.Infinity: + return S.Zero + elif arg is S.NegativeInfinity: + return S.Zero + elif arg.is_zero: + return S.One / (3**Rational(2, 3) * gamma(Rational(2, 3))) + if arg.is_zero: + return S.One / (3**Rational(2, 3) * gamma(Rational(2, 3))) + + def fdiff(self, argindex=1): + if argindex == 1: + return airyaiprime(self.args[0]) + else: + raise ArgumentIndexError(self, argindex) + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + if n < 0: + return S.Zero + else: + x = sympify(x) + if len(previous_terms) > 1: + p = previous_terms[-1] + return ((cbrt(3)*x)**(-n)*(cbrt(3)*x)**(n + 1)*sin(pi*(n*Rational(2, 3) + Rational(4, 3)))*factorial(n) * + gamma(n/3 + Rational(2, 3))/(sin(pi*(n*Rational(2, 3) + Rational(2, 3)))*factorial(n + 1)*gamma(n/3 + Rational(1, 3))) * p) + else: + return (S.One/(3**Rational(2, 3)*pi) * gamma((n+S.One)/S(3)) * sin(Rational(2, 3)*pi*(n+S.One)) / + factorial(n) * (cbrt(3)*x)**n) + + def _eval_rewrite_as_besselj(self, z, **kwargs): + ot = Rational(1, 3) + tt = Rational(2, 3) + a = Pow(-z, Rational(3, 2)) + if re(z).is_negative: + return ot*sqrt(-z) * (besselj(-ot, tt*a) + besselj(ot, tt*a)) + + def _eval_rewrite_as_besseli(self, z, **kwargs): + ot = Rational(1, 3) + tt = Rational(2, 3) + a = Pow(z, Rational(3, 2)) + if re(z).is_positive: + return ot*sqrt(z) * (besseli(-ot, tt*a) - besseli(ot, tt*a)) + else: + return ot*(Pow(a, ot)*besseli(-ot, tt*a) - z*Pow(a, -ot)*besseli(ot, tt*a)) + + def _eval_rewrite_as_hyper(self, z, **kwargs): + pf1 = S.One / (3**Rational(2, 3)*gamma(Rational(2, 3))) + pf2 = z / (root(3, 3)*gamma(Rational(1, 3))) + return pf1 * hyper([], [Rational(2, 3)], z**3/9) - pf2 * hyper([], [Rational(4, 3)], z**3/9) + + def _eval_expand_func(self, **hints): + arg = self.args[0] + symbs = arg.free_symbols + + if len(symbs) == 1: + z = symbs.pop() + c = Wild("c", exclude=[z]) + d = Wild("d", exclude=[z]) + m = Wild("m", exclude=[z]) + n = Wild("n", exclude=[z]) + M = arg.match(c*(d*z**n)**m) + if M is not None: + m = M[m] + # The transformation is given by 03.05.16.0001.01 + # https://functions.wolfram.com/Bessel-TypeFunctions/AiryAi/16/01/01/0001/ + if (3*m).is_integer: + c = M[c] + d = M[d] + n = M[n] + pf = (d * z**n)**m / (d**m * z**(m*n)) + newarg = c * d**m * z**(m*n) + return S.Half * ((pf + S.One)*airyai(newarg) - (pf - S.One)/sqrt(3)*airybi(newarg)) + + +class airybi(AiryBase): + r""" + The Airy function $\operatorname{Bi}$ of the second kind. + + Explanation + =========== + + The Airy function $\operatorname{Bi}(z)$ is defined to be the function + satisfying Airy's differential equation + + .. math:: + \frac{\mathrm{d}^2 w(z)}{\mathrm{d}z^2} - z w(z) = 0. + + Equivalently, for real $z$ + + .. math:: + \operatorname{Bi}(z) := \frac{1}{\pi} + \int_0^\infty + \exp\left(-\frac{t^3}{3} + z t\right) + + \sin\left(\frac{t^3}{3} + z t\right) \mathrm{d}t. + + Examples + ======== + + Create an Airy function object: + + >>> from sympy import airybi + >>> from sympy.abc import z + + >>> airybi(z) + airybi(z) + + Several special values are known: + + >>> airybi(0) + 3**(5/6)/(3*gamma(2/3)) + >>> from sympy import oo + >>> airybi(oo) + oo + >>> airybi(-oo) + 0 + + The Airy function obeys the mirror symmetry: + + >>> from sympy import conjugate + >>> conjugate(airybi(z)) + airybi(conjugate(z)) + + Differentiation with respect to $z$ is supported: + + >>> from sympy import diff + >>> diff(airybi(z), z) + airybiprime(z) + >>> diff(airybi(z), z, 2) + z*airybi(z) + + Series expansion is also supported: + + >>> from sympy import series + >>> series(airybi(z), z, 0, 3) + 3**(1/3)*gamma(1/3)/(2*pi) + 3**(2/3)*z*gamma(2/3)/(2*pi) + O(z**3) + + We can numerically evaluate the Airy function to arbitrary precision + on the whole complex plane: + + >>> airybi(-2).evalf(50) + -0.41230258795639848808323405461146104203453483447240 + + Rewrite $\operatorname{Bi}(z)$ in terms of hypergeometric functions: + + >>> from sympy import hyper + >>> airybi(z).rewrite(hyper) + 3**(1/6)*z*hyper((), (4/3,), z**3/9)/gamma(1/3) + 3**(5/6)*hyper((), (2/3,), z**3/9)/(3*gamma(2/3)) + + See Also + ======== + + airyai: Airy function of the first kind. + airyaiprime: Derivative of the Airy function of the first kind. + airybiprime: Derivative of the Airy function of the second kind. + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Airy_function + .. [2] https://dlmf.nist.gov/9 + .. [3] https://encyclopediaofmath.org/wiki/Airy_functions + .. [4] https://mathworld.wolfram.com/AiryFunctions.html + + """ + + nargs = 1 + unbranched = True + + @classmethod + def eval(cls, arg): + if arg.is_Number: + if arg is S.NaN: + return S.NaN + elif arg is S.Infinity: + return S.Infinity + elif arg is S.NegativeInfinity: + return S.Zero + elif arg.is_zero: + return S.One / (3**Rational(1, 6) * gamma(Rational(2, 3))) + + if arg.is_zero: + return S.One / (3**Rational(1, 6) * gamma(Rational(2, 3))) + + def fdiff(self, argindex=1): + if argindex == 1: + return airybiprime(self.args[0]) + else: + raise ArgumentIndexError(self, argindex) + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + if n < 0: + return S.Zero + else: + x = sympify(x) + if len(previous_terms) > 1: + p = previous_terms[-1] + return (cbrt(3)*x * Abs(sin(Rational(2, 3)*pi*(n + S.One))) * factorial((n - S.One)/S(3)) / + ((n + S.One) * Abs(cos(Rational(2, 3)*pi*(n + S.Half))) * factorial((n - 2)/S(3))) * p) + else: + return (S.One/(root(3, 6)*pi) * gamma((n + S.One)/S(3)) * Abs(sin(Rational(2, 3)*pi*(n + S.One))) / + factorial(n) * (cbrt(3)*x)**n) + + def _eval_rewrite_as_besselj(self, z, **kwargs): + ot = Rational(1, 3) + tt = Rational(2, 3) + a = Pow(-z, Rational(3, 2)) + if re(z).is_negative: + return sqrt(-z/3) * (besselj(-ot, tt*a) - besselj(ot, tt*a)) + + def _eval_rewrite_as_besseli(self, z, **kwargs): + ot = Rational(1, 3) + tt = Rational(2, 3) + a = Pow(z, Rational(3, 2)) + if re(z).is_positive: + return sqrt(z)/sqrt(3) * (besseli(-ot, tt*a) + besseli(ot, tt*a)) + else: + b = Pow(a, ot) + c = Pow(a, -ot) + return sqrt(ot)*(b*besseli(-ot, tt*a) + z*c*besseli(ot, tt*a)) + + def _eval_rewrite_as_hyper(self, z, **kwargs): + pf1 = S.One / (root(3, 6)*gamma(Rational(2, 3))) + pf2 = z*root(3, 6) / gamma(Rational(1, 3)) + return pf1 * hyper([], [Rational(2, 3)], z**3/9) + pf2 * hyper([], [Rational(4, 3)], z**3/9) + + def _eval_expand_func(self, **hints): + arg = self.args[0] + symbs = arg.free_symbols + + if len(symbs) == 1: + z = symbs.pop() + c = Wild("c", exclude=[z]) + d = Wild("d", exclude=[z]) + m = Wild("m", exclude=[z]) + n = Wild("n", exclude=[z]) + M = arg.match(c*(d*z**n)**m) + if M is not None: + m = M[m] + # The transformation is given by 03.06.16.0001.01 + # https://functions.wolfram.com/Bessel-TypeFunctions/AiryBi/16/01/01/0001/ + if (3*m).is_integer: + c = M[c] + d = M[d] + n = M[n] + pf = (d * z**n)**m / (d**m * z**(m*n)) + newarg = c * d**m * z**(m*n) + return S.Half * (sqrt(3)*(S.One - pf)*airyai(newarg) + (S.One + pf)*airybi(newarg)) + + +class airyaiprime(AiryBase): + r""" + The derivative $\operatorname{Ai}^\prime$ of the Airy function of the first + kind. + + Explanation + =========== + + The Airy function $\operatorname{Ai}^\prime(z)$ is defined to be the + function + + .. math:: + \operatorname{Ai}^\prime(z) := \frac{\mathrm{d} \operatorname{Ai}(z)}{\mathrm{d} z}. + + Examples + ======== + + Create an Airy function object: + + >>> from sympy import airyaiprime + >>> from sympy.abc import z + + >>> airyaiprime(z) + airyaiprime(z) + + Several special values are known: + + >>> airyaiprime(0) + -3**(2/3)/(3*gamma(1/3)) + >>> from sympy import oo + >>> airyaiprime(oo) + 0 + + The Airy function obeys the mirror symmetry: + + >>> from sympy import conjugate + >>> conjugate(airyaiprime(z)) + airyaiprime(conjugate(z)) + + Differentiation with respect to $z$ is supported: + + >>> from sympy import diff + >>> diff(airyaiprime(z), z) + z*airyai(z) + >>> diff(airyaiprime(z), z, 2) + z*airyaiprime(z) + airyai(z) + + Series expansion is also supported: + + >>> from sympy import series + >>> series(airyaiprime(z), z, 0, 3) + -3**(2/3)/(3*gamma(1/3)) + 3**(1/3)*z**2/(6*gamma(2/3)) + O(z**3) + + We can numerically evaluate the Airy function to arbitrary precision + on the whole complex plane: + + >>> airyaiprime(-2).evalf(50) + 0.61825902074169104140626429133247528291577794512415 + + Rewrite $\operatorname{Ai}^\prime(z)$ in terms of hypergeometric functions: + + >>> from sympy import hyper + >>> airyaiprime(z).rewrite(hyper) + 3**(1/3)*z**2*hyper((), (5/3,), z**3/9)/(6*gamma(2/3)) - 3**(2/3)*hyper((), (1/3,), z**3/9)/(3*gamma(1/3)) + + See Also + ======== + + airyai: Airy function of the first kind. + airybi: Airy function of the second kind. + airybiprime: Derivative of the Airy function of the second kind. + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Airy_function + .. [2] https://dlmf.nist.gov/9 + .. [3] https://encyclopediaofmath.org/wiki/Airy_functions + .. [4] https://mathworld.wolfram.com/AiryFunctions.html + + """ + + nargs = 1 + unbranched = True + + @classmethod + def eval(cls, arg): + if arg.is_Number: + if arg is S.NaN: + return S.NaN + elif arg is S.Infinity: + return S.Zero + + if arg.is_zero: + return S.NegativeOne / (3**Rational(1, 3) * gamma(Rational(1, 3))) + + def fdiff(self, argindex=1): + if argindex == 1: + return self.args[0]*airyai(self.args[0]) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_evalf(self, prec): + z = self.args[0]._to_mpmath(prec) + with workprec(prec): + res = mp.airyai(z, derivative=1) + return Expr._from_mpmath(res, prec) + + def _eval_rewrite_as_besselj(self, z, **kwargs): + tt = Rational(2, 3) + a = Pow(-z, Rational(3, 2)) + if re(z).is_negative: + return z/3 * (besselj(-tt, tt*a) - besselj(tt, tt*a)) + + def _eval_rewrite_as_besseli(self, z, **kwargs): + ot = Rational(1, 3) + tt = Rational(2, 3) + a = tt * Pow(z, Rational(3, 2)) + if re(z).is_positive: + return z/3 * (besseli(tt, a) - besseli(-tt, a)) + else: + a = Pow(z, Rational(3, 2)) + b = Pow(a, tt) + c = Pow(a, -tt) + return ot * (z**2*c*besseli(tt, tt*a) - b*besseli(-ot, tt*a)) + + def _eval_rewrite_as_hyper(self, z, **kwargs): + pf1 = z**2 / (2*3**Rational(2, 3)*gamma(Rational(2, 3))) + pf2 = 1 / (root(3, 3)*gamma(Rational(1, 3))) + return pf1 * hyper([], [Rational(5, 3)], z**3/9) - pf2 * hyper([], [Rational(1, 3)], z**3/9) + + def _eval_expand_func(self, **hints): + arg = self.args[0] + symbs = arg.free_symbols + + if len(symbs) == 1: + z = symbs.pop() + c = Wild("c", exclude=[z]) + d = Wild("d", exclude=[z]) + m = Wild("m", exclude=[z]) + n = Wild("n", exclude=[z]) + M = arg.match(c*(d*z**n)**m) + if M is not None: + m = M[m] + # The transformation is in principle + # given by 03.07.16.0001.01 but note + # that there is an error in this formula. + # https://functions.wolfram.com/Bessel-TypeFunctions/AiryAiPrime/16/01/01/0001/ + if (3*m).is_integer: + c = M[c] + d = M[d] + n = M[n] + pf = (d**m * z**(n*m)) / (d * z**n)**m + newarg = c * d**m * z**(n*m) + return S.Half * ((pf + S.One)*airyaiprime(newarg) + (pf - S.One)/sqrt(3)*airybiprime(newarg)) + + +class airybiprime(AiryBase): + r""" + The derivative $\operatorname{Bi}^\prime$ of the Airy function of the first + kind. + + Explanation + =========== + + The Airy function $\operatorname{Bi}^\prime(z)$ is defined to be the + function + + .. math:: + \operatorname{Bi}^\prime(z) := \frac{\mathrm{d} \operatorname{Bi}(z)}{\mathrm{d} z}. + + Examples + ======== + + Create an Airy function object: + + >>> from sympy import airybiprime + >>> from sympy.abc import z + + >>> airybiprime(z) + airybiprime(z) + + Several special values are known: + + >>> airybiprime(0) + 3**(1/6)/gamma(1/3) + >>> from sympy import oo + >>> airybiprime(oo) + oo + >>> airybiprime(-oo) + 0 + + The Airy function obeys the mirror symmetry: + + >>> from sympy import conjugate + >>> conjugate(airybiprime(z)) + airybiprime(conjugate(z)) + + Differentiation with respect to $z$ is supported: + + >>> from sympy import diff + >>> diff(airybiprime(z), z) + z*airybi(z) + >>> diff(airybiprime(z), z, 2) + z*airybiprime(z) + airybi(z) + + Series expansion is also supported: + + >>> from sympy import series + >>> series(airybiprime(z), z, 0, 3) + 3**(1/6)/gamma(1/3) + 3**(5/6)*z**2/(6*gamma(2/3)) + O(z**3) + + We can numerically evaluate the Airy function to arbitrary precision + on the whole complex plane: + + >>> airybiprime(-2).evalf(50) + 0.27879516692116952268509756941098324140300059345163 + + Rewrite $\operatorname{Bi}^\prime(z)$ in terms of hypergeometric functions: + + >>> from sympy import hyper + >>> airybiprime(z).rewrite(hyper) + 3**(5/6)*z**2*hyper((), (5/3,), z**3/9)/(6*gamma(2/3)) + 3**(1/6)*hyper((), (1/3,), z**3/9)/gamma(1/3) + + See Also + ======== + + airyai: Airy function of the first kind. + airybi: Airy function of the second kind. + airyaiprime: Derivative of the Airy function of the first kind. + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Airy_function + .. [2] https://dlmf.nist.gov/9 + .. [3] https://encyclopediaofmath.org/wiki/Airy_functions + .. [4] https://mathworld.wolfram.com/AiryFunctions.html + + """ + + nargs = 1 + unbranched = True + + @classmethod + def eval(cls, arg): + if arg.is_Number: + if arg is S.NaN: + return S.NaN + elif arg is S.Infinity: + return S.Infinity + elif arg is S.NegativeInfinity: + return S.Zero + elif arg.is_zero: + return 3**Rational(1, 6) / gamma(Rational(1, 3)) + + if arg.is_zero: + return 3**Rational(1, 6) / gamma(Rational(1, 3)) + + + def fdiff(self, argindex=1): + if argindex == 1: + return self.args[0]*airybi(self.args[0]) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_evalf(self, prec): + z = self.args[0]._to_mpmath(prec) + with workprec(prec): + res = mp.airybi(z, derivative=1) + return Expr._from_mpmath(res, prec) + + def _eval_rewrite_as_besselj(self, z, **kwargs): + tt = Rational(2, 3) + a = tt * Pow(-z, Rational(3, 2)) + if re(z).is_negative: + return -z/sqrt(3) * (besselj(-tt, a) + besselj(tt, a)) + + def _eval_rewrite_as_besseli(self, z, **kwargs): + ot = Rational(1, 3) + tt = Rational(2, 3) + a = tt * Pow(z, Rational(3, 2)) + if re(z).is_positive: + return z/sqrt(3) * (besseli(-tt, a) + besseli(tt, a)) + else: + a = Pow(z, Rational(3, 2)) + b = Pow(a, tt) + c = Pow(a, -tt) + return sqrt(ot) * (b*besseli(-tt, tt*a) + z**2*c*besseli(tt, tt*a)) + + def _eval_rewrite_as_hyper(self, z, **kwargs): + pf1 = z**2 / (2*root(3, 6)*gamma(Rational(2, 3))) + pf2 = root(3, 6) / gamma(Rational(1, 3)) + return pf1 * hyper([], [Rational(5, 3)], z**3/9) + pf2 * hyper([], [Rational(1, 3)], z**3/9) + + def _eval_expand_func(self, **hints): + arg = self.args[0] + symbs = arg.free_symbols + + if len(symbs) == 1: + z = symbs.pop() + c = Wild("c", exclude=[z]) + d = Wild("d", exclude=[z]) + m = Wild("m", exclude=[z]) + n = Wild("n", exclude=[z]) + M = arg.match(c*(d*z**n)**m) + if M is not None: + m = M[m] + # The transformation is in principle + # given by 03.08.16.0001.01 but note + # that there is an error in this formula. + # https://functions.wolfram.com/Bessel-TypeFunctions/AiryBiPrime/16/01/01/0001/ + if (3*m).is_integer: + c = M[c] + d = M[d] + n = M[n] + pf = (d**m * z**(n*m)) / (d * z**n)**m + newarg = c * d**m * z**(n*m) + return S.Half * (sqrt(3)*(pf - S.One)*airyaiprime(newarg) + (pf + S.One)*airybiprime(newarg)) + + +class marcumq(DefinedFunction): + r""" + The Marcum Q-function. + + Explanation + =========== + + The Marcum Q-function is defined by the meromorphic continuation of + + .. math:: + Q_m(a, b) = a^{- m + 1} \int_{b}^{\infty} x^{m} e^{- \frac{a^{2}}{2} - \frac{x^{2}}{2}} I_{m - 1}\left(a x\right)\, dx + + Examples + ======== + + >>> from sympy import marcumq + >>> from sympy.abc import m, a, b + >>> marcumq(m, a, b) + marcumq(m, a, b) + + Special values: + + >>> marcumq(m, 0, b) + uppergamma(m, b**2/2)/gamma(m) + >>> marcumq(0, 0, 0) + 0 + >>> marcumq(0, a, 0) + 1 - exp(-a**2/2) + >>> marcumq(1, a, a) + 1/2 + exp(-a**2)*besseli(0, a**2)/2 + >>> marcumq(2, a, a) + 1/2 + exp(-a**2)*besseli(0, a**2)/2 + exp(-a**2)*besseli(1, a**2) + + Differentiation with respect to $a$ and $b$ is supported: + + >>> from sympy import diff + >>> diff(marcumq(m, a, b), a) + a*(-marcumq(m, a, b) + marcumq(m + 1, a, b)) + >>> diff(marcumq(m, a, b), b) + -a**(1 - m)*b**m*exp(-a**2/2 - b**2/2)*besseli(m - 1, a*b) + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Marcum_Q-function + .. [2] https://mathworld.wolfram.com/MarcumQ-Function.html + + """ + + @classmethod + def eval(cls, m, a, b): + if a is S.Zero: + if m is S.Zero and b is S.Zero: + return S.Zero + return uppergamma(m, b**2 * S.Half) / gamma(m) + + if m is S.Zero and b is S.Zero: + return 1 - 1 / exp(a**2 * S.Half) + + if a == b: + if m is S.One: + return (1 + exp(-a**2) * besseli(0, a**2))*S.Half + if m == 2: + return S.Half + S.Half * exp(-a**2) * besseli(0, a**2) + exp(-a**2) * besseli(1, a**2) + + if a.is_zero: + if m.is_zero and b.is_zero: + return S.Zero + return uppergamma(m, b**2*S.Half) / gamma(m) + + if m.is_zero and b.is_zero: + return 1 - 1 / exp(a**2*S.Half) + + def fdiff(self, argindex=2): + m, a, b = self.args + if argindex == 2: + return a * (-marcumq(m, a, b) + marcumq(1+m, a, b)) + elif argindex == 3: + return (-b**m / a**(m-1)) * exp(-(a**2 + b**2)/2) * besseli(m-1, a*b) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_rewrite_as_Integral(self, m, a, b, **kwargs): + from sympy.integrals.integrals import Integral + x = kwargs.get('x', Dummy(uniquely_named_symbol('x').name)) + return a ** (1 - m) * \ + Integral(x**m * exp(-(x**2 + a**2)/2) * besseli(m-1, a*x), [x, b, S.Infinity]) + + def _eval_rewrite_as_Sum(self, m, a, b, **kwargs): + from sympy.concrete.summations import Sum + k = kwargs.get('k', Dummy('k')) + return exp(-(a**2 + b**2) / 2) * Sum((a/b)**k * besseli(k, a*b), [k, 1-m, S.Infinity]) + + def _eval_rewrite_as_besseli(self, m, a, b, **kwargs): + if a == b: + if m == 1: + return (1 + exp(-a**2) * besseli(0, a**2)) / 2 + if m.is_Integer and m >= 2: + s = sum(besseli(i, a**2) for i in range(1, m)) + return S.Half + exp(-a**2) * besseli(0, a**2) / 2 + exp(-a**2) * s + + def _eval_is_zero(self): + if all(arg.is_zero for arg in self.args): + return True + +class _besseli(DefinedFunction): + """ + Helper function to make the $\\mathrm{besseli}(nu, z)$ + function tractable for the Gruntz algorithm. + + """ + + def _eval_aseries(self, n, args0, x, logx): + from sympy.functions.combinatorial.factorials import RisingFactorial + from sympy.series.order import Order + point = args0[1] + + if point in [S.Infinity, S.NegativeInfinity]: + nu, z = self.args + l = [((RisingFactorial(Rational(2*nu - 1, 2), k)*RisingFactorial( + Rational(2*nu + 1, 2), k))/((2)**(k)*z**(Rational(2*k + 1, 2))*factorial(k))) for k in range(n)] + return sqrt(pi/(2))*(Add(*l)) + Order(1/z**(Rational(2*n + 1, 2)), x) + + return super()._eval_aseries(n, args0, x, logx) + + def _eval_rewrite_as_intractable(self, nu, z, **kwargs): + return exp(-z)*besseli(nu, z) + + def _eval_nseries(self, x, n, logx, cdir=0): + x0 = self.args[0].limit(x, 0) + if x0.is_zero: + f = self._eval_rewrite_as_intractable(*self.args) + return f._eval_nseries(x, n, logx) + return super()._eval_nseries(x, n, logx) + + +class _besselk(DefinedFunction): + """ + Helper function to make the $\\mathrm{besselk}(nu, z)$ + function tractable for the Gruntz algorithm. + + """ + + def _eval_aseries(self, n, args0, x, logx): + from sympy.functions.combinatorial.factorials import RisingFactorial + from sympy.series.order import Order + point = args0[1] + + if point in [S.Infinity, S.NegativeInfinity]: + nu, z = self.args + l = [((RisingFactorial(Rational(2*nu - 1, 2), k)*RisingFactorial( + Rational(2*nu + 1, 2), k))/((-2)**(k)*z**(Rational(2*k + 1, 2))*factorial(k))) for k in range(n)] + return sqrt(pi/(2))*(Add(*l)) + Order(1/z**(Rational(2*n + 1, 2)), x) + + return super()._eval_aseries(n, args0, x, logx) + + def _eval_rewrite_as_intractable(self,nu, z, **kwargs): + return exp(z)*besselk(nu, z) + + def _eval_nseries(self, x, n, logx, cdir=0): + x0 = self.args[0].limit(x, 0) + if x0.is_zero: + f = self._eval_rewrite_as_intractable(*self.args) + return f._eval_nseries(x, n, logx) + return super()._eval_nseries(x, n, logx) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/beta_functions.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/beta_functions.py new file mode 100644 index 0000000000000000000000000000000000000000..337ae6c71fe5a38cc0fcd819e9d489ebbbd1946b --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/beta_functions.py @@ -0,0 +1,389 @@ +from sympy.core import S +from sympy.core.function import DefinedFunction, ArgumentIndexError +from sympy.core.symbol import Dummy, uniquely_named_symbol +from sympy.functions.special.gamma_functions import gamma, digamma +from sympy.functions.combinatorial.numbers import catalan +from sympy.functions.elementary.complexes import conjugate + +# See mpmath #569 and SymPy #20569 +def betainc_mpmath_fix(a, b, x1, x2, reg=0): + from mpmath import betainc, mpf + if x1 == x2: + return mpf(0) + else: + return betainc(a, b, x1, x2, reg) + +############################################################################### +############################ COMPLETE BETA FUNCTION ########################## +############################################################################### + +class beta(DefinedFunction): + r""" + The beta integral is called the Eulerian integral of the first kind by + Legendre: + + .. math:: + \mathrm{B}(x,y) \int^{1}_{0} t^{x-1} (1-t)^{y-1} \mathrm{d}t. + + Explanation + =========== + + The Beta function or Euler's first integral is closely associated + with the gamma function. The Beta function is often used in probability + theory and mathematical statistics. It satisfies properties like: + + .. math:: + \mathrm{B}(a,1) = \frac{1}{a} \\ + \mathrm{B}(a,b) = \mathrm{B}(b,a) \\ + \mathrm{B}(a,b) = \frac{\Gamma(a) \Gamma(b)}{\Gamma(a+b)} + + Therefore for integral values of $a$ and $b$: + + .. math:: + \mathrm{B} = \frac{(a-1)! (b-1)!}{(a+b-1)!} + + A special case of the Beta function when `x = y` is the + Central Beta function. It satisfies properties like: + + .. math:: + \mathrm{B}(x) = 2^{1 - 2x}\mathrm{B}(x, \frac{1}{2}) + \mathrm{B}(x) = 2^{1 - 2x} cos(\pi x) \mathrm{B}(\frac{1}{2} - x, x) + \mathrm{B}(x) = \int_{0}^{1} \frac{t^x}{(1 + t)^{2x}} dt + \mathrm{B}(x) = \frac{2}{x} \prod_{n = 1}^{\infty} \frac{n(n + 2x)}{(n + x)^2} + + Examples + ======== + + >>> from sympy import I, pi + >>> from sympy.abc import x, y + + The Beta function obeys the mirror symmetry: + + >>> from sympy import beta, conjugate + >>> conjugate(beta(x, y)) + beta(conjugate(x), conjugate(y)) + + Differentiation with respect to both $x$ and $y$ is supported: + + >>> from sympy import beta, diff + >>> diff(beta(x, y), x) + (polygamma(0, x) - polygamma(0, x + y))*beta(x, y) + + >>> diff(beta(x, y), y) + (polygamma(0, y) - polygamma(0, x + y))*beta(x, y) + + >>> diff(beta(x), x) + 2*(polygamma(0, x) - polygamma(0, 2*x))*beta(x, x) + + We can numerically evaluate the Beta function to + arbitrary precision for any complex numbers x and y: + + >>> from sympy import beta + >>> beta(pi).evalf(40) + 0.02671848900111377452242355235388489324562 + + >>> beta(1 + I).evalf(20) + -0.2112723729365330143 - 0.7655283165378005676*I + + See Also + ======== + + gamma: Gamma function. + uppergamma: Upper incomplete gamma function. + lowergamma: Lower incomplete gamma function. + polygamma: Polygamma function. + loggamma: Log Gamma function. + digamma: Digamma function. + trigamma: Trigamma function. + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Beta_function + .. [2] https://mathworld.wolfram.com/BetaFunction.html + .. [3] https://dlmf.nist.gov/5.12 + + """ + unbranched = True + + def fdiff(self, argindex): + x, y = self.args + if argindex == 1: + # Diff wrt x + return beta(x, y)*(digamma(x) - digamma(x + y)) + elif argindex == 2: + # Diff wrt y + return beta(x, y)*(digamma(y) - digamma(x + y)) + else: + raise ArgumentIndexError(self, argindex) + + @classmethod + def eval(cls, x, y=None): + if y is None: + return beta(x, x) + if x.is_Number and y.is_Number: + return beta(x, y, evaluate=False).doit() + + def doit(self, **hints): + x = xold = self.args[0] + # Deal with unevaluated single argument beta + single_argument = len(self.args) == 1 + y = yold = self.args[0] if single_argument else self.args[1] + if hints.get('deep', True): + x = x.doit(**hints) + y = y.doit(**hints) + if y.is_zero or x.is_zero: + return S.ComplexInfinity + if y is S.One: + return 1/x + if x is S.One: + return 1/y + if y == x + 1: + return 1/(x*y*catalan(x)) + s = x + y + if (s.is_integer and s.is_negative and x.is_integer is False and + y.is_integer is False): + return S.Zero + if x == xold and y == yold and not single_argument: + return self + return beta(x, y) + + def _eval_expand_func(self, **hints): + x, y = self.args + return gamma(x)*gamma(y) / gamma(x + y) + + def _eval_is_real(self): + return self.args[0].is_real and self.args[1].is_real + + def _eval_conjugate(self): + return self.func(self.args[0].conjugate(), self.args[1].conjugate()) + + def _eval_rewrite_as_gamma(self, x, y, piecewise=True, **kwargs): + return self._eval_expand_func(**kwargs) + + def _eval_rewrite_as_Integral(self, x, y, **kwargs): + from sympy.integrals.integrals import Integral + t = Dummy(uniquely_named_symbol('t', [x, y]).name) + return Integral(t**(x - 1)*(1 - t)**(y - 1), (t, 0, 1)) + +############################################################################### +########################## INCOMPLETE BETA FUNCTION ########################### +############################################################################### + +class betainc(DefinedFunction): + r""" + The Generalized Incomplete Beta function is defined as + + .. math:: + \mathrm{B}_{(x_1, x_2)}(a, b) = \int_{x_1}^{x_2} t^{a - 1} (1 - t)^{b - 1} dt + + The Incomplete Beta function is a special case + of the Generalized Incomplete Beta function : + + .. math:: \mathrm{B}_z (a, b) = \mathrm{B}_{(0, z)}(a, b) + + The Incomplete Beta function satisfies : + + .. math:: \mathrm{B}_z (a, b) = (-1)^a \mathrm{B}_{\frac{z}{z - 1}} (a, 1 - a - b) + + The Beta function is a special case of the Incomplete Beta function : + + .. math:: \mathrm{B}(a, b) = \mathrm{B}_{1}(a, b) + + Examples + ======== + + >>> from sympy import betainc, symbols, conjugate + >>> a, b, x, x1, x2 = symbols('a b x x1 x2') + + The Generalized Incomplete Beta function is given by: + + >>> betainc(a, b, x1, x2) + betainc(a, b, x1, x2) + + The Incomplete Beta function can be obtained as follows: + + >>> betainc(a, b, 0, x) + betainc(a, b, 0, x) + + The Incomplete Beta function obeys the mirror symmetry: + + >>> conjugate(betainc(a, b, x1, x2)) + betainc(conjugate(a), conjugate(b), conjugate(x1), conjugate(x2)) + + We can numerically evaluate the Incomplete Beta function to + arbitrary precision for any complex numbers a, b, x1 and x2: + + >>> from sympy import betainc, I + >>> betainc(2, 3, 4, 5).evalf(10) + 56.08333333 + >>> betainc(0.75, 1 - 4*I, 0, 2 + 3*I).evalf(25) + 0.2241657956955709603655887 + 0.3619619242700451992411724*I + + The Generalized Incomplete Beta function can be expressed + in terms of the Generalized Hypergeometric function. + + >>> from sympy import hyper + >>> betainc(a, b, x1, x2).rewrite(hyper) + (-x1**a*hyper((a, 1 - b), (a + 1,), x1) + x2**a*hyper((a, 1 - b), (a + 1,), x2))/a + + See Also + ======== + + beta: Beta function + hyper: Generalized Hypergeometric function + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Beta_function#Incomplete_beta_function + .. [2] https://dlmf.nist.gov/8.17 + .. [3] https://functions.wolfram.com/GammaBetaErf/Beta4/ + .. [4] https://functions.wolfram.com/GammaBetaErf/BetaRegularized4/02/ + + """ + nargs = 4 + unbranched = True + + def fdiff(self, argindex): + a, b, x1, x2 = self.args + if argindex == 3: + # Diff wrt x1 + return -(1 - x1)**(b - 1)*x1**(a - 1) + elif argindex == 4: + # Diff wrt x2 + return (1 - x2)**(b - 1)*x2**(a - 1) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_mpmath(self): + return betainc_mpmath_fix, self.args + + def _eval_is_real(self): + if all(arg.is_real for arg in self.args): + return True + + def _eval_conjugate(self): + return self.func(*map(conjugate, self.args)) + + def _eval_rewrite_as_Integral(self, a, b, x1, x2, **kwargs): + from sympy.integrals.integrals import Integral + t = Dummy(uniquely_named_symbol('t', [a, b, x1, x2]).name) + return Integral(t**(a - 1)*(1 - t)**(b - 1), (t, x1, x2)) + + def _eval_rewrite_as_hyper(self, a, b, x1, x2, **kwargs): + from sympy.functions.special.hyper import hyper + return (x2**a * hyper((a, 1 - b), (a + 1,), x2) - x1**a * hyper((a, 1 - b), (a + 1,), x1)) / a + +############################################################################### +#################### REGULARIZED INCOMPLETE BETA FUNCTION ##################### +############################################################################### + +class betainc_regularized(DefinedFunction): + r""" + The Generalized Regularized Incomplete Beta function is given by + + .. math:: + \mathrm{I}_{(x_1, x_2)}(a, b) = \frac{\mathrm{B}_{(x_1, x_2)}(a, b)}{\mathrm{B}(a, b)} + + The Regularized Incomplete Beta function is a special case + of the Generalized Regularized Incomplete Beta function : + + .. math:: \mathrm{I}_z (a, b) = \mathrm{I}_{(0, z)}(a, b) + + The Regularized Incomplete Beta function is the cumulative distribution + function of the beta distribution. + + Examples + ======== + + >>> from sympy import betainc_regularized, symbols, conjugate + >>> a, b, x, x1, x2 = symbols('a b x x1 x2') + + The Generalized Regularized Incomplete Beta + function is given by: + + >>> betainc_regularized(a, b, x1, x2) + betainc_regularized(a, b, x1, x2) + + The Regularized Incomplete Beta function + can be obtained as follows: + + >>> betainc_regularized(a, b, 0, x) + betainc_regularized(a, b, 0, x) + + The Regularized Incomplete Beta function + obeys the mirror symmetry: + + >>> conjugate(betainc_regularized(a, b, x1, x2)) + betainc_regularized(conjugate(a), conjugate(b), conjugate(x1), conjugate(x2)) + + We can numerically evaluate the Regularized Incomplete Beta function + to arbitrary precision for any complex numbers a, b, x1 and x2: + + >>> from sympy import betainc_regularized, pi, E + >>> betainc_regularized(1, 2, 0, 0.25).evalf(10) + 0.4375000000 + >>> betainc_regularized(pi, E, 0, 1).evalf(5) + 1.00000 + + The Generalized Regularized Incomplete Beta function can be + expressed in terms of the Generalized Hypergeometric function. + + >>> from sympy import hyper + >>> betainc_regularized(a, b, x1, x2).rewrite(hyper) + (-x1**a*hyper((a, 1 - b), (a + 1,), x1) + x2**a*hyper((a, 1 - b), (a + 1,), x2))/(a*beta(a, b)) + + See Also + ======== + + beta: Beta function + hyper: Generalized Hypergeometric function + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Beta_function#Incomplete_beta_function + .. [2] https://dlmf.nist.gov/8.17 + .. [3] https://functions.wolfram.com/GammaBetaErf/Beta4/ + .. [4] https://functions.wolfram.com/GammaBetaErf/BetaRegularized4/02/ + + """ + nargs = 4 + unbranched = True + + def __new__(cls, a, b, x1, x2): + return super().__new__(cls, a, b, x1, x2) + + def _eval_mpmath(self): + return betainc_mpmath_fix, (*self.args, S(1)) + + def fdiff(self, argindex): + a, b, x1, x2 = self.args + if argindex == 3: + # Diff wrt x1 + return -(1 - x1)**(b - 1)*x1**(a - 1) / beta(a, b) + elif argindex == 4: + # Diff wrt x2 + return (1 - x2)**(b - 1)*x2**(a - 1) / beta(a, b) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_is_real(self): + if all(arg.is_real for arg in self.args): + return True + + def _eval_conjugate(self): + return self.func(*map(conjugate, self.args)) + + def _eval_rewrite_as_Integral(self, a, b, x1, x2, **kwargs): + from sympy.integrals.integrals import Integral + t = Dummy(uniquely_named_symbol('t', [a, b, x1, x2]).name) + integrand = t**(a - 1)*(1 - t)**(b - 1) + expr = Integral(integrand, (t, x1, x2)) + return expr / Integral(integrand, (t, 0, 1)) + + def _eval_rewrite_as_hyper(self, a, b, x1, x2, **kwargs): + from sympy.functions.special.hyper import hyper + expr = (x2**a * hyper((a, 1 - b), (a + 1,), x2) - x1**a * hyper((a, 1 - b), (a + 1,), x1)) / a + return expr / beta(a, b) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/bsplines.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/bsplines.py new file mode 100644 index 0000000000000000000000000000000000000000..50c9141e841288aa02457c466fc6573f9a20d09f --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/bsplines.py @@ -0,0 +1,348 @@ +from sympy.core import S, sympify +from sympy.core.symbol import (Dummy, symbols) +from sympy.functions import Piecewise, piecewise_fold +from sympy.logic.boolalg import And +from sympy.sets.sets import Interval + +from functools import lru_cache + + +def _ivl(cond, x): + """return the interval corresponding to the condition + + Conditions in spline's Piecewise give the range over + which an expression is valid like (lo <= x) & (x <= hi). + This function returns (lo, hi). + """ + if isinstance(cond, And) and len(cond.args) == 2: + a, b = cond.args + if a.lts == x: + a, b = b, a + return a.lts, b.gts + raise TypeError('unexpected cond type: %s' % cond) + + +def _add_splines(c, b1, d, b2, x): + """Construct c*b1 + d*b2.""" + + if S.Zero in (b1, c): + rv = piecewise_fold(d * b2) + elif S.Zero in (b2, d): + rv = piecewise_fold(c * b1) + else: + new_args = [] + # Just combining the Piecewise without any fancy optimization + p1 = piecewise_fold(c * b1) + p2 = piecewise_fold(d * b2) + + # Search all Piecewise arguments except (0, True) + p2args = list(p2.args[:-1]) + + # This merging algorithm assumes the conditions in + # p1 and p2 are sorted + for arg in p1.args[:-1]: + expr = arg.expr + cond = arg.cond + + lower = _ivl(cond, x)[0] + + # Check p2 for matching conditions that can be merged + for i, arg2 in enumerate(p2args): + expr2 = arg2.expr + cond2 = arg2.cond + + lower_2, upper_2 = _ivl(cond2, x) + if cond2 == cond: + # Conditions match, join expressions + expr += expr2 + # Remove matching element + del p2args[i] + # No need to check the rest + break + elif lower_2 < lower and upper_2 <= lower: + # Check if arg2 condition smaller than arg1, + # add to new_args by itself (no match expected + # in p1) + new_args.append(arg2) + del p2args[i] + break + + # Checked all, add expr and cond + new_args.append((expr, cond)) + + # Add remaining items from p2args + new_args.extend(p2args) + + # Add final (0, True) + new_args.append((0, True)) + + rv = Piecewise(*new_args, evaluate=False) + + return rv.expand() + + +@lru_cache(maxsize=128) +def bspline_basis(d, knots, n, x): + """ + The $n$-th B-spline at $x$ of degree $d$ with knots. + + Explanation + =========== + + B-Splines are piecewise polynomials of degree $d$. They are defined on a + set of knots, which is a sequence of integers or floats. + + Examples + ======== + + The 0th degree splines have a value of 1 on a single interval: + + >>> from sympy import bspline_basis + >>> from sympy.abc import x + >>> d = 0 + >>> knots = tuple(range(5)) + >>> bspline_basis(d, knots, 0, x) + Piecewise((1, (x >= 0) & (x <= 1)), (0, True)) + + For a given ``(d, knots)`` there are ``len(knots)-d-1`` B-splines + defined, that are indexed by ``n`` (starting at 0). + + Here is an example of a cubic B-spline: + + >>> bspline_basis(3, tuple(range(5)), 0, x) + Piecewise((x**3/6, (x >= 0) & (x <= 1)), + (-x**3/2 + 2*x**2 - 2*x + 2/3, + (x >= 1) & (x <= 2)), + (x**3/2 - 4*x**2 + 10*x - 22/3, + (x >= 2) & (x <= 3)), + (-x**3/6 + 2*x**2 - 8*x + 32/3, + (x >= 3) & (x <= 4)), + (0, True)) + + By repeating knot points, you can introduce discontinuities in the + B-splines and their derivatives: + + >>> d = 1 + >>> knots = (0, 0, 2, 3, 4) + >>> bspline_basis(d, knots, 0, x) + Piecewise((1 - x/2, (x >= 0) & (x <= 2)), (0, True)) + + It is quite time consuming to construct and evaluate B-splines. If + you need to evaluate a B-spline many times, it is best to lambdify them + first: + + >>> from sympy import lambdify + >>> d = 3 + >>> knots = tuple(range(10)) + >>> b0 = bspline_basis(d, knots, 0, x) + >>> f = lambdify(x, b0) + >>> y = f(0.5) + + Parameters + ========== + + d : integer + degree of bspline + + knots : list of integer values + list of knots points of bspline + + n : integer + $n$-th B-spline + + x : symbol + + See Also + ======== + + bspline_basis_set + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/B-spline + + """ + # make sure x has no assumptions so conditions don't evaluate + xvar = x + x = Dummy() + + knots = tuple(sympify(k) for k in knots) + d = int(d) + n = int(n) + n_knots = len(knots) + n_intervals = n_knots - 1 + if n + d + 1 > n_intervals: + raise ValueError("n + d + 1 must not exceed len(knots) - 1") + if d == 0: + result = Piecewise( + (S.One, Interval(knots[n], knots[n + 1]).contains(x)), (0, True) + ) + elif d > 0: + denom = knots[n + d + 1] - knots[n + 1] + if denom != S.Zero: + B = (knots[n + d + 1] - x) / denom + b2 = bspline_basis(d - 1, knots, n + 1, x) + else: + b2 = B = S.Zero + + denom = knots[n + d] - knots[n] + if denom != S.Zero: + A = (x - knots[n]) / denom + b1 = bspline_basis(d - 1, knots, n, x) + else: + b1 = A = S.Zero + + result = _add_splines(A, b1, B, b2, x) + else: + raise ValueError("degree must be non-negative: %r" % n) + + # return result with user-given x + return result.xreplace({x: xvar}) + + +def bspline_basis_set(d, knots, x): + """ + Return the ``len(knots)-d-1`` B-splines at *x* of degree *d* + with *knots*. + + Explanation + =========== + + This function returns a list of piecewise polynomials that are the + ``len(knots)-d-1`` B-splines of degree *d* for the given knots. + This function calls ``bspline_basis(d, knots, n, x)`` for different + values of *n*. + + Examples + ======== + + >>> from sympy import bspline_basis_set + >>> from sympy.abc import x + >>> d = 2 + >>> knots = range(5) + >>> splines = bspline_basis_set(d, knots, x) + >>> splines + [Piecewise((x**2/2, (x >= 0) & (x <= 1)), + (-x**2 + 3*x - 3/2, (x >= 1) & (x <= 2)), + (x**2/2 - 3*x + 9/2, (x >= 2) & (x <= 3)), + (0, True)), + Piecewise((x**2/2 - x + 1/2, (x >= 1) & (x <= 2)), + (-x**2 + 5*x - 11/2, (x >= 2) & (x <= 3)), + (x**2/2 - 4*x + 8, (x >= 3) & (x <= 4)), + (0, True))] + + Parameters + ========== + + d : integer + degree of bspline + + knots : list of integers + list of knots points of bspline + + x : symbol + + See Also + ======== + + bspline_basis + + """ + n_splines = len(knots) - d - 1 + return [bspline_basis(d, tuple(knots), i, x) for i in range(n_splines)] + + +def interpolating_spline(d, x, X, Y): + """ + Return spline of degree *d*, passing through the given *X* + and *Y* values. + + Explanation + =========== + + This function returns a piecewise function such that each part is + a polynomial of degree not greater than *d*. The value of *d* + must be 1 or greater and the values of *X* must be strictly + increasing. + + Examples + ======== + + >>> from sympy import interpolating_spline + >>> from sympy.abc import x + >>> interpolating_spline(1, x, [1, 2, 4, 7], [3, 6, 5, 7]) + Piecewise((3*x, (x >= 1) & (x <= 2)), + (7 - x/2, (x >= 2) & (x <= 4)), + (2*x/3 + 7/3, (x >= 4) & (x <= 7))) + >>> interpolating_spline(3, x, [-2, 0, 1, 3, 4], [4, 2, 1, 1, 3]) + Piecewise((7*x**3/117 + 7*x**2/117 - 131*x/117 + 2, (x >= -2) & (x <= 1)), + (10*x**3/117 - 2*x**2/117 - 122*x/117 + 77/39, (x >= 1) & (x <= 4))) + + Parameters + ========== + + d : integer + Degree of Bspline strictly greater than equal to one + + x : symbol + + X : list of strictly increasing real values + list of X coordinates through which the spline passes + + Y : list of real values + list of corresponding Y coordinates through which the spline passes + + See Also + ======== + + bspline_basis_set, interpolating_poly + + """ + from sympy.solvers.solveset import linsolve + from sympy.matrices.dense import Matrix + + # Input sanitization + d = sympify(d) + if not (d.is_Integer and d.is_positive): + raise ValueError("Spline degree must be a positive integer, not %s." % d) + if len(X) != len(Y): + raise ValueError("Number of X and Y coordinates must be the same.") + if len(X) < d + 1: + raise ValueError("Degree must be less than the number of control points.") + if not all(a < b for a, b in zip(X, X[1:])): + raise ValueError("The x-coordinates must be strictly increasing.") + X = [sympify(i) for i in X] + + # Evaluating knots value + if d.is_odd: + j = (d + 1) // 2 + interior_knots = X[j:-j] + else: + j = d // 2 + interior_knots = [ + (a + b)/2 for a, b in zip(X[j : -j - 1], X[j + 1 : -j]) + ] + + knots = [X[0]] * (d + 1) + list(interior_knots) + [X[-1]] * (d + 1) + + basis = bspline_basis_set(d, knots, x) + + A = [[b.subs(x, v) for b in basis] for v in X] + + coeff = linsolve((Matrix(A), Matrix(Y)), symbols("c0:{}".format(len(X)), cls=Dummy)) + coeff = list(coeff)[0] + intervals = {c for b in basis for (e, c) in b.args if c != True} + + # Sorting the intervals + # ival contains the end-points of each interval + intervals = sorted(intervals, key=lambda c: _ivl(c, x)) + + basis_dicts = [{c: e for (e, c) in b.args} for b in basis] + spline = [] + for i in intervals: + piece = sum( + [c * d.get(i, S.Zero) for (c, d) in zip(coeff, basis_dicts)], S.Zero + ) + spline.append((piece, i)) + return Piecewise(*spline) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/delta_functions.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/delta_functions.py new file mode 100644 index 0000000000000000000000000000000000000000..698d8c0c3ba5e68c2f084e83e7a9ec070ce83307 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/delta_functions.py @@ -0,0 +1,664 @@ +from sympy.core import S, diff +from sympy.core.function import DefinedFunction, ArgumentIndexError +from sympy.core.logic import fuzzy_not +from sympy.core.relational import Eq, Ne +from sympy.functions.elementary.complexes import im, sign +from sympy.functions.elementary.piecewise import Piecewise +from sympy.polys.polyerrors import PolynomialError +from sympy.polys.polyroots import roots +from sympy.utilities.misc import filldedent + + +############################################################################### +################################ DELTA FUNCTION ############################### +############################################################################### + + +class DiracDelta(DefinedFunction): + r""" + The DiracDelta function and its derivatives. + + Explanation + =========== + + DiracDelta is not an ordinary function. It can be rigorously defined either + as a distribution or as a measure. + + DiracDelta only makes sense in definite integrals, and in particular, + integrals of the form ``Integral(f(x)*DiracDelta(x - x0), (x, a, b))``, + where it equals ``f(x0)`` if ``a <= x0 <= b`` and ``0`` otherwise. Formally, + DiracDelta acts in some ways like a function that is ``0`` everywhere except + at ``0``, but in many ways it also does not. It can often be useful to treat + DiracDelta in formal ways, building up and manipulating expressions with + delta functions (which may eventually be integrated), but care must be taken + to not treat it as a real function. SymPy's ``oo`` is similar. It only + truly makes sense formally in certain contexts (such as integration limits), + but SymPy allows its use everywhere, and it tries to be consistent with + operations on it (like ``1/oo``), but it is easy to get into trouble and get + wrong results if ``oo`` is treated too much like a number. Similarly, if + DiracDelta is treated too much like a function, it is easy to get wrong or + nonsensical results. + + DiracDelta function has the following properties: + + 1) $\frac{d}{d x} \theta(x) = \delta(x)$ + 2) $\int_{-\infty}^\infty \delta(x - a)f(x)\, dx = f(a)$ and $\int_{a- + \epsilon}^{a+\epsilon} \delta(x - a)f(x)\, dx = f(a)$ + 3) $\delta(x) = 0$ for all $x \neq 0$ + 4) $\delta(g(x)) = \sum_i \frac{\delta(x - x_i)}{\|g'(x_i)\|}$ where $x_i$ + are the roots of $g$ + 5) $\delta(-x) = \delta(x)$ + + Derivatives of ``k``-th order of DiracDelta have the following properties: + + 6) $\delta(x, k) = 0$ for all $x \neq 0$ + 7) $\delta(-x, k) = -\delta(x, k)$ for odd $k$ + 8) $\delta(-x, k) = \delta(x, k)$ for even $k$ + + Examples + ======== + + >>> from sympy import DiracDelta, diff, pi + >>> from sympy.abc import x, y + + >>> DiracDelta(x) + DiracDelta(x) + >>> DiracDelta(1) + 0 + >>> DiracDelta(-1) + 0 + >>> DiracDelta(pi) + 0 + >>> DiracDelta(x - 4).subs(x, 4) + DiracDelta(0) + >>> diff(DiracDelta(x)) + DiracDelta(x, 1) + >>> diff(DiracDelta(x - 1), x, 2) + DiracDelta(x - 1, 2) + >>> diff(DiracDelta(x**2 - 1), x, 2) + 2*(2*x**2*DiracDelta(x**2 - 1, 2) + DiracDelta(x**2 - 1, 1)) + >>> DiracDelta(3*x).is_simple(x) + True + >>> DiracDelta(x**2).is_simple(x) + False + >>> DiracDelta((x**2 - 1)*y).expand(diracdelta=True, wrt=x) + DiracDelta(x - 1)/(2*Abs(y)) + DiracDelta(x + 1)/(2*Abs(y)) + + See Also + ======== + + Heaviside + sympy.simplify.simplify.simplify, is_simple + sympy.functions.special.tensor_functions.KroneckerDelta + + References + ========== + + .. [1] https://mathworld.wolfram.com/DeltaFunction.html + + """ + + is_real = True + + def fdiff(self, argindex=1): + """ + Returns the first derivative of a DiracDelta Function. + + Explanation + =========== + + The difference between ``diff()`` and ``fdiff()`` is: ``diff()`` is the + user-level function and ``fdiff()`` is an object method. ``fdiff()`` is + a convenience method available in the ``Function`` class. It returns + the derivative of the function without considering the chain rule. + ``diff(function, x)`` calls ``Function._eval_derivative`` which in turn + calls ``fdiff()`` internally to compute the derivative of the function. + + Examples + ======== + + >>> from sympy import DiracDelta, diff + >>> from sympy.abc import x + + >>> DiracDelta(x).fdiff() + DiracDelta(x, 1) + + >>> DiracDelta(x, 1).fdiff() + DiracDelta(x, 2) + + >>> DiracDelta(x**2 - 1).fdiff() + DiracDelta(x**2 - 1, 1) + + >>> diff(DiracDelta(x, 1)).fdiff() + DiracDelta(x, 3) + + Parameters + ========== + + argindex : integer + degree of derivative + + """ + if argindex == 1: + #I didn't know if there is a better way to handle default arguments + k = 0 + if len(self.args) > 1: + k = self.args[1] + return self.func(self.args[0], k + 1) + else: + raise ArgumentIndexError(self, argindex) + + @classmethod + def eval(cls, arg, k=S.Zero): + """ + Returns a simplified form or a value of DiracDelta depending on the + argument passed by the DiracDelta object. + + Explanation + =========== + + The ``eval()`` method is automatically called when the ``DiracDelta`` + class is about to be instantiated and it returns either some simplified + instance or the unevaluated instance depending on the argument passed. + In other words, ``eval()`` method is not needed to be called explicitly, + it is being called and evaluated once the object is called. + + Examples + ======== + + >>> from sympy import DiracDelta, S + >>> from sympy.abc import x + + >>> DiracDelta(x) + DiracDelta(x) + + >>> DiracDelta(-x, 1) + -DiracDelta(x, 1) + + >>> DiracDelta(1) + 0 + + >>> DiracDelta(5, 1) + 0 + + >>> DiracDelta(0) + DiracDelta(0) + + >>> DiracDelta(-1) + 0 + + >>> DiracDelta(S.NaN) + nan + + >>> DiracDelta(x - 100).subs(x, 5) + 0 + + >>> DiracDelta(x - 100).subs(x, 100) + DiracDelta(0) + + Parameters + ========== + + k : integer + order of derivative + + arg : argument passed to DiracDelta + + """ + if not k.is_Integer or k.is_negative: + raise ValueError("Error: the second argument of DiracDelta must be \ + a non-negative integer, %s given instead." % (k,)) + if arg is S.NaN: + return S.NaN + if arg.is_nonzero: + return S.Zero + if fuzzy_not(im(arg).is_zero): + raise ValueError(filldedent(''' + Function defined only for Real Values. + Complex part: %s found in %s .''' % ( + repr(im(arg)), repr(arg)))) + c, nc = arg.args_cnc() + if c and c[0] is S.NegativeOne: + # keep this fast and simple instead of using + # could_extract_minus_sign + if k.is_odd: + return -cls(-arg, k) + elif k.is_even: + return cls(-arg, k) if k else cls(-arg) + elif k.is_zero: + return cls(arg, evaluate=False) + + def _eval_expand_diracdelta(self, **hints): + """ + Compute a simplified representation of the function using + property number 4. Pass ``wrt`` as a hint to expand the expression + with respect to a particular variable. + + Explanation + =========== + + ``wrt`` is: + + - a variable with respect to which a DiracDelta expression will + get expanded. + + Examples + ======== + + >>> from sympy import DiracDelta + >>> from sympy.abc import x, y + + >>> DiracDelta(x*y).expand(diracdelta=True, wrt=x) + DiracDelta(x)/Abs(y) + >>> DiracDelta(x*y).expand(diracdelta=True, wrt=y) + DiracDelta(y)/Abs(x) + + >>> DiracDelta(x**2 + x - 2).expand(diracdelta=True, wrt=x) + DiracDelta(x - 1)/3 + DiracDelta(x + 2)/3 + + See Also + ======== + + is_simple, Diracdelta + + """ + wrt = hints.get('wrt', None) + if wrt is None: + free = self.free_symbols + if len(free) == 1: + wrt = free.pop() + else: + raise TypeError(filldedent(''' + When there is more than 1 free symbol or variable in the expression, + the 'wrt' keyword is required as a hint to expand when using the + DiracDelta hint.''')) + + if not self.args[0].has(wrt) or (len(self.args) > 1 and self.args[1] != 0 ): + return self + try: + argroots = roots(self.args[0], wrt) + result = 0 + valid = True + darg = abs(diff(self.args[0], wrt)) + for r, m in argroots.items(): + if r.is_real is not False and m == 1: + result += self.func(wrt - r)/darg.subs(wrt, r) + else: + # don't handle non-real and if m != 1 then + # a polynomial will have a zero in the derivative (darg) + # at r + valid = False + break + if valid: + return result + except PolynomialError: + pass + return self + + def is_simple(self, x): + """ + Tells whether the argument(args[0]) of DiracDelta is a linear + expression in *x*. + + Examples + ======== + + >>> from sympy import DiracDelta, cos + >>> from sympy.abc import x, y + + >>> DiracDelta(x*y).is_simple(x) + True + >>> DiracDelta(x*y).is_simple(y) + True + + >>> DiracDelta(x**2 + x - 2).is_simple(x) + False + + >>> DiracDelta(cos(x)).is_simple(x) + False + + Parameters + ========== + + x : can be a symbol + + See Also + ======== + + sympy.simplify.simplify.simplify, DiracDelta + + """ + p = self.args[0].as_poly(x) + if p: + return p.degree() == 1 + return False + + def _eval_rewrite_as_Piecewise(self, *args, **kwargs): + """ + Represents DiracDelta in a piecewise form. + + Examples + ======== + + >>> from sympy import DiracDelta, Piecewise, Symbol + >>> x = Symbol('x') + + >>> DiracDelta(x).rewrite(Piecewise) + Piecewise((DiracDelta(0), Eq(x, 0)), (0, True)) + + >>> DiracDelta(x - 5).rewrite(Piecewise) + Piecewise((DiracDelta(0), Eq(x, 5)), (0, True)) + + >>> DiracDelta(x**2 - 5).rewrite(Piecewise) + Piecewise((DiracDelta(0), Eq(x**2, 5)), (0, True)) + + >>> DiracDelta(x - 5, 4).rewrite(Piecewise) + DiracDelta(x - 5, 4) + + """ + if len(args) == 1: + return Piecewise((DiracDelta(0), Eq(args[0], 0)), (0, True)) + + def _eval_rewrite_as_SingularityFunction(self, *args, **kwargs): + """ + Returns the DiracDelta expression written in the form of Singularity + Functions. + + """ + from sympy.solvers import solve + from sympy.functions.special.singularity_functions import SingularityFunction + if self == DiracDelta(0): + return SingularityFunction(0, 0, -1) + if self == DiracDelta(0, 1): + return SingularityFunction(0, 0, -2) + free = self.free_symbols + if len(free) == 1: + x = (free.pop()) + if len(args) == 1: + return SingularityFunction(x, solve(args[0], x)[0], -1) + return SingularityFunction(x, solve(args[0], x)[0], -args[1] - 1) + else: + # I don't know how to handle the case for DiracDelta expressions + # having arguments with more than one variable. + raise TypeError(filldedent(''' + rewrite(SingularityFunction) does not support + arguments with more that one variable.''')) + + +############################################################################### +############################## HEAVISIDE FUNCTION ############################# +############################################################################### + + +class Heaviside(DefinedFunction): + r""" + Heaviside step function. + + Explanation + =========== + + The Heaviside step function has the following properties: + + 1) $\frac{d}{d x} \theta(x) = \delta(x)$ + 2) $\theta(x) = \begin{cases} 0 & \text{for}\: x < 0 \\ \frac{1}{2} & + \text{for}\: x = 0 \\1 & \text{for}\: x > 0 \end{cases}$ + 3) $\frac{d}{d x} \max(x, 0) = \theta(x)$ + + Heaviside(x) is printed as $\theta(x)$ with the SymPy LaTeX printer. + + The value at 0 is set differently in different fields. SymPy uses 1/2, + which is a convention from electronics and signal processing, and is + consistent with solving improper integrals by Fourier transform and + convolution. + + To specify a different value of Heaviside at ``x=0``, a second argument + can be given. Using ``Heaviside(x, nan)`` gives an expression that will + evaluate to nan for x=0. + + .. versionchanged:: 1.9 ``Heaviside(0)`` now returns 1/2 (before: undefined) + + Examples + ======== + + >>> from sympy import Heaviside, nan + >>> from sympy.abc import x + >>> Heaviside(9) + 1 + >>> Heaviside(-9) + 0 + >>> Heaviside(0) + 1/2 + >>> Heaviside(0, nan) + nan + >>> (Heaviside(x) + 1).replace(Heaviside(x), Heaviside(x, 1)) + Heaviside(x, 1) + 1 + + See Also + ======== + + DiracDelta + + References + ========== + + .. [1] https://mathworld.wolfram.com/HeavisideStepFunction.html + .. [2] https://dlmf.nist.gov/1.16#iv + + """ + + is_real = True + + def fdiff(self, argindex=1): + """ + Returns the first derivative of a Heaviside Function. + + Examples + ======== + + >>> from sympy import Heaviside, diff + >>> from sympy.abc import x + + >>> Heaviside(x).fdiff() + DiracDelta(x) + + >>> Heaviside(x**2 - 1).fdiff() + DiracDelta(x**2 - 1) + + >>> diff(Heaviside(x)).fdiff() + DiracDelta(x, 1) + + Parameters + ========== + + argindex : integer + order of derivative + + """ + if argindex == 1: + return DiracDelta(self.args[0]) + else: + raise ArgumentIndexError(self, argindex) + + def __new__(cls, arg, H0=S.Half, **options): + if isinstance(H0, Heaviside) and len(H0.args) == 1: + H0 = S.Half + return super(cls, cls).__new__(cls, arg, H0, **options) + + @property + def pargs(self): + """Args without default S.Half""" + args = self.args + if args[1] is S.Half: + args = args[:1] + return args + + @classmethod + def eval(cls, arg, H0=S.Half): + """ + Returns a simplified form or a value of Heaviside depending on the + argument passed by the Heaviside object. + + Explanation + =========== + + The ``eval()`` method is automatically called when the ``Heaviside`` + class is about to be instantiated and it returns either some simplified + instance or the unevaluated instance depending on the argument passed. + In other words, ``eval()`` method is not needed to be called explicitly, + it is being called and evaluated once the object is called. + + Examples + ======== + + >>> from sympy import Heaviside, S + >>> from sympy.abc import x + + >>> Heaviside(x) + Heaviside(x) + + >>> Heaviside(19) + 1 + + >>> Heaviside(0) + 1/2 + + >>> Heaviside(0, 1) + 1 + + >>> Heaviside(-5) + 0 + + >>> Heaviside(S.NaN) + nan + + >>> Heaviside(x - 100).subs(x, 5) + 0 + + >>> Heaviside(x - 100).subs(x, 105) + 1 + + Parameters + ========== + + arg : argument passed by Heaviside object + + H0 : value of Heaviside(0) + + """ + if arg.is_extended_negative: + return S.Zero + elif arg.is_extended_positive: + return S.One + elif arg.is_zero: + return H0 + elif arg is S.NaN: + return S.NaN + elif fuzzy_not(im(arg).is_zero): + raise ValueError("Function defined only for Real Values. Complex part: %s found in %s ." % (repr(im(arg)), repr(arg)) ) + + def _eval_rewrite_as_Piecewise(self, arg, H0=None, **kwargs): + """ + Represents Heaviside in a Piecewise form. + + Examples + ======== + + >>> from sympy import Heaviside, Piecewise, Symbol, nan + >>> x = Symbol('x') + + >>> Heaviside(x).rewrite(Piecewise) + Piecewise((0, x < 0), (1/2, Eq(x, 0)), (1, True)) + + >>> Heaviside(x,nan).rewrite(Piecewise) + Piecewise((0, x < 0), (nan, Eq(x, 0)), (1, True)) + + >>> Heaviside(x - 5).rewrite(Piecewise) + Piecewise((0, x < 5), (1/2, Eq(x, 5)), (1, True)) + + >>> Heaviside(x**2 - 1).rewrite(Piecewise) + Piecewise((0, x**2 < 1), (1/2, Eq(x**2, 1)), (1, True)) + + """ + if H0 == 0: + return Piecewise((0, arg <= 0), (1, True)) + if H0 == 1: + return Piecewise((0, arg < 0), (1, True)) + return Piecewise((0, arg < 0), (H0, Eq(arg, 0)), (1, True)) + + def _eval_rewrite_as_sign(self, arg, H0=S.Half, **kwargs): + """ + Represents the Heaviside function in the form of sign function. + + Explanation + =========== + + The value of Heaviside(0) must be 1/2 for rewriting as sign to be + strictly equivalent. For easier usage, we also allow this rewriting + when Heaviside(0) is undefined. + + Examples + ======== + + >>> from sympy import Heaviside, Symbol, sign, nan + >>> x = Symbol('x', real=True) + >>> y = Symbol('y') + + >>> Heaviside(x).rewrite(sign) + sign(x)/2 + 1/2 + + >>> Heaviside(x, 0).rewrite(sign) + Piecewise((sign(x)/2 + 1/2, Ne(x, 0)), (0, True)) + + >>> Heaviside(x, nan).rewrite(sign) + Piecewise((sign(x)/2 + 1/2, Ne(x, 0)), (nan, True)) + + >>> Heaviside(x - 2).rewrite(sign) + sign(x - 2)/2 + 1/2 + + >>> Heaviside(x**2 - 2*x + 1).rewrite(sign) + sign(x**2 - 2*x + 1)/2 + 1/2 + + >>> Heaviside(y).rewrite(sign) + Heaviside(y) + + >>> Heaviside(y**2 - 2*y + 1).rewrite(sign) + Heaviside(y**2 - 2*y + 1) + + See Also + ======== + + sign + + """ + if arg.is_extended_real: + pw1 = Piecewise( + ((sign(arg) + 1)/2, Ne(arg, 0)), + (Heaviside(0, H0=H0), True)) + pw2 = Piecewise( + ((sign(arg) + 1)/2, Eq(Heaviside(0, H0=H0), S.Half)), + (pw1, True)) + return pw2 + + def _eval_rewrite_as_SingularityFunction(self, args, H0=S.Half, **kwargs): + """ + Returns the Heaviside expression written in the form of Singularity + Functions. + + """ + from sympy.solvers import solve + from sympy.functions.special.singularity_functions import SingularityFunction + if self == Heaviside(0): + return SingularityFunction(0, 0, 0) + free = self.free_symbols + if len(free) == 1: + x = (free.pop()) + return SingularityFunction(x, solve(args, x)[0], 0) + # TODO + # ((x - 5)**3*Heaviside(x - 5)).rewrite(SingularityFunction) should output + # SingularityFunction(x, 5, 0) instead of (x - 5)**3*SingularityFunction(x, 5, 0) + else: + # I don't know how to handle the case for Heaviside expressions + # having arguments with more than one variable. + raise TypeError(filldedent(''' + rewrite(SingularityFunction) does not + support arguments with more that one variable.''')) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/elliptic_integrals.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/elliptic_integrals.py new file mode 100644 index 0000000000000000000000000000000000000000..a94e343c0106891db44668ae05c33e84ecd05d0b --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/elliptic_integrals.py @@ -0,0 +1,445 @@ +""" Elliptic Integrals. """ + +from sympy.core import S, pi, I, Rational +from sympy.core.function import DefinedFunction, ArgumentIndexError +from sympy.core.symbol import Dummy,uniquely_named_symbol +from sympy.functions.elementary.complexes import sign +from sympy.functions.elementary.hyperbolic import atanh +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import sin, tan +from sympy.functions.special.gamma_functions import gamma +from sympy.functions.special.hyper import hyper, meijerg + +class elliptic_k(DefinedFunction): + r""" + The complete elliptic integral of the first kind, defined by + + .. math:: K(m) = F\left(\tfrac{\pi}{2}\middle| m\right) + + where $F\left(z\middle| m\right)$ is the Legendre incomplete + elliptic integral of the first kind. + + Explanation + =========== + + The function $K(m)$ is a single-valued function on the complex + plane with branch cut along the interval $(1, \infty)$. + + Note that our notation defines the incomplete elliptic integral + in terms of the parameter $m$ instead of the elliptic modulus + (eccentricity) $k$. + In this case, the parameter $m$ is defined as $m=k^2$. + + Examples + ======== + + >>> from sympy import elliptic_k, I + >>> from sympy.abc import m + >>> elliptic_k(0) + pi/2 + >>> elliptic_k(1.0 + I) + 1.50923695405127 + 0.625146415202697*I + >>> elliptic_k(m).series(n=3) + pi/2 + pi*m/8 + 9*pi*m**2/128 + O(m**3) + + See Also + ======== + + elliptic_f + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Elliptic_integrals + .. [2] https://functions.wolfram.com/EllipticIntegrals/EllipticK + + """ + + @classmethod + def eval(cls, m): + if m.is_zero: + return pi*S.Half + elif m is S.Half: + return 8*pi**Rational(3, 2)/gamma(Rational(-1, 4))**2 + elif m is S.One: + return S.ComplexInfinity + elif m is S.NegativeOne: + return gamma(Rational(1, 4))**2/(4*sqrt(2*pi)) + elif m in (S.Infinity, S.NegativeInfinity, I*S.Infinity, + I*S.NegativeInfinity, S.ComplexInfinity): + return S.Zero + + def fdiff(self, argindex=1): + m = self.args[0] + return (elliptic_e(m) - (1 - m)*elliptic_k(m))/(2*m*(1 - m)) + + def _eval_conjugate(self): + m = self.args[0] + if (m.is_real and (m - 1).is_positive) is False: + return self.func(m.conjugate()) + + def _eval_nseries(self, x, n, logx, cdir=0): + from sympy.simplify import hyperexpand + return hyperexpand(self.rewrite(hyper)._eval_nseries(x, n=n, logx=logx)) + + def _eval_rewrite_as_hyper(self, m, **kwargs): + return pi*S.Half*hyper((S.Half, S.Half), (S.One,), m) + + def _eval_rewrite_as_meijerg(self, m, **kwargs): + return meijerg(((S.Half, S.Half), []), ((S.Zero,), (S.Zero,)), -m)/2 + + def _eval_is_zero(self): + m = self.args[0] + if m.is_infinite: + return True + + def _eval_rewrite_as_Integral(self, *args, **kwargs): + from sympy.integrals.integrals import Integral + t = Dummy(uniquely_named_symbol('t', args).name) + m = self.args[0] + return Integral(1/sqrt(1 - m*sin(t)**2), (t, 0, pi/2)) + + +class elliptic_f(DefinedFunction): + r""" + The Legendre incomplete elliptic integral of the first + kind, defined by + + .. math:: F\left(z\middle| m\right) = + \int_0^z \frac{dt}{\sqrt{1 - m \sin^2 t}} + + Explanation + =========== + + This function reduces to a complete elliptic integral of + the first kind, $K(m)$, when $z = \pi/2$. + + Note that our notation defines the incomplete elliptic integral + in terms of the parameter $m$ instead of the elliptic modulus + (eccentricity) $k$. + In this case, the parameter $m$ is defined as $m=k^2$. + + Examples + ======== + + >>> from sympy import elliptic_f, I + >>> from sympy.abc import z, m + >>> elliptic_f(z, m).series(z) + z + z**5*(3*m**2/40 - m/30) + m*z**3/6 + O(z**6) + >>> elliptic_f(3.0 + I/2, 1.0 + I) + 2.909449841483 + 1.74720545502474*I + + See Also + ======== + + elliptic_k + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Elliptic_integrals + .. [2] https://functions.wolfram.com/EllipticIntegrals/EllipticF + + """ + + @classmethod + def eval(cls, z, m): + if z.is_zero: + return S.Zero + if m.is_zero: + return z + k = 2*z/pi + if k.is_integer: + return k*elliptic_k(m) + elif m in (S.Infinity, S.NegativeInfinity): + return S.Zero + elif z.could_extract_minus_sign(): + return -elliptic_f(-z, m) + + def fdiff(self, argindex=1): + z, m = self.args + fm = sqrt(1 - m*sin(z)**2) + if argindex == 1: + return 1/fm + elif argindex == 2: + return (elliptic_e(z, m)/(2*m*(1 - m)) - elliptic_f(z, m)/(2*m) - + sin(2*z)/(4*(1 - m)*fm)) + raise ArgumentIndexError(self, argindex) + + def _eval_conjugate(self): + z, m = self.args + if (m.is_real and (m - 1).is_positive) is False: + return self.func(z.conjugate(), m.conjugate()) + + def _eval_rewrite_as_Integral(self, *args, **kwargs): + from sympy.integrals.integrals import Integral + t = Dummy(uniquely_named_symbol('t', args).name) + z, m = self.args[0], self.args[1] + return Integral(1/(sqrt(1 - m*sin(t)**2)), (t, 0, z)) + + def _eval_is_zero(self): + z, m = self.args + if z.is_zero: + return True + if m.is_extended_real and m.is_infinite: + return True + + +class elliptic_e(DefinedFunction): + r""" + Called with two arguments $z$ and $m$, evaluates the + incomplete elliptic integral of the second kind, defined by + + .. math:: E\left(z\middle| m\right) = \int_0^z \sqrt{1 - m \sin^2 t} dt + + Called with a single argument $m$, evaluates the Legendre complete + elliptic integral of the second kind + + .. math:: E(m) = E\left(\tfrac{\pi}{2}\middle| m\right) + + Explanation + =========== + + The function $E(m)$ is a single-valued function on the complex + plane with branch cut along the interval $(1, \infty)$. + + Note that our notation defines the incomplete elliptic integral + in terms of the parameter $m$ instead of the elliptic modulus + (eccentricity) $k$. + In this case, the parameter $m$ is defined as $m=k^2$. + + Examples + ======== + + >>> from sympy import elliptic_e, I + >>> from sympy.abc import z, m + >>> elliptic_e(z, m).series(z) + z + z**5*(-m**2/40 + m/30) - m*z**3/6 + O(z**6) + >>> elliptic_e(m).series(n=4) + pi/2 - pi*m/8 - 3*pi*m**2/128 - 5*pi*m**3/512 + O(m**4) + >>> elliptic_e(1 + I, 2 - I/2).n() + 1.55203744279187 + 0.290764986058437*I + >>> elliptic_e(0) + pi/2 + >>> elliptic_e(2.0 - I) + 0.991052601328069 + 0.81879421395609*I + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Elliptic_integrals + .. [2] https://functions.wolfram.com/EllipticIntegrals/EllipticE2 + .. [3] https://functions.wolfram.com/EllipticIntegrals/EllipticE + + """ + + @classmethod + def eval(cls, m, z=None): + if z is not None: + z, m = m, z + k = 2*z/pi + if m.is_zero: + return z + if z.is_zero: + return S.Zero + elif k.is_integer: + return k*elliptic_e(m) + elif m in (S.Infinity, S.NegativeInfinity): + return S.ComplexInfinity + elif z.could_extract_minus_sign(): + return -elliptic_e(-z, m) + else: + if m.is_zero: + return pi/2 + elif m is S.One: + return S.One + elif m is S.Infinity: + return I*S.Infinity + elif m is S.NegativeInfinity: + return S.Infinity + elif m is S.ComplexInfinity: + return S.ComplexInfinity + + def fdiff(self, argindex=1): + if len(self.args) == 2: + z, m = self.args + if argindex == 1: + return sqrt(1 - m*sin(z)**2) + elif argindex == 2: + return (elliptic_e(z, m) - elliptic_f(z, m))/(2*m) + else: + m = self.args[0] + if argindex == 1: + return (elliptic_e(m) - elliptic_k(m))/(2*m) + raise ArgumentIndexError(self, argindex) + + def _eval_conjugate(self): + if len(self.args) == 2: + z, m = self.args + if (m.is_real and (m - 1).is_positive) is False: + return self.func(z.conjugate(), m.conjugate()) + else: + m = self.args[0] + if (m.is_real and (m - 1).is_positive) is False: + return self.func(m.conjugate()) + + def _eval_nseries(self, x, n, logx, cdir=0): + from sympy.simplify import hyperexpand + if len(self.args) == 1: + return hyperexpand(self.rewrite(hyper)._eval_nseries(x, n=n, logx=logx)) + return super()._eval_nseries(x, n=n, logx=logx) + + def _eval_rewrite_as_hyper(self, *args, **kwargs): + if len(args) == 1: + m = args[0] + return (pi/2)*hyper((Rational(-1, 2), S.Half), (S.One,), m) + + def _eval_rewrite_as_meijerg(self, *args, **kwargs): + if len(args) == 1: + m = args[0] + return -meijerg(((S.Half, Rational(3, 2)), []), \ + ((S.Zero,), (S.Zero,)), -m)/4 + + def _eval_rewrite_as_Integral(self, *args, **kwargs): + from sympy.integrals.integrals import Integral + z, m = (pi/2, self.args[0]) if len(self.args) == 1 else self.args + t = Dummy(uniquely_named_symbol('t', args).name) + return Integral(sqrt(1 - m*sin(t)**2), (t, 0, z)) + + +class elliptic_pi(DefinedFunction): + r""" + Called with three arguments $n$, $z$ and $m$, evaluates the + Legendre incomplete elliptic integral of the third kind, defined by + + .. math:: \Pi\left(n; z\middle| m\right) = \int_0^z \frac{dt} + {\left(1 - n \sin^2 t\right) \sqrt{1 - m \sin^2 t}} + + Called with two arguments $n$ and $m$, evaluates the complete + elliptic integral of the third kind: + + .. math:: \Pi\left(n\middle| m\right) = + \Pi\left(n; \tfrac{\pi}{2}\middle| m\right) + + Explanation + =========== + + Note that our notation defines the incomplete elliptic integral + in terms of the parameter $m$ instead of the elliptic modulus + (eccentricity) $k$. + In this case, the parameter $m$ is defined as $m=k^2$. + + Examples + ======== + + >>> from sympy import elliptic_pi, I + >>> from sympy.abc import z, n, m + >>> elliptic_pi(n, z, m).series(z, n=4) + z + z**3*(m/6 + n/3) + O(z**4) + >>> elliptic_pi(0.5 + I, 1.0 - I, 1.2) + 2.50232379629182 - 0.760939574180767*I + >>> elliptic_pi(0, 0) + pi/2 + >>> elliptic_pi(1.0 - I/3, 2.0 + I) + 3.29136443417283 + 0.32555634906645*I + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Elliptic_integrals + .. [2] https://functions.wolfram.com/EllipticIntegrals/EllipticPi3 + .. [3] https://functions.wolfram.com/EllipticIntegrals/EllipticPi + + """ + + @classmethod + def eval(cls, n, m, z=None): + if z is not None: + z, m = m, z + if n.is_zero: + return elliptic_f(z, m) + elif n is S.One: + return (elliptic_f(z, m) + + (sqrt(1 - m*sin(z)**2)*tan(z) - + elliptic_e(z, m))/(1 - m)) + k = 2*z/pi + if k.is_integer: + return k*elliptic_pi(n, m) + elif m.is_zero: + return atanh(sqrt(n - 1)*tan(z))/sqrt(n - 1) + elif n == m: + return (elliptic_f(z, n) - elliptic_pi(1, z, n) + + tan(z)/sqrt(1 - n*sin(z)**2)) + elif n in (S.Infinity, S.NegativeInfinity): + return S.Zero + elif m in (S.Infinity, S.NegativeInfinity): + return S.Zero + elif z.could_extract_minus_sign(): + return -elliptic_pi(n, -z, m) + if n.is_zero: + return elliptic_f(z, m) + if m.is_extended_real and m.is_infinite or \ + n.is_extended_real and n.is_infinite: + return S.Zero + else: + if n.is_zero: + return elliptic_k(m) + elif n is S.One: + return S.ComplexInfinity + elif m.is_zero: + return pi/(2*sqrt(1 - n)) + elif m == S.One: + return S.NegativeInfinity/sign(n - 1) + elif n == m: + return elliptic_e(n)/(1 - n) + elif n in (S.Infinity, S.NegativeInfinity): + return S.Zero + elif m in (S.Infinity, S.NegativeInfinity): + return S.Zero + if n.is_zero: + return elliptic_k(m) + if m.is_extended_real and m.is_infinite or \ + n.is_extended_real and n.is_infinite: + return S.Zero + + def _eval_conjugate(self): + if len(self.args) == 3: + n, z, m = self.args + if (n.is_real and (n - 1).is_positive) is False and \ + (m.is_real and (m - 1).is_positive) is False: + return self.func(n.conjugate(), z.conjugate(), m.conjugate()) + else: + n, m = self.args + return self.func(n.conjugate(), m.conjugate()) + + def fdiff(self, argindex=1): + if len(self.args) == 3: + n, z, m = self.args + fm, fn = sqrt(1 - m*sin(z)**2), 1 - n*sin(z)**2 + if argindex == 1: + return (elliptic_e(z, m) + (m - n)*elliptic_f(z, m)/n + + (n**2 - m)*elliptic_pi(n, z, m)/n - + n*fm*sin(2*z)/(2*fn))/(2*(m - n)*(n - 1)) + elif argindex == 2: + return 1/(fm*fn) + elif argindex == 3: + return (elliptic_e(z, m)/(m - 1) + + elliptic_pi(n, z, m) - + m*sin(2*z)/(2*(m - 1)*fm))/(2*(n - m)) + else: + n, m = self.args + if argindex == 1: + return (elliptic_e(m) + (m - n)*elliptic_k(m)/n + + (n**2 - m)*elliptic_pi(n, m)/n)/(2*(m - n)*(n - 1)) + elif argindex == 2: + return (elliptic_e(m)/(m - 1) + elliptic_pi(n, m))/(2*(n - m)) + raise ArgumentIndexError(self, argindex) + + def _eval_rewrite_as_Integral(self, *args, **kwargs): + from sympy.integrals.integrals import Integral + if len(self.args) == 2: + n, m, z = self.args[0], self.args[1], pi/2 + else: + n, z, m = self.args + t = Dummy(uniquely_named_symbol('t', args).name) + return Integral(1/((1 - n*sin(t)**2)*sqrt(1 - m*sin(t)**2)), (t, 0, z)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/error_functions.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/error_functions.py new file mode 100644 index 0000000000000000000000000000000000000000..a778127d8b80583a892285fadbb8230f72de39f9 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/error_functions.py @@ -0,0 +1,2801 @@ +""" This module contains various functions that are special cases + of incomplete gamma functions. It should probably be renamed. """ + +from sympy.core import EulerGamma # Must be imported from core, not core.numbers +from sympy.core.add import Add +from sympy.core.cache import cacheit +from sympy.core.function import DefinedFunction, ArgumentIndexError, expand_mul +from sympy.core.logic import fuzzy_or +from sympy.core.numbers import I, pi, Rational, Integer +from sympy.core.relational import is_eq +from sympy.core.power import Pow +from sympy.core.singleton import S +from sympy.core.symbol import Dummy, uniquely_named_symbol +from sympy.core.sympify import sympify +from sympy.functions.combinatorial.factorials import factorial, factorial2, RisingFactorial +from sympy.functions.elementary.complexes import polar_lift, re, unpolarify +from sympy.functions.elementary.integers import ceiling, floor +from sympy.functions.elementary.miscellaneous import sqrt, root +from sympy.functions.elementary.exponential import exp, log, exp_polar +from sympy.functions.elementary.hyperbolic import cosh, sinh +from sympy.functions.elementary.trigonometric import cos, sin, sinc +from sympy.functions.special.hyper import hyper, meijerg + +# TODO series expansions +# TODO see the "Note:" in Ei + +# Helper function +def real_to_real_as_real_imag(self, deep=True, **hints): + if self.args[0].is_extended_real: + if deep: + hints['complex'] = False + return (self.expand(deep, **hints), S.Zero) + else: + return (self, S.Zero) + if deep: + x, y = self.args[0].expand(deep, **hints).as_real_imag() + else: + x, y = self.args[0].as_real_imag() + re = (self.func(x + I*y) + self.func(x - I*y))/2 + im = (self.func(x + I*y) - self.func(x - I*y))/(2*I) + return (re, im) + + +############################################################################### +################################ ERROR FUNCTION ############################### +############################################################################### + + +class erf(DefinedFunction): + r""" + The Gauss error function. + + Explanation + =========== + + This function is defined as: + + .. math :: + \mathrm{erf}(x) = \frac{2}{\sqrt{\pi}} \int_0^x e^{-t^2} \mathrm{d}t. + + Examples + ======== + + >>> from sympy import I, oo, erf + >>> from sympy.abc import z + + Several special values are known: + + >>> erf(0) + 0 + >>> erf(oo) + 1 + >>> erf(-oo) + -1 + >>> erf(I*oo) + oo*I + >>> erf(-I*oo) + -oo*I + + In general one can pull out factors of -1 and $I$ from the argument: + + >>> erf(-z) + -erf(z) + + The error function obeys the mirror symmetry: + + >>> from sympy import conjugate + >>> conjugate(erf(z)) + erf(conjugate(z)) + + Differentiation with respect to $z$ is supported: + + >>> from sympy import diff + >>> diff(erf(z), z) + 2*exp(-z**2)/sqrt(pi) + + We can numerically evaluate the error function to arbitrary precision + on the whole complex plane: + + >>> erf(4).evalf(30) + 0.999999984582742099719981147840 + + >>> erf(-4*I).evalf(30) + -1296959.73071763923152794095062*I + + See Also + ======== + + erfc: Complementary error function. + erfi: Imaginary error function. + erf2: Two-argument error function. + erfinv: Inverse error function. + erfcinv: Inverse Complementary error function. + erf2inv: Inverse two-argument error function. + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Error_function + .. [2] https://dlmf.nist.gov/7 + .. [3] https://mathworld.wolfram.com/Erf.html + .. [4] https://functions.wolfram.com/GammaBetaErf/Erf + + """ + + unbranched = True + + def fdiff(self, argindex=1): + if argindex == 1: + return 2*exp(-self.args[0]**2)/sqrt(pi) + else: + raise ArgumentIndexError(self, argindex) + + + def inverse(self, argindex=1): + """ + Returns the inverse of this function. + + """ + return erfinv + + @classmethod + def eval(cls, arg): + if arg.is_Number: + if arg is S.NaN: + return S.NaN + elif arg is S.Infinity: + return S.One + elif arg is S.NegativeInfinity: + return S.NegativeOne + elif arg.is_zero: + return S.Zero + + if isinstance(arg, erfinv): + return arg.args[0] + + if isinstance(arg, erfcinv): + return S.One - arg.args[0] + + if arg.is_zero: + return S.Zero + + # Only happens with unevaluated erf2inv + if isinstance(arg, erf2inv) and arg.args[0].is_zero: + return arg.args[1] + + # Try to pull out factors of I + t = arg.extract_multiplicatively(I) + if t in (S.Infinity, S.NegativeInfinity): + return arg + + # Try to pull out factors of -1 + if arg.could_extract_minus_sign(): + return -cls(-arg) + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + if n < 0 or n % 2 == 0: + return S.Zero + else: + x = sympify(x) + k = floor((n - 1)/S(2)) + if len(previous_terms) > 2: + return -previous_terms[-2] * x**2 * (n - 2)/(n*k) + else: + return 2*S.NegativeOne**k * x**n/(n*factorial(k)*sqrt(pi)) + + def _eval_conjugate(self): + return self.func(self.args[0].conjugate()) + + def _eval_is_real(self): + if self.args[0].is_extended_real is True: + return True + # There are cases where erf(z) becomes a real number + # even if z is a complex number + + def _eval_is_imaginary(self): + if self.args[0].is_imaginary is True: + return True + + def _eval_is_finite(self): + z = self.args[0] + return fuzzy_or([z.is_finite, z.is_extended_real]) + + def _eval_is_zero(self): + if self.args[0].is_extended_real is True: + return self.args[0].is_zero + + def _eval_is_positive(self): + if self.args[0].is_extended_real is True: + return self.args[0].is_extended_positive + + def _eval_is_negative(self): + if self.args[0].is_extended_real is True: + return self.args[0].is_extended_negative + + def _eval_rewrite_as_uppergamma(self, z, **kwargs): + from sympy.functions.special.gamma_functions import uppergamma + return sqrt(z**2)/z*(S.One - uppergamma(S.Half, z**2)/sqrt(pi)) + + def _eval_rewrite_as_fresnels(self, z, **kwargs): + arg = (S.One - I)*z/sqrt(pi) + return (S.One + I)*(fresnelc(arg) - I*fresnels(arg)) + + def _eval_rewrite_as_fresnelc(self, z, **kwargs): + arg = (S.One - I)*z/sqrt(pi) + return (S.One + I)*(fresnelc(arg) - I*fresnels(arg)) + + def _eval_rewrite_as_meijerg(self, z, **kwargs): + return z/sqrt(pi)*meijerg([S.Half], [], [0], [Rational(-1, 2)], z**2) + + def _eval_rewrite_as_hyper(self, z, **kwargs): + return 2*z/sqrt(pi)*hyper([S.Half], [3*S.Half], -z**2) + + def _eval_rewrite_as_expint(self, z, **kwargs): + return sqrt(z**2)/z - z*expint(S.Half, z**2)/sqrt(pi) + + def _eval_rewrite_as_tractable(self, z, limitvar=None, **kwargs): + from sympy.series.limits import limit + if limitvar: + lim = limit(z, limitvar, S.Infinity) + if lim is S.NegativeInfinity: + return S.NegativeOne + _erfs(-z)*exp(-z**2) + return S.One - _erfs(z)*exp(-z**2) + + def _eval_rewrite_as_erfc(self, z, **kwargs): + return S.One - erfc(z) + + def _eval_rewrite_as_erfi(self, z, **kwargs): + return -I*erfi(I*z) + + def _eval_as_leading_term(self, x, logx, cdir): + arg = self.args[0].as_leading_term(x, logx=logx, cdir=cdir) + arg0 = arg.subs(x, 0) + + if arg0 is S.ComplexInfinity: + arg0 = arg.limit(x, 0, dir='-' if cdir == -1 else '+') + if x in arg.free_symbols and arg0.is_zero: + return 2*arg/sqrt(pi) + else: + return self.func(arg0) + + def _eval_aseries(self, n, args0, x, logx): + from sympy.series.order import Order + point = args0[0] + + if point in [S.Infinity, S.NegativeInfinity]: + z = self.args[0] + + try: + _, ex = z.leadterm(x) + except (ValueError, NotImplementedError): + return self + + ex = -ex # as x->1/x for aseries + if ex.is_positive: + newn = ceiling(n/ex) + s = [S.NegativeOne**k * factorial2(2*k - 1) / (z**(2*k + 1) * 2**k) + for k in range(newn)] + [Order(1/z**newn, x)] + return S.One - (exp(-z**2)/sqrt(pi)) * Add(*s) + + return super(erf, self)._eval_aseries(n, args0, x, logx) + + as_real_imag = real_to_real_as_real_imag + + +class erfc(DefinedFunction): + r""" + Complementary Error Function. + + Explanation + =========== + + The function is defined as: + + .. math :: + \mathrm{erfc}(x) = \frac{2}{\sqrt{\pi}} \int_x^\infty e^{-t^2} \mathrm{d}t + + Examples + ======== + + >>> from sympy import I, oo, erfc + >>> from sympy.abc import z + + Several special values are known: + + >>> erfc(0) + 1 + >>> erfc(oo) + 0 + >>> erfc(-oo) + 2 + >>> erfc(I*oo) + -oo*I + >>> erfc(-I*oo) + oo*I + + The error function obeys the mirror symmetry: + + >>> from sympy import conjugate + >>> conjugate(erfc(z)) + erfc(conjugate(z)) + + Differentiation with respect to $z$ is supported: + + >>> from sympy import diff + >>> diff(erfc(z), z) + -2*exp(-z**2)/sqrt(pi) + + It also follows + + >>> erfc(-z) + 2 - erfc(z) + + We can numerically evaluate the complementary error function to arbitrary + precision on the whole complex plane: + + >>> erfc(4).evalf(30) + 0.0000000154172579002800188521596734869 + + >>> erfc(4*I).evalf(30) + 1.0 - 1296959.73071763923152794095062*I + + See Also + ======== + + erf: Gaussian error function. + erfi: Imaginary error function. + erf2: Two-argument error function. + erfinv: Inverse error function. + erfcinv: Inverse Complementary error function. + erf2inv: Inverse two-argument error function. + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Error_function + .. [2] https://dlmf.nist.gov/7 + .. [3] https://mathworld.wolfram.com/Erfc.html + .. [4] https://functions.wolfram.com/GammaBetaErf/Erfc + + """ + + unbranched = True + + def fdiff(self, argindex=1): + if argindex == 1: + return -2*exp(-self.args[0]**2)/sqrt(pi) + else: + raise ArgumentIndexError(self, argindex) + + def inverse(self, argindex=1): + """ + Returns the inverse of this function. + + """ + return erfcinv + + @classmethod + def eval(cls, arg): + if arg.is_Number: + if arg is S.NaN: + return S.NaN + elif arg is S.Infinity: + return S.Zero + elif arg.is_zero: + return S.One + + if isinstance(arg, erfinv): + return S.One - arg.args[0] + + if isinstance(arg, erfcinv): + return arg.args[0] + + if arg.is_zero: + return S.One + + # Try to pull out factors of I + t = arg.extract_multiplicatively(I) + if t in (S.Infinity, S.NegativeInfinity): + return -arg + + # Try to pull out factors of -1 + if arg.could_extract_minus_sign(): + return 2 - cls(-arg) + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + if n == 0: + return S.One + elif n < 0 or n % 2 == 0: + return S.Zero + else: + x = sympify(x) + k = floor((n - 1)/S(2)) + if len(previous_terms) > 2: + return -previous_terms[-2] * x**2 * (n - 2)/(n*k) + else: + return -2*S.NegativeOne**k * x**n/(n*factorial(k)*sqrt(pi)) + + def _eval_conjugate(self): + return self.func(self.args[0].conjugate()) + + def _eval_is_real(self): + if self.args[0].is_extended_real is True: + return True + if self.args[0].is_imaginary is True: + return False + + def _eval_rewrite_as_tractable(self, z, limitvar=None, **kwargs): + return self.rewrite(erf).rewrite("tractable", deep=True, limitvar=limitvar) + + def _eval_rewrite_as_erf(self, z, **kwargs): + return S.One - erf(z) + + def _eval_rewrite_as_erfi(self, z, **kwargs): + return S.One + I*erfi(I*z) + + def _eval_rewrite_as_fresnels(self, z, **kwargs): + arg = (S.One - I)*z/sqrt(pi) + return S.One - (S.One + I)*(fresnelc(arg) - I*fresnels(arg)) + + def _eval_rewrite_as_fresnelc(self, z, **kwargs): + arg = (S.One-I)*z/sqrt(pi) + return S.One - (S.One + I)*(fresnelc(arg) - I*fresnels(arg)) + + def _eval_rewrite_as_meijerg(self, z, **kwargs): + return S.One - z/sqrt(pi)*meijerg([S.Half], [], [0], [Rational(-1, 2)], z**2) + + def _eval_rewrite_as_hyper(self, z, **kwargs): + return S.One - 2*z/sqrt(pi)*hyper([S.Half], [3*S.Half], -z**2) + + def _eval_rewrite_as_uppergamma(self, z, **kwargs): + from sympy.functions.special.gamma_functions import uppergamma + return S.One - sqrt(z**2)/z*(S.One - uppergamma(S.Half, z**2)/sqrt(pi)) + + def _eval_rewrite_as_expint(self, z, **kwargs): + return S.One - sqrt(z**2)/z + z*expint(S.Half, z**2)/sqrt(pi) + + def _eval_expand_func(self, **hints): + return self.rewrite(erf) + + def _eval_as_leading_term(self, x, logx, cdir): + arg = self.args[0].as_leading_term(x, logx=logx, cdir=cdir) + arg0 = arg.subs(x, 0) + + if arg0 is S.ComplexInfinity: + arg0 = arg.limit(x, 0, dir='-' if cdir == -1 else '+') + if arg0.is_zero: + return S.One + else: + return self.func(arg0) + + as_real_imag = real_to_real_as_real_imag + + def _eval_aseries(self, n, args0, x, logx): + return S.One - erf(*self.args)._eval_aseries(n, args0, x, logx) + + +class erfi(DefinedFunction): + r""" + Imaginary error function. + + Explanation + =========== + + The function erfi is defined as: + + .. math :: + \mathrm{erfi}(x) = \frac{2}{\sqrt{\pi}} \int_0^x e^{t^2} \mathrm{d}t + + Examples + ======== + + >>> from sympy import I, oo, erfi + >>> from sympy.abc import z + + Several special values are known: + + >>> erfi(0) + 0 + >>> erfi(oo) + oo + >>> erfi(-oo) + -oo + >>> erfi(I*oo) + I + >>> erfi(-I*oo) + -I + + In general one can pull out factors of -1 and $I$ from the argument: + + >>> erfi(-z) + -erfi(z) + + >>> from sympy import conjugate + >>> conjugate(erfi(z)) + erfi(conjugate(z)) + + Differentiation with respect to $z$ is supported: + + >>> from sympy import diff + >>> diff(erfi(z), z) + 2*exp(z**2)/sqrt(pi) + + We can numerically evaluate the imaginary error function to arbitrary + precision on the whole complex plane: + + >>> erfi(2).evalf(30) + 18.5648024145755525987042919132 + + >>> erfi(-2*I).evalf(30) + -0.995322265018952734162069256367*I + + See Also + ======== + + erf: Gaussian error function. + erfc: Complementary error function. + erf2: Two-argument error function. + erfinv: Inverse error function. + erfcinv: Inverse Complementary error function. + erf2inv: Inverse two-argument error function. + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Error_function + .. [2] https://mathworld.wolfram.com/Erfi.html + .. [3] https://functions.wolfram.com/GammaBetaErf/Erfi + + """ + + unbranched = True + + def fdiff(self, argindex=1): + if argindex == 1: + return 2*exp(self.args[0]**2)/sqrt(pi) + else: + raise ArgumentIndexError(self, argindex) + + @classmethod + def eval(cls, z): + if z.is_Number: + if z is S.NaN: + return S.NaN + elif z.is_zero: + return S.Zero + elif z is S.Infinity: + return S.Infinity + + if z.is_zero: + return S.Zero + + # Try to pull out factors of -1 + if z.could_extract_minus_sign(): + return -cls(-z) + + # Try to pull out factors of I + nz = z.extract_multiplicatively(I) + if nz is not None: + if nz is S.Infinity: + return I + if isinstance(nz, erfinv): + return I*nz.args[0] + if isinstance(nz, erfcinv): + return I*(S.One - nz.args[0]) + # Only happens with unevaluated erf2inv + if isinstance(nz, erf2inv) and nz.args[0].is_zero: + return I*nz.args[1] + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + if n < 0 or n % 2 == 0: + return S.Zero + else: + x = sympify(x) + k = floor((n - 1)/S(2)) + if len(previous_terms) > 2: + return previous_terms[-2] * x**2 * (n - 2)/(n*k) + else: + return 2 * x**n/(n*factorial(k)*sqrt(pi)) + + def _eval_conjugate(self): + return self.func(self.args[0].conjugate()) + + def _eval_is_extended_real(self): + return self.args[0].is_extended_real + + def _eval_is_zero(self): + return self.args[0].is_zero + + def _eval_rewrite_as_tractable(self, z, limitvar=None, **kwargs): + return self.rewrite(erf).rewrite("tractable", deep=True, limitvar=limitvar) + + def _eval_rewrite_as_erf(self, z, **kwargs): + return -I*erf(I*z) + + def _eval_rewrite_as_erfc(self, z, **kwargs): + return I*erfc(I*z) - I + + def _eval_rewrite_as_fresnels(self, z, **kwargs): + arg = (S.One + I)*z/sqrt(pi) + return (S.One - I)*(fresnelc(arg) - I*fresnels(arg)) + + def _eval_rewrite_as_fresnelc(self, z, **kwargs): + arg = (S.One + I)*z/sqrt(pi) + return (S.One - I)*(fresnelc(arg) - I*fresnels(arg)) + + def _eval_rewrite_as_meijerg(self, z, **kwargs): + return z/sqrt(pi)*meijerg([S.Half], [], [0], [Rational(-1, 2)], -z**2) + + def _eval_rewrite_as_hyper(self, z, **kwargs): + return 2*z/sqrt(pi)*hyper([S.Half], [3*S.Half], z**2) + + def _eval_rewrite_as_uppergamma(self, z, **kwargs): + from sympy.functions.special.gamma_functions import uppergamma + return sqrt(-z**2)/z*(uppergamma(S.Half, -z**2)/sqrt(pi) - S.One) + + def _eval_rewrite_as_expint(self, z, **kwargs): + return sqrt(-z**2)/z - z*expint(S.Half, -z**2)/sqrt(pi) + + def _eval_expand_func(self, **hints): + return self.rewrite(erf) + + as_real_imag = real_to_real_as_real_imag + + def _eval_as_leading_term(self, x, logx, cdir): + arg = self.args[0].as_leading_term(x, logx=logx, cdir=cdir) + arg0 = arg.subs(x, 0) + + if x in arg.free_symbols and arg0.is_zero: + return 2*arg/sqrt(pi) + elif arg0.is_finite: + return self.func(arg0) + return self.func(arg) + + def _eval_aseries(self, n, args0, x, logx): + from sympy.series.order import Order + point = args0[0] + + if point is S.Infinity: + z = self.args[0] + s = [factorial2(2*k - 1) / (2**k * z**(2*k + 1)) + for k in range(n)] + [Order(1/z**n, x)] + return -I + (exp(z**2)/sqrt(pi)) * Add(*s) + + return super(erfi, self)._eval_aseries(n, args0, x, logx) + + +class erf2(DefinedFunction): + r""" + Two-argument error function. + + Explanation + =========== + + This function is defined as: + + .. math :: + \mathrm{erf2}(x, y) = \frac{2}{\sqrt{\pi}} \int_x^y e^{-t^2} \mathrm{d}t + + Examples + ======== + + >>> from sympy import oo, erf2 + >>> from sympy.abc import x, y + + Several special values are known: + + >>> erf2(0, 0) + 0 + >>> erf2(x, x) + 0 + >>> erf2(x, oo) + 1 - erf(x) + >>> erf2(x, -oo) + -erf(x) - 1 + >>> erf2(oo, y) + erf(y) - 1 + >>> erf2(-oo, y) + erf(y) + 1 + + In general one can pull out factors of -1: + + >>> erf2(-x, -y) + -erf2(x, y) + + The error function obeys the mirror symmetry: + + >>> from sympy import conjugate + >>> conjugate(erf2(x, y)) + erf2(conjugate(x), conjugate(y)) + + Differentiation with respect to $x$, $y$ is supported: + + >>> from sympy import diff + >>> diff(erf2(x, y), x) + -2*exp(-x**2)/sqrt(pi) + >>> diff(erf2(x, y), y) + 2*exp(-y**2)/sqrt(pi) + + See Also + ======== + + erf: Gaussian error function. + erfc: Complementary error function. + erfi: Imaginary error function. + erfinv: Inverse error function. + erfcinv: Inverse Complementary error function. + erf2inv: Inverse two-argument error function. + + References + ========== + + .. [1] https://functions.wolfram.com/GammaBetaErf/Erf2/ + + """ + + + def fdiff(self, argindex): + x, y = self.args + if argindex == 1: + return -2*exp(-x**2)/sqrt(pi) + elif argindex == 2: + return 2*exp(-y**2)/sqrt(pi) + else: + raise ArgumentIndexError(self, argindex) + + @classmethod + def eval(cls, x, y): + chk = (S.Infinity, S.NegativeInfinity, S.Zero) + if x is S.NaN or y is S.NaN: + return S.NaN + elif x == y: + return S.Zero + elif x in chk or y in chk: + return erf(y) - erf(x) + + if isinstance(y, erf2inv) and y.args[0] == x: + return y.args[1] + + if x.is_zero or y.is_zero or x.is_extended_real and x.is_infinite or \ + y.is_extended_real and y.is_infinite: + return erf(y) - erf(x) + + #Try to pull out -1 factor + sign_x = x.could_extract_minus_sign() + sign_y = y.could_extract_minus_sign() + if (sign_x and sign_y): + return -cls(-x, -y) + elif (sign_x or sign_y): + return erf(y)-erf(x) + + def _eval_conjugate(self): + return self.func(self.args[0].conjugate(), self.args[1].conjugate()) + + def _eval_is_extended_real(self): + return self.args[0].is_extended_real and self.args[1].is_extended_real + + def _eval_rewrite_as_erf(self, x, y, **kwargs): + return erf(y) - erf(x) + + def _eval_rewrite_as_erfc(self, x, y, **kwargs): + return erfc(x) - erfc(y) + + def _eval_rewrite_as_erfi(self, x, y, **kwargs): + return I*(erfi(I*x)-erfi(I*y)) + + def _eval_rewrite_as_fresnels(self, x, y, **kwargs): + return erf(y).rewrite(fresnels) - erf(x).rewrite(fresnels) + + def _eval_rewrite_as_fresnelc(self, x, y, **kwargs): + return erf(y).rewrite(fresnelc) - erf(x).rewrite(fresnelc) + + def _eval_rewrite_as_meijerg(self, x, y, **kwargs): + return erf(y).rewrite(meijerg) - erf(x).rewrite(meijerg) + + def _eval_rewrite_as_hyper(self, x, y, **kwargs): + return erf(y).rewrite(hyper) - erf(x).rewrite(hyper) + + def _eval_rewrite_as_uppergamma(self, x, y, **kwargs): + from sympy.functions.special.gamma_functions import uppergamma + return (sqrt(y**2)/y*(S.One - uppergamma(S.Half, y**2)/sqrt(pi)) - + sqrt(x**2)/x*(S.One - uppergamma(S.Half, x**2)/sqrt(pi))) + + def _eval_rewrite_as_expint(self, x, y, **kwargs): + return erf(y).rewrite(expint) - erf(x).rewrite(expint) + + def _eval_expand_func(self, **hints): + return self.rewrite(erf) + + def _eval_is_zero(self): + return is_eq(*self.args) + +class erfinv(DefinedFunction): + r""" + Inverse Error Function. The erfinv function is defined as: + + .. math :: + \mathrm{erf}(x) = y \quad \Rightarrow \quad \mathrm{erfinv}(y) = x + + Examples + ======== + + >>> from sympy import erfinv + >>> from sympy.abc import x + + Several special values are known: + + >>> erfinv(0) + 0 + >>> erfinv(1) + oo + + Differentiation with respect to $x$ is supported: + + >>> from sympy import diff + >>> diff(erfinv(x), x) + sqrt(pi)*exp(erfinv(x)**2)/2 + + We can numerically evaluate the inverse error function to arbitrary + precision on [-1, 1]: + + >>> erfinv(0.2).evalf(30) + 0.179143454621291692285822705344 + + See Also + ======== + + erf: Gaussian error function. + erfc: Complementary error function. + erfi: Imaginary error function. + erf2: Two-argument error function. + erfcinv: Inverse Complementary error function. + erf2inv: Inverse two-argument error function. + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Error_function#Inverse_functions + .. [2] https://functions.wolfram.com/GammaBetaErf/InverseErf/ + + """ + + + def fdiff(self, argindex =1): + if argindex == 1: + return sqrt(pi)*exp(self.func(self.args[0])**2)*S.Half + else : + raise ArgumentIndexError(self, argindex) + + def inverse(self, argindex=1): + """ + Returns the inverse of this function. + + """ + return erf + + @classmethod + def eval(cls, z): + if z is S.NaN: + return S.NaN + elif z is S.NegativeOne: + return S.NegativeInfinity + elif z.is_zero: + return S.Zero + elif z is S.One: + return S.Infinity + + if isinstance(z, erf) and z.args[0].is_extended_real: + return z.args[0] + + if z.is_zero: + return S.Zero + + # Try to pull out factors of -1 + nz = z.extract_multiplicatively(-1) + if nz is not None and (isinstance(nz, erf) and (nz.args[0]).is_extended_real): + return -nz.args[0] + + def _eval_rewrite_as_erfcinv(self, z, **kwargs): + return erfcinv(1-z) + + def _eval_is_zero(self): + return self.args[0].is_zero + + +class erfcinv (DefinedFunction): + r""" + Inverse Complementary Error Function. The erfcinv function is defined as: + + .. math :: + \mathrm{erfc}(x) = y \quad \Rightarrow \quad \mathrm{erfcinv}(y) = x + + Examples + ======== + + >>> from sympy import erfcinv + >>> from sympy.abc import x + + Several special values are known: + + >>> erfcinv(1) + 0 + >>> erfcinv(0) + oo + + Differentiation with respect to $x$ is supported: + + >>> from sympy import diff + >>> diff(erfcinv(x), x) + -sqrt(pi)*exp(erfcinv(x)**2)/2 + + See Also + ======== + + erf: Gaussian error function. + erfc: Complementary error function. + erfi: Imaginary error function. + erf2: Two-argument error function. + erfinv: Inverse error function. + erf2inv: Inverse two-argument error function. + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Error_function#Inverse_functions + .. [2] https://functions.wolfram.com/GammaBetaErf/InverseErfc/ + + """ + + + def fdiff(self, argindex =1): + if argindex == 1: + return -sqrt(pi)*exp(self.func(self.args[0])**2)*S.Half + else: + raise ArgumentIndexError(self, argindex) + + def inverse(self, argindex=1): + """ + Returns the inverse of this function. + + """ + return erfc + + @classmethod + def eval(cls, z): + if z is S.NaN: + return S.NaN + elif z.is_zero: + return S.Infinity + elif z is S.One: + return S.Zero + elif z == 2: + return S.NegativeInfinity + + if z.is_zero: + return S.Infinity + + def _eval_rewrite_as_erfinv(self, z, **kwargs): + return erfinv(1-z) + + def _eval_is_zero(self): + return (self.args[0] - 1).is_zero + + def _eval_is_infinite(self): + z = self.args[0] + return fuzzy_or([z.is_zero, is_eq(z, Integer(2))]) + + +class erf2inv(DefinedFunction): + r""" + Two-argument Inverse error function. The erf2inv function is defined as: + + .. math :: + \mathrm{erf2}(x, w) = y \quad \Rightarrow \quad \mathrm{erf2inv}(x, y) = w + + Examples + ======== + + >>> from sympy import erf2inv, oo + >>> from sympy.abc import x, y + + Several special values are known: + + >>> erf2inv(0, 0) + 0 + >>> erf2inv(1, 0) + 1 + >>> erf2inv(0, 1) + oo + >>> erf2inv(0, y) + erfinv(y) + >>> erf2inv(oo, y) + erfcinv(-y) + + Differentiation with respect to $x$ and $y$ is supported: + + >>> from sympy import diff + >>> diff(erf2inv(x, y), x) + exp(-x**2 + erf2inv(x, y)**2) + >>> diff(erf2inv(x, y), y) + sqrt(pi)*exp(erf2inv(x, y)**2)/2 + + See Also + ======== + + erf: Gaussian error function. + erfc: Complementary error function. + erfi: Imaginary error function. + erf2: Two-argument error function. + erfinv: Inverse error function. + erfcinv: Inverse complementary error function. + + References + ========== + + .. [1] https://functions.wolfram.com/GammaBetaErf/InverseErf2/ + + """ + + + def fdiff(self, argindex): + x, y = self.args + if argindex == 1: + return exp(self.func(x,y)**2-x**2) + elif argindex == 2: + return sqrt(pi)*S.Half*exp(self.func(x,y)**2) + else: + raise ArgumentIndexError(self, argindex) + + @classmethod + def eval(cls, x, y): + if x is S.NaN or y is S.NaN: + return S.NaN + elif x.is_zero and y.is_zero: + return S.Zero + elif x.is_zero and y is S.One: + return S.Infinity + elif x is S.One and y.is_zero: + return S.One + elif x.is_zero: + return erfinv(y) + elif x is S.Infinity: + return erfcinv(-y) + elif y.is_zero: + return x + elif y is S.Infinity: + return erfinv(x) + + if x.is_zero: + if y.is_zero: + return S.Zero + else: + return erfinv(y) + if y.is_zero: + return x + + def _eval_is_zero(self): + x, y = self.args + if x.is_zero and y.is_zero: + return True + +############################################################################### +#################### EXPONENTIAL INTEGRALS #################################### +############################################################################### + +class Ei(DefinedFunction): + r""" + The classical exponential integral. + + Explanation + =========== + + For use in SymPy, this function is defined as + + .. math:: \operatorname{Ei}(x) = \sum_{n=1}^\infty \frac{x^n}{n\, n!} + + \log(x) + \gamma, + + where $\gamma$ is the Euler-Mascheroni constant. + + If $x$ is a polar number, this defines an analytic function on the + Riemann surface of the logarithm. Otherwise this defines an analytic + function in the cut plane $\mathbb{C} \setminus (-\infty, 0]$. + + **Background** + + The name exponential integral comes from the following statement: + + .. math:: \operatorname{Ei}(x) = \int_{-\infty}^x \frac{e^t}{t} \mathrm{d}t + + If the integral is interpreted as a Cauchy principal value, this statement + holds for $x > 0$ and $\operatorname{Ei}(x)$ as defined above. + + Examples + ======== + + >>> from sympy import Ei, polar_lift, exp_polar, I, pi + >>> from sympy.abc import x + + >>> Ei(-1) + Ei(-1) + + This yields a real value: + + >>> Ei(-1).n(chop=True) + -0.219383934395520 + + On the other hand the analytic continuation is not real: + + >>> Ei(polar_lift(-1)).n(chop=True) + -0.21938393439552 + 3.14159265358979*I + + The exponential integral has a logarithmic branch point at the origin: + + >>> Ei(x*exp_polar(2*I*pi)) + Ei(x) + 2*I*pi + + Differentiation is supported: + + >>> Ei(x).diff(x) + exp(x)/x + + The exponential integral is related to many other special functions. + For example: + + >>> from sympy import expint, Shi + >>> Ei(x).rewrite(expint) + -expint(1, x*exp_polar(I*pi)) - I*pi + >>> Ei(x).rewrite(Shi) + Chi(x) + Shi(x) + + See Also + ======== + + expint: Generalised exponential integral. + E1: Special case of the generalised exponential integral. + li: Logarithmic integral. + Li: Offset logarithmic integral. + Si: Sine integral. + Ci: Cosine integral. + Shi: Hyperbolic sine integral. + Chi: Hyperbolic cosine integral. + uppergamma: Upper incomplete gamma function. + + References + ========== + + .. [1] https://dlmf.nist.gov/6.6 + .. [2] https://en.wikipedia.org/wiki/Exponential_integral + .. [3] Abramowitz & Stegun, section 5: https://web.archive.org/web/20201128173312/http://people.math.sfu.ca/~cbm/aands/page_228.htm + + """ + + + @classmethod + def eval(cls, z): + if z.is_zero: + return S.NegativeInfinity + elif z is S.Infinity: + return S.Infinity + elif z is S.NegativeInfinity: + return S.Zero + + if z.is_zero: + return S.NegativeInfinity + + nz, n = z.extract_branch_factor() + if n: + return Ei(nz) + 2*I*pi*n + + def fdiff(self, argindex=1): + arg = unpolarify(self.args[0]) + if argindex == 1: + return exp(arg)/arg + else: + raise ArgumentIndexError(self, argindex) + + def _eval_evalf(self, prec): + if (self.args[0]/polar_lift(-1)).is_positive: + return super()._eval_evalf(prec) + (I*pi)._eval_evalf(prec) + return super()._eval_evalf(prec) + + def _eval_rewrite_as_uppergamma(self, z, **kwargs): + from sympy.functions.special.gamma_functions import uppergamma + # XXX this does not currently work usefully because uppergamma + # immediately turns into expint + return -uppergamma(0, polar_lift(-1)*z) - I*pi + + def _eval_rewrite_as_expint(self, z, **kwargs): + return -expint(1, polar_lift(-1)*z) - I*pi + + def _eval_rewrite_as_li(self, z, **kwargs): + if isinstance(z, log): + return li(z.args[0]) + # TODO: + # Actually it only holds that: + # Ei(z) = li(exp(z)) + # for -pi < imag(z) <= pi + return li(exp(z)) + + def _eval_rewrite_as_Si(self, z, **kwargs): + if z.is_negative: + return Shi(z) + Chi(z) - I*pi + else: + return Shi(z) + Chi(z) + _eval_rewrite_as_Ci = _eval_rewrite_as_Si + _eval_rewrite_as_Chi = _eval_rewrite_as_Si + _eval_rewrite_as_Shi = _eval_rewrite_as_Si + + def _eval_rewrite_as_tractable(self, z, limitvar=None, **kwargs): + return exp(z) * _eis(z) + + def _eval_rewrite_as_Integral(self, z, **kwargs): + from sympy.integrals.integrals import Integral + t = Dummy(uniquely_named_symbol('t', [z]).name) + return Integral(S.Exp1**t/t, (t, S.NegativeInfinity, z)) + + def _eval_as_leading_term(self, x, logx, cdir): + from sympy import re + x0 = self.args[0].limit(x, 0) + arg = self.args[0].as_leading_term(x, cdir=cdir) + cdir = arg.dir(x, cdir) + if x0.is_zero: + c, e = arg.as_coeff_exponent(x) + logx = log(x) if logx is None else logx + return log(c) + e*logx + EulerGamma - ( + I*pi if re(cdir).is_negative else S.Zero) + return super()._eval_as_leading_term(x, logx=logx, cdir=cdir) + + def _eval_nseries(self, x, n, logx, cdir=0): + x0 = self.args[0].limit(x, 0) + if x0.is_zero: + f = self._eval_rewrite_as_Si(*self.args) + return f._eval_nseries(x, n, logx) + return super()._eval_nseries(x, n, logx) + + def _eval_aseries(self, n, args0, x, logx): + from sympy.series.order import Order + point = args0[0] + + if point in (S.Infinity, S.NegativeInfinity): + z = self.args[0] + s = [factorial(k) / (z)**k for k in range(n)] + \ + [Order(1/z**n, x)] + return (exp(z)/z) * Add(*s) + + return super(Ei, self)._eval_aseries(n, args0, x, logx) + + +class expint(DefinedFunction): + r""" + Generalized exponential integral. + + Explanation + =========== + + This function is defined as + + .. math:: \operatorname{E}_\nu(z) = z^{\nu - 1} \Gamma(1 - \nu, z), + + where $\Gamma(1 - \nu, z)$ is the upper incomplete gamma function + (``uppergamma``). + + Hence for $z$ with positive real part we have + + .. math:: \operatorname{E}_\nu(z) + = \int_1^\infty \frac{e^{-zt}}{t^\nu} \mathrm{d}t, + + which explains the name. + + The representation as an incomplete gamma function provides an analytic + continuation for $\operatorname{E}_\nu(z)$. If $\nu$ is a + non-positive integer, the exponential integral is thus an unbranched + function of $z$, otherwise there is a branch point at the origin. + Refer to the incomplete gamma function documentation for details of the + branching behavior. + + Examples + ======== + + >>> from sympy import expint, S + >>> from sympy.abc import nu, z + + Differentiation is supported. Differentiation with respect to $z$ further + explains the name: for integral orders, the exponential integral is an + iterated integral of the exponential function. + + >>> expint(nu, z).diff(z) + -expint(nu - 1, z) + + Differentiation with respect to $\nu$ has no classical expression: + + >>> expint(nu, z).diff(nu) + -z**(nu - 1)*meijerg(((), (1, 1)), ((0, 0, 1 - nu), ()), z) + + At non-postive integer orders, the exponential integral reduces to the + exponential function: + + >>> expint(0, z) + exp(-z)/z + >>> expint(-1, z) + exp(-z)/z + exp(-z)/z**2 + + At half-integers it reduces to error functions: + + >>> expint(S(1)/2, z) + sqrt(pi)*erfc(sqrt(z))/sqrt(z) + + At positive integer orders it can be rewritten in terms of exponentials + and ``expint(1, z)``. Use ``expand_func()`` to do this: + + >>> from sympy import expand_func + >>> expand_func(expint(5, z)) + z**4*expint(1, z)/24 + (-z**3 + z**2 - 2*z + 6)*exp(-z)/24 + + The generalised exponential integral is essentially equivalent to the + incomplete gamma function: + + >>> from sympy import uppergamma + >>> expint(nu, z).rewrite(uppergamma) + z**(nu - 1)*uppergamma(1 - nu, z) + + As such it is branched at the origin: + + >>> from sympy import exp_polar, pi, I + >>> expint(4, z*exp_polar(2*pi*I)) + I*pi*z**3/3 + expint(4, z) + >>> expint(nu, z*exp_polar(2*pi*I)) + z**(nu - 1)*(exp(2*I*pi*nu) - 1)*gamma(1 - nu) + expint(nu, z) + + See Also + ======== + + Ei: Another related function called exponential integral. + E1: The classical case, returns expint(1, z). + li: Logarithmic integral. + Li: Offset logarithmic integral. + Si: Sine integral. + Ci: Cosine integral. + Shi: Hyperbolic sine integral. + Chi: Hyperbolic cosine integral. + uppergamma + + References + ========== + + .. [1] https://dlmf.nist.gov/8.19 + .. [2] https://functions.wolfram.com/GammaBetaErf/ExpIntegralE/ + .. [3] https://en.wikipedia.org/wiki/Exponential_integral + + """ + + + @classmethod + def eval(cls, nu, z): + from sympy.functions.special.gamma_functions import (gamma, uppergamma) + nu2 = unpolarify(nu) + if nu != nu2: + return expint(nu2, z) + if nu.is_Integer and nu <= 0 or (not nu.is_Integer and (2*nu).is_Integer): + return unpolarify(expand_mul(z**(nu - 1)*uppergamma(1 - nu, z))) + + # Extract branching information. This can be deduced from what is + # explained in lowergamma.eval(). + z, n = z.extract_branch_factor() + if n is S.Zero: + return + if nu.is_integer: + if not nu > 0: + return + return expint(nu, z) \ + - 2*pi*I*n*S.NegativeOne**(nu - 1)/factorial(nu - 1)*unpolarify(z)**(nu - 1) + else: + return (exp(2*I*pi*nu*n) - 1)*z**(nu - 1)*gamma(1 - nu) + expint(nu, z) + + def fdiff(self, argindex): + nu, z = self.args + if argindex == 1: + return -z**(nu - 1)*meijerg([], [1, 1], [0, 0, 1 - nu], [], z) + elif argindex == 2: + return -expint(nu - 1, z) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_rewrite_as_uppergamma(self, nu, z, **kwargs): + from sympy.functions.special.gamma_functions import uppergamma + return z**(nu - 1)*uppergamma(1 - nu, z) + + def _eval_rewrite_as_Ei(self, nu, z, **kwargs): + if nu == 1: + return -Ei(z*exp_polar(-I*pi)) - I*pi + elif nu.is_Integer and nu > 1: + # DLMF, 8.19.7 + x = -unpolarify(z) + return x**(nu - 1)/factorial(nu - 1)*E1(z).rewrite(Ei) + \ + exp(x)/factorial(nu - 1) * \ + Add(*[factorial(nu - k - 2)*x**k for k in range(nu - 1)]) + else: + return self + + def _eval_expand_func(self, **hints): + return self.rewrite(Ei).rewrite(expint, **hints) + + def _eval_rewrite_as_Si(self, nu, z, **kwargs): + if nu != 1: + return self + return Shi(z) - Chi(z) + _eval_rewrite_as_Ci = _eval_rewrite_as_Si + _eval_rewrite_as_Chi = _eval_rewrite_as_Si + _eval_rewrite_as_Shi = _eval_rewrite_as_Si + + def _eval_nseries(self, x, n, logx, cdir=0): + if not self.args[0].has(x): + nu = self.args[0] + if nu == 1: + f = self._eval_rewrite_as_Si(*self.args) + return f._eval_nseries(x, n, logx) + elif nu.is_Integer and nu > 1: + f = self._eval_rewrite_as_Ei(*self.args) + return f._eval_nseries(x, n, logx) + return super()._eval_nseries(x, n, logx) + + def _eval_aseries(self, n, args0, x, logx): + from sympy.series.order import Order + point = args0[1] + nu = self.args[0] + + if point is S.Infinity: + z = self.args[1] + s = [S.NegativeOne**k * RisingFactorial(nu, k) / z**k for k in range(n)] + [Order(1/z**n, x)] + return (exp(-z)/z) * Add(*s) + + return super(expint, self)._eval_aseries(n, args0, x, logx) + + def _eval_rewrite_as_Integral(self, *args, **kwargs): + from sympy.integrals.integrals import Integral + n, x = self.args + t = Dummy(uniquely_named_symbol('t', args).name) + return Integral(t**-n * exp(-t*x), (t, 1, S.Infinity)) + + +def E1(z): + """ + Classical case of the generalized exponential integral. + + Explanation + =========== + + This is equivalent to ``expint(1, z)``. + + Examples + ======== + + >>> from sympy import E1 + >>> E1(0) + expint(1, 0) + + >>> E1(5) + expint(1, 5) + + See Also + ======== + + Ei: Exponential integral. + expint: Generalised exponential integral. + li: Logarithmic integral. + Li: Offset logarithmic integral. + Si: Sine integral. + Ci: Cosine integral. + Shi: Hyperbolic sine integral. + Chi: Hyperbolic cosine integral. + + """ + return expint(1, z) + + +class li(DefinedFunction): + r""" + The classical logarithmic integral. + + Explanation + =========== + + For use in SymPy, this function is defined as + + .. math:: \operatorname{li}(x) = \int_0^x \frac{1}{\log(t)} \mathrm{d}t \,. + + Examples + ======== + + >>> from sympy import I, oo, li + >>> from sympy.abc import z + + Several special values are known: + + >>> li(0) + 0 + >>> li(1) + -oo + >>> li(oo) + oo + + Differentiation with respect to $z$ is supported: + + >>> from sympy import diff + >>> diff(li(z), z) + 1/log(z) + + Defining the ``li`` function via an integral: + >>> from sympy import integrate + >>> integrate(li(z)) + z*li(z) - Ei(2*log(z)) + + >>> integrate(li(z),z) + z*li(z) - Ei(2*log(z)) + + + The logarithmic integral can also be defined in terms of ``Ei``: + + >>> from sympy import Ei + >>> li(z).rewrite(Ei) + Ei(log(z)) + >>> diff(li(z).rewrite(Ei), z) + 1/log(z) + + We can numerically evaluate the logarithmic integral to arbitrary precision + on the whole complex plane (except the singular points): + + >>> li(2).evalf(30) + 1.04516378011749278484458888919 + + >>> li(2*I).evalf(30) + 1.0652795784357498247001125598 + 3.08346052231061726610939702133*I + + We can even compute Soldner's constant by the help of mpmath: + + >>> from mpmath import findroot + >>> findroot(li, 2) + 1.45136923488338 + + Further transformations include rewriting ``li`` in terms of + the trigonometric integrals ``Si``, ``Ci``, ``Shi`` and ``Chi``: + + >>> from sympy import Si, Ci, Shi, Chi + >>> li(z).rewrite(Si) + -log(I*log(z)) - log(1/log(z))/2 + log(log(z))/2 + Ci(I*log(z)) + Shi(log(z)) + >>> li(z).rewrite(Ci) + -log(I*log(z)) - log(1/log(z))/2 + log(log(z))/2 + Ci(I*log(z)) + Shi(log(z)) + >>> li(z).rewrite(Shi) + -log(1/log(z))/2 + log(log(z))/2 + Chi(log(z)) - Shi(log(z)) + >>> li(z).rewrite(Chi) + -log(1/log(z))/2 + log(log(z))/2 + Chi(log(z)) - Shi(log(z)) + + See Also + ======== + + Li: Offset logarithmic integral. + Ei: Exponential integral. + expint: Generalised exponential integral. + E1: Special case of the generalised exponential integral. + Si: Sine integral. + Ci: Cosine integral. + Shi: Hyperbolic sine integral. + Chi: Hyperbolic cosine integral. + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Logarithmic_integral + .. [2] https://mathworld.wolfram.com/LogarithmicIntegral.html + .. [3] https://dlmf.nist.gov/6 + .. [4] https://mathworld.wolfram.com/SoldnersConstant.html + + """ + + + @classmethod + def eval(cls, z): + if z.is_zero: + return S.Zero + elif z is S.One: + return S.NegativeInfinity + elif z is S.Infinity: + return S.Infinity + if z.is_zero: + return S.Zero + + def fdiff(self, argindex=1): + arg = self.args[0] + if argindex == 1: + return S.One / log(arg) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_conjugate(self): + z = self.args[0] + # Exclude values on the branch cut (-oo, 0) + if not z.is_extended_negative: + return self.func(z.conjugate()) + + def _eval_rewrite_as_Li(self, z, **kwargs): + return Li(z) + li(2) + + def _eval_rewrite_as_Ei(self, z, **kwargs): + return Ei(log(z)) + + def _eval_rewrite_as_uppergamma(self, z, **kwargs): + from sympy.functions.special.gamma_functions import uppergamma + return (-uppergamma(0, -log(z)) + + S.Half*(log(log(z)) - log(S.One/log(z))) - log(-log(z))) + + def _eval_rewrite_as_Si(self, z, **kwargs): + return (Ci(I*log(z)) - I*Si(I*log(z)) - + S.Half*(log(S.One/log(z)) - log(log(z))) - log(I*log(z))) + + _eval_rewrite_as_Ci = _eval_rewrite_as_Si + + def _eval_rewrite_as_Shi(self, z, **kwargs): + return (Chi(log(z)) - Shi(log(z)) - S.Half*(log(S.One/log(z)) - log(log(z)))) + + _eval_rewrite_as_Chi = _eval_rewrite_as_Shi + + def _eval_rewrite_as_hyper(self, z, **kwargs): + return (log(z)*hyper((1, 1), (2, 2), log(z)) + + S.Half*(log(log(z)) - log(S.One/log(z))) + EulerGamma) + + def _eval_rewrite_as_meijerg(self, z, **kwargs): + return (-log(-log(z)) - S.Half*(log(S.One/log(z)) - log(log(z))) + - meijerg(((), (1,)), ((0, 0), ()), -log(z))) + + def _eval_rewrite_as_tractable(self, z, limitvar=None, **kwargs): + return z * _eis(log(z)) + + def _eval_nseries(self, x, n, logx, cdir=0): + z = self.args[0] + s = [(log(z))**k / (factorial(k) * k) for k in range(1, n)] + return EulerGamma + log(log(z)) + Add(*s) + + def _eval_is_zero(self): + z = self.args[0] + if z.is_zero: + return True + +class Li(DefinedFunction): + r""" + The offset logarithmic integral. + + Explanation + =========== + + For use in SymPy, this function is defined as + + .. math:: \operatorname{Li}(x) = \operatorname{li}(x) - \operatorname{li}(2) + + Examples + ======== + + >>> from sympy import Li + >>> from sympy.abc import z + + The following special value is known: + + >>> Li(2) + 0 + + Differentiation with respect to $z$ is supported: + + >>> from sympy import diff + >>> diff(Li(z), z) + 1/log(z) + + The shifted logarithmic integral can be written in terms of $li(z)$: + + >>> from sympy import li + >>> Li(z).rewrite(li) + li(z) - li(2) + + We can numerically evaluate the logarithmic integral to arbitrary precision + on the whole complex plane (except the singular points): + + >>> Li(2).evalf(30) + 0 + + >>> Li(4).evalf(30) + 1.92242131492155809316615998938 + + See Also + ======== + + li: Logarithmic integral. + Ei: Exponential integral. + expint: Generalised exponential integral. + E1: Special case of the generalised exponential integral. + Si: Sine integral. + Ci: Cosine integral. + Shi: Hyperbolic sine integral. + Chi: Hyperbolic cosine integral. + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Logarithmic_integral + .. [2] https://mathworld.wolfram.com/LogarithmicIntegral.html + .. [3] https://dlmf.nist.gov/6 + + """ + + + @classmethod + def eval(cls, z): + if z is S.Infinity: + return S.Infinity + elif z == S(2): + return S.Zero + + def fdiff(self, argindex=1): + arg = self.args[0] + if argindex == 1: + return S.One / log(arg) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_evalf(self, prec): + return self.rewrite(li).evalf(prec) + + def _eval_rewrite_as_li(self, z, **kwargs): + return li(z) - li(2) + + def _eval_rewrite_as_tractable(self, z, limitvar=None, **kwargs): + return self.rewrite(li).rewrite("tractable", deep=True) + + def _eval_nseries(self, x, n, logx, cdir=0): + f = self._eval_rewrite_as_li(*self.args) + return f._eval_nseries(x, n, logx) + +############################################################################### +#################### TRIGONOMETRIC INTEGRALS ################################## +############################################################################### + +class TrigonometricIntegral(DefinedFunction): + """ Base class for trigonometric integrals. """ + + + @classmethod + def eval(cls, z): + if z is S.Zero: + return cls._atzero + elif z is S.Infinity: + return cls._atinf() + elif z is S.NegativeInfinity: + return cls._atneginf() + + if z.is_zero: + return cls._atzero + + nz = z.extract_multiplicatively(polar_lift(I)) + if nz is None and cls._trigfunc(0) == 0: + nz = z.extract_multiplicatively(I) + if nz is not None: + return cls._Ifactor(nz, 1) + nz = z.extract_multiplicatively(polar_lift(-I)) + if nz is not None: + return cls._Ifactor(nz, -1) + + nz = z.extract_multiplicatively(polar_lift(-1)) + if nz is None and cls._trigfunc(0) == 0: + nz = z.extract_multiplicatively(-1) + if nz is not None: + return cls._minusfactor(nz) + + nz, n = z.extract_branch_factor() + if n == 0 and nz == z: + return + return 2*pi*I*n*cls._trigfunc(0) + cls(nz) + + def fdiff(self, argindex=1): + arg = unpolarify(self.args[0]) + if argindex == 1: + return self._trigfunc(arg)/arg + else: + raise ArgumentIndexError(self, argindex) + + def _eval_rewrite_as_Ei(self, z, **kwargs): + return self._eval_rewrite_as_expint(z).rewrite(Ei) + + def _eval_rewrite_as_uppergamma(self, z, **kwargs): + from sympy.functions.special.gamma_functions import uppergamma + return self._eval_rewrite_as_expint(z).rewrite(uppergamma) + + def _eval_nseries(self, x, n, logx, cdir=0): + # NOTE this is fairly inefficient + if self.args[0].subs(x, 0) != 0: + return super()._eval_nseries(x, n, logx) + baseseries = self._trigfunc(x)._eval_nseries(x, n, logx) + if self._trigfunc(0) != 0: + baseseries -= 1 + baseseries = baseseries.replace(Pow, lambda t, n: t**n/n, simultaneous=False) + if self._trigfunc(0) != 0: + baseseries += EulerGamma + log(x) + return baseseries.subs(x, self.args[0])._eval_nseries(x, n, logx) + + +class Si(TrigonometricIntegral): + r""" + Sine integral. + + Explanation + =========== + + This function is defined by + + .. math:: \operatorname{Si}(z) = \int_0^z \frac{\sin{t}}{t} \mathrm{d}t. + + It is an entire function. + + Examples + ======== + + >>> from sympy import Si + >>> from sympy.abc import z + + The sine integral is an antiderivative of $sin(z)/z$: + + >>> Si(z).diff(z) + sin(z)/z + + It is unbranched: + + >>> from sympy import exp_polar, I, pi + >>> Si(z*exp_polar(2*I*pi)) + Si(z) + + Sine integral behaves much like ordinary sine under multiplication by ``I``: + + >>> Si(I*z) + I*Shi(z) + >>> Si(-z) + -Si(z) + + It can also be expressed in terms of exponential integrals, but beware + that the latter is branched: + + >>> from sympy import expint + >>> Si(z).rewrite(expint) + -I*(-expint(1, z*exp_polar(-I*pi/2))/2 + + expint(1, z*exp_polar(I*pi/2))/2) + pi/2 + + It can be rewritten in the form of sinc function (by definition): + + >>> from sympy import sinc + >>> Si(z).rewrite(sinc) + Integral(sinc(_t), (_t, 0, z)) + + See Also + ======== + + Ci: Cosine integral. + Shi: Hyperbolic sine integral. + Chi: Hyperbolic cosine integral. + Ei: Exponential integral. + expint: Generalised exponential integral. + sinc: unnormalized sinc function + E1: Special case of the generalised exponential integral. + li: Logarithmic integral. + Li: Offset logarithmic integral. + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Trigonometric_integral + + """ + + _trigfunc = sin + _atzero = S.Zero + + @classmethod + def _atinf(cls): + return pi*S.Half + + @classmethod + def _atneginf(cls): + return -pi*S.Half + + @classmethod + def _minusfactor(cls, z): + return -Si(z) + + @classmethod + def _Ifactor(cls, z, sign): + return I*Shi(z)*sign + + def _eval_rewrite_as_expint(self, z, **kwargs): + # XXX should we polarify z? + return pi/2 + (E1(polar_lift(I)*z) - E1(polar_lift(-I)*z))/2/I + + def _eval_rewrite_as_Integral(self, z, **kwargs): + from sympy.integrals.integrals import Integral + t = Dummy(uniquely_named_symbol('t', [z]).name) + return Integral(sinc(t), (t, 0, z)) + + _eval_rewrite_as_sinc = _eval_rewrite_as_Integral + + def _eval_as_leading_term(self, x, logx, cdir): + arg = self.args[0].as_leading_term(x, logx=logx, cdir=cdir) + arg0 = arg.subs(x, 0) + + if arg0 is S.NaN: + arg0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+') + if arg0.is_zero: + return arg + elif not arg0.is_infinite: + return self.func(arg0) + else: + return self + + def _eval_aseries(self, n, args0, x, logx): + from sympy.series.order import Order + point = args0[0] + + # Expansion at oo + if point is S.Infinity: + z = self.args[0] + p = [S.NegativeOne**k * factorial(2*k) / z**(2*k + 1) + for k in range(n//2 + 1)] + [Order(1/z**n, x)] + q = [S.NegativeOne**k * factorial(2*k + 1) / z**(2*(k + 1)) + for k in range(n//2)] + [Order(1/z**n, x)] + return pi/2 - cos(z)*Add(*p) - sin(z)*Add(*q) + + # All other points are not handled + return super(Si, self)._eval_aseries(n, args0, x, logx) + + def _eval_is_zero(self): + z = self.args[0] + if z.is_zero: + return True + + +class Ci(TrigonometricIntegral): + r""" + Cosine integral. + + Explanation + =========== + + This function is defined for positive $x$ by + + .. math:: \operatorname{Ci}(x) = \gamma + \log{x} + + \int_0^x \frac{\cos{t} - 1}{t} \mathrm{d}t + = -\int_x^\infty \frac{\cos{t}}{t} \mathrm{d}t, + + where $\gamma$ is the Euler-Mascheroni constant. + + We have + + .. math:: \operatorname{Ci}(z) = + -\frac{\operatorname{E}_1\left(e^{i\pi/2} z\right) + + \operatorname{E}_1\left(e^{-i \pi/2} z\right)}{2} + + which holds for all polar $z$ and thus provides an analytic + continuation to the Riemann surface of the logarithm. + + The formula also holds as stated + for $z \in \mathbb{C}$ with $\Re(z) > 0$. + By lifting to the principal branch, we obtain an analytic function on the + cut complex plane. + + Examples + ======== + + >>> from sympy import Ci + >>> from sympy.abc import z + + The cosine integral is a primitive of $\cos(z)/z$: + + >>> Ci(z).diff(z) + cos(z)/z + + It has a logarithmic branch point at the origin: + + >>> from sympy import exp_polar, I, pi + >>> Ci(z*exp_polar(2*I*pi)) + Ci(z) + 2*I*pi + + The cosine integral behaves somewhat like ordinary $\cos$ under + multiplication by $i$: + + >>> from sympy import polar_lift + >>> Ci(polar_lift(I)*z) + Chi(z) + I*pi/2 + >>> Ci(polar_lift(-1)*z) + Ci(z) + I*pi + + It can also be expressed in terms of exponential integrals: + + >>> from sympy import expint + >>> Ci(z).rewrite(expint) + -expint(1, z*exp_polar(-I*pi/2))/2 - expint(1, z*exp_polar(I*pi/2))/2 + + See Also + ======== + + Si: Sine integral. + Shi: Hyperbolic sine integral. + Chi: Hyperbolic cosine integral. + Ei: Exponential integral. + expint: Generalised exponential integral. + E1: Special case of the generalised exponential integral. + li: Logarithmic integral. + Li: Offset logarithmic integral. + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Trigonometric_integral + + """ + + _trigfunc = cos + _atzero = S.ComplexInfinity + + @classmethod + def _atinf(cls): + return S.Zero + + @classmethod + def _atneginf(cls): + return I*pi + + @classmethod + def _minusfactor(cls, z): + return Ci(z) + I*pi + + @classmethod + def _Ifactor(cls, z, sign): + return Chi(z) + I*pi/2*sign + + def _eval_rewrite_as_expint(self, z, **kwargs): + return -(E1(polar_lift(I)*z) + E1(polar_lift(-I)*z))/2 + + def _eval_rewrite_as_Integral(self, z, **kwargs): + from sympy.integrals.integrals import Integral + t = Dummy(uniquely_named_symbol('t', [z]).name) + return S.EulerGamma + log(z) - Integral((1-cos(t))/t, (t, 0, z)) + + def _eval_as_leading_term(self, x, logx, cdir): + arg = self.args[0].as_leading_term(x, logx=logx, cdir=cdir) + arg0 = arg.subs(x, 0) + + if arg0 is S.NaN: + arg0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+') + if arg0.is_zero: + c, e = arg.as_coeff_exponent(x) + logx = log(x) if logx is None else logx + return log(c) + e*logx + EulerGamma + elif arg0.is_finite: + return self.func(arg0) + else: + return self + + def _eval_aseries(self, n, args0, x, logx): + from sympy.series.order import Order + point = args0[0] + + if point in (S.Infinity, S.NegativeInfinity): + z = self.args[0] + p = [S.NegativeOne**k * factorial(2*k) / z**(2*k + 1) + for k in range(n//2 + 1)] + [Order(1/z**n, x)] + q = [S.NegativeOne**k * factorial(2*k + 1) / z**(2*(k + 1)) + for k in range(n//2)] + [Order(1/z**n, x)] + result = sin(z)*(Add(*p)) - cos(z)*(Add(*q)) + + if point is S.NegativeInfinity: + result += I*pi + return result + + return super(Ci, self)._eval_aseries(n, args0, x, logx) + +class Shi(TrigonometricIntegral): + r""" + Sinh integral. + + Explanation + =========== + + This function is defined by + + .. math:: \operatorname{Shi}(z) = \int_0^z \frac{\sinh{t}}{t} \mathrm{d}t. + + It is an entire function. + + Examples + ======== + + >>> from sympy import Shi + >>> from sympy.abc import z + + The Sinh integral is a primitive of $\sinh(z)/z$: + + >>> Shi(z).diff(z) + sinh(z)/z + + It is unbranched: + + >>> from sympy import exp_polar, I, pi + >>> Shi(z*exp_polar(2*I*pi)) + Shi(z) + + The $\sinh$ integral behaves much like ordinary $\sinh$ under + multiplication by $i$: + + >>> Shi(I*z) + I*Si(z) + >>> Shi(-z) + -Shi(z) + + It can also be expressed in terms of exponential integrals, but beware + that the latter is branched: + + >>> from sympy import expint + >>> Shi(z).rewrite(expint) + expint(1, z)/2 - expint(1, z*exp_polar(I*pi))/2 - I*pi/2 + + See Also + ======== + + Si: Sine integral. + Ci: Cosine integral. + Chi: Hyperbolic cosine integral. + Ei: Exponential integral. + expint: Generalised exponential integral. + E1: Special case of the generalised exponential integral. + li: Logarithmic integral. + Li: Offset logarithmic integral. + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Trigonometric_integral + + """ + + _trigfunc = sinh + _atzero = S.Zero + + @classmethod + def _atinf(cls): + return S.Infinity + + @classmethod + def _atneginf(cls): + return S.NegativeInfinity + + @classmethod + def _minusfactor(cls, z): + return -Shi(z) + + @classmethod + def _Ifactor(cls, z, sign): + return I*Si(z)*sign + + def _eval_rewrite_as_expint(self, z, **kwargs): + # XXX should we polarify z? + return (E1(z) - E1(exp_polar(I*pi)*z))/2 - I*pi/2 + + def _eval_is_zero(self): + z = self.args[0] + if z.is_zero: + return True + + def _eval_as_leading_term(self, x, logx, cdir): + arg = self.args[0].as_leading_term(x) + arg0 = arg.subs(x, 0) + + if arg0 is S.NaN: + arg0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+') + if arg0.is_zero: + return arg + elif not arg0.is_infinite: + return self.func(arg0) + else: + return self + + +class Chi(TrigonometricIntegral): + r""" + Cosh integral. + + Explanation + =========== + + This function is defined for positive $x$ by + + .. math:: \operatorname{Chi}(x) = \gamma + \log{x} + + \int_0^x \frac{\cosh{t} - 1}{t} \mathrm{d}t, + + where $\gamma$ is the Euler-Mascheroni constant. + + We have + + .. math:: \operatorname{Chi}(z) = \operatorname{Ci}\left(e^{i \pi/2}z\right) + - i\frac{\pi}{2}, + + which holds for all polar $z$ and thus provides an analytic + continuation to the Riemann surface of the logarithm. + By lifting to the principal branch we obtain an analytic function on the + cut complex plane. + + Examples + ======== + + >>> from sympy import Chi + >>> from sympy.abc import z + + The $\cosh$ integral is a primitive of $\cosh(z)/z$: + + >>> Chi(z).diff(z) + cosh(z)/z + + It has a logarithmic branch point at the origin: + + >>> from sympy import exp_polar, I, pi + >>> Chi(z*exp_polar(2*I*pi)) + Chi(z) + 2*I*pi + + The $\cosh$ integral behaves somewhat like ordinary $\cosh$ under + multiplication by $i$: + + >>> from sympy import polar_lift + >>> Chi(polar_lift(I)*z) + Ci(z) + I*pi/2 + >>> Chi(polar_lift(-1)*z) + Chi(z) + I*pi + + It can also be expressed in terms of exponential integrals: + + >>> from sympy import expint + >>> Chi(z).rewrite(expint) + -expint(1, z)/2 - expint(1, z*exp_polar(I*pi))/2 - I*pi/2 + + See Also + ======== + + Si: Sine integral. + Ci: Cosine integral. + Shi: Hyperbolic sine integral. + Ei: Exponential integral. + expint: Generalised exponential integral. + E1: Special case of the generalised exponential integral. + li: Logarithmic integral. + Li: Offset logarithmic integral. + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Trigonometric_integral + + """ + + _trigfunc = cosh + _atzero = S.ComplexInfinity + + @classmethod + def _atinf(cls): + return S.Infinity + + @classmethod + def _atneginf(cls): + return S.Infinity + + @classmethod + def _minusfactor(cls, z): + return Chi(z) + I*pi + + @classmethod + def _Ifactor(cls, z, sign): + return Ci(z) + I*pi/2*sign + + def _eval_rewrite_as_expint(self, z, **kwargs): + return -I*pi/2 - (E1(z) + E1(exp_polar(I*pi)*z))/2 + + def _eval_as_leading_term(self, x, logx, cdir): + arg = self.args[0].as_leading_term(x, logx=logx, cdir=cdir) + arg0 = arg.subs(x, 0) + + if arg0 is S.NaN: + arg0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+') + if arg0.is_zero: + c, e = arg.as_coeff_exponent(x) + logx = log(x) if logx is None else logx + return log(c) + e*logx + EulerGamma + elif arg0.is_finite: + return self.func(arg0) + else: + return self + + +############################################################################### +#################### FRESNEL INTEGRALS ######################################## +############################################################################### + +class FresnelIntegral(DefinedFunction): + """ Base class for the Fresnel integrals.""" + + unbranched = True + + @classmethod + def eval(cls, z): + # Values at positive infinities signs + # if any were extracted automatically + if z is S.Infinity: + return S.Half + + # Value at zero + if z.is_zero: + return S.Zero + + # Try to pull out factors of -1 and I + prefact = S.One + newarg = z + changed = False + + nz = newarg.extract_multiplicatively(-1) + if nz is not None: + prefact = -prefact + newarg = nz + changed = True + + nz = newarg.extract_multiplicatively(I) + if nz is not None: + prefact = cls._sign*I*prefact + newarg = nz + changed = True + + if changed: + return prefact*cls(newarg) + + def fdiff(self, argindex=1): + if argindex == 1: + return self._trigfunc(S.Half*pi*self.args[0]**2) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_is_extended_real(self): + return self.args[0].is_extended_real + + _eval_is_finite = _eval_is_extended_real + + def _eval_is_zero(self): + return self.args[0].is_zero + + def _eval_conjugate(self): + return self.func(self.args[0].conjugate()) + + as_real_imag = real_to_real_as_real_imag + + +class fresnels(FresnelIntegral): + r""" + Fresnel integral S. + + Explanation + =========== + + This function is defined by + + .. math:: \operatorname{S}(z) = \int_0^z \sin{\frac{\pi}{2} t^2} \mathrm{d}t. + + It is an entire function. + + Examples + ======== + + >>> from sympy import I, oo, fresnels + >>> from sympy.abc import z + + Several special values are known: + + >>> fresnels(0) + 0 + >>> fresnels(oo) + 1/2 + >>> fresnels(-oo) + -1/2 + >>> fresnels(I*oo) + -I/2 + >>> fresnels(-I*oo) + I/2 + + In general one can pull out factors of -1 and $i$ from the argument: + + >>> fresnels(-z) + -fresnels(z) + >>> fresnels(I*z) + -I*fresnels(z) + + The Fresnel S integral obeys the mirror symmetry + $\overline{S(z)} = S(\bar{z})$: + + >>> from sympy import conjugate + >>> conjugate(fresnels(z)) + fresnels(conjugate(z)) + + Differentiation with respect to $z$ is supported: + + >>> from sympy import diff + >>> diff(fresnels(z), z) + sin(pi*z**2/2) + + Defining the Fresnel functions via an integral: + + >>> from sympy import integrate, pi, sin, expand_func + >>> integrate(sin(pi*z**2/2), z) + 3*fresnels(z)*gamma(3/4)/(4*gamma(7/4)) + >>> expand_func(integrate(sin(pi*z**2/2), z)) + fresnels(z) + + We can numerically evaluate the Fresnel integral to arbitrary precision + on the whole complex plane: + + >>> fresnels(2).evalf(30) + 0.343415678363698242195300815958 + + >>> fresnels(-2*I).evalf(30) + 0.343415678363698242195300815958*I + + See Also + ======== + + fresnelc: Fresnel cosine integral. + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Fresnel_integral + .. [2] https://dlmf.nist.gov/7 + .. [3] https://mathworld.wolfram.com/FresnelIntegrals.html + .. [4] https://functions.wolfram.com/GammaBetaErf/FresnelS + .. [5] The converging factors for the fresnel integrals + by John W. Wrench Jr. and Vicki Alley + + """ + _trigfunc = sin + _sign = -S.One + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + if n < 0: + return S.Zero + else: + x = sympify(x) + if len(previous_terms) > 1: + p = previous_terms[-1] + return (-pi**2*x**4*(4*n - 1)/(8*n*(2*n + 1)*(4*n + 3))) * p + else: + return x**3 * (-x**4)**n * (S(2)**(-2*n - 1)*pi**(2*n + 1)) / ((4*n + 3)*factorial(2*n + 1)) + + def _eval_rewrite_as_erf(self, z, **kwargs): + return (S.One + I)/4 * (erf((S.One + I)/2*sqrt(pi)*z) - I*erf((S.One - I)/2*sqrt(pi)*z)) + + def _eval_rewrite_as_hyper(self, z, **kwargs): + return pi*z**3/6 * hyper([Rational(3, 4)], [Rational(3, 2), Rational(7, 4)], -pi**2*z**4/16) + + def _eval_rewrite_as_meijerg(self, z, **kwargs): + return (pi*z**Rational(9, 4) / (sqrt(2)*(z**2)**Rational(3, 4)*(-z)**Rational(3, 4)) + * meijerg([], [1], [Rational(3, 4)], [Rational(1, 4), 0], -pi**2*z**4/16)) + + def _eval_rewrite_as_Integral(self, z, **kwargs): + from sympy.integrals.integrals import Integral + t = Dummy(uniquely_named_symbol('t', [z]).name) + return Integral(sin(pi*t**2/2), (t, 0, z)) + + def _eval_as_leading_term(self, x, logx, cdir): + from sympy.series.order import Order + arg = self.args[0].as_leading_term(x, logx=logx, cdir=cdir) + arg0 = arg.subs(x, 0) + + if arg0 is S.ComplexInfinity: + arg0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+') + if arg0.is_zero: + return pi*arg**3/6 + elif arg0 in [S.Infinity, S.NegativeInfinity]: + s = 1 if arg0 is S.Infinity else -1 + return s*S.Half + Order(x, x) + else: + return self.func(arg0) + + def _eval_aseries(self, n, args0, x, logx): + from sympy.series.order import Order + point = args0[0] + + # Expansion at oo and -oo + if point in [S.Infinity, -S.Infinity]: + z = self.args[0] + + # expansion of S(x) = S1(x*sqrt(pi/2)), see reference[5] page 1-8 + # as only real infinities are dealt with, sin and cos are O(1) + p = [S.NegativeOne**k * factorial(4*k + 1) / + (2**(2*k + 2) * z**(4*k + 3) * 2**(2*k)*factorial(2*k)) + for k in range(0, n) if 4*k + 3 < n] + q = [1/(2*z)] + [S.NegativeOne**k * factorial(4*k - 1) / + (2**(2*k + 1) * z**(4*k + 1) * 2**(2*k - 1)*factorial(2*k - 1)) + for k in range(1, n) if 4*k + 1 < n] + + p = [-sqrt(2/pi)*t for t in p] + q = [-sqrt(2/pi)*t for t in q] + s = 1 if point is S.Infinity else -1 + # The expansion at oo is 1/2 + some odd powers of z + # To get the expansion at -oo, replace z by -z and flip the sign + # The result -1/2 + the same odd powers of z as before. + return s*S.Half + (sin(z**2)*Add(*p) + cos(z**2)*Add(*q) + ).subs(x, sqrt(2/pi)*x) + Order(1/z**n, x) + + # All other points are not handled + return super()._eval_aseries(n, args0, x, logx) + + +class fresnelc(FresnelIntegral): + r""" + Fresnel integral C. + + Explanation + =========== + + This function is defined by + + .. math:: \operatorname{C}(z) = \int_0^z \cos{\frac{\pi}{2} t^2} \mathrm{d}t. + + It is an entire function. + + Examples + ======== + + >>> from sympy import I, oo, fresnelc + >>> from sympy.abc import z + + Several special values are known: + + >>> fresnelc(0) + 0 + >>> fresnelc(oo) + 1/2 + >>> fresnelc(-oo) + -1/2 + >>> fresnelc(I*oo) + I/2 + >>> fresnelc(-I*oo) + -I/2 + + In general one can pull out factors of -1 and $i$ from the argument: + + >>> fresnelc(-z) + -fresnelc(z) + >>> fresnelc(I*z) + I*fresnelc(z) + + The Fresnel C integral obeys the mirror symmetry + $\overline{C(z)} = C(\bar{z})$: + + >>> from sympy import conjugate + >>> conjugate(fresnelc(z)) + fresnelc(conjugate(z)) + + Differentiation with respect to $z$ is supported: + + >>> from sympy import diff + >>> diff(fresnelc(z), z) + cos(pi*z**2/2) + + Defining the Fresnel functions via an integral: + + >>> from sympy import integrate, pi, cos, expand_func + >>> integrate(cos(pi*z**2/2), z) + fresnelc(z)*gamma(1/4)/(4*gamma(5/4)) + >>> expand_func(integrate(cos(pi*z**2/2), z)) + fresnelc(z) + + We can numerically evaluate the Fresnel integral to arbitrary precision + on the whole complex plane: + + >>> fresnelc(2).evalf(30) + 0.488253406075340754500223503357 + + >>> fresnelc(-2*I).evalf(30) + -0.488253406075340754500223503357*I + + See Also + ======== + + fresnels: Fresnel sine integral. + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Fresnel_integral + .. [2] https://dlmf.nist.gov/7 + .. [3] https://mathworld.wolfram.com/FresnelIntegrals.html + .. [4] https://functions.wolfram.com/GammaBetaErf/FresnelC + .. [5] The converging factors for the fresnel integrals + by John W. Wrench Jr. and Vicki Alley + + """ + _trigfunc = cos + _sign = S.One + + @staticmethod + @cacheit + def taylor_term(n, x, *previous_terms): + if n < 0: + return S.Zero + else: + x = sympify(x) + if len(previous_terms) > 1: + p = previous_terms[-1] + return (-pi**2*x**4*(4*n - 3)/(8*n*(2*n - 1)*(4*n + 1))) * p + else: + return x * (-x**4)**n * (S(2)**(-2*n)*pi**(2*n)) / ((4*n + 1)*factorial(2*n)) + + def _eval_rewrite_as_erf(self, z, **kwargs): + return (S.One - I)/4 * (erf((S.One + I)/2*sqrt(pi)*z) + I*erf((S.One - I)/2*sqrt(pi)*z)) + + def _eval_rewrite_as_hyper(self, z, **kwargs): + return z * hyper([Rational(1, 4)], [S.Half, Rational(5, 4)], -pi**2*z**4/16) + + def _eval_rewrite_as_meijerg(self, z, **kwargs): + return (pi*z**Rational(3, 4) / (sqrt(2)*root(z**2, 4)*root(-z, 4)) + * meijerg([], [1], [Rational(1, 4)], [Rational(3, 4), 0], -pi**2*z**4/16)) + + def _eval_rewrite_as_Integral(self, z, **kwargs): + from sympy.integrals.integrals import Integral + t = Dummy(uniquely_named_symbol('t', [z]).name) + return Integral(cos(pi*t**2/2), (t, 0, z)) + + def _eval_as_leading_term(self, x, logx, cdir): + from sympy.series.order import Order + arg = self.args[0].as_leading_term(x, logx=logx, cdir=cdir) + arg0 = arg.subs(x, 0) + + if arg0 is S.ComplexInfinity: + arg0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+') + if arg0.is_zero: + return arg + elif arg0 in [S.Infinity, S.NegativeInfinity]: + s = 1 if arg0 is S.Infinity else -1 + return s*S.Half + Order(x, x) + else: + return self.func(arg0) + + def _eval_aseries(self, n, args0, x, logx): + from sympy.series.order import Order + point = args0[0] + + # Expansion at oo + if point in [S.Infinity, -S.Infinity]: + z = self.args[0] + + # expansion of C(x) = C1(x*sqrt(pi/2)), see reference[5] page 1-8 + # as only real infinities are dealt with, sin and cos are O(1) + p = [S.NegativeOne**k * factorial(4*k + 1) / + (2**(2*k + 2) * z**(4*k + 3) * 2**(2*k)*factorial(2*k)) + for k in range(n) if 4*k + 3 < n] + q = [1/(2*z)] + [S.NegativeOne**k * factorial(4*k - 1) / + (2**(2*k + 1) * z**(4*k + 1) * 2**(2*k - 1)*factorial(2*k - 1)) + for k in range(1, n) if 4*k + 1 < n] + + p = [-sqrt(2/pi)*t for t in p] + q = [ sqrt(2/pi)*t for t in q] + s = 1 if point is S.Infinity else -1 + # The expansion at oo is 1/2 + some odd powers of z + # To get the expansion at -oo, replace z by -z and flip the sign + # The result -1/2 + the same odd powers of z as before. + return s*S.Half + (cos(z**2)*Add(*p) + sin(z**2)*Add(*q) + ).subs(x, sqrt(2/pi)*x) + Order(1/z**n, x) + + # All other points are not handled + return super()._eval_aseries(n, args0, x, logx) + + +############################################################################### +#################### HELPER FUNCTIONS ######################################### +############################################################################### + + +class _erfs(DefinedFunction): + """ + Helper function to make the $\\mathrm{erf}(z)$ function + tractable for the Gruntz algorithm. + + """ + @classmethod + def eval(cls, arg): + if arg.is_zero: + return S.One + + def _eval_aseries(self, n, args0, x, logx): + from sympy.series.order import Order + point = args0[0] + + # Expansion at oo + if point is S.Infinity: + z = self.args[0] + l = [1/sqrt(pi) * factorial(2*k)*(-S( + 4))**(-k)/factorial(k) * (1/z)**(2*k + 1) for k in range(n)] + o = Order(1/z**(2*n + 1), x) + # It is very inefficient to first add the order and then do the nseries + return (Add(*l))._eval_nseries(x, n, logx) + o + + # Expansion at I*oo + t = point.extract_multiplicatively(I) + if t is S.Infinity: + z = self.args[0] + # TODO: is the series really correct? + l = [1/sqrt(pi) * factorial(2*k)*(-S( + 4))**(-k)/factorial(k) * (1/z)**(2*k + 1) for k in range(n)] + o = Order(1/z**(2*n + 1), x) + # It is very inefficient to first add the order and then do the nseries + return (Add(*l))._eval_nseries(x, n, logx) + o + + # All other points are not handled + return super()._eval_aseries(n, args0, x, logx) + + def fdiff(self, argindex=1): + if argindex == 1: + z = self.args[0] + return -2/sqrt(pi) + 2*z*_erfs(z) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_rewrite_as_intractable(self, z, **kwargs): + return (S.One - erf(z))*exp(z**2) + + +class _eis(DefinedFunction): + """ + Helper function to make the $\\mathrm{Ei}(z)$ and $\\mathrm{li}(z)$ + functions tractable for the Gruntz algorithm. + + """ + + + def _eval_aseries(self, n, args0, x, logx): + from sympy.series.order import Order + if args0[0] not in (S.Infinity, S.NegativeInfinity): + return super()._eval_aseries(n, args0, x, logx) + + z = self.args[0] + l = [factorial(k) * (1/z)**(k + 1) for k in range(n)] + o = Order(1/z**(n + 1), x) + # It is very inefficient to first add the order and then do the nseries + return (Add(*l))._eval_nseries(x, n, logx) + o + + + def fdiff(self, argindex=1): + if argindex == 1: + z = self.args[0] + return S.One / z - _eis(z) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_rewrite_as_intractable(self, z, **kwargs): + return exp(-z)*Ei(z) + + def _eval_as_leading_term(self, x, logx, cdir): + x0 = self.args[0].limit(x, 0) + if x0.is_zero: + f = self._eval_rewrite_as_intractable(*self.args) + return f._eval_as_leading_term(x, logx=logx, cdir=cdir) + return super()._eval_as_leading_term(x, logx=logx, cdir=cdir) + + def _eval_nseries(self, x, n, logx, cdir=0): + x0 = self.args[0].limit(x, 0) + if x0.is_zero: + f = self._eval_rewrite_as_intractable(*self.args) + return f._eval_nseries(x, n, logx) + return super()._eval_nseries(x, n, logx) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/gamma_functions.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/gamma_functions.py new file mode 100644 index 0000000000000000000000000000000000000000..73a5a1585154c603e9c510b3c61144039e0e5502 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/gamma_functions.py @@ -0,0 +1,1344 @@ +from math import prod + +from sympy.core import Add, S, Dummy, expand_func +from sympy.core.expr import Expr +from sympy.core.function import DefinedFunction, ArgumentIndexError, PoleError +from sympy.core.logic import fuzzy_and, fuzzy_not +from sympy.core.numbers import Rational, pi, oo, I +from sympy.core.power import Pow +from sympy.functions.special.zeta_functions import zeta +from sympy.functions.special.error_functions import erf, erfc, Ei +from sympy.functions.elementary.complexes import re, unpolarify +from sympy.functions.elementary.exponential import exp, log +from sympy.functions.elementary.integers import ceiling, floor +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import sin, cos, cot +from sympy.functions.combinatorial.numbers import bernoulli, harmonic +from sympy.functions.combinatorial.factorials import factorial, rf, RisingFactorial +from sympy.utilities.misc import as_int + +from mpmath import mp, workprec +from mpmath.libmp.libmpf import prec_to_dps + +def intlike(n): + try: + as_int(n, strict=False) + return True + except ValueError: + return False + +############################################################################### +############################ COMPLETE GAMMA FUNCTION ########################## +############################################################################### + +class gamma(DefinedFunction): + r""" + The gamma function + + .. math:: + \Gamma(x) := \int^{\infty}_{0} t^{x-1} e^{-t} \mathrm{d}t. + + Explanation + =========== + + The ``gamma`` function implements the function which passes through the + values of the factorial function (i.e., $\Gamma(n) = (n - 1)!$ when n is + an integer). More generally, $\Gamma(z)$ is defined in the whole complex + plane except at the negative integers where there are simple poles. + + Examples + ======== + + >>> from sympy import S, I, pi, gamma + >>> from sympy.abc import x + + Several special values are known: + + >>> gamma(1) + 1 + >>> gamma(4) + 6 + >>> gamma(S(3)/2) + sqrt(pi)/2 + + The ``gamma`` function obeys the mirror symmetry: + + >>> from sympy import conjugate + >>> conjugate(gamma(x)) + gamma(conjugate(x)) + + Differentiation with respect to $x$ is supported: + + >>> from sympy import diff + >>> diff(gamma(x), x) + gamma(x)*polygamma(0, x) + + Series expansion is also supported: + + >>> from sympy import series + >>> series(gamma(x), x, 0, 3) + 1/x - EulerGamma + x*(EulerGamma**2/2 + pi**2/12) + x**2*(-EulerGamma*pi**2/12 - zeta(3)/3 - EulerGamma**3/6) + O(x**3) + + We can numerically evaluate the ``gamma`` function to arbitrary precision + on the whole complex plane: + + >>> gamma(pi).evalf(40) + 2.288037795340032417959588909060233922890 + >>> gamma(1+I).evalf(20) + 0.49801566811835604271 - 0.15494982830181068512*I + + See Also + ======== + + lowergamma: Lower incomplete gamma function. + uppergamma: Upper incomplete gamma function. + polygamma: Polygamma function. + loggamma: Log Gamma function. + digamma: Digamma function. + trigamma: Trigamma function. + sympy.functions.special.beta_functions.beta: Euler Beta function. + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Gamma_function + .. [2] https://dlmf.nist.gov/5 + .. [3] https://mathworld.wolfram.com/GammaFunction.html + .. [4] https://functions.wolfram.com/GammaBetaErf/Gamma/ + + """ + + unbranched = True + _singularities = (S.ComplexInfinity,) + + def fdiff(self, argindex=1): + if argindex == 1: + return self.func(self.args[0])*polygamma(0, self.args[0]) + else: + raise ArgumentIndexError(self, argindex) + + @classmethod + def eval(cls, arg): + if arg.is_Number: + if arg is S.NaN: + return S.NaN + elif arg is oo: + return oo + elif intlike(arg): + if arg.is_positive: + return factorial(arg - 1) + else: + return S.ComplexInfinity + elif arg.is_Rational: + if arg.q == 2: + n = abs(arg.p) // arg.q + + if arg.is_positive: + k, coeff = n, S.One + else: + n = k = n + 1 + + if n & 1 == 0: + coeff = S.One + else: + coeff = S.NegativeOne + + coeff *= prod(range(3, 2*k, 2)) + + if arg.is_positive: + return coeff*sqrt(pi) / 2**n + else: + return 2**n*sqrt(pi) / coeff + + def _eval_expand_func(self, **hints): + arg = self.args[0] + if arg.is_Rational: + if abs(arg.p) > arg.q: + x = Dummy('x') + n = arg.p // arg.q + p = arg.p - n*arg.q + return self.func(x + n)._eval_expand_func().subs(x, Rational(p, arg.q)) + + if arg.is_Add: + coeff, tail = arg.as_coeff_add() + if coeff and coeff.q != 1: + intpart = floor(coeff) + tail = (coeff - intpart,) + tail + coeff = intpart + tail = arg._new_rawargs(*tail, reeval=False) + return self.func(tail)*RisingFactorial(tail, coeff) + + return self.func(*self.args) + + def _eval_conjugate(self): + return self.func(self.args[0].conjugate()) + + def _eval_is_real(self): + x = self.args[0] + if x.is_nonpositive and x.is_integer: + return False + if intlike(x) and x <= 0: + return False + if x.is_positive or x.is_noninteger: + return True + + def _eval_is_positive(self): + x = self.args[0] + if x.is_positive: + return True + elif x.is_noninteger: + return floor(x).is_even + + def _eval_rewrite_as_tractable(self, z, limitvar=None, **kwargs): + return exp(loggamma(z)) + + def _eval_rewrite_as_factorial(self, z, **kwargs): + return factorial(z - 1) + + def _eval_nseries(self, x, n, logx, cdir=0): + x0 = self.args[0].limit(x, 0) + if not (x0.is_Integer and x0 <= 0): + return super()._eval_nseries(x, n, logx) + t = self.args[0] - x0 + return (self.func(t + 1)/rf(self.args[0], -x0 + 1))._eval_nseries(x, n, logx) + + def _eval_as_leading_term(self, x, logx, cdir): + arg = self.args[0] + x0 = arg.subs(x, 0) + + if x0.is_integer and x0.is_nonpositive: + n = -x0 + res = S.NegativeOne**n/self.func(n + 1) + return res/(arg + n).as_leading_term(x) + elif not x0.is_infinite: + return self.func(x0) + raise PoleError() + + +############################################################################### +################## LOWER and UPPER INCOMPLETE GAMMA FUNCTIONS ################# +############################################################################### + +class lowergamma(DefinedFunction): + r""" + The lower incomplete gamma function. + + Explanation + =========== + + It can be defined as the meromorphic continuation of + + .. math:: + \gamma(s, x) := \int_0^x t^{s-1} e^{-t} \mathrm{d}t = \Gamma(s) - \Gamma(s, x). + + This can be shown to be the same as + + .. math:: + \gamma(s, x) = \frac{x^s}{s} {}_1F_1\left({s \atop s+1} \middle| -x\right), + + where ${}_1F_1$ is the (confluent) hypergeometric function. + + Examples + ======== + + >>> from sympy import lowergamma, S + >>> from sympy.abc import s, x + >>> lowergamma(s, x) + lowergamma(s, x) + >>> lowergamma(3, x) + -2*(x**2/2 + x + 1)*exp(-x) + 2 + >>> lowergamma(-S(1)/2, x) + -2*sqrt(pi)*erf(sqrt(x)) - 2*exp(-x)/sqrt(x) + + See Also + ======== + + gamma: Gamma function. + uppergamma: Upper incomplete gamma function. + polygamma: Polygamma function. + loggamma: Log Gamma function. + digamma: Digamma function. + trigamma: Trigamma function. + sympy.functions.special.beta_functions.beta: Euler Beta function. + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Incomplete_gamma_function#Lower_incomplete_gamma_function + .. [2] Abramowitz, Milton; Stegun, Irene A., eds. (1965), Chapter 6, + Section 5, Handbook of Mathematical Functions with Formulas, Graphs, + and Mathematical Tables + .. [3] https://dlmf.nist.gov/8 + .. [4] https://functions.wolfram.com/GammaBetaErf/Gamma2/ + .. [5] https://functions.wolfram.com/GammaBetaErf/Gamma3/ + + """ + + + def fdiff(self, argindex=2): + from sympy.functions.special.hyper import meijerg + if argindex == 2: + a, z = self.args + return exp(-unpolarify(z))*z**(a - 1) + elif argindex == 1: + a, z = self.args + return gamma(a)*digamma(a) - log(z)*uppergamma(a, z) \ + - meijerg([], [1, 1], [0, 0, a], [], z) + + else: + raise ArgumentIndexError(self, argindex) + + @classmethod + def eval(cls, a, x): + # For lack of a better place, we use this one to extract branching + # information. The following can be + # found in the literature (c/f references given above), albeit scattered: + # 1) For fixed x != 0, lowergamma(s, x) is an entire function of s + # 2) For fixed positive integers s, lowergamma(s, x) is an entire + # function of x. + # 3) For fixed non-positive integers s, + # lowergamma(s, exp(I*2*pi*n)*x) = + # 2*pi*I*n*(-1)**(-s)/factorial(-s) + lowergamma(s, x) + # (this follows from lowergamma(s, x).diff(x) = x**(s-1)*exp(-x)). + # 4) For fixed non-integral s, + # lowergamma(s, x) = x**s*gamma(s)*lowergamma_unbranched(s, x), + # where lowergamma_unbranched(s, x) is an entire function (in fact + # of both s and x), i.e. + # lowergamma(s, exp(2*I*pi*n)*x) = exp(2*pi*I*n*a)*lowergamma(a, x) + if x is S.Zero: + return S.Zero + nx, n = x.extract_branch_factor() + if a.is_integer and a.is_positive: + nx = unpolarify(x) + if nx != x: + return lowergamma(a, nx) + elif a.is_integer and a.is_nonpositive: + if n != 0: + return 2*pi*I*n*S.NegativeOne**(-a)/factorial(-a) + lowergamma(a, nx) + elif n != 0: + return exp(2*pi*I*n*a)*lowergamma(a, nx) + + # Special values. + if a.is_Number: + if a is S.One: + return S.One - exp(-x) + elif a is S.Half: + return sqrt(pi)*erf(sqrt(x)) + elif a.is_Integer or (2*a).is_Integer: + b = a - 1 + if b.is_positive: + if a.is_integer: + return factorial(b) - exp(-x) * factorial(b) * Add(*[x ** k / factorial(k) for k in range(a)]) + else: + return gamma(a)*(lowergamma(S.Half, x)/sqrt(pi) - exp(-x)*Add(*[x**(k - S.Half)/gamma(S.Half + k) for k in range(1, a + S.Half)])) + + if not a.is_Integer: + return S.NegativeOne**(S.Half - a)*pi*erf(sqrt(x))/gamma(1 - a) + exp(-x)*Add(*[x**(k + a - 1)*gamma(a)/gamma(a + k) for k in range(1, Rational(3, 2) - a)]) + + if x.is_zero: + return S.Zero + + def _eval_evalf(self, prec): + if all(x.is_number for x in self.args): + a = self.args[0]._to_mpmath(prec) + z = self.args[1]._to_mpmath(prec) + with workprec(prec): + res = mp.gammainc(a, 0, z) + return Expr._from_mpmath(res, prec) + else: + return self + + def _eval_conjugate(self): + x = self.args[1] + if x not in (S.Zero, S.NegativeInfinity): + return self.func(self.args[0].conjugate(), x.conjugate()) + + def _eval_is_meromorphic(self, x, a): + # By https://en.wikipedia.org/wiki/Incomplete_gamma_function#Holomorphic_extension, + # lowergamma(s, z) = z**s*gamma(s)*gammastar(s, z), + # where gammastar(s, z) is holomorphic for all s and z. + # Hence the singularities of lowergamma are z = 0 (branch + # point) and nonpositive integer values of s (poles of gamma(s)). + s, z = self.args + args_merom = fuzzy_and([z._eval_is_meromorphic(x, a), + s._eval_is_meromorphic(x, a)]) + if not args_merom: + return args_merom + z0 = z.subs(x, a) + if s.is_integer: + return fuzzy_and([s.is_positive, z0.is_finite]) + s0 = s.subs(x, a) + return fuzzy_and([s0.is_finite, z0.is_finite, fuzzy_not(z0.is_zero)]) + + def _eval_aseries(self, n, args0, x, logx): + from sympy.series.order import O + s, z = self.args + if args0[0] is oo and not z.has(x): + coeff = z**s*exp(-z) + sum_expr = sum(z**k/rf(s, k + 1) for k in range(n - 1)) + o = O(z**s*s**(-n)) + return coeff*sum_expr + o + return super()._eval_aseries(n, args0, x, logx) + + def _eval_rewrite_as_uppergamma(self, s, x, **kwargs): + return gamma(s) - uppergamma(s, x) + + def _eval_rewrite_as_expint(self, s, x, **kwargs): + from sympy.functions.special.error_functions import expint + if s.is_integer and s.is_nonpositive: + return self + return self.rewrite(uppergamma).rewrite(expint) + + def _eval_is_zero(self): + x = self.args[1] + if x.is_zero: + return True + + +class uppergamma(DefinedFunction): + r""" + The upper incomplete gamma function. + + Explanation + =========== + + It can be defined as the meromorphic continuation of + + .. math:: + \Gamma(s, x) := \int_x^\infty t^{s-1} e^{-t} \mathrm{d}t = \Gamma(s) - \gamma(s, x). + + where $\gamma(s, x)$ is the lower incomplete gamma function, + :class:`lowergamma`. This can be shown to be the same as + + .. math:: + \Gamma(s, x) = \Gamma(s) - \frac{x^s}{s} {}_1F_1\left({s \atop s+1} \middle| -x\right), + + where ${}_1F_1$ is the (confluent) hypergeometric function. + + The upper incomplete gamma function is also essentially equivalent to the + generalized exponential integral: + + .. math:: + \operatorname{E}_{n}(x) = \int_{1}^{\infty}{\frac{e^{-xt}}{t^n} \, dt} = x^{n-1}\Gamma(1-n,x). + + Examples + ======== + + >>> from sympy import uppergamma, S + >>> from sympy.abc import s, x + >>> uppergamma(s, x) + uppergamma(s, x) + >>> uppergamma(3, x) + 2*(x**2/2 + x + 1)*exp(-x) + >>> uppergamma(-S(1)/2, x) + -2*sqrt(pi)*erfc(sqrt(x)) + 2*exp(-x)/sqrt(x) + >>> uppergamma(-2, x) + expint(3, x)/x**2 + + See Also + ======== + + gamma: Gamma function. + lowergamma: Lower incomplete gamma function. + polygamma: Polygamma function. + loggamma: Log Gamma function. + digamma: Digamma function. + trigamma: Trigamma function. + sympy.functions.special.beta_functions.beta: Euler Beta function. + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Incomplete_gamma_function#Upper_incomplete_gamma_function + .. [2] Abramowitz, Milton; Stegun, Irene A., eds. (1965), Chapter 6, + Section 5, Handbook of Mathematical Functions with Formulas, Graphs, + and Mathematical Tables + .. [3] https://dlmf.nist.gov/8 + .. [4] https://functions.wolfram.com/GammaBetaErf/Gamma2/ + .. [5] https://functions.wolfram.com/GammaBetaErf/Gamma3/ + .. [6] https://en.wikipedia.org/wiki/Exponential_integral#Relation_with_other_functions + + """ + + + def fdiff(self, argindex=2): + from sympy.functions.special.hyper import meijerg + if argindex == 2: + a, z = self.args + return -exp(-unpolarify(z))*z**(a - 1) + elif argindex == 1: + a, z = self.args + return uppergamma(a, z)*log(z) + meijerg([], [1, 1], [0, 0, a], [], z) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_evalf(self, prec): + if all(x.is_number for x in self.args): + a = self.args[0]._to_mpmath(prec) + z = self.args[1]._to_mpmath(prec) + with workprec(prec): + res = mp.gammainc(a, z, mp.inf) + return Expr._from_mpmath(res, prec) + return self + + @classmethod + def eval(cls, a, z): + from sympy.functions.special.error_functions import expint + if z.is_Number: + if z is S.NaN: + return S.NaN + elif z is oo: + return S.Zero + elif z.is_zero: + if re(a).is_positive: + return gamma(a) + + # We extract branching information here. C/f lowergamma. + nx, n = z.extract_branch_factor() + if a.is_integer and a.is_positive: + nx = unpolarify(z) + if z != nx: + return uppergamma(a, nx) + elif a.is_integer and a.is_nonpositive: + if n != 0: + return -2*pi*I*n*S.NegativeOne**(-a)/factorial(-a) + uppergamma(a, nx) + elif n != 0: + return gamma(a)*(1 - exp(2*pi*I*n*a)) + exp(2*pi*I*n*a)*uppergamma(a, nx) + + # Special values. + if a.is_Number: + if a is S.Zero and z.is_positive: + return -Ei(-z) + elif a is S.One: + return exp(-z) + elif a is S.Half: + return sqrt(pi)*erfc(sqrt(z)) + elif a.is_Integer or (2*a).is_Integer: + b = a - 1 + if b.is_positive: + if a.is_integer: + return exp(-z) * factorial(b) * Add(*[z**k / factorial(k) + for k in range(a)]) + else: + return (gamma(a) * erfc(sqrt(z)) + + S.NegativeOne**(a - S(3)/2) * exp(-z) * sqrt(z) + * Add(*[gamma(-S.Half - k) * (-z)**k / gamma(1-a) + for k in range(a - S.Half)])) + elif b.is_Integer: + return expint(-b, z)*unpolarify(z)**(b + 1) + + if not a.is_Integer: + return (S.NegativeOne**(S.Half - a) * pi*erfc(sqrt(z))/gamma(1-a) + - z**a * exp(-z) * Add(*[z**k * gamma(a) / gamma(a+k+1) + for k in range(S.Half - a)])) + + if a.is_zero and z.is_positive: + return -Ei(-z) + + if z.is_zero and re(a).is_positive: + return gamma(a) + + def _eval_conjugate(self): + z = self.args[1] + if z not in (S.Zero, S.NegativeInfinity): + return self.func(self.args[0].conjugate(), z.conjugate()) + + def _eval_is_meromorphic(self, x, a): + return lowergamma._eval_is_meromorphic(self, x, a) + + def _eval_rewrite_as_lowergamma(self, s, x, **kwargs): + return gamma(s) - lowergamma(s, x) + + def _eval_rewrite_as_tractable(self, s, x, **kwargs): + return exp(loggamma(s)) - lowergamma(s, x) + + def _eval_rewrite_as_expint(self, s, x, **kwargs): + from sympy.functions.special.error_functions import expint + return expint(1 - s, x)*x**s + + +############################################################################### +###################### POLYGAMMA and LOGGAMMA FUNCTIONS ####################### +############################################################################### + +class polygamma(DefinedFunction): + r""" + The function ``polygamma(n, z)`` returns ``log(gamma(z)).diff(n + 1)``. + + Explanation + =========== + + It is a meromorphic function on $\mathbb{C}$ and defined as the $(n+1)$-th + derivative of the logarithm of the gamma function: + + .. math:: + \psi^{(n)} (z) := \frac{\mathrm{d}^{n+1}}{\mathrm{d} z^{n+1}} \log\Gamma(z). + + For `n` not a nonnegative integer the generalization by Espinosa and Moll [5]_ + is used: + + .. math:: \psi(s,z) = \frac{\zeta'(s+1, z) + (\gamma + \psi(-s)) \zeta(s+1, z)} + {\Gamma(-s)} + + Examples + ======== + + Several special values are known: + + >>> from sympy import S, polygamma + >>> polygamma(0, 1) + -EulerGamma + >>> polygamma(0, 1/S(2)) + -2*log(2) - EulerGamma + >>> polygamma(0, 1/S(3)) + -log(3) - sqrt(3)*pi/6 - EulerGamma - log(sqrt(3)) + >>> polygamma(0, 1/S(4)) + -pi/2 - log(4) - log(2) - EulerGamma + >>> polygamma(0, 2) + 1 - EulerGamma + >>> polygamma(0, 23) + 19093197/5173168 - EulerGamma + + >>> from sympy import oo, I + >>> polygamma(0, oo) + oo + >>> polygamma(0, -oo) + oo + >>> polygamma(0, I*oo) + oo + >>> polygamma(0, -I*oo) + oo + + Differentiation with respect to $x$ is supported: + + >>> from sympy import Symbol, diff + >>> x = Symbol("x") + >>> diff(polygamma(0, x), x) + polygamma(1, x) + >>> diff(polygamma(0, x), x, 2) + polygamma(2, x) + >>> diff(polygamma(0, x), x, 3) + polygamma(3, x) + >>> diff(polygamma(1, x), x) + polygamma(2, x) + >>> diff(polygamma(1, x), x, 2) + polygamma(3, x) + >>> diff(polygamma(2, x), x) + polygamma(3, x) + >>> diff(polygamma(2, x), x, 2) + polygamma(4, x) + + >>> n = Symbol("n") + >>> diff(polygamma(n, x), x) + polygamma(n + 1, x) + >>> diff(polygamma(n, x), x, 2) + polygamma(n + 2, x) + + We can rewrite ``polygamma`` functions in terms of harmonic numbers: + + >>> from sympy import harmonic + >>> polygamma(0, x).rewrite(harmonic) + harmonic(x - 1) - EulerGamma + >>> polygamma(2, x).rewrite(harmonic) + 2*harmonic(x - 1, 3) - 2*zeta(3) + >>> ni = Symbol("n", integer=True) + >>> polygamma(ni, x).rewrite(harmonic) + (-1)**(n + 1)*(-harmonic(x - 1, n + 1) + zeta(n + 1))*factorial(n) + + See Also + ======== + + gamma: Gamma function. + lowergamma: Lower incomplete gamma function. + uppergamma: Upper incomplete gamma function. + loggamma: Log Gamma function. + digamma: Digamma function. + trigamma: Trigamma function. + sympy.functions.special.beta_functions.beta: Euler Beta function. + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Polygamma_function + .. [2] https://mathworld.wolfram.com/PolygammaFunction.html + .. [3] https://functions.wolfram.com/GammaBetaErf/PolyGamma/ + .. [4] https://functions.wolfram.com/GammaBetaErf/PolyGamma2/ + .. [5] O. Espinosa and V. Moll, "A generalized polygamma function", + *Integral Transforms and Special Functions* (2004), 101-115. + + """ + + @classmethod + def eval(cls, n, z): + if n is S.NaN or z is S.NaN: + return S.NaN + elif z is oo: + return oo if n.is_zero else S.Zero + elif z.is_Integer and z.is_nonpositive: + return S.ComplexInfinity + elif n is S.NegativeOne: + return loggamma(z) - log(2*pi) / 2 + elif n.is_zero: + if z is -oo or z.extract_multiplicatively(I) in (oo, -oo): + return oo + elif z.is_Integer: + return harmonic(z-1) - S.EulerGamma + elif z.is_Rational: + # TODO n == 1 also can do some rational z + p, q = z.as_numer_denom() + # only expand for small denominators to avoid creating long expressions + if q <= 6: + return expand_func(polygamma(S.Zero, z, evaluate=False)) + elif n.is_integer and n.is_nonnegative: + nz = unpolarify(z) + if z != nz: + return polygamma(n, nz) + if z.is_Integer: + return S.NegativeOne**(n+1) * factorial(n) * zeta(n+1, z) + elif z is S.Half: + return S.NegativeOne**(n+1) * factorial(n) * (2**(n+1)-1) * zeta(n+1) + + def _eval_is_real(self): + if self.args[0].is_positive and self.args[1].is_positive: + return True + + def _eval_is_complex(self): + z = self.args[1] + is_negative_integer = fuzzy_and([z.is_negative, z.is_integer]) + return fuzzy_and([z.is_complex, fuzzy_not(is_negative_integer)]) + + def _eval_is_positive(self): + n, z = self.args + if n.is_positive: + if n.is_odd and z.is_real: + return True + if n.is_even and z.is_positive: + return False + + def _eval_is_negative(self): + n, z = self.args + if n.is_positive: + if n.is_even and z.is_positive: + return True + if n.is_odd and z.is_real: + return False + + def _eval_expand_func(self, **hints): + n, z = self.args + + if n.is_Integer and n.is_nonnegative: + if z.is_Add: + coeff = z.args[0] + if coeff.is_Integer: + e = -(n + 1) + if coeff > 0: + tail = Add(*[Pow( + z - i, e) for i in range(1, int(coeff) + 1)]) + else: + tail = -Add(*[Pow( + z + i, e) for i in range(int(-coeff))]) + return polygamma(n, z - coeff) + S.NegativeOne**n*factorial(n)*tail + + elif z.is_Mul: + coeff, z = z.as_two_terms() + if coeff.is_Integer and coeff.is_positive: + tail = [polygamma(n, z + Rational( + i, coeff)) for i in range(int(coeff))] + if n == 0: + return Add(*tail)/coeff + log(coeff) + else: + return Add(*tail)/coeff**(n + 1) + z *= coeff + + if n == 0 and z.is_Rational: + p, q = z.as_numer_denom() + + # Reference: + # Values of the polygamma functions at rational arguments, J. Choi, 2007 + part_1 = -S.EulerGamma - pi * cot(p * pi / q) / 2 - log(q) + Add( + *[cos(2 * k * pi * p / q) * log(2 * sin(k * pi / q)) for k in range(1, q)]) + + if z > 0: + n = floor(z) + z0 = z - n + return part_1 + Add(*[1 / (z0 + k) for k in range(n)]) + elif z < 0: + n = floor(1 - z) + z0 = z + n + return part_1 - Add(*[1 / (z0 - 1 - k) for k in range(n)]) + + if n == -1: + return loggamma(z) - log(2*pi) / 2 + if n.is_integer is False or n.is_nonnegative is False: + s = Dummy("s") + dzt = zeta(s, z).diff(s).subs(s, n+1) + return (dzt + (S.EulerGamma + digamma(-n)) * zeta(n+1, z)) / gamma(-n) + + return polygamma(n, z) + + def _eval_rewrite_as_zeta(self, n, z, **kwargs): + if n.is_integer and n.is_positive: + return S.NegativeOne**(n + 1)*factorial(n)*zeta(n + 1, z) + + def _eval_rewrite_as_harmonic(self, n, z, **kwargs): + if n.is_integer: + if n.is_zero: + return harmonic(z - 1) - S.EulerGamma + else: + return S.NegativeOne**(n+1) * factorial(n) * (zeta(n+1) - harmonic(z-1, n+1)) + + def _eval_as_leading_term(self, x, logx, cdir): + from sympy.series.order import Order + n, z = [a.as_leading_term(x) for a in self.args] + o = Order(z, x) + if n == 0 and o.contains(1/x): + logx = log(x) if logx is None else logx + return o.getn() * logx + else: + return self.func(n, z) + + def fdiff(self, argindex=2): + if argindex == 2: + n, z = self.args[:2] + return polygamma(n + 1, z) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_aseries(self, n, args0, x, logx): + from sympy.series.order import Order + if args0[1] != oo or not \ + (self.args[0].is_Integer and self.args[0].is_nonnegative): + return super()._eval_aseries(n, args0, x, logx) + z = self.args[1] + N = self.args[0] + + if N == 0: + # digamma function series + # Abramowitz & Stegun, p. 259, 6.3.18 + r = log(z) - 1/(2*z) + o = None + if n < 2: + o = Order(1/z, x) + else: + m = ceiling((n + 1)//2) + l = [bernoulli(2*k) / (2*k*z**(2*k)) for k in range(1, m)] + r -= Add(*l) + o = Order(1/z**n, x) + return r._eval_nseries(x, n, logx) + o + else: + # proper polygamma function + # Abramowitz & Stegun, p. 260, 6.4.10 + # We return terms to order higher than O(x**n) on purpose + # -- otherwise we would not be able to return any terms for + # quite a long time! + fac = gamma(N) + e0 = fac + N*fac/(2*z) + m = ceiling((n + 1)//2) + for k in range(1, m): + fac = fac*(2*k + N - 1)*(2*k + N - 2) / ((2*k)*(2*k - 1)) + e0 += bernoulli(2*k)*fac/z**(2*k) + o = Order(1/z**(2*m), x) + if n == 0: + o = Order(1/z, x) + elif n == 1: + o = Order(1/z**2, x) + r = e0._eval_nseries(z, n, logx) + o + return (-1 * (-1/z)**N * r)._eval_nseries(x, n, logx) + + def _eval_evalf(self, prec): + if not all(i.is_number for i in self.args): + return + s = self.args[0]._to_mpmath(prec+12) + z = self.args[1]._to_mpmath(prec+12) + if mp.isint(z) and z <= 0: + return S.ComplexInfinity + with workprec(prec+12): + if mp.isint(s) and s >= 0: + res = mp.polygamma(s, z) + else: + zt = mp.zeta(s+1, z) + dzt = mp.zeta(s+1, z, 1) + res = (dzt + (mp.euler + mp.digamma(-s)) * zt) * mp.rgamma(-s) + return Expr._from_mpmath(res, prec) + + +class loggamma(DefinedFunction): + r""" + The ``loggamma`` function implements the logarithm of the + gamma function (i.e., $\log\Gamma(x)$). + + Examples + ======== + + Several special values are known. For numerical integral + arguments we have: + + >>> from sympy import loggamma + >>> loggamma(-2) + oo + >>> loggamma(0) + oo + >>> loggamma(1) + 0 + >>> loggamma(2) + 0 + >>> loggamma(3) + log(2) + + And for symbolic values: + + >>> from sympy import Symbol + >>> n = Symbol("n", integer=True, positive=True) + >>> loggamma(n) + log(gamma(n)) + >>> loggamma(-n) + oo + + For half-integral values: + + >>> from sympy import S + >>> loggamma(S(5)/2) + log(3*sqrt(pi)/4) + >>> loggamma(n/2) + log(2**(1 - n)*sqrt(pi)*gamma(n)/gamma(n/2 + 1/2)) + + And general rational arguments: + + >>> from sympy import expand_func + >>> L = loggamma(S(16)/3) + >>> expand_func(L).doit() + -5*log(3) + loggamma(1/3) + log(4) + log(7) + log(10) + log(13) + >>> L = loggamma(S(19)/4) + >>> expand_func(L).doit() + -4*log(4) + loggamma(3/4) + log(3) + log(7) + log(11) + log(15) + >>> L = loggamma(S(23)/7) + >>> expand_func(L).doit() + -3*log(7) + log(2) + loggamma(2/7) + log(9) + log(16) + + The ``loggamma`` function has the following limits towards infinity: + + >>> from sympy import oo + >>> loggamma(oo) + oo + >>> loggamma(-oo) + zoo + + The ``loggamma`` function obeys the mirror symmetry + if $x \in \mathbb{C} \setminus \{-\infty, 0\}$: + + >>> from sympy.abc import x + >>> from sympy import conjugate + >>> conjugate(loggamma(x)) + loggamma(conjugate(x)) + + Differentiation with respect to $x$ is supported: + + >>> from sympy import diff + >>> diff(loggamma(x), x) + polygamma(0, x) + + Series expansion is also supported: + + >>> from sympy import series + >>> series(loggamma(x), x, 0, 4).cancel() + -log(x) - EulerGamma*x + pi**2*x**2/12 - x**3*zeta(3)/3 + O(x**4) + + We can numerically evaluate the ``loggamma`` function + to arbitrary precision on the whole complex plane: + + >>> from sympy import I + >>> loggamma(5).evalf(30) + 3.17805383034794561964694160130 + >>> loggamma(I).evalf(20) + -0.65092319930185633889 - 1.8724366472624298171*I + + See Also + ======== + + gamma: Gamma function. + lowergamma: Lower incomplete gamma function. + uppergamma: Upper incomplete gamma function. + polygamma: Polygamma function. + digamma: Digamma function. + trigamma: Trigamma function. + sympy.functions.special.beta_functions.beta: Euler Beta function. + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Gamma_function + .. [2] https://dlmf.nist.gov/5 + .. [3] https://mathworld.wolfram.com/LogGammaFunction.html + .. [4] https://functions.wolfram.com/GammaBetaErf/LogGamma/ + + """ + @classmethod + def eval(cls, z): + if z.is_integer: + if z.is_nonpositive: + return oo + elif z.is_positive: + return log(gamma(z)) + elif z.is_rational: + p, q = z.as_numer_denom() + # Half-integral values: + if p.is_positive and q == 2: + return log(sqrt(pi) * 2**(1 - p) * gamma(p) / gamma((p + 1)*S.Half)) + + if z is oo: + return oo + elif abs(z) is oo: + return S.ComplexInfinity + if z is S.NaN: + return S.NaN + + def _eval_expand_func(self, **hints): + from sympy.concrete.summations import Sum + z = self.args[0] + + if z.is_Rational: + p, q = z.as_numer_denom() + # General rational arguments (u + p/q) + # Split z as n + p/q with p < q + n = p // q + p = p - n*q + if p.is_positive and q.is_positive and p < q: + k = Dummy("k") + if n.is_positive: + return loggamma(p / q) - n*log(q) + Sum(log((k - 1)*q + p), (k, 1, n)) + elif n.is_negative: + return loggamma(p / q) - n*log(q) + pi*I*n - Sum(log(k*q - p), (k, 1, -n)) + elif n.is_zero: + return loggamma(p / q) + + return self + + def _eval_nseries(self, x, n, logx=None, cdir=0): + x0 = self.args[0].limit(x, 0) + if x0.is_zero: + f = self._eval_rewrite_as_intractable(*self.args) + return f._eval_nseries(x, n, logx) + return super()._eval_nseries(x, n, logx) + + def _eval_aseries(self, n, args0, x, logx): + from sympy.series.order import Order + if args0[0] != oo: + return super()._eval_aseries(n, args0, x, logx) + z = self.args[0] + r = log(z)*(z - S.Half) - z + log(2*pi)/2 + l = [bernoulli(2*k) / (2*k*(2*k - 1)*z**(2*k - 1)) for k in range(1, n)] + o = None + if n == 0: + o = Order(1, x) + else: + o = Order(1/z**n, x) + # It is very inefficient to first add the order and then do the nseries + return (r + Add(*l))._eval_nseries(x, n, logx) + o + + def _eval_rewrite_as_intractable(self, z, **kwargs): + return log(gamma(z)) + + def _eval_is_real(self): + z = self.args[0] + if z.is_positive: + return True + elif z.is_nonpositive: + return False + + def _eval_conjugate(self): + z = self.args[0] + if z not in (S.Zero, S.NegativeInfinity): + return self.func(z.conjugate()) + + def fdiff(self, argindex=1): + if argindex == 1: + return polygamma(0, self.args[0]) + else: + raise ArgumentIndexError(self, argindex) + + +class digamma(DefinedFunction): + r""" + The ``digamma`` function is the first derivative of the ``loggamma`` + function + + .. math:: + \psi(x) := \frac{\mathrm{d}}{\mathrm{d} z} \log\Gamma(z) + = \frac{\Gamma'(z)}{\Gamma(z) }. + + In this case, ``digamma(z) = polygamma(0, z)``. + + Examples + ======== + + >>> from sympy import digamma + >>> digamma(0) + zoo + >>> from sympy import Symbol + >>> z = Symbol('z') + >>> digamma(z) + polygamma(0, z) + + To retain ``digamma`` as it is: + + >>> digamma(0, evaluate=False) + digamma(0) + >>> digamma(z, evaluate=False) + digamma(z) + + See Also + ======== + + gamma: Gamma function. + lowergamma: Lower incomplete gamma function. + uppergamma: Upper incomplete gamma function. + polygamma: Polygamma function. + loggamma: Log Gamma function. + trigamma: Trigamma function. + sympy.functions.special.beta_functions.beta: Euler Beta function. + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Digamma_function + .. [2] https://mathworld.wolfram.com/DigammaFunction.html + .. [3] https://functions.wolfram.com/GammaBetaErf/PolyGamma2/ + + """ + def _eval_evalf(self, prec): + z = self.args[0] + nprec = prec_to_dps(prec) + return polygamma(0, z).evalf(n=nprec) + + def fdiff(self, argindex=1): + z = self.args[0] + return polygamma(0, z).fdiff() + + def _eval_is_real(self): + z = self.args[0] + return polygamma(0, z).is_real + + def _eval_is_positive(self): + z = self.args[0] + return polygamma(0, z).is_positive + + def _eval_is_negative(self): + z = self.args[0] + return polygamma(0, z).is_negative + + def _eval_aseries(self, n, args0, x, logx): + as_polygamma = self.rewrite(polygamma) + args0 = [S.Zero,] + args0 + return as_polygamma._eval_aseries(n, args0, x, logx) + + @classmethod + def eval(cls, z): + return polygamma(0, z) + + def _eval_expand_func(self, **hints): + z = self.args[0] + return polygamma(0, z).expand(func=True) + + def _eval_rewrite_as_harmonic(self, z, **kwargs): + return harmonic(z - 1) - S.EulerGamma + + def _eval_rewrite_as_polygamma(self, z, **kwargs): + return polygamma(0, z) + + def _eval_as_leading_term(self, x, logx, cdir): + z = self.args[0] + return polygamma(0, z).as_leading_term(x) + + + +class trigamma(DefinedFunction): + r""" + The ``trigamma`` function is the second derivative of the ``loggamma`` + function + + .. math:: + \psi^{(1)}(z) := \frac{\mathrm{d}^{2}}{\mathrm{d} z^{2}} \log\Gamma(z). + + In this case, ``trigamma(z) = polygamma(1, z)``. + + Examples + ======== + + >>> from sympy import trigamma + >>> trigamma(0) + zoo + >>> from sympy import Symbol + >>> z = Symbol('z') + >>> trigamma(z) + polygamma(1, z) + + To retain ``trigamma`` as it is: + + >>> trigamma(0, evaluate=False) + trigamma(0) + >>> trigamma(z, evaluate=False) + trigamma(z) + + + See Also + ======== + + gamma: Gamma function. + lowergamma: Lower incomplete gamma function. + uppergamma: Upper incomplete gamma function. + polygamma: Polygamma function. + loggamma: Log Gamma function. + digamma: Digamma function. + sympy.functions.special.beta_functions.beta: Euler Beta function. + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Trigamma_function + .. [2] https://mathworld.wolfram.com/TrigammaFunction.html + .. [3] https://functions.wolfram.com/GammaBetaErf/PolyGamma2/ + + """ + def _eval_evalf(self, prec): + z = self.args[0] + nprec = prec_to_dps(prec) + return polygamma(1, z).evalf(n=nprec) + + def fdiff(self, argindex=1): + z = self.args[0] + return polygamma(1, z).fdiff() + + def _eval_is_real(self): + z = self.args[0] + return polygamma(1, z).is_real + + def _eval_is_positive(self): + z = self.args[0] + return polygamma(1, z).is_positive + + def _eval_is_negative(self): + z = self.args[0] + return polygamma(1, z).is_negative + + def _eval_aseries(self, n, args0, x, logx): + as_polygamma = self.rewrite(polygamma) + args0 = [S.One,] + args0 + return as_polygamma._eval_aseries(n, args0, x, logx) + + @classmethod + def eval(cls, z): + return polygamma(1, z) + + def _eval_expand_func(self, **hints): + z = self.args[0] + return polygamma(1, z).expand(func=True) + + def _eval_rewrite_as_zeta(self, z, **kwargs): + return zeta(2, z) + + def _eval_rewrite_as_polygamma(self, z, **kwargs): + return polygamma(1, z) + + def _eval_rewrite_as_harmonic(self, z, **kwargs): + return -harmonic(z - 1, 2) + pi**2 / 6 + + def _eval_as_leading_term(self, x, logx, cdir): + z = self.args[0] + return polygamma(1, z).as_leading_term(x) + + +############################################################################### +##################### COMPLETE MULTIVARIATE GAMMA FUNCTION #################### +############################################################################### + + +class multigamma(DefinedFunction): + r""" + The multivariate gamma function is a generalization of the gamma function + + .. math:: + \Gamma_p(z) = \pi^{p(p-1)/4}\prod_{k=1}^p \Gamma[z + (1 - k)/2]. + + In a special case, ``multigamma(x, 1) = gamma(x)``. + + Examples + ======== + + >>> from sympy import S, multigamma + >>> from sympy import Symbol + >>> x = Symbol('x') + >>> p = Symbol('p', positive=True, integer=True) + + >>> multigamma(x, p) + pi**(p*(p - 1)/4)*Product(gamma(-_k/2 + x + 1/2), (_k, 1, p)) + + Several special values are known: + + >>> multigamma(1, 1) + 1 + >>> multigamma(4, 1) + 6 + >>> multigamma(S(3)/2, 1) + sqrt(pi)/2 + + Writing ``multigamma`` in terms of the ``gamma`` function: + + >>> multigamma(x, 1) + gamma(x) + + >>> multigamma(x, 2) + sqrt(pi)*gamma(x)*gamma(x - 1/2) + + >>> multigamma(x, 3) + pi**(3/2)*gamma(x)*gamma(x - 1)*gamma(x - 1/2) + + Parameters + ========== + + p : order or dimension of the multivariate gamma function + + See Also + ======== + + gamma, lowergamma, uppergamma, polygamma, loggamma, digamma, trigamma, + sympy.functions.special.beta_functions.beta + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Multivariate_gamma_function + + """ + unbranched = True + + def fdiff(self, argindex=2): + from sympy.concrete.summations import Sum + if argindex == 2: + x, p = self.args + k = Dummy("k") + return self.func(x, p)*Sum(polygamma(0, x + (1 - k)/2), (k, 1, p)) + else: + raise ArgumentIndexError(self, argindex) + + @classmethod + def eval(cls, x, p): + from sympy.concrete.products import Product + if p.is_positive is False or p.is_integer is False: + raise ValueError('Order parameter p must be positive integer.') + k = Dummy("k") + return (pi**(p*(p - 1)/4)*Product(gamma(x + (1 - k)/2), + (k, 1, p))).doit() + + def _eval_conjugate(self): + x, p = self.args + return self.func(x.conjugate(), p) + + def _eval_is_real(self): + x, p = self.args + y = 2*x + if y.is_integer and (y <= (p - 1)) is True: + return False + if intlike(y) and (y <= (p - 1)): + return False + if y > (p - 1) or y.is_noninteger: + return True diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/hyper.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/hyper.py new file mode 100644 index 0000000000000000000000000000000000000000..3943e140821222a510c609a071b5dbbf08883745 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/hyper.py @@ -0,0 +1,1185 @@ +"""Hypergeometric and Meijer G-functions""" +from collections import Counter + +from sympy.core import S, Mod +from sympy.core.add import Add +from sympy.core.expr import Expr +from sympy.core.function import DefinedFunction, Derivative, ArgumentIndexError + +from sympy.core.containers import Tuple +from sympy.core.mul import Mul +from sympy.core.numbers import I, pi, oo, zoo +from sympy.core.parameters import global_parameters +from sympy.core.relational import Ne +from sympy.core.sorting import default_sort_key +from sympy.core.symbol import Dummy + +from sympy.external.gmpy import lcm +from sympy.functions import (sqrt, exp, log, sin, cos, asin, atan, + sinh, cosh, asinh, acosh, atanh, acoth) +from sympy.functions import factorial, RisingFactorial +from sympy.functions.elementary.complexes import Abs, re, unpolarify +from sympy.functions.elementary.exponential import exp_polar +from sympy.functions.elementary.integers import ceiling +from sympy.functions.elementary.piecewise import Piecewise +from sympy.logic.boolalg import (And, Or) +from sympy import ordered + + +class TupleArg(Tuple): + + # This method is only needed because hyper._eval_as_leading_term falls back + # (via super()) on using Function._eval_as_leading_term, which in turn + # calls as_leading_term on the args of the hyper. Ideally hyper should just + # have an _eval_as_leading_term method that handles all cases and this + # method should be removed because leading terms of tuples don't make + # sense. + def as_leading_term(self, *x, logx=None, cdir=0): + return TupleArg(*[f.as_leading_term(*x, logx=logx, cdir=cdir) for f in self.args]) + + def limit(self, x, xlim, dir='+'): + """ Compute limit x->xlim. + """ + from sympy.series.limits import limit + return TupleArg(*[limit(f, x, xlim, dir) for f in self.args]) + + +# TODO should __new__ accept **options? +# TODO should constructors should check if parameters are sensible? + + +def _prep_tuple(v): + """ + Turn an iterable argument *v* into a tuple and unpolarify, since both + hypergeometric and meijer g-functions are unbranched in their parameters. + + Examples + ======== + + >>> from sympy.functions.special.hyper import _prep_tuple + >>> _prep_tuple([1, 2, 3]) + (1, 2, 3) + >>> _prep_tuple((4, 5)) + (4, 5) + >>> _prep_tuple((7, 8, 9)) + (7, 8, 9) + + """ + return TupleArg(*[unpolarify(x) for x in v]) + + +class TupleParametersBase(DefinedFunction): + """ Base class that takes care of differentiation, when some of + the arguments are actually tuples. """ + # This is not deduced automatically since there are Tuples as arguments. + is_commutative = True + + def _eval_derivative(self, s): + try: + res = 0 + if self.args[0].has(s) or self.args[1].has(s): + for i, p in enumerate(self._diffargs): + m = self._diffargs[i].diff(s) + if m != 0: + res += self.fdiff((1, i))*m + return res + self.fdiff(3)*self.args[2].diff(s) + except (ArgumentIndexError, NotImplementedError): + return Derivative(self, s) + + +class hyper(TupleParametersBase): + r""" + The generalized hypergeometric function is defined by a series where + the ratios of successive terms are a rational function of the summation + index. When convergent, it is continued analytically to the largest + possible domain. + + Explanation + =========== + + The hypergeometric function depends on two vectors of parameters, called + the numerator parameters $a_p$, and the denominator parameters + $b_q$. It also has an argument $z$. The series definition is + + .. math :: + {}_pF_q\left(\begin{matrix} a_1, \cdots, a_p \\ b_1, \cdots, b_q \end{matrix} + \middle| z \right) + = \sum_{n=0}^\infty \frac{(a_1)_n \cdots (a_p)_n}{(b_1)_n \cdots (b_q)_n} + \frac{z^n}{n!}, + + where $(a)_n = (a)(a+1)\cdots(a+n-1)$ denotes the rising factorial. + + If one of the $b_q$ is a non-positive integer then the series is + undefined unless one of the $a_p$ is a larger (i.e., smaller in + magnitude) non-positive integer. If none of the $b_q$ is a + non-positive integer and one of the $a_p$ is a non-positive + integer, then the series reduces to a polynomial. To simplify the + following discussion, we assume that none of the $a_p$ or + $b_q$ is a non-positive integer. For more details, see the + references. + + The series converges for all $z$ if $p \le q$, and thus + defines an entire single-valued function in this case. If $p = + q+1$ the series converges for $|z| < 1$, and can be continued + analytically into a half-plane. If $p > q+1$ the series is + divergent for all $z$. + + Please note the hypergeometric function constructor currently does *not* + check if the parameters actually yield a well-defined function. + + Examples + ======== + + The parameters $a_p$ and $b_q$ can be passed as arbitrary + iterables, for example: + + >>> from sympy import hyper + >>> from sympy.abc import x, n, a + >>> h = hyper((1, 2, 3), [3, 4], x); h + hyper((1, 2), (4,), x) + >>> hyper((3, 1, 2), [3, 4], x, evaluate=False) # don't remove duplicates + hyper((1, 2, 3), (3, 4), x) + + There is also pretty printing (it looks better using Unicode): + + >>> from sympy import pprint + >>> pprint(h, use_unicode=False) + _ + |_ /1, 2 | \ + | | | x| + 2 1 \ 4 | / + + The parameters must always be iterables, even if they are vectors of + length one or zero: + + >>> hyper((1, ), [], x) + hyper((1,), (), x) + + But of course they may be variables (but if they depend on $x$ then you + should not expect much implemented functionality): + + >>> hyper((n, a), (n**2,), x) + hyper((a, n), (n**2,), x) + + The hypergeometric function generalizes many named special functions. + The function ``hyperexpand()`` tries to express a hypergeometric function + using named special functions. For example: + + >>> from sympy import hyperexpand + >>> hyperexpand(hyper([], [], x)) + exp(x) + + You can also use ``expand_func()``: + + >>> from sympy import expand_func + >>> expand_func(x*hyper([1, 1], [2], -x)) + log(x + 1) + + More examples: + + >>> from sympy import S + >>> hyperexpand(hyper([], [S(1)/2], -x**2/4)) + cos(x) + >>> hyperexpand(x*hyper([S(1)/2, S(1)/2], [S(3)/2], x**2)) + asin(x) + + We can also sometimes ``hyperexpand()`` parametric functions: + + >>> from sympy.abc import a + >>> hyperexpand(hyper([-a], [], x)) + (1 - x)**a + + See Also + ======== + + sympy.simplify.hyperexpand + gamma + meijerg + + References + ========== + + .. [1] Luke, Y. L. (1969), The Special Functions and Their Approximations, + Volume 1 + .. [2] https://en.wikipedia.org/wiki/Generalized_hypergeometric_function + + """ + + + def __new__(cls, ap, bq, z, **kwargs): + # TODO should we check convergence conditions? + if kwargs.pop('evaluate', global_parameters.evaluate): + ca = Counter(Tuple(*ap)) + cb = Counter(Tuple(*bq)) + common = ca & cb + arg = ap, bq = [], [] + for i, c in enumerate((ca, cb)): + c -= common + for k in ordered(c): + arg[i].extend([k]*c[k]) + else: + ap = list(ordered(ap)) + bq = list(ordered(bq)) + return super().__new__(cls, _prep_tuple(ap), _prep_tuple(bq), z, **kwargs) + + @classmethod + def eval(cls, ap, bq, z): + if len(ap) <= len(bq) or (len(ap) == len(bq) + 1 and (Abs(z) <= 1) == True): + nz = unpolarify(z) + if z != nz: + return hyper(ap, bq, nz) + + def fdiff(self, argindex=3): + if argindex != 3: + raise ArgumentIndexError(self, argindex) + nap = Tuple(*[a + 1 for a in self.ap]) + nbq = Tuple(*[b + 1 for b in self.bq]) + fac = Mul(*self.ap)/Mul(*self.bq) + return fac*hyper(nap, nbq, self.argument) + + def _eval_expand_func(self, **hints): + from sympy.functions.special.gamma_functions import gamma + from sympy.simplify.hyperexpand import hyperexpand + if len(self.ap) == 2 and len(self.bq) == 1 and self.argument == 1: + a, b = self.ap + c = self.bq[0] + return gamma(c)*gamma(c - a - b)/gamma(c - a)/gamma(c - b) + return hyperexpand(self) + + def _eval_rewrite_as_Sum(self, ap, bq, z, **kwargs): + from sympy.concrete.summations import Sum + n = Dummy("n", integer=True) + rfap = [RisingFactorial(a, n) for a in ap] + rfbq = [RisingFactorial(b, n) for b in bq] + coeff = Mul(*rfap) / Mul(*rfbq) + return Piecewise((Sum(coeff * z**n / factorial(n), (n, 0, oo)), + self.convergence_statement), (self, True)) + + def _eval_as_leading_term(self, x, logx, cdir): + arg = self.args[2] + x0 = arg.subs(x, 0) + if x0 is S.NaN: + x0 = arg.limit(x, 0, dir='-' if re(cdir).is_negative else '+') + + if x0 is S.Zero: + return S.One + return super()._eval_as_leading_term(x, logx=logx, cdir=cdir) + + def _eval_nseries(self, x, n, logx, cdir=0): + + from sympy.series.order import Order + + arg = self.args[2] + x0 = arg.limit(x, 0) + ap = self.args[0] + bq = self.args[1] + + if not (arg == x and x0 == 0): + # It would be better to do something with arg.nseries here, rather + # than falling back on Function._eval_nseries. The code below + # though is not sufficient if arg is something like x/(x+1). + from sympy.simplify.hyperexpand import hyperexpand + return hyperexpand(super()._eval_nseries(x, n, logx)) + + terms = [] + + for i in range(n): + num = Mul(*[RisingFactorial(a, i) for a in ap]) + den = Mul(*[RisingFactorial(b, i) for b in bq]) + terms.append(((num/den) * (arg**i)) / factorial(i)) + + return (Add(*terms) + Order(x**n,x)) + + @property + def argument(self): + """ Argument of the hypergeometric function. """ + return self.args[2] + + @property + def ap(self): + """ Numerator parameters of the hypergeometric function. """ + return Tuple(*self.args[0]) + + @property + def bq(self): + """ Denominator parameters of the hypergeometric function. """ + return Tuple(*self.args[1]) + + @property + def _diffargs(self): + return self.ap + self.bq + + @property + def eta(self): + """ A quantity related to the convergence of the series. """ + return sum(self.ap) - sum(self.bq) + + @property + def radius_of_convergence(self): + """ + Compute the radius of convergence of the defining series. + + Explanation + =========== + + Note that even if this is not ``oo``, the function may still be + evaluated outside of the radius of convergence by analytic + continuation. But if this is zero, then the function is not actually + defined anywhere else. + + Examples + ======== + + >>> from sympy import hyper + >>> from sympy.abc import z + >>> hyper((1, 2), [3], z).radius_of_convergence + 1 + >>> hyper((1, 2, 3), [4], z).radius_of_convergence + 0 + >>> hyper((1, 2), (3, 4), z).radius_of_convergence + oo + + """ + if any(a.is_integer and (a <= 0) == True for a in self.ap + self.bq): + aints = [a for a in self.ap if a.is_Integer and (a <= 0) == True] + bints = [a for a in self.bq if a.is_Integer and (a <= 0) == True] + if len(aints) < len(bints): + return S.Zero + popped = False + for b in bints: + cancelled = False + while aints: + a = aints.pop() + if a >= b: + cancelled = True + break + popped = True + if not cancelled: + return S.Zero + if aints or popped: + # There are still non-positive numerator parameters. + # This is a polynomial. + return oo + if len(self.ap) == len(self.bq) + 1: + return S.One + elif len(self.ap) <= len(self.bq): + return oo + else: + return S.Zero + + @property + def convergence_statement(self): + """ Return a condition on z under which the series converges. """ + R = self.radius_of_convergence + if R == 0: + return False + if R == oo: + return True + # The special functions and their approximations, page 44 + e = self.eta + z = self.argument + c1 = And(re(e) < 0, abs(z) <= 1) + c2 = And(0 <= re(e), re(e) < 1, abs(z) <= 1, Ne(z, 1)) + c3 = And(re(e) >= 1, abs(z) < 1) + return Or(c1, c2, c3) + + def _eval_simplify(self, **kwargs): + from sympy.simplify.hyperexpand import hyperexpand + return hyperexpand(self) + + +class meijerg(TupleParametersBase): + r""" + The Meijer G-function is defined by a Mellin-Barnes type integral that + resembles an inverse Mellin transform. It generalizes the hypergeometric + functions. + + Explanation + =========== + + The Meijer G-function depends on four sets of parameters. There are + "*numerator parameters*" + $a_1, \ldots, a_n$ and $a_{n+1}, \ldots, a_p$, and there are + "*denominator parameters*" + $b_1, \ldots, b_m$ and $b_{m+1}, \ldots, b_q$. + Confusingly, it is traditionally denoted as follows (note the position + of $m$, $n$, $p$, $q$, and how they relate to the lengths of the four + parameter vectors): + + .. math :: + G_{p,q}^{m,n} \left(\begin{matrix}a_1, \cdots, a_n & a_{n+1}, \cdots, a_p \\ + b_1, \cdots, b_m & b_{m+1}, \cdots, b_q + \end{matrix} \middle| z \right). + + However, in SymPy the four parameter vectors are always available + separately (see examples), so that there is no need to keep track of the + decorating sub- and super-scripts on the G symbol. + + The G function is defined as the following integral: + + .. math :: + \frac{1}{2 \pi i} \int_L \frac{\prod_{j=1}^m \Gamma(b_j - s) + \prod_{j=1}^n \Gamma(1 - a_j + s)}{\prod_{j=m+1}^q \Gamma(1- b_j +s) + \prod_{j=n+1}^p \Gamma(a_j - s)} z^s \mathrm{d}s, + + where $\Gamma(z)$ is the gamma function. There are three possible + contours which we will not describe in detail here (see the references). + If the integral converges along more than one of them, the definitions + agree. The contours all separate the poles of $\Gamma(1-a_j+s)$ + from the poles of $\Gamma(b_k-s)$, so in particular the G function + is undefined if $a_j - b_k \in \mathbb{Z}_{>0}$ for some + $j \le n$ and $k \le m$. + + The conditions under which one of the contours yields a convergent integral + are complicated and we do not state them here, see the references. + + Please note currently the Meijer G-function constructor does *not* check any + convergence conditions. + + Examples + ======== + + You can pass the parameters either as four separate vectors: + + >>> from sympy import meijerg, Tuple, pprint + >>> from sympy.abc import x, a + >>> pprint(meijerg((1, 2), (a, 4), (5,), [], x), use_unicode=False) + __1, 2 /1, 2 4, a | \ + /__ | | x| + \_|4, 1 \ 5 | / + + Or as two nested vectors: + + >>> pprint(meijerg([(1, 2), (3, 4)], ([5], Tuple()), x), use_unicode=False) + __1, 2 /1, 2 3, 4 | \ + /__ | | x| + \_|4, 1 \ 5 | / + + As with the hypergeometric function, the parameters may be passed as + arbitrary iterables. Vectors of length zero and one also have to be + passed as iterables. The parameters need not be constants, but if they + depend on the argument then not much implemented functionality should be + expected. + + All the subvectors of parameters are available: + + >>> from sympy import pprint + >>> g = meijerg([1], [2], [3], [4], x) + >>> pprint(g, use_unicode=False) + __1, 1 /1 2 | \ + /__ | | x| + \_|2, 2 \3 4 | / + >>> g.an + (1,) + >>> g.ap + (1, 2) + >>> g.aother + (2,) + >>> g.bm + (3,) + >>> g.bq + (3, 4) + >>> g.bother + (4,) + + The Meijer G-function generalizes the hypergeometric functions. + In some cases it can be expressed in terms of hypergeometric functions, + using Slater's theorem. For example: + + >>> from sympy import hyperexpand + >>> from sympy.abc import a, b, c + >>> hyperexpand(meijerg([a], [], [c], [b], x), allow_hyper=True) + x**c*gamma(-a + c + 1)*hyper((-a + c + 1,), + (-b + c + 1,), -x)/gamma(-b + c + 1) + + Thus the Meijer G-function also subsumes many named functions as special + cases. You can use ``expand_func()`` or ``hyperexpand()`` to (try to) + rewrite a Meijer G-function in terms of named special functions. For + example: + + >>> from sympy import expand_func, S + >>> expand_func(meijerg([[],[]], [[0],[]], -x)) + exp(x) + >>> hyperexpand(meijerg([[],[]], [[S(1)/2],[0]], (x/2)**2)) + sin(x)/sqrt(pi) + + See Also + ======== + + hyper + sympy.simplify.hyperexpand + + References + ========== + + .. [1] Luke, Y. L. (1969), The Special Functions and Their Approximations, + Volume 1 + .. [2] https://en.wikipedia.org/wiki/Meijer_G-function + + """ + + + def __new__(cls, *args, **kwargs): + if len(args) == 5: + args = [(args[0], args[1]), (args[2], args[3]), args[4]] + if len(args) != 3: + raise TypeError("args must be either as, as', bs, bs', z or " + "as, bs, z") + + def tr(p): + if len(p) != 2: + raise TypeError("wrong argument") + p = [list(ordered(i)) for i in p] + return TupleArg(_prep_tuple(p[0]), _prep_tuple(p[1])) + + arg0, arg1 = tr(args[0]), tr(args[1]) + if Tuple(arg0, arg1).has(oo, zoo, -oo): + raise ValueError("G-function parameters must be finite") + if any((a - b).is_Integer and a - b > 0 + for a in arg0[0] for b in arg1[0]): + raise ValueError("no parameter a1, ..., an may differ from " + "any b1, ..., bm by a positive integer") + + # TODO should we check convergence conditions? + return super().__new__(cls, arg0, arg1, args[2], **kwargs) + + def fdiff(self, argindex=3): + if argindex != 3: + return self._diff_wrt_parameter(argindex[1]) + if len(self.an) >= 1: + a = list(self.an) + a[0] -= 1 + G = meijerg(a, self.aother, self.bm, self.bother, self.argument) + return 1/self.argument * ((self.an[0] - 1)*self + G) + elif len(self.bm) >= 1: + b = list(self.bm) + b[0] += 1 + G = meijerg(self.an, self.aother, b, self.bother, self.argument) + return 1/self.argument * (self.bm[0]*self - G) + else: + return S.Zero + + def _diff_wrt_parameter(self, idx): + # Differentiation wrt a parameter can only be done in very special + # cases. In particular, if we want to differentiate with respect to + # `a`, all other gamma factors have to reduce to rational functions. + # + # Let MT denote mellin transform. Suppose T(-s) is the gamma factor + # appearing in the definition of G. Then + # + # MT(log(z)G(z)) = d/ds T(s) = d/da T(s) + ... + # + # Thus d/da G(z) = log(z)G(z) - ... + # The ... can be evaluated as a G function under the above conditions, + # the formula being most easily derived by using + # + # d Gamma(s + n) Gamma(s + n) / 1 1 1 \ + # -- ------------ = ------------ | - + ---- + ... + --------- | + # ds Gamma(s) Gamma(s) \ s s + 1 s + n - 1 / + # + # which follows from the difference equation of the digamma function. + # (There is a similar equation for -n instead of +n). + + # We first figure out how to pair the parameters. + an = list(self.an) + ap = list(self.aother) + bm = list(self.bm) + bq = list(self.bother) + if idx < len(an): + an.pop(idx) + else: + idx -= len(an) + if idx < len(ap): + ap.pop(idx) + else: + idx -= len(ap) + if idx < len(bm): + bm.pop(idx) + else: + bq.pop(idx - len(bm)) + pairs1 = [] + pairs2 = [] + for l1, l2, pairs in [(an, bq, pairs1), (ap, bm, pairs2)]: + while l1: + x = l1.pop() + found = None + for i, y in enumerate(l2): + if not Mod((x - y).simplify(), 1): + found = i + break + if found is None: + raise NotImplementedError('Derivative not expressible ' + 'as G-function?') + y = l2[i] + l2.pop(i) + pairs.append((x, y)) + + # Now build the result. + res = log(self.argument)*self + + for a, b in pairs1: + sign = 1 + n = a - b + base = b + if n < 0: + sign = -1 + n = b - a + base = a + for k in range(n): + res -= sign*meijerg(self.an + (base + k + 1,), self.aother, + self.bm, self.bother + (base + k + 0,), + self.argument) + + for a, b in pairs2: + sign = 1 + n = b - a + base = a + if n < 0: + sign = -1 + n = a - b + base = b + for k in range(n): + res -= sign*meijerg(self.an, self.aother + (base + k + 1,), + self.bm + (base + k + 0,), self.bother, + self.argument) + + return res + + def get_period(self): + """ + Return a number $P$ such that $G(x*exp(I*P)) == G(x)$. + + Examples + ======== + + >>> from sympy import meijerg, pi, S + >>> from sympy.abc import z + + >>> meijerg([1], [], [], [], z).get_period() + 2*pi + >>> meijerg([pi], [], [], [], z).get_period() + oo + >>> meijerg([1, 2], [], [], [], z).get_period() + oo + >>> meijerg([1,1], [2], [1, S(1)/2, S(1)/3], [1], z).get_period() + 12*pi + + """ + # This follows from slater's theorem. + def compute(l): + # first check that no two differ by an integer + for i, b in enumerate(l): + if not b.is_Rational: + return oo + for j in range(i + 1, len(l)): + if not Mod((b - l[j]).simplify(), 1): + return oo + return lcm(*(x.q for x in l)) + beta = compute(self.bm) + alpha = compute(self.an) + p, q = len(self.ap), len(self.bq) + if p == q: + if oo in (alpha, beta): + return oo + return 2*pi*lcm(alpha, beta) + elif p < q: + return 2*pi*beta + else: + return 2*pi*alpha + + def _eval_expand_func(self, **hints): + from sympy.simplify.hyperexpand import hyperexpand + return hyperexpand(self) + + def _eval_evalf(self, prec): + # The default code is insufficient for polar arguments. + # mpmath provides an optional argument "r", which evaluates + # G(z**(1/r)). I am not sure what its intended use is, but we hijack it + # here in the following way: to evaluate at a number z of |argument| + # less than (say) n*pi, we put r=1/n, compute z' = root(z, n) + # (carefully so as not to loose the branch information), and evaluate + # G(z'**(1/r)) = G(z'**n) = G(z). + import mpmath + znum = self.argument._eval_evalf(prec) + if znum.has(exp_polar): + znum, branch = znum.as_coeff_mul(exp_polar) + if len(branch) != 1: + return + branch = branch[0].args[0]/I + else: + branch = S.Zero + n = ceiling(abs(branch/pi)) + 1 + znum = znum**(S.One/n)*exp(I*branch / n) + + # Convert all args to mpf or mpc + try: + [z, r, ap, bq] = [arg._to_mpmath(prec) + for arg in [znum, 1/n, self.args[0], self.args[1]]] + except ValueError: + return + + with mpmath.workprec(prec): + v = mpmath.meijerg(ap, bq, z, r) + + return Expr._from_mpmath(v, prec) + + def _eval_as_leading_term(self, x, logx, cdir): + from sympy.simplify.hyperexpand import hyperexpand + return hyperexpand(self).as_leading_term(x, logx=logx, cdir=cdir) + + def integrand(self, s): + """ Get the defining integrand D(s). """ + from sympy.functions.special.gamma_functions import gamma + return self.argument**s \ + * Mul(*(gamma(b - s) for b in self.bm)) \ + * Mul(*(gamma(1 - a + s) for a in self.an)) \ + / Mul(*(gamma(1 - b + s) for b in self.bother)) \ + / Mul(*(gamma(a - s) for a in self.aother)) + + @property + def argument(self): + """ Argument of the Meijer G-function. """ + return self.args[2] + + @property + def an(self): + """ First set of numerator parameters. """ + return Tuple(*self.args[0][0]) + + @property + def ap(self): + """ Combined numerator parameters. """ + return Tuple(*(self.args[0][0] + self.args[0][1])) + + @property + def aother(self): + """ Second set of numerator parameters. """ + return Tuple(*self.args[0][1]) + + @property + def bm(self): + """ First set of denominator parameters. """ + return Tuple(*self.args[1][0]) + + @property + def bq(self): + """ Combined denominator parameters. """ + return Tuple(*(self.args[1][0] + self.args[1][1])) + + @property + def bother(self): + """ Second set of denominator parameters. """ + return Tuple(*self.args[1][1]) + + @property + def _diffargs(self): + return self.ap + self.bq + + @property + def nu(self): + """ A quantity related to the convergence region of the integral, + c.f. references. """ + return sum(self.bq) - sum(self.ap) + + @property + def delta(self): + """ A quantity related to the convergence region of the integral, + c.f. references. """ + return len(self.bm) + len(self.an) - S(len(self.ap) + len(self.bq))/2 + + @property + def is_number(self): + """ Returns true if expression has numeric data only. """ + return not self.free_symbols + + +class HyperRep(DefinedFunction): + """ + A base class for "hyper representation functions". + + This is used exclusively in ``hyperexpand()``, but fits more logically here. + + pFq is branched at 1 if p == q+1. For use with slater-expansion, we want + define an "analytic continuation" to all polar numbers, which is + continuous on circles and on the ray t*exp_polar(I*pi). Moreover, we want + a "nice" expression for the various cases. + + This base class contains the core logic, concrete derived classes only + supply the actual functions. + + """ + + + @classmethod + def eval(cls, *args): + newargs = tuple(map(unpolarify, args[:-1])) + args[-1:] + if args != newargs: + return cls(*newargs) + + @classmethod + def _expr_small(cls, x): + """ An expression for F(x) which holds for |x| < 1. """ + raise NotImplementedError + + @classmethod + def _expr_small_minus(cls, x): + """ An expression for F(-x) which holds for |x| < 1. """ + raise NotImplementedError + + @classmethod + def _expr_big(cls, x, n): + """ An expression for F(exp_polar(2*I*pi*n)*x), |x| > 1. """ + raise NotImplementedError + + @classmethod + def _expr_big_minus(cls, x, n): + """ An expression for F(exp_polar(2*I*pi*n + pi*I)*x), |x| > 1. """ + raise NotImplementedError + + def _eval_rewrite_as_nonrep(self, *args, **kwargs): + x, n = self.args[-1].extract_branch_factor(allow_half=True) + minus = False + newargs = self.args[:-1] + (x,) + if not n.is_Integer: + minus = True + n -= S.Half + newerargs = newargs + (n,) + if minus: + small = self._expr_small_minus(*newargs) + big = self._expr_big_minus(*newerargs) + else: + small = self._expr_small(*newargs) + big = self._expr_big(*newerargs) + + if big == small: + return small + return Piecewise((big, abs(x) > 1), (small, True)) + + def _eval_rewrite_as_nonrepsmall(self, *args, **kwargs): + x, n = self.args[-1].extract_branch_factor(allow_half=True) + args = self.args[:-1] + (x,) + if not n.is_Integer: + return self._expr_small_minus(*args) + return self._expr_small(*args) + + +class HyperRep_power1(HyperRep): + """ Return a representative for hyper([-a], [], z) == (1 - z)**a. """ + + @classmethod + def _expr_small(cls, a, x): + return (1 - x)**a + + @classmethod + def _expr_small_minus(cls, a, x): + return (1 + x)**a + + @classmethod + def _expr_big(cls, a, x, n): + if a.is_integer: + return cls._expr_small(a, x) + return (x - 1)**a*exp((2*n - 1)*pi*I*a) + + @classmethod + def _expr_big_minus(cls, a, x, n): + if a.is_integer: + return cls._expr_small_minus(a, x) + return (1 + x)**a*exp(2*n*pi*I*a) + + +class HyperRep_power2(HyperRep): + """ Return a representative for hyper([a, a - 1/2], [2*a], z). """ + + @classmethod + def _expr_small(cls, a, x): + return 2**(2*a - 1)*(1 + sqrt(1 - x))**(1 - 2*a) + + @classmethod + def _expr_small_minus(cls, a, x): + return 2**(2*a - 1)*(1 + sqrt(1 + x))**(1 - 2*a) + + @classmethod + def _expr_big(cls, a, x, n): + sgn = -1 + if n.is_odd: + sgn = 1 + n -= 1 + return 2**(2*a - 1)*(1 + sgn*I*sqrt(x - 1))**(1 - 2*a) \ + *exp(-2*n*pi*I*a) + + @classmethod + def _expr_big_minus(cls, a, x, n): + sgn = 1 + if n.is_odd: + sgn = -1 + return sgn*2**(2*a - 1)*(sqrt(1 + x) + sgn)**(1 - 2*a)*exp(-2*pi*I*a*n) + + +class HyperRep_log1(HyperRep): + """ Represent -z*hyper([1, 1], [2], z) == log(1 - z). """ + @classmethod + def _expr_small(cls, x): + return log(1 - x) + + @classmethod + def _expr_small_minus(cls, x): + return log(1 + x) + + @classmethod + def _expr_big(cls, x, n): + return log(x - 1) + (2*n - 1)*pi*I + + @classmethod + def _expr_big_minus(cls, x, n): + return log(1 + x) + 2*n*pi*I + + +class HyperRep_atanh(HyperRep): + """ Represent hyper([1/2, 1], [3/2], z) == atanh(sqrt(z))/sqrt(z). """ + @classmethod + def _expr_small(cls, x): + return atanh(sqrt(x))/sqrt(x) + + def _expr_small_minus(cls, x): + return atan(sqrt(x))/sqrt(x) + + def _expr_big(cls, x, n): + if n.is_even: + return (acoth(sqrt(x)) + I*pi/2)/sqrt(x) + else: + return (acoth(sqrt(x)) - I*pi/2)/sqrt(x) + + def _expr_big_minus(cls, x, n): + if n.is_even: + return atan(sqrt(x))/sqrt(x) + else: + return (atan(sqrt(x)) - pi)/sqrt(x) + + +class HyperRep_asin1(HyperRep): + """ Represent hyper([1/2, 1/2], [3/2], z) == asin(sqrt(z))/sqrt(z). """ + @classmethod + def _expr_small(cls, z): + return asin(sqrt(z))/sqrt(z) + + @classmethod + def _expr_small_minus(cls, z): + return asinh(sqrt(z))/sqrt(z) + + @classmethod + def _expr_big(cls, z, n): + return S.NegativeOne**n*((S.Half - n)*pi/sqrt(z) + I*acosh(sqrt(z))/sqrt(z)) + + @classmethod + def _expr_big_minus(cls, z, n): + return S.NegativeOne**n*(asinh(sqrt(z))/sqrt(z) + n*pi*I/sqrt(z)) + + +class HyperRep_asin2(HyperRep): + """ Represent hyper([1, 1], [3/2], z) == asin(sqrt(z))/sqrt(z)/sqrt(1-z). """ + # TODO this can be nicer + @classmethod + def _expr_small(cls, z): + return HyperRep_asin1._expr_small(z) \ + /HyperRep_power1._expr_small(S.Half, z) + + @classmethod + def _expr_small_minus(cls, z): + return HyperRep_asin1._expr_small_minus(z) \ + /HyperRep_power1._expr_small_minus(S.Half, z) + + @classmethod + def _expr_big(cls, z, n): + return HyperRep_asin1._expr_big(z, n) \ + /HyperRep_power1._expr_big(S.Half, z, n) + + @classmethod + def _expr_big_minus(cls, z, n): + return HyperRep_asin1._expr_big_minus(z, n) \ + /HyperRep_power1._expr_big_minus(S.Half, z, n) + + +class HyperRep_sqrts1(HyperRep): + """ Return a representative for hyper([-a, 1/2 - a], [1/2], z). """ + + @classmethod + def _expr_small(cls, a, z): + return ((1 - sqrt(z))**(2*a) + (1 + sqrt(z))**(2*a))/2 + + @classmethod + def _expr_small_minus(cls, a, z): + return (1 + z)**a*cos(2*a*atan(sqrt(z))) + + @classmethod + def _expr_big(cls, a, z, n): + if n.is_even: + return ((sqrt(z) + 1)**(2*a)*exp(2*pi*I*n*a) + + (sqrt(z) - 1)**(2*a)*exp(2*pi*I*(n - 1)*a))/2 + else: + n -= 1 + return ((sqrt(z) - 1)**(2*a)*exp(2*pi*I*a*(n + 1)) + + (sqrt(z) + 1)**(2*a)*exp(2*pi*I*a*n))/2 + + @classmethod + def _expr_big_minus(cls, a, z, n): + if n.is_even: + return (1 + z)**a*exp(2*pi*I*n*a)*cos(2*a*atan(sqrt(z))) + else: + return (1 + z)**a*exp(2*pi*I*n*a)*cos(2*a*atan(sqrt(z)) - 2*pi*a) + + +class HyperRep_sqrts2(HyperRep): + """ Return a representative for + sqrt(z)/2*[(1-sqrt(z))**2a - (1 + sqrt(z))**2a] + == -2*z/(2*a+1) d/dz hyper([-a - 1/2, -a], [1/2], z)""" + + @classmethod + def _expr_small(cls, a, z): + return sqrt(z)*((1 - sqrt(z))**(2*a) - (1 + sqrt(z))**(2*a))/2 + + @classmethod + def _expr_small_minus(cls, a, z): + return sqrt(z)*(1 + z)**a*sin(2*a*atan(sqrt(z))) + + @classmethod + def _expr_big(cls, a, z, n): + if n.is_even: + return sqrt(z)/2*((sqrt(z) - 1)**(2*a)*exp(2*pi*I*a*(n - 1)) - + (sqrt(z) + 1)**(2*a)*exp(2*pi*I*a*n)) + else: + n -= 1 + return sqrt(z)/2*((sqrt(z) - 1)**(2*a)*exp(2*pi*I*a*(n + 1)) - + (sqrt(z) + 1)**(2*a)*exp(2*pi*I*a*n)) + + def _expr_big_minus(cls, a, z, n): + if n.is_even: + return (1 + z)**a*exp(2*pi*I*n*a)*sqrt(z)*sin(2*a*atan(sqrt(z))) + else: + return (1 + z)**a*exp(2*pi*I*n*a)*sqrt(z) \ + *sin(2*a*atan(sqrt(z)) - 2*pi*a) + + +class HyperRep_log2(HyperRep): + """ Represent log(1/2 + sqrt(1 - z)/2) == -z/4*hyper([3/2, 1, 1], [2, 2], z) """ + + @classmethod + def _expr_small(cls, z): + return log(S.Half + sqrt(1 - z)/2) + + @classmethod + def _expr_small_minus(cls, z): + return log(S.Half + sqrt(1 + z)/2) + + @classmethod + def _expr_big(cls, z, n): + if n.is_even: + return (n - S.Half)*pi*I + log(sqrt(z)/2) + I*asin(1/sqrt(z)) + else: + return (n - S.Half)*pi*I + log(sqrt(z)/2) - I*asin(1/sqrt(z)) + + def _expr_big_minus(cls, z, n): + if n.is_even: + return pi*I*n + log(S.Half + sqrt(1 + z)/2) + else: + return pi*I*n + log(sqrt(1 + z)/2 - S.Half) + + +class HyperRep_cosasin(HyperRep): + """ Represent hyper([a, -a], [1/2], z) == cos(2*a*asin(sqrt(z))). """ + # Note there are many alternative expressions, e.g. as powers of a sum of + # square roots. + + @classmethod + def _expr_small(cls, a, z): + return cos(2*a*asin(sqrt(z))) + + @classmethod + def _expr_small_minus(cls, a, z): + return cosh(2*a*asinh(sqrt(z))) + + @classmethod + def _expr_big(cls, a, z, n): + return cosh(2*a*acosh(sqrt(z)) + a*pi*I*(2*n - 1)) + + @classmethod + def _expr_big_minus(cls, a, z, n): + return cosh(2*a*asinh(sqrt(z)) + 2*a*pi*I*n) + + +class HyperRep_sinasin(HyperRep): + """ Represent 2*a*z*hyper([1 - a, 1 + a], [3/2], z) + == sqrt(z)/sqrt(1-z)*sin(2*a*asin(sqrt(z))) """ + + @classmethod + def _expr_small(cls, a, z): + return sqrt(z)/sqrt(1 - z)*sin(2*a*asin(sqrt(z))) + + @classmethod + def _expr_small_minus(cls, a, z): + return -sqrt(z)/sqrt(1 + z)*sinh(2*a*asinh(sqrt(z))) + + @classmethod + def _expr_big(cls, a, z, n): + return -1/sqrt(1 - 1/z)*sinh(2*a*acosh(sqrt(z)) + a*pi*I*(2*n - 1)) + + @classmethod + def _expr_big_minus(cls, a, z, n): + return -1/sqrt(1 + 1/z)*sinh(2*a*asinh(sqrt(z)) + 2*a*pi*I*n) + +class appellf1(DefinedFunction): + r""" + This is the Appell hypergeometric function of two variables as: + + .. math :: + F_1(a,b_1,b_2,c,x,y) = \sum_{m=0}^{\infty} \sum_{n=0}^{\infty} + \frac{(a)_{m+n} (b_1)_m (b_2)_n}{(c)_{m+n}} + \frac{x^m y^n}{m! n!}. + + Examples + ======== + + >>> from sympy import appellf1, symbols + >>> x, y, a, b1, b2, c = symbols('x y a b1 b2 c') + >>> appellf1(2., 1., 6., 4., 5., 6.) + 0.0063339426292673 + >>> appellf1(12., 12., 6., 4., 0.5, 0.12) + 172870711.659936 + >>> appellf1(40, 2, 6, 4, 15, 60) + appellf1(40, 2, 6, 4, 15, 60) + >>> appellf1(20., 12., 10., 3., 0.5, 0.12) + 15605338197184.4 + >>> appellf1(40, 2, 6, 4, x, y) + appellf1(40, 2, 6, 4, x, y) + >>> appellf1(a, b1, b2, c, x, y) + appellf1(a, b1, b2, c, x, y) + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Appell_series + .. [2] https://functions.wolfram.com/HypergeometricFunctions/AppellF1/ + + """ + + @classmethod + def eval(cls, a, b1, b2, c, x, y): + if default_sort_key(b1) > default_sort_key(b2): + b1, b2 = b2, b1 + x, y = y, x + return cls(a, b1, b2, c, x, y) + elif b1 == b2 and default_sort_key(x) > default_sort_key(y): + x, y = y, x + return cls(a, b1, b2, c, x, y) + if x == 0 and y == 0: + return S.One + + def fdiff(self, argindex=5): + a, b1, b2, c, x, y = self.args + if argindex == 5: + return (a*b1/c)*appellf1(a + 1, b1 + 1, b2, c + 1, x, y) + elif argindex == 6: + return (a*b2/c)*appellf1(a + 1, b1, b2 + 1, c + 1, x, y) + elif argindex in (1, 2, 3, 4): + return Derivative(self, self.args[argindex-1]) + else: + raise ArgumentIndexError(self, argindex) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/mathieu_functions.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/mathieu_functions.py new file mode 100644 index 0000000000000000000000000000000000000000..66bccd8d3e6dd357e1e0b93fb5cb5ad4c5f1367f --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/mathieu_functions.py @@ -0,0 +1,269 @@ +""" This module contains the Mathieu functions. +""" + +from sympy.core.function import DefinedFunction, ArgumentIndexError +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import sin, cos + + +class MathieuBase(DefinedFunction): + """ + Abstract base class for Mathieu functions. + + This class is meant to reduce code duplication. + + """ + + unbranched = True + + def _eval_conjugate(self): + a, q, z = self.args + return self.func(a.conjugate(), q.conjugate(), z.conjugate()) + + +class mathieus(MathieuBase): + r""" + The Mathieu Sine function $S(a,q,z)$. + + Explanation + =========== + + This function is one solution of the Mathieu differential equation: + + .. math :: + y(x)^{\prime\prime} + (a - 2 q \cos(2 x)) y(x) = 0 + + The other solution is the Mathieu Cosine function. + + Examples + ======== + + >>> from sympy import diff, mathieus + >>> from sympy.abc import a, q, z + + >>> mathieus(a, q, z) + mathieus(a, q, z) + + >>> mathieus(a, 0, z) + sin(sqrt(a)*z) + + >>> diff(mathieus(a, q, z), z) + mathieusprime(a, q, z) + + See Also + ======== + + mathieuc: Mathieu cosine function. + mathieusprime: Derivative of Mathieu sine function. + mathieucprime: Derivative of Mathieu cosine function. + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Mathieu_function + .. [2] https://dlmf.nist.gov/28 + .. [3] https://mathworld.wolfram.com/MathieuFunction.html + .. [4] https://functions.wolfram.com/MathieuandSpheroidalFunctions/MathieuS/ + + """ + + def fdiff(self, argindex=1): + if argindex == 3: + a, q, z = self.args + return mathieusprime(a, q, z) + else: + raise ArgumentIndexError(self, argindex) + + @classmethod + def eval(cls, a, q, z): + if q.is_Number and q.is_zero: + return sin(sqrt(a)*z) + # Try to pull out factors of -1 + if z.could_extract_minus_sign(): + return -cls(a, q, -z) + + +class mathieuc(MathieuBase): + r""" + The Mathieu Cosine function $C(a,q,z)$. + + Explanation + =========== + + This function is one solution of the Mathieu differential equation: + + .. math :: + y(x)^{\prime\prime} + (a - 2 q \cos(2 x)) y(x) = 0 + + The other solution is the Mathieu Sine function. + + Examples + ======== + + >>> from sympy import diff, mathieuc + >>> from sympy.abc import a, q, z + + >>> mathieuc(a, q, z) + mathieuc(a, q, z) + + >>> mathieuc(a, 0, z) + cos(sqrt(a)*z) + + >>> diff(mathieuc(a, q, z), z) + mathieucprime(a, q, z) + + See Also + ======== + + mathieus: Mathieu sine function + mathieusprime: Derivative of Mathieu sine function + mathieucprime: Derivative of Mathieu cosine function + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Mathieu_function + .. [2] https://dlmf.nist.gov/28 + .. [3] https://mathworld.wolfram.com/MathieuFunction.html + .. [4] https://functions.wolfram.com/MathieuandSpheroidalFunctions/MathieuC/ + + """ + + def fdiff(self, argindex=1): + if argindex == 3: + a, q, z = self.args + return mathieucprime(a, q, z) + else: + raise ArgumentIndexError(self, argindex) + + @classmethod + def eval(cls, a, q, z): + if q.is_Number and q.is_zero: + return cos(sqrt(a)*z) + # Try to pull out factors of -1 + if z.could_extract_minus_sign(): + return cls(a, q, -z) + + +class mathieusprime(MathieuBase): + r""" + The derivative $S^{\prime}(a,q,z)$ of the Mathieu Sine function. + + Explanation + =========== + + This function is one solution of the Mathieu differential equation: + + .. math :: + y(x)^{\prime\prime} + (a - 2 q \cos(2 x)) y(x) = 0 + + The other solution is the Mathieu Cosine function. + + Examples + ======== + + >>> from sympy import diff, mathieusprime + >>> from sympy.abc import a, q, z + + >>> mathieusprime(a, q, z) + mathieusprime(a, q, z) + + >>> mathieusprime(a, 0, z) + sqrt(a)*cos(sqrt(a)*z) + + >>> diff(mathieusprime(a, q, z), z) + (-a + 2*q*cos(2*z))*mathieus(a, q, z) + + See Also + ======== + + mathieus: Mathieu sine function + mathieuc: Mathieu cosine function + mathieucprime: Derivative of Mathieu cosine function + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Mathieu_function + .. [2] https://dlmf.nist.gov/28 + .. [3] https://mathworld.wolfram.com/MathieuFunction.html + .. [4] https://functions.wolfram.com/MathieuandSpheroidalFunctions/MathieuSPrime/ + + """ + + def fdiff(self, argindex=1): + if argindex == 3: + a, q, z = self.args + return (2*q*cos(2*z) - a)*mathieus(a, q, z) + else: + raise ArgumentIndexError(self, argindex) + + @classmethod + def eval(cls, a, q, z): + if q.is_Number and q.is_zero: + return sqrt(a)*cos(sqrt(a)*z) + # Try to pull out factors of -1 + if z.could_extract_minus_sign(): + return cls(a, q, -z) + + +class mathieucprime(MathieuBase): + r""" + The derivative $C^{\prime}(a,q,z)$ of the Mathieu Cosine function. + + Explanation + =========== + + This function is one solution of the Mathieu differential equation: + + .. math :: + y(x)^{\prime\prime} + (a - 2 q \cos(2 x)) y(x) = 0 + + The other solution is the Mathieu Sine function. + + Examples + ======== + + >>> from sympy import diff, mathieucprime + >>> from sympy.abc import a, q, z + + >>> mathieucprime(a, q, z) + mathieucprime(a, q, z) + + >>> mathieucprime(a, 0, z) + -sqrt(a)*sin(sqrt(a)*z) + + >>> diff(mathieucprime(a, q, z), z) + (-a + 2*q*cos(2*z))*mathieuc(a, q, z) + + See Also + ======== + + mathieus: Mathieu sine function + mathieuc: Mathieu cosine function + mathieusprime: Derivative of Mathieu sine function + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Mathieu_function + .. [2] https://dlmf.nist.gov/28 + .. [3] https://mathworld.wolfram.com/MathieuFunction.html + .. [4] https://functions.wolfram.com/MathieuandSpheroidalFunctions/MathieuCPrime/ + + """ + + def fdiff(self, argindex=1): + if argindex == 3: + a, q, z = self.args + return (2*q*cos(2*z) - a)*mathieuc(a, q, z) + else: + raise ArgumentIndexError(self, argindex) + + @classmethod + def eval(cls, a, q, z): + if q.is_Number and q.is_zero: + return -sqrt(a)*sin(sqrt(a)*z) + # Try to pull out factors of -1 + if z.could_extract_minus_sign(): + return -cls(a, q, -z) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/polynomials.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/polynomials.py new file mode 100644 index 0000000000000000000000000000000000000000..5816baef600baf957c31a9dddaa5571da86d754a --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/polynomials.py @@ -0,0 +1,1447 @@ +""" +This module mainly implements special orthogonal polynomials. + +See also functions.combinatorial.numbers which contains some +combinatorial polynomials. + +""" + +from sympy.core import Rational +from sympy.core.function import DefinedFunction, ArgumentIndexError +from sympy.core.singleton import S +from sympy.core.symbol import Dummy +from sympy.functions.combinatorial.factorials import binomial, factorial, RisingFactorial +from sympy.functions.elementary.complexes import re +from sympy.functions.elementary.exponential import exp +from sympy.functions.elementary.integers import floor +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import cos, sec +from sympy.functions.special.gamma_functions import gamma +from sympy.functions.special.hyper import hyper +from sympy.polys.orthopolys import (chebyshevt_poly, chebyshevu_poly, + gegenbauer_poly, hermite_poly, hermite_prob_poly, + jacobi_poly, laguerre_poly, legendre_poly) + +_x = Dummy('x') + + +class OrthogonalPolynomial(DefinedFunction): + """Base class for orthogonal polynomials. + """ + + @classmethod + def _eval_at_order(cls, n, x): + if n.is_integer and n >= 0: + return cls._ortho_poly(int(n), _x).subs(_x, x) + + def _eval_conjugate(self): + return self.func(self.args[0], self.args[1].conjugate()) + +#---------------------------------------------------------------------------- +# Jacobi polynomials +# + + +class jacobi(OrthogonalPolynomial): + r""" + Jacobi polynomial $P_n^{\left(\alpha, \beta\right)}(x)$. + + Explanation + =========== + + ``jacobi(n, alpha, beta, x)`` gives the $n$th Jacobi polynomial + in $x$, $P_n^{\left(\alpha, \beta\right)}(x)$. + + The Jacobi polynomials are orthogonal on $[-1, 1]$ with respect + to the weight $\left(1-x\right)^\alpha \left(1+x\right)^\beta$. + + Examples + ======== + + >>> from sympy import jacobi, S, conjugate, diff + >>> from sympy.abc import a, b, n, x + + >>> jacobi(0, a, b, x) + 1 + >>> jacobi(1, a, b, x) + a/2 - b/2 + x*(a/2 + b/2 + 1) + >>> jacobi(2, a, b, x) + a**2/8 - a*b/4 - a/8 + b**2/8 - b/8 + x**2*(a**2/8 + a*b/4 + 7*a/8 + b**2/8 + 7*b/8 + 3/2) + x*(a**2/4 + 3*a/4 - b**2/4 - 3*b/4) - 1/2 + + >>> jacobi(n, a, b, x) + jacobi(n, a, b, x) + + >>> jacobi(n, a, a, x) + RisingFactorial(a + 1, n)*gegenbauer(n, + a + 1/2, x)/RisingFactorial(2*a + 1, n) + + >>> jacobi(n, 0, 0, x) + legendre(n, x) + + >>> jacobi(n, S(1)/2, S(1)/2, x) + RisingFactorial(3/2, n)*chebyshevu(n, x)/factorial(n + 1) + + >>> jacobi(n, -S(1)/2, -S(1)/2, x) + RisingFactorial(1/2, n)*chebyshevt(n, x)/factorial(n) + + >>> jacobi(n, a, b, -x) + (-1)**n*jacobi(n, b, a, x) + + >>> jacobi(n, a, b, 0) + gamma(a + n + 1)*hyper((-n, -b - n), (a + 1,), -1)/(2**n*factorial(n)*gamma(a + 1)) + >>> jacobi(n, a, b, 1) + RisingFactorial(a + 1, n)/factorial(n) + + >>> conjugate(jacobi(n, a, b, x)) + jacobi(n, conjugate(a), conjugate(b), conjugate(x)) + + >>> diff(jacobi(n,a,b,x), x) + (a/2 + b/2 + n/2 + 1/2)*jacobi(n - 1, a + 1, b + 1, x) + + See Also + ======== + + gegenbauer, + chebyshevt_root, chebyshevu, chebyshevu_root, + legendre, assoc_legendre, + hermite, hermite_prob, + laguerre, assoc_laguerre, + sympy.polys.orthopolys.jacobi_poly, + sympy.polys.orthopolys.gegenbauer_poly + sympy.polys.orthopolys.chebyshevt_poly + sympy.polys.orthopolys.chebyshevu_poly + sympy.polys.orthopolys.hermite_poly + sympy.polys.orthopolys.legendre_poly + sympy.polys.orthopolys.laguerre_poly + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Jacobi_polynomials + .. [2] https://mathworld.wolfram.com/JacobiPolynomial.html + .. [3] https://functions.wolfram.com/Polynomials/JacobiP/ + + """ + + @classmethod + def eval(cls, n, a, b, x): + # Simplify to other polynomials + # P^{a, a}_n(x) + if a == b: + if a == Rational(-1, 2): + return RisingFactorial(S.Half, n) / factorial(n) * chebyshevt(n, x) + elif a.is_zero: + return legendre(n, x) + elif a == S.Half: + return RisingFactorial(3*S.Half, n) / factorial(n + 1) * chebyshevu(n, x) + else: + return RisingFactorial(a + 1, n) / RisingFactorial(2*a + 1, n) * gegenbauer(n, a + S.Half, x) + elif b == -a: + # P^{a, -a}_n(x) + return gamma(n + a + 1) / gamma(n + 1) * (1 + x)**(a/2) / (1 - x)**(a/2) * assoc_legendre(n, -a, x) + + if not n.is_Number: + # Symbolic result P^{a,b}_n(x) + # P^{a,b}_n(-x) ---> (-1)**n * P^{b,a}_n(-x) + if x.could_extract_minus_sign(): + return S.NegativeOne**n * jacobi(n, b, a, -x) + # We can evaluate for some special values of x + if x.is_zero: + return (2**(-n) * gamma(a + n + 1) / (gamma(a + 1) * factorial(n)) * + hyper([-b - n, -n], [a + 1], -1)) + if x == S.One: + return RisingFactorial(a + 1, n) / factorial(n) + elif x is S.Infinity: + if n.is_positive: + # Make sure a+b+2*n \notin Z + if (a + b + 2*n).is_integer: + raise ValueError("Error. a + b + 2*n should not be an integer.") + return RisingFactorial(a + b + n + 1, n) * S.Infinity + else: + # n is a given fixed integer, evaluate into polynomial + return jacobi_poly(n, a, b, x) + + def fdiff(self, argindex=4): + from sympy.concrete.summations import Sum + if argindex == 1: + # Diff wrt n + raise ArgumentIndexError(self, argindex) + elif argindex == 2: + # Diff wrt a + n, a, b, x = self.args + k = Dummy("k") + f1 = 1 / (a + b + n + k + 1) + f2 = ((a + b + 2*k + 1) * RisingFactorial(b + k + 1, n - k) / + ((n - k) * RisingFactorial(a + b + k + 1, n - k))) + return Sum(f1 * (jacobi(n, a, b, x) + f2*jacobi(k, a, b, x)), (k, 0, n - 1)) + elif argindex == 3: + # Diff wrt b + n, a, b, x = self.args + k = Dummy("k") + f1 = 1 / (a + b + n + k + 1) + f2 = (-1)**(n - k) * ((a + b + 2*k + 1) * RisingFactorial(a + k + 1, n - k) / + ((n - k) * RisingFactorial(a + b + k + 1, n - k))) + return Sum(f1 * (jacobi(n, a, b, x) + f2*jacobi(k, a, b, x)), (k, 0, n - 1)) + elif argindex == 4: + # Diff wrt x + n, a, b, x = self.args + return S.Half * (a + b + n + 1) * jacobi(n - 1, a + 1, b + 1, x) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_rewrite_as_Sum(self, n, a, b, x, **kwargs): + from sympy.concrete.summations import Sum + # Make sure n \in N + if n.is_negative or n.is_integer is False: + raise ValueError("Error: n should be a non-negative integer.") + k = Dummy("k") + kern = (RisingFactorial(-n, k) * RisingFactorial(a + b + n + 1, k) * RisingFactorial(a + k + 1, n - k) / + factorial(k) * ((1 - x)/2)**k) + return 1 / factorial(n) * Sum(kern, (k, 0, n)) + + def _eval_rewrite_as_polynomial(self, n, a, b, x, **kwargs): + # This function is just kept for backwards compatibility + # but should not be used + return self._eval_rewrite_as_Sum(n, a, b, x, **kwargs) + + def _eval_conjugate(self): + n, a, b, x = self.args + return self.func(n, a.conjugate(), b.conjugate(), x.conjugate()) + + +def jacobi_normalized(n, a, b, x): + r""" + Jacobi polynomial $P_n^{\left(\alpha, \beta\right)}(x)$. + + Explanation + =========== + + ``jacobi_normalized(n, alpha, beta, x)`` gives the $n$th + Jacobi polynomial in $x$, $P_n^{\left(\alpha, \beta\right)}(x)$. + + The Jacobi polynomials are orthogonal on $[-1, 1]$ with respect + to the weight $\left(1-x\right)^\alpha \left(1+x\right)^\beta$. + + This functions returns the polynomials normilzed: + + .. math:: + + \int_{-1}^{1} + P_m^{\left(\alpha, \beta\right)}(x) + P_n^{\left(\alpha, \beta\right)}(x) + (1-x)^{\alpha} (1+x)^{\beta} \mathrm{d}x + = \delta_{m,n} + + Examples + ======== + + >>> from sympy import jacobi_normalized + >>> from sympy.abc import n,a,b,x + + >>> jacobi_normalized(n, a, b, x) + jacobi(n, a, b, x)/sqrt(2**(a + b + 1)*gamma(a + n + 1)*gamma(b + n + 1)/((a + b + 2*n + 1)*factorial(n)*gamma(a + b + n + 1))) + + Parameters + ========== + + n : integer degree of polynomial + + a : alpha value + + b : beta value + + x : symbol + + See Also + ======== + + gegenbauer, + chebyshevt_root, chebyshevu, chebyshevu_root, + legendre, assoc_legendre, + hermite, hermite_prob, + laguerre, assoc_laguerre, + sympy.polys.orthopolys.jacobi_poly, + sympy.polys.orthopolys.gegenbauer_poly + sympy.polys.orthopolys.chebyshevt_poly + sympy.polys.orthopolys.chebyshevu_poly + sympy.polys.orthopolys.hermite_poly + sympy.polys.orthopolys.legendre_poly + sympy.polys.orthopolys.laguerre_poly + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Jacobi_polynomials + .. [2] https://mathworld.wolfram.com/JacobiPolynomial.html + .. [3] https://functions.wolfram.com/Polynomials/JacobiP/ + + """ + nfactor = (S(2)**(a + b + 1) * (gamma(n + a + 1) * gamma(n + b + 1)) + / (2*n + a + b + 1) / (factorial(n) * gamma(n + a + b + 1))) + + return jacobi(n, a, b, x) / sqrt(nfactor) + + +#---------------------------------------------------------------------------- +# Gegenbauer polynomials +# + + +class gegenbauer(OrthogonalPolynomial): + r""" + Gegenbauer polynomial $C_n^{\left(\alpha\right)}(x)$. + + Explanation + =========== + + ``gegenbauer(n, alpha, x)`` gives the $n$th Gegenbauer polynomial + in $x$, $C_n^{\left(\alpha\right)}(x)$. + + The Gegenbauer polynomials are orthogonal on $[-1, 1]$ with + respect to the weight $\left(1-x^2\right)^{\alpha-\frac{1}{2}}$. + + Examples + ======== + + >>> from sympy import gegenbauer, conjugate, diff + >>> from sympy.abc import n,a,x + >>> gegenbauer(0, a, x) + 1 + >>> gegenbauer(1, a, x) + 2*a*x + >>> gegenbauer(2, a, x) + -a + x**2*(2*a**2 + 2*a) + >>> gegenbauer(3, a, x) + x**3*(4*a**3/3 + 4*a**2 + 8*a/3) + x*(-2*a**2 - 2*a) + + >>> gegenbauer(n, a, x) + gegenbauer(n, a, x) + >>> gegenbauer(n, a, -x) + (-1)**n*gegenbauer(n, a, x) + + >>> gegenbauer(n, a, 0) + 2**n*sqrt(pi)*gamma(a + n/2)/(gamma(a)*gamma(1/2 - n/2)*gamma(n + 1)) + >>> gegenbauer(n, a, 1) + gamma(2*a + n)/(gamma(2*a)*gamma(n + 1)) + + >>> conjugate(gegenbauer(n, a, x)) + gegenbauer(n, conjugate(a), conjugate(x)) + + >>> diff(gegenbauer(n, a, x), x) + 2*a*gegenbauer(n - 1, a + 1, x) + + See Also + ======== + + jacobi, + chebyshevt_root, chebyshevu, chebyshevu_root, + legendre, assoc_legendre, + hermite, hermite_prob, + laguerre, assoc_laguerre, + sympy.polys.orthopolys.jacobi_poly + sympy.polys.orthopolys.gegenbauer_poly + sympy.polys.orthopolys.chebyshevt_poly + sympy.polys.orthopolys.chebyshevu_poly + sympy.polys.orthopolys.hermite_poly + sympy.polys.orthopolys.hermite_prob_poly + sympy.polys.orthopolys.legendre_poly + sympy.polys.orthopolys.laguerre_poly + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Gegenbauer_polynomials + .. [2] https://mathworld.wolfram.com/GegenbauerPolynomial.html + .. [3] https://functions.wolfram.com/Polynomials/GegenbauerC3/ + + """ + + @classmethod + def eval(cls, n, a, x): + # For negative n the polynomials vanish + # See https://functions.wolfram.com/Polynomials/GegenbauerC3/03/01/03/0012/ + if n.is_negative: + return S.Zero + + # Some special values for fixed a + if a == S.Half: + return legendre(n, x) + elif a == S.One: + return chebyshevu(n, x) + elif a == S.NegativeOne: + return S.Zero + + if not n.is_Number: + # Handle this before the general sign extraction rule + if x == S.NegativeOne: + if (re(a) > S.Half) == True: + return S.ComplexInfinity + else: + return (cos(S.Pi*(a+n)) * sec(S.Pi*a) * gamma(2*a+n) / + (gamma(2*a) * gamma(n+1))) + + # Symbolic result C^a_n(x) + # C^a_n(-x) ---> (-1)**n * C^a_n(x) + if x.could_extract_minus_sign(): + return S.NegativeOne**n * gegenbauer(n, a, -x) + # We can evaluate for some special values of x + if x.is_zero: + return (2**n * sqrt(S.Pi) * gamma(a + S.Half*n) / + (gamma((1 - n)/2) * gamma(n + 1) * gamma(a)) ) + if x == S.One: + return gamma(2*a + n) / (gamma(2*a) * gamma(n + 1)) + elif x is S.Infinity: + if n.is_positive: + return RisingFactorial(a, n) * S.Infinity + else: + # n is a given fixed integer, evaluate into polynomial + return gegenbauer_poly(n, a, x) + + def fdiff(self, argindex=3): + from sympy.concrete.summations import Sum + if argindex == 1: + # Diff wrt n + raise ArgumentIndexError(self, argindex) + elif argindex == 2: + # Diff wrt a + n, a, x = self.args + k = Dummy("k") + factor1 = 2 * (1 + (-1)**(n - k)) * (k + a) / ((k + + n + 2*a) * (n - k)) + factor2 = 2*(k + 1) / ((k + 2*a) * (2*k + 2*a + 1)) + \ + 2 / (k + n + 2*a) + kern = factor1*gegenbauer(k, a, x) + factor2*gegenbauer(n, a, x) + return Sum(kern, (k, 0, n - 1)) + elif argindex == 3: + # Diff wrt x + n, a, x = self.args + return 2*a*gegenbauer(n - 1, a + 1, x) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_rewrite_as_Sum(self, n, a, x, **kwargs): + from sympy.concrete.summations import Sum + k = Dummy("k") + kern = ((-1)**k * RisingFactorial(a, n - k) * (2*x)**(n - 2*k) / + (factorial(k) * factorial(n - 2*k))) + return Sum(kern, (k, 0, floor(n/2))) + + def _eval_rewrite_as_polynomial(self, n, a, x, **kwargs): + # This function is just kept for backwards compatibility + # but should not be used + return self._eval_rewrite_as_Sum(n, a, x, **kwargs) + + def _eval_conjugate(self): + n, a, x = self.args + return self.func(n, a.conjugate(), x.conjugate()) + +#---------------------------------------------------------------------------- +# Chebyshev polynomials of first and second kind +# + + +class chebyshevt(OrthogonalPolynomial): + r""" + Chebyshev polynomial of the first kind, $T_n(x)$. + + Explanation + =========== + + ``chebyshevt(n, x)`` gives the $n$th Chebyshev polynomial (of the first + kind) in $x$, $T_n(x)$. + + The Chebyshev polynomials of the first kind are orthogonal on + $[-1, 1]$ with respect to the weight $\frac{1}{\sqrt{1-x^2}}$. + + Examples + ======== + + >>> from sympy import chebyshevt, diff + >>> from sympy.abc import n,x + >>> chebyshevt(0, x) + 1 + >>> chebyshevt(1, x) + x + >>> chebyshevt(2, x) + 2*x**2 - 1 + + >>> chebyshevt(n, x) + chebyshevt(n, x) + >>> chebyshevt(n, -x) + (-1)**n*chebyshevt(n, x) + >>> chebyshevt(-n, x) + chebyshevt(n, x) + + >>> chebyshevt(n, 0) + cos(pi*n/2) + >>> chebyshevt(n, -1) + (-1)**n + + >>> diff(chebyshevt(n, x), x) + n*chebyshevu(n - 1, x) + + See Also + ======== + + jacobi, gegenbauer, + chebyshevt_root, chebyshevu, chebyshevu_root, + legendre, assoc_legendre, + hermite, hermite_prob, + laguerre, assoc_laguerre, + sympy.polys.orthopolys.jacobi_poly + sympy.polys.orthopolys.gegenbauer_poly + sympy.polys.orthopolys.chebyshevt_poly + sympy.polys.orthopolys.chebyshevu_poly + sympy.polys.orthopolys.hermite_poly + sympy.polys.orthopolys.hermite_prob_poly + sympy.polys.orthopolys.legendre_poly + sympy.polys.orthopolys.laguerre_poly + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Chebyshev_polynomial + .. [2] https://mathworld.wolfram.com/ChebyshevPolynomialoftheFirstKind.html + .. [3] https://mathworld.wolfram.com/ChebyshevPolynomialoftheSecondKind.html + .. [4] https://functions.wolfram.com/Polynomials/ChebyshevT/ + .. [5] https://functions.wolfram.com/Polynomials/ChebyshevU/ + + """ + + _ortho_poly = staticmethod(chebyshevt_poly) + + @classmethod + def eval(cls, n, x): + if not n.is_Number: + # Symbolic result T_n(x) + # T_n(-x) ---> (-1)**n * T_n(x) + if x.could_extract_minus_sign(): + return S.NegativeOne**n * chebyshevt(n, -x) + # T_{-n}(x) ---> T_n(x) + if n.could_extract_minus_sign(): + return chebyshevt(-n, x) + # We can evaluate for some special values of x + if x.is_zero: + return cos(S.Half * S.Pi * n) + if x == S.One: + return S.One + elif x is S.Infinity: + return S.Infinity + else: + # n is a given fixed integer, evaluate into polynomial + if n.is_negative: + # T_{-n}(x) == T_n(x) + return cls._eval_at_order(-n, x) + else: + return cls._eval_at_order(n, x) + + def fdiff(self, argindex=2): + if argindex == 1: + # Diff wrt n + raise ArgumentIndexError(self, argindex) + elif argindex == 2: + # Diff wrt x + n, x = self.args + return n * chebyshevu(n - 1, x) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_rewrite_as_Sum(self, n, x, **kwargs): + from sympy.concrete.summations import Sum + k = Dummy("k") + kern = binomial(n, 2*k) * (x**2 - 1)**k * x**(n - 2*k) + return Sum(kern, (k, 0, floor(n/2))) + + def _eval_rewrite_as_polynomial(self, n, x, **kwargs): + # This function is just kept for backwards compatibility + # but should not be used + return self._eval_rewrite_as_Sum(n, x, **kwargs) + + +class chebyshevu(OrthogonalPolynomial): + r""" + Chebyshev polynomial of the second kind, $U_n(x)$. + + Explanation + =========== + + ``chebyshevu(n, x)`` gives the $n$th Chebyshev polynomial of the second + kind in x, $U_n(x)$. + + The Chebyshev polynomials of the second kind are orthogonal on + $[-1, 1]$ with respect to the weight $\sqrt{1-x^2}$. + + Examples + ======== + + >>> from sympy import chebyshevu, diff + >>> from sympy.abc import n,x + >>> chebyshevu(0, x) + 1 + >>> chebyshevu(1, x) + 2*x + >>> chebyshevu(2, x) + 4*x**2 - 1 + + >>> chebyshevu(n, x) + chebyshevu(n, x) + >>> chebyshevu(n, -x) + (-1)**n*chebyshevu(n, x) + >>> chebyshevu(-n, x) + -chebyshevu(n - 2, x) + + >>> chebyshevu(n, 0) + cos(pi*n/2) + >>> chebyshevu(n, 1) + n + 1 + + >>> diff(chebyshevu(n, x), x) + (-x*chebyshevu(n, x) + (n + 1)*chebyshevt(n + 1, x))/(x**2 - 1) + + See Also + ======== + + jacobi, gegenbauer, + chebyshevt, chebyshevt_root, chebyshevu_root, + legendre, assoc_legendre, + hermite, hermite_prob, + laguerre, assoc_laguerre, + sympy.polys.orthopolys.jacobi_poly + sympy.polys.orthopolys.gegenbauer_poly + sympy.polys.orthopolys.chebyshevt_poly + sympy.polys.orthopolys.chebyshevu_poly + sympy.polys.orthopolys.hermite_poly + sympy.polys.orthopolys.hermite_prob_poly + sympy.polys.orthopolys.legendre_poly + sympy.polys.orthopolys.laguerre_poly + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Chebyshev_polynomial + .. [2] https://mathworld.wolfram.com/ChebyshevPolynomialoftheFirstKind.html + .. [3] https://mathworld.wolfram.com/ChebyshevPolynomialoftheSecondKind.html + .. [4] https://functions.wolfram.com/Polynomials/ChebyshevT/ + .. [5] https://functions.wolfram.com/Polynomials/ChebyshevU/ + + """ + + _ortho_poly = staticmethod(chebyshevu_poly) + + @classmethod + def eval(cls, n, x): + if not n.is_Number: + # Symbolic result U_n(x) + # U_n(-x) ---> (-1)**n * U_n(x) + if x.could_extract_minus_sign(): + return S.NegativeOne**n * chebyshevu(n, -x) + # U_{-n}(x) ---> -U_{n-2}(x) + if n.could_extract_minus_sign(): + if n == S.NegativeOne: + # n can not be -1 here + return S.Zero + elif not (-n - 2).could_extract_minus_sign(): + return -chebyshevu(-n - 2, x) + # We can evaluate for some special values of x + if x.is_zero: + return cos(S.Half * S.Pi * n) + if x == S.One: + return S.One + n + elif x is S.Infinity: + return S.Infinity + else: + # n is a given fixed integer, evaluate into polynomial + if n.is_negative: + # U_{-n}(x) ---> -U_{n-2}(x) + if n == S.NegativeOne: + return S.Zero + else: + return -cls._eval_at_order(-n - 2, x) + else: + return cls._eval_at_order(n, x) + + def fdiff(self, argindex=2): + if argindex == 1: + # Diff wrt n + raise ArgumentIndexError(self, argindex) + elif argindex == 2: + # Diff wrt x + n, x = self.args + return ((n + 1) * chebyshevt(n + 1, x) - x * chebyshevu(n, x)) / (x**2 - 1) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_rewrite_as_Sum(self, n, x, **kwargs): + from sympy.concrete.summations import Sum + k = Dummy("k") + kern = S.NegativeOne**k * factorial( + n - k) * (2*x)**(n - 2*k) / (factorial(k) * factorial(n - 2*k)) + return Sum(kern, (k, 0, floor(n/2))) + + def _eval_rewrite_as_polynomial(self, n, x, **kwargs): + # This function is just kept for backwards compatibility + # but should not be used + return self._eval_rewrite_as_Sum(n, x, **kwargs) + + +class chebyshevt_root(DefinedFunction): + r""" + ``chebyshev_root(n, k)`` returns the $k$th root (indexed from zero) of + the $n$th Chebyshev polynomial of the first kind; that is, if + $0 \le k < n$, ``chebyshevt(n, chebyshevt_root(n, k)) == 0``. + + Examples + ======== + + >>> from sympy import chebyshevt, chebyshevt_root + >>> chebyshevt_root(3, 2) + -sqrt(3)/2 + >>> chebyshevt(3, chebyshevt_root(3, 2)) + 0 + + See Also + ======== + + jacobi, gegenbauer, + chebyshevt, chebyshevu, chebyshevu_root, + legendre, assoc_legendre, + hermite, hermite_prob, + laguerre, assoc_laguerre, + sympy.polys.orthopolys.jacobi_poly + sympy.polys.orthopolys.gegenbauer_poly + sympy.polys.orthopolys.chebyshevt_poly + sympy.polys.orthopolys.chebyshevu_poly + sympy.polys.orthopolys.hermite_poly + sympy.polys.orthopolys.hermite_prob_poly + sympy.polys.orthopolys.legendre_poly + sympy.polys.orthopolys.laguerre_poly + """ + + @classmethod + def eval(cls, n, k): + if not ((0 <= k) and (k < n)): + raise ValueError("must have 0 <= k < n, " + "got k = %s and n = %s" % (k, n)) + return cos(S.Pi*(2*k + 1)/(2*n)) + + +class chebyshevu_root(DefinedFunction): + r""" + ``chebyshevu_root(n, k)`` returns the $k$th root (indexed from zero) of the + $n$th Chebyshev polynomial of the second kind; that is, if $0 \le k < n$, + ``chebyshevu(n, chebyshevu_root(n, k)) == 0``. + + Examples + ======== + + >>> from sympy import chebyshevu, chebyshevu_root + >>> chebyshevu_root(3, 2) + -sqrt(2)/2 + >>> chebyshevu(3, chebyshevu_root(3, 2)) + 0 + + See Also + ======== + + chebyshevt, chebyshevt_root, chebyshevu, + legendre, assoc_legendre, + hermite, hermite_prob, + laguerre, assoc_laguerre, + sympy.polys.orthopolys.jacobi_poly + sympy.polys.orthopolys.gegenbauer_poly + sympy.polys.orthopolys.chebyshevt_poly + sympy.polys.orthopolys.chebyshevu_poly + sympy.polys.orthopolys.hermite_poly + sympy.polys.orthopolys.hermite_prob_poly + sympy.polys.orthopolys.legendre_poly + sympy.polys.orthopolys.laguerre_poly + """ + + + @classmethod + def eval(cls, n, k): + if not ((0 <= k) and (k < n)): + raise ValueError("must have 0 <= k < n, " + "got k = %s and n = %s" % (k, n)) + return cos(S.Pi*(k + 1)/(n + 1)) + +#---------------------------------------------------------------------------- +# Legendre polynomials and Associated Legendre polynomials +# + + +class legendre(OrthogonalPolynomial): + r""" + ``legendre(n, x)`` gives the $n$th Legendre polynomial of $x$, $P_n(x)$ + + Explanation + =========== + + The Legendre polynomials are orthogonal on $[-1, 1]$ with respect to + the constant weight 1. They satisfy $P_n(1) = 1$ for all $n$; further, + $P_n$ is odd for odd $n$ and even for even $n$. + + Examples + ======== + + >>> from sympy import legendre, diff + >>> from sympy.abc import x, n + >>> legendre(0, x) + 1 + >>> legendre(1, x) + x + >>> legendre(2, x) + 3*x**2/2 - 1/2 + >>> legendre(n, x) + legendre(n, x) + >>> diff(legendre(n,x), x) + n*(x*legendre(n, x) - legendre(n - 1, x))/(x**2 - 1) + + See Also + ======== + + jacobi, gegenbauer, + chebyshevt, chebyshevt_root, chebyshevu, chebyshevu_root, + assoc_legendre, + hermite, hermite_prob, + laguerre, assoc_laguerre, + sympy.polys.orthopolys.jacobi_poly + sympy.polys.orthopolys.gegenbauer_poly + sympy.polys.orthopolys.chebyshevt_poly + sympy.polys.orthopolys.chebyshevu_poly + sympy.polys.orthopolys.hermite_poly + sympy.polys.orthopolys.hermite_prob_poly + sympy.polys.orthopolys.legendre_poly + sympy.polys.orthopolys.laguerre_poly + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Legendre_polynomial + .. [2] https://mathworld.wolfram.com/LegendrePolynomial.html + .. [3] https://functions.wolfram.com/Polynomials/LegendreP/ + .. [4] https://functions.wolfram.com/Polynomials/LegendreP2/ + + """ + + _ortho_poly = staticmethod(legendre_poly) + + @classmethod + def eval(cls, n, x): + if not n.is_Number: + # Symbolic result L_n(x) + # L_n(-x) ---> (-1)**n * L_n(x) + if x.could_extract_minus_sign(): + return S.NegativeOne**n * legendre(n, -x) + # L_{-n}(x) ---> L_{n-1}(x) + if n.could_extract_minus_sign() and not(-n - 1).could_extract_minus_sign(): + return legendre(-n - S.One, x) + # We can evaluate for some special values of x + if x.is_zero: + return sqrt(S.Pi)/(gamma(S.Half - n/2)*gamma(S.One + n/2)) + elif x == S.One: + return S.One + elif x is S.Infinity: + return S.Infinity + else: + # n is a given fixed integer, evaluate into polynomial; + # L_{-n}(x) ---> L_{n-1}(x) + if n.is_negative: + n = -n - S.One + return cls._eval_at_order(n, x) + + def fdiff(self, argindex=2): + if argindex == 1: + # Diff wrt n + raise ArgumentIndexError(self, argindex) + elif argindex == 2: + # Diff wrt x + # Find better formula, this is unsuitable for x = +/-1 + # https://www.autodiff.org/ad16/Oral/Buecker_Legendre.pdf says + # at x = 1: + # n*(n + 1)/2 , m = 0 + # oo , m = 1 + # -(n-1)*n*(n+1)*(n+2)/4 , m = 2 + # 0 , m = 3, 4, ..., n + # + # at x = -1 + # (-1)**(n+1)*n*(n + 1)/2 , m = 0 + # (-1)**n*oo , m = 1 + # (-1)**n*(n-1)*n*(n+1)*(n+2)/4 , m = 2 + # 0 , m = 3, 4, ..., n + n, x = self.args + return n/(x**2 - 1)*(x*legendre(n, x) - legendre(n - 1, x)) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_rewrite_as_Sum(self, n, x, **kwargs): + from sympy.concrete.summations import Sum + k = Dummy("k") + kern = S.NegativeOne**k*binomial(n, k)**2*((1 + x)/2)**(n - k)*((1 - x)/2)**k + return Sum(kern, (k, 0, n)) + + def _eval_rewrite_as_polynomial(self, n, x, **kwargs): + # This function is just kept for backwards compatibility + # but should not be used + return self._eval_rewrite_as_Sum(n, x, **kwargs) + + +class assoc_legendre(DefinedFunction): + r""" + ``assoc_legendre(n, m, x)`` gives $P_n^m(x)$, where $n$ and $m$ are + the degree and order or an expression which is related to the nth + order Legendre polynomial, $P_n(x)$ in the following manner: + + .. math:: + P_n^m(x) = (-1)^m (1 - x^2)^{\frac{m}{2}} + \frac{\mathrm{d}^m P_n(x)}{\mathrm{d} x^m} + + Explanation + =========== + + Associated Legendre polynomials are orthogonal on $[-1, 1]$ with: + + - weight $= 1$ for the same $m$ and different $n$. + - weight $= \frac{1}{1-x^2}$ for the same $n$ and different $m$. + + Examples + ======== + + >>> from sympy import assoc_legendre + >>> from sympy.abc import x, m, n + >>> assoc_legendre(0,0, x) + 1 + >>> assoc_legendre(1,0, x) + x + >>> assoc_legendre(1,1, x) + -sqrt(1 - x**2) + >>> assoc_legendre(n,m,x) + assoc_legendre(n, m, x) + + See Also + ======== + + jacobi, gegenbauer, + chebyshevt, chebyshevt_root, chebyshevu, chebyshevu_root, + legendre, + hermite, hermite_prob, + laguerre, assoc_laguerre, + sympy.polys.orthopolys.jacobi_poly + sympy.polys.orthopolys.gegenbauer_poly + sympy.polys.orthopolys.chebyshevt_poly + sympy.polys.orthopolys.chebyshevu_poly + sympy.polys.orthopolys.hermite_poly + sympy.polys.orthopolys.hermite_prob_poly + sympy.polys.orthopolys.legendre_poly + sympy.polys.orthopolys.laguerre_poly + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Associated_Legendre_polynomials + .. [2] https://mathworld.wolfram.com/LegendrePolynomial.html + .. [3] https://functions.wolfram.com/Polynomials/LegendreP/ + .. [4] https://functions.wolfram.com/Polynomials/LegendreP2/ + + """ + + @classmethod + def _eval_at_order(cls, n, m): + P = legendre_poly(n, _x, polys=True).diff((_x, m)) + return S.NegativeOne**m * (1 - _x**2)**Rational(m, 2) * P.as_expr() + + @classmethod + def eval(cls, n, m, x): + if m.could_extract_minus_sign(): + # P^{-m}_n ---> F * P^m_n + return S.NegativeOne**(-m) * (factorial(m + n)/factorial(n - m)) * assoc_legendre(n, -m, x) + if m == 0: + # P^0_n ---> L_n + return legendre(n, x) + if x == 0: + return 2**m*sqrt(S.Pi) / (gamma((1 - m - n)/2)*gamma(1 - (m - n)/2)) + if n.is_Number and m.is_Number and n.is_integer and m.is_integer: + if n.is_negative: + raise ValueError("%s : 1st index must be nonnegative integer (got %r)" % (cls, n)) + if abs(m) > n: + raise ValueError("%s : abs('2nd index') must be <= '1st index' (got %r, %r)" % (cls, n, m)) + return cls._eval_at_order(int(n), abs(int(m))).subs(_x, x) + + def fdiff(self, argindex=3): + if argindex == 1: + # Diff wrt n + raise ArgumentIndexError(self, argindex) + elif argindex == 2: + # Diff wrt m + raise ArgumentIndexError(self, argindex) + elif argindex == 3: + # Diff wrt x + # Find better formula, this is unsuitable for x = 1 + n, m, x = self.args + return 1/(x**2 - 1)*(x*n*assoc_legendre(n, m, x) - (m + n)*assoc_legendre(n - 1, m, x)) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_rewrite_as_Sum(self, n, m, x, **kwargs): + from sympy.concrete.summations import Sum + k = Dummy("k") + kern = factorial(2*n - 2*k)/(2**n*factorial(n - k)*factorial( + k)*factorial(n - 2*k - m))*S.NegativeOne**k*x**(n - m - 2*k) + return (1 - x**2)**(m/2) * Sum(kern, (k, 0, floor((n - m)*S.Half))) + + def _eval_rewrite_as_polynomial(self, n, m, x, **kwargs): + # This function is just kept for backwards compatibility + # but should not be used + return self._eval_rewrite_as_Sum(n, m, x, **kwargs) + + def _eval_conjugate(self): + n, m, x = self.args + return self.func(n, m.conjugate(), x.conjugate()) + +#---------------------------------------------------------------------------- +# Hermite polynomials +# + + +class hermite(OrthogonalPolynomial): + r""" + ``hermite(n, x)`` gives the $n$th Hermite polynomial in $x$, $H_n(x)$. + + Explanation + =========== + + The Hermite polynomials are orthogonal on $(-\infty, \infty)$ + with respect to the weight $\exp\left(-x^2\right)$. + + Examples + ======== + + >>> from sympy import hermite, diff + >>> from sympy.abc import x, n + >>> hermite(0, x) + 1 + >>> hermite(1, x) + 2*x + >>> hermite(2, x) + 4*x**2 - 2 + >>> hermite(n, x) + hermite(n, x) + >>> diff(hermite(n,x), x) + 2*n*hermite(n - 1, x) + >>> hermite(n, -x) + (-1)**n*hermite(n, x) + + See Also + ======== + + jacobi, gegenbauer, + chebyshevt, chebyshevt_root, chebyshevu, chebyshevu_root, + legendre, assoc_legendre, + hermite_prob, + laguerre, assoc_laguerre, + sympy.polys.orthopolys.jacobi_poly + sympy.polys.orthopolys.gegenbauer_poly + sympy.polys.orthopolys.chebyshevt_poly + sympy.polys.orthopolys.chebyshevu_poly + sympy.polys.orthopolys.hermite_poly + sympy.polys.orthopolys.hermite_prob_poly + sympy.polys.orthopolys.legendre_poly + sympy.polys.orthopolys.laguerre_poly + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Hermite_polynomial + .. [2] https://mathworld.wolfram.com/HermitePolynomial.html + .. [3] https://functions.wolfram.com/Polynomials/HermiteH/ + + """ + + _ortho_poly = staticmethod(hermite_poly) + + @classmethod + def eval(cls, n, x): + if not n.is_Number: + # Symbolic result H_n(x) + # H_n(-x) ---> (-1)**n * H_n(x) + if x.could_extract_minus_sign(): + return S.NegativeOne**n * hermite(n, -x) + # We can evaluate for some special values of x + if x.is_zero: + return 2**n * sqrt(S.Pi) / gamma((S.One - n)/2) + elif x is S.Infinity: + return S.Infinity + else: + # n is a given fixed integer, evaluate into polynomial + if n.is_negative: + raise ValueError( + "The index n must be nonnegative integer (got %r)" % n) + else: + return cls._eval_at_order(n, x) + + def fdiff(self, argindex=2): + if argindex == 1: + # Diff wrt n + raise ArgumentIndexError(self, argindex) + elif argindex == 2: + # Diff wrt x + n, x = self.args + return 2*n*hermite(n - 1, x) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_rewrite_as_Sum(self, n, x, **kwargs): + from sympy.concrete.summations import Sum + k = Dummy("k") + kern = S.NegativeOne**k / (factorial(k)*factorial(n - 2*k)) * (2*x)**(n - 2*k) + return factorial(n)*Sum(kern, (k, 0, floor(n/2))) + + def _eval_rewrite_as_polynomial(self, n, x, **kwargs): + # This function is just kept for backwards compatibility + # but should not be used + return self._eval_rewrite_as_Sum(n, x, **kwargs) + + def _eval_rewrite_as_hermite_prob(self, n, x, **kwargs): + return sqrt(2)**n * hermite_prob(n, x*sqrt(2)) + + +class hermite_prob(OrthogonalPolynomial): + r""" + ``hermite_prob(n, x)`` gives the $n$th probabilist's Hermite polynomial + in $x$, $He_n(x)$. + + Explanation + =========== + + The probabilist's Hermite polynomials are orthogonal on $(-\infty, \infty)$ + with respect to the weight $\exp\left(-\frac{x^2}{2}\right)$. They are monic + polynomials, related to the plain Hermite polynomials (:py:class:`~.hermite`) by + + .. math :: He_n(x) = 2^{-n/2} H_n(x/\sqrt{2}) + + Examples + ======== + + >>> from sympy import hermite_prob, diff, I + >>> from sympy.abc import x, n + >>> hermite_prob(1, x) + x + >>> hermite_prob(5, x) + x**5 - 10*x**3 + 15*x + >>> diff(hermite_prob(n,x), x) + n*hermite_prob(n - 1, x) + >>> hermite_prob(n, -x) + (-1)**n*hermite_prob(n, x) + + The sum of absolute values of coefficients of $He_n(x)$ is the number of + matchings in the complete graph $K_n$ or telephone number, A000085 in the OEIS: + + >>> [hermite_prob(n,I) / I**n for n in range(11)] + [1, 1, 2, 4, 10, 26, 76, 232, 764, 2620, 9496] + + See Also + ======== + + jacobi, gegenbauer, + chebyshevt, chebyshevt_root, chebyshevu, chebyshevu_root, + legendre, assoc_legendre, + hermite, + laguerre, assoc_laguerre, + sympy.polys.orthopolys.jacobi_poly + sympy.polys.orthopolys.gegenbauer_poly + sympy.polys.orthopolys.chebyshevt_poly + sympy.polys.orthopolys.chebyshevu_poly + sympy.polys.orthopolys.hermite_poly + sympy.polys.orthopolys.hermite_prob_poly + sympy.polys.orthopolys.legendre_poly + sympy.polys.orthopolys.laguerre_poly + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Hermite_polynomial + .. [2] https://mathworld.wolfram.com/HermitePolynomial.html + """ + + _ortho_poly = staticmethod(hermite_prob_poly) + + @classmethod + def eval(cls, n, x): + if not n.is_Number: + if x.could_extract_minus_sign(): + return S.NegativeOne**n * hermite_prob(n, -x) + if x.is_zero: + return sqrt(S.Pi) / gamma((S.One-n) / 2) + elif x is S.Infinity: + return S.Infinity + else: + if n.is_negative: + ValueError("n must be a nonnegative integer, not %r" % n) + else: + return cls._eval_at_order(n, x) + + def fdiff(self, argindex=2): + if argindex == 2: + n, x = self.args + return n*hermite_prob(n-1, x) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_rewrite_as_Sum(self, n, x, **kwargs): + from sympy.concrete.summations import Sum + k = Dummy("k") + kern = (-S.Half)**k * x**(n-2*k) / (factorial(k) * factorial(n-2*k)) + return factorial(n)*Sum(kern, (k, 0, floor(n/2))) + + def _eval_rewrite_as_polynomial(self, n, x, **kwargs): + # This function is just kept for backwards compatibility + # but should not be used + return self._eval_rewrite_as_Sum(n, x, **kwargs) + + def _eval_rewrite_as_hermite(self, n, x, **kwargs): + return sqrt(2)**(-n) * hermite(n, x/sqrt(2)) + + +#---------------------------------------------------------------------------- +# Laguerre polynomials +# + + +class laguerre(OrthogonalPolynomial): + r""" + Returns the $n$th Laguerre polynomial in $x$, $L_n(x)$. + + Examples + ======== + + >>> from sympy import laguerre, diff + >>> from sympy.abc import x, n + >>> laguerre(0, x) + 1 + >>> laguerre(1, x) + 1 - x + >>> laguerre(2, x) + x**2/2 - 2*x + 1 + >>> laguerre(3, x) + -x**3/6 + 3*x**2/2 - 3*x + 1 + + >>> laguerre(n, x) + laguerre(n, x) + + >>> diff(laguerre(n, x), x) + -assoc_laguerre(n - 1, 1, x) + + Parameters + ========== + + n : int + Degree of Laguerre polynomial. Must be `n \ge 0`. + + See Also + ======== + + jacobi, gegenbauer, + chebyshevt, chebyshevt_root, chebyshevu, chebyshevu_root, + legendre, assoc_legendre, + hermite, hermite_prob, + assoc_laguerre, + sympy.polys.orthopolys.jacobi_poly + sympy.polys.orthopolys.gegenbauer_poly + sympy.polys.orthopolys.chebyshevt_poly + sympy.polys.orthopolys.chebyshevu_poly + sympy.polys.orthopolys.hermite_poly + sympy.polys.orthopolys.hermite_prob_poly + sympy.polys.orthopolys.legendre_poly + sympy.polys.orthopolys.laguerre_poly + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Laguerre_polynomial + .. [2] https://mathworld.wolfram.com/LaguerrePolynomial.html + .. [3] https://functions.wolfram.com/Polynomials/LaguerreL/ + .. [4] https://functions.wolfram.com/Polynomials/LaguerreL3/ + + """ + + _ortho_poly = staticmethod(laguerre_poly) + + @classmethod + def eval(cls, n, x): + if n.is_integer is False: + raise ValueError("Error: n should be an integer.") + if not n.is_Number: + # Symbolic result L_n(x) + # L_{n}(-x) ---> exp(-x) * L_{-n-1}(x) + # L_{-n}(x) ---> exp(x) * L_{n-1}(-x) + if n.could_extract_minus_sign() and not(-n - 1).could_extract_minus_sign(): + return exp(x)*laguerre(-n - 1, -x) + # We can evaluate for some special values of x + if x.is_zero: + return S.One + elif x is S.NegativeInfinity: + return S.Infinity + elif x is S.Infinity: + return S.NegativeOne**n * S.Infinity + else: + if n.is_negative: + return exp(x)*laguerre(-n - 1, -x) + else: + return cls._eval_at_order(n, x) + + def fdiff(self, argindex=2): + if argindex == 1: + # Diff wrt n + raise ArgumentIndexError(self, argindex) + elif argindex == 2: + # Diff wrt x + n, x = self.args + return -assoc_laguerre(n - 1, 1, x) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_rewrite_as_Sum(self, n, x, **kwargs): + from sympy.concrete.summations import Sum + # Make sure n \in N_0 + if n.is_negative: + return exp(x) * self._eval_rewrite_as_Sum(-n - 1, -x, **kwargs) + if n.is_integer is False: + raise ValueError("Error: n should be an integer.") + k = Dummy("k") + kern = RisingFactorial(-n, k) / factorial(k)**2 * x**k + return Sum(kern, (k, 0, n)) + + def _eval_rewrite_as_polynomial(self, n, x, **kwargs): + # This function is just kept for backwards compatibility + # but should not be used + return self._eval_rewrite_as_Sum(n, x, **kwargs) + + +class assoc_laguerre(OrthogonalPolynomial): + r""" + Returns the $n$th generalized Laguerre polynomial in $x$, $L_n(x)$. + + Examples + ======== + + >>> from sympy import assoc_laguerre, diff + >>> from sympy.abc import x, n, a + >>> assoc_laguerre(0, a, x) + 1 + >>> assoc_laguerre(1, a, x) + a - x + 1 + >>> assoc_laguerre(2, a, x) + a**2/2 + 3*a/2 + x**2/2 + x*(-a - 2) + 1 + >>> assoc_laguerre(3, a, x) + a**3/6 + a**2 + 11*a/6 - x**3/6 + x**2*(a/2 + 3/2) + + x*(-a**2/2 - 5*a/2 - 3) + 1 + + >>> assoc_laguerre(n, a, 0) + binomial(a + n, a) + + >>> assoc_laguerre(n, a, x) + assoc_laguerre(n, a, x) + + >>> assoc_laguerre(n, 0, x) + laguerre(n, x) + + >>> diff(assoc_laguerre(n, a, x), x) + -assoc_laguerre(n - 1, a + 1, x) + + >>> diff(assoc_laguerre(n, a, x), a) + Sum(assoc_laguerre(_k, a, x)/(-a + n), (_k, 0, n - 1)) + + Parameters + ========== + + n : int + Degree of Laguerre polynomial. Must be `n \ge 0`. + + alpha : Expr + Arbitrary expression. For ``alpha=0`` regular Laguerre + polynomials will be generated. + + See Also + ======== + + jacobi, gegenbauer, + chebyshevt, chebyshevt_root, chebyshevu, chebyshevu_root, + legendre, assoc_legendre, + hermite, hermite_prob, + laguerre, + sympy.polys.orthopolys.jacobi_poly + sympy.polys.orthopolys.gegenbauer_poly + sympy.polys.orthopolys.chebyshevt_poly + sympy.polys.orthopolys.chebyshevu_poly + sympy.polys.orthopolys.hermite_poly + sympy.polys.orthopolys.hermite_prob_poly + sympy.polys.orthopolys.legendre_poly + sympy.polys.orthopolys.laguerre_poly + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Laguerre_polynomial#Generalized_Laguerre_polynomials + .. [2] https://mathworld.wolfram.com/AssociatedLaguerrePolynomial.html + .. [3] https://functions.wolfram.com/Polynomials/LaguerreL/ + .. [4] https://functions.wolfram.com/Polynomials/LaguerreL3/ + + """ + + @classmethod + def eval(cls, n, alpha, x): + # L_{n}^{0}(x) ---> L_{n}(x) + if alpha.is_zero: + return laguerre(n, x) + + if not n.is_Number: + # We can evaluate for some special values of x + if x.is_zero: + return binomial(n + alpha, alpha) + elif x is S.Infinity and n > 0: + return S.NegativeOne**n * S.Infinity + elif x is S.NegativeInfinity and n > 0: + return S.Infinity + else: + # n is a given fixed integer, evaluate into polynomial + if n.is_negative: + raise ValueError( + "The index n must be nonnegative integer (got %r)" % n) + else: + return laguerre_poly(n, x, alpha) + + def fdiff(self, argindex=3): + from sympy.concrete.summations import Sum + if argindex == 1: + # Diff wrt n + raise ArgumentIndexError(self, argindex) + elif argindex == 2: + # Diff wrt alpha + n, alpha, x = self.args + k = Dummy("k") + return Sum(assoc_laguerre(k, alpha, x) / (n - alpha), (k, 0, n - 1)) + elif argindex == 3: + # Diff wrt x + n, alpha, x = self.args + return -assoc_laguerre(n - 1, alpha + 1, x) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_rewrite_as_Sum(self, n, alpha, x, **kwargs): + from sympy.concrete.summations import Sum + # Make sure n \in N_0 + if n.is_negative or n.is_integer is False: + raise ValueError("Error: n should be a non-negative integer.") + k = Dummy("k") + kern = RisingFactorial( + -n, k) / (gamma(k + alpha + 1) * factorial(k)) * x**k + return gamma(n + alpha + 1) / factorial(n) * Sum(kern, (k, 0, n)) + + def _eval_rewrite_as_polynomial(self, n, alpha, x, **kwargs): + # This function is just kept for backwards compatibility + # but should not be used + return self._eval_rewrite_as_Sum(n, alpha, x, **kwargs) + + def _eval_conjugate(self): + n, alpha, x = self.args + return self.func(n, alpha.conjugate(), x.conjugate()) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/singularity_functions.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/singularity_functions.py new file mode 100644 index 0000000000000000000000000000000000000000..a69026e6e657b1131880b47cb32202b6825b7158 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/singularity_functions.py @@ -0,0 +1,235 @@ +from sympy.core import S, oo, diff +from sympy.core.function import DefinedFunction, ArgumentIndexError +from sympy.core.logic import fuzzy_not +from sympy.core.relational import Eq +from sympy.functions.elementary.complexes import im +from sympy.functions.elementary.piecewise import Piecewise +from sympy.functions.special.delta_functions import Heaviside + +############################################################################### +############################# SINGULARITY FUNCTION ############################ +############################################################################### + + +class SingularityFunction(DefinedFunction): + r""" + Singularity functions are a class of discontinuous functions. + + Explanation + =========== + + Singularity functions take a variable, an offset, and an exponent as + arguments. These functions are represented using Macaulay brackets as: + + SingularityFunction(x, a, n) := ^n + + The singularity function will automatically evaluate to + ``Derivative(DiracDelta(x - a), x, -n - 1)`` if ``n < 0`` + and ``(x - a)**n*Heaviside(x - a, 1)`` if ``n >= 0``. + + Examples + ======== + + >>> from sympy import SingularityFunction, diff, Piecewise, DiracDelta, Heaviside, Symbol + >>> from sympy.abc import x, a, n + >>> SingularityFunction(x, a, n) + SingularityFunction(x, a, n) + >>> y = Symbol('y', positive=True) + >>> n = Symbol('n', nonnegative=True) + >>> SingularityFunction(y, -10, n) + (y + 10)**n + >>> y = Symbol('y', negative=True) + >>> SingularityFunction(y, 10, n) + 0 + >>> SingularityFunction(x, 4, -1).subs(x, 4) + oo + >>> SingularityFunction(x, 10, -2).subs(x, 10) + oo + >>> SingularityFunction(4, 1, 5) + 243 + >>> diff(SingularityFunction(x, 1, 5) + SingularityFunction(x, 1, 4), x) + 4*SingularityFunction(x, 1, 3) + 5*SingularityFunction(x, 1, 4) + >>> diff(SingularityFunction(x, 4, 0), x, 2) + SingularityFunction(x, 4, -2) + >>> SingularityFunction(x, 4, 5).rewrite(Piecewise) + Piecewise(((x - 4)**5, x >= 4), (0, True)) + >>> expr = SingularityFunction(x, a, n) + >>> y = Symbol('y', positive=True) + >>> n = Symbol('n', nonnegative=True) + >>> expr.subs({x: y, a: -10, n: n}) + (y + 10)**n + + The methods ``rewrite(DiracDelta)``, ``rewrite(Heaviside)``, and + ``rewrite('HeavisideDiracDelta')`` returns the same output. One can use any + of these methods according to their choice. + + >>> expr = SingularityFunction(x, 4, 5) + SingularityFunction(x, -3, -1) - SingularityFunction(x, 0, -2) + >>> expr.rewrite(Heaviside) + (x - 4)**5*Heaviside(x - 4, 1) + DiracDelta(x + 3) - DiracDelta(x, 1) + >>> expr.rewrite(DiracDelta) + (x - 4)**5*Heaviside(x - 4, 1) + DiracDelta(x + 3) - DiracDelta(x, 1) + >>> expr.rewrite('HeavisideDiracDelta') + (x - 4)**5*Heaviside(x - 4, 1) + DiracDelta(x + 3) - DiracDelta(x, 1) + + See Also + ======== + + DiracDelta, Heaviside + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Singularity_function + + """ + + is_real = True + + def fdiff(self, argindex=1): + """ + Returns the first derivative of a DiracDelta Function. + + Explanation + =========== + + The difference between ``diff()`` and ``fdiff()`` is: ``diff()`` is the + user-level function and ``fdiff()`` is an object method. ``fdiff()`` is + a convenience method available in the ``Function`` class. It returns + the derivative of the function without considering the chain rule. + ``diff(function, x)`` calls ``Function._eval_derivative`` which in turn + calls ``fdiff()`` internally to compute the derivative of the function. + + """ + + if argindex == 1: + x, a, n = self.args + if n in (S.Zero, S.NegativeOne, S(-2), S(-3)): + return self.func(x, a, n-1) + elif n.is_positive: + return n*self.func(x, a, n-1) + else: + raise ArgumentIndexError(self, argindex) + + @classmethod + def eval(cls, variable, offset, exponent): + """ + Returns a simplified form or a value of Singularity Function depending + on the argument passed by the object. + + Explanation + =========== + + The ``eval()`` method is automatically called when the + ``SingularityFunction`` class is about to be instantiated and it + returns either some simplified instance or the unevaluated instance + depending on the argument passed. In other words, ``eval()`` method is + not needed to be called explicitly, it is being called and evaluated + once the object is called. + + Examples + ======== + + >>> from sympy import SingularityFunction, Symbol, nan + >>> from sympy.abc import x, a, n + >>> SingularityFunction(x, a, n) + SingularityFunction(x, a, n) + >>> SingularityFunction(5, 3, 2) + 4 + >>> SingularityFunction(x, a, nan) + nan + >>> SingularityFunction(x, 3, 0).subs(x, 3) + 1 + >>> SingularityFunction(4, 1, 5) + 243 + >>> x = Symbol('x', positive = True) + >>> a = Symbol('a', negative = True) + >>> n = Symbol('n', nonnegative = True) + >>> SingularityFunction(x, a, n) + (-a + x)**n + >>> x = Symbol('x', negative = True) + >>> a = Symbol('a', positive = True) + >>> SingularityFunction(x, a, n) + 0 + + """ + + x = variable + a = offset + n = exponent + shift = (x - a) + + if fuzzy_not(im(shift).is_zero): + raise ValueError("Singularity Functions are defined only for Real Numbers.") + if fuzzy_not(im(n).is_zero): + raise ValueError("Singularity Functions are not defined for imaginary exponents.") + if shift is S.NaN or n is S.NaN: + return S.NaN + if (n + 4).is_negative: + raise ValueError("Singularity Functions are not defined for exponents less than -4.") + if shift.is_extended_negative: + return S.Zero + if n.is_nonnegative: + if shift.is_zero: # use literal 0 in case of Symbol('z', zero=True) + return S.Zero**n + if shift.is_extended_nonnegative: + return shift**n + if n in (S.NegativeOne, -2, -3, -4): + if shift.is_negative or shift.is_extended_positive: + return S.Zero + if shift.is_zero: + return oo + + def _eval_rewrite_as_Piecewise(self, *args, **kwargs): + ''' + Converts a Singularity Function expression into its Piecewise form. + + ''' + x, a, n = self.args + + if n in (S.NegativeOne, S(-2), S(-3), S(-4)): + return Piecewise((oo, Eq(x - a, 0)), (0, True)) + elif n.is_nonnegative: + return Piecewise(((x - a)**n, x - a >= 0), (0, True)) + + def _eval_rewrite_as_Heaviside(self, *args, **kwargs): + ''' + Rewrites a Singularity Function expression using Heavisides and DiracDeltas. + + ''' + x, a, n = self.args + + if n == -4: + return diff(Heaviside(x - a), x.free_symbols.pop(), 4) + if n == -3: + return diff(Heaviside(x - a), x.free_symbols.pop(), 3) + if n == -2: + return diff(Heaviside(x - a), x.free_symbols.pop(), 2) + if n == -1: + return diff(Heaviside(x - a), x.free_symbols.pop(), 1) + if n.is_nonnegative: + return (x - a)**n*Heaviside(x - a, 1) + + def _eval_as_leading_term(self, x, logx, cdir): + z, a, n = self.args + shift = (z - a).subs(x, 0) + if n < 0: + return S.Zero + elif n.is_zero and shift.is_zero: + return S.Zero if cdir == -1 else S.One + elif shift.is_positive: + return shift**n + return S.Zero + + def _eval_nseries(self, x, n, logx=None, cdir=0): + z, a, n = self.args + shift = (z - a).subs(x, 0) + if n < 0: + return S.Zero + elif n.is_zero and shift.is_zero: + return S.Zero if cdir == -1 else S.One + elif shift.is_positive: + return ((z - a)**n)._eval_nseries(x, n, logx=logx, cdir=cdir) + return S.Zero + + _eval_rewrite_as_DiracDelta = _eval_rewrite_as_Heaviside + _eval_rewrite_as_HeavisideDiracDelta = _eval_rewrite_as_Heaviside diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/spherical_harmonics.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/spherical_harmonics.py new file mode 100644 index 0000000000000000000000000000000000000000..541546b75e882b43c41814b5e92bb85ee41628d1 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/spherical_harmonics.py @@ -0,0 +1,334 @@ +from sympy.core.expr import Expr +from sympy.core.function import DefinedFunction, ArgumentIndexError +from sympy.core.numbers import I, pi +from sympy.core.singleton import S +from sympy.core.symbol import Dummy +from sympy.functions import assoc_legendre +from sympy.functions.combinatorial.factorials import factorial +from sympy.functions.elementary.complexes import Abs, conjugate +from sympy.functions.elementary.exponential import exp +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import sin, cos, cot + +_x = Dummy("x") + +class Ynm(DefinedFunction): + r""" + Spherical harmonics defined as + + .. math:: + Y_n^m(\theta, \varphi) := \sqrt{\frac{(2n+1)(n-m)!}{4\pi(n+m)!}} + \exp(i m \varphi) + \mathrm{P}_n^m\left(\cos(\theta)\right) + + Explanation + =========== + + ``Ynm()`` gives the spherical harmonic function of order $n$ and $m$ + in $\theta$ and $\varphi$, $Y_n^m(\theta, \varphi)$. The four + parameters are as follows: $n \geq 0$ an integer and $m$ an integer + such that $-n \leq m \leq n$ holds. The two angles are real-valued + with $\theta \in [0, \pi]$ and $\varphi \in [0, 2\pi]$. + + Examples + ======== + + >>> from sympy import Ynm, Symbol, simplify + >>> from sympy.abc import n,m + >>> theta = Symbol("theta") + >>> phi = Symbol("phi") + + >>> Ynm(n, m, theta, phi) + Ynm(n, m, theta, phi) + + Several symmetries are known, for the order: + + >>> Ynm(n, -m, theta, phi) + (-1)**m*exp(-2*I*m*phi)*Ynm(n, m, theta, phi) + + As well as for the angles: + + >>> Ynm(n, m, -theta, phi) + Ynm(n, m, theta, phi) + + >>> Ynm(n, m, theta, -phi) + exp(-2*I*m*phi)*Ynm(n, m, theta, phi) + + For specific integers $n$ and $m$ we can evaluate the harmonics + to more useful expressions: + + >>> simplify(Ynm(0, 0, theta, phi).expand(func=True)) + 1/(2*sqrt(pi)) + + >>> simplify(Ynm(1, -1, theta, phi).expand(func=True)) + sqrt(6)*exp(-I*phi)*sin(theta)/(4*sqrt(pi)) + + >>> simplify(Ynm(1, 0, theta, phi).expand(func=True)) + sqrt(3)*cos(theta)/(2*sqrt(pi)) + + >>> simplify(Ynm(1, 1, theta, phi).expand(func=True)) + -sqrt(6)*exp(I*phi)*sin(theta)/(4*sqrt(pi)) + + >>> simplify(Ynm(2, -2, theta, phi).expand(func=True)) + sqrt(30)*exp(-2*I*phi)*sin(theta)**2/(8*sqrt(pi)) + + >>> simplify(Ynm(2, -1, theta, phi).expand(func=True)) + sqrt(30)*exp(-I*phi)*sin(2*theta)/(8*sqrt(pi)) + + >>> simplify(Ynm(2, 0, theta, phi).expand(func=True)) + sqrt(5)*(3*cos(theta)**2 - 1)/(4*sqrt(pi)) + + >>> simplify(Ynm(2, 1, theta, phi).expand(func=True)) + -sqrt(30)*exp(I*phi)*sin(2*theta)/(8*sqrt(pi)) + + >>> simplify(Ynm(2, 2, theta, phi).expand(func=True)) + sqrt(30)*exp(2*I*phi)*sin(theta)**2/(8*sqrt(pi)) + + We can differentiate the functions with respect + to both angles: + + >>> from sympy import Ynm, Symbol, diff + >>> from sympy.abc import n,m + >>> theta = Symbol("theta") + >>> phi = Symbol("phi") + + >>> diff(Ynm(n, m, theta, phi), theta) + m*cot(theta)*Ynm(n, m, theta, phi) + sqrt((-m + n)*(m + n + 1))*exp(-I*phi)*Ynm(n, m + 1, theta, phi) + + >>> diff(Ynm(n, m, theta, phi), phi) + I*m*Ynm(n, m, theta, phi) + + Further we can compute the complex conjugation: + + >>> from sympy import Ynm, Symbol, conjugate + >>> from sympy.abc import n,m + >>> theta = Symbol("theta") + >>> phi = Symbol("phi") + + >>> conjugate(Ynm(n, m, theta, phi)) + (-1)**(2*m)*exp(-2*I*m*phi)*Ynm(n, m, theta, phi) + + To get back the well known expressions in spherical + coordinates, we use full expansion: + + >>> from sympy import Ynm, Symbol, expand_func + >>> from sympy.abc import n,m + >>> theta = Symbol("theta") + >>> phi = Symbol("phi") + + >>> expand_func(Ynm(n, m, theta, phi)) + sqrt((2*n + 1)*factorial(-m + n)/factorial(m + n))*exp(I*m*phi)*assoc_legendre(n, m, cos(theta))/(2*sqrt(pi)) + + See Also + ======== + + Ynm_c, Znm + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Spherical_harmonics + .. [2] https://mathworld.wolfram.com/SphericalHarmonic.html + .. [3] https://functions.wolfram.com/Polynomials/SphericalHarmonicY/ + .. [4] https://dlmf.nist.gov/14.30 + + """ + + @classmethod + def eval(cls, n, m, theta, phi): + # Handle negative index m and arguments theta, phi + if m.could_extract_minus_sign(): + m = -m + return S.NegativeOne**m * exp(-2*I*m*phi) * Ynm(n, m, theta, phi) + if theta.could_extract_minus_sign(): + theta = -theta + return Ynm(n, m, theta, phi) + if phi.could_extract_minus_sign(): + phi = -phi + return exp(-2*I*m*phi) * Ynm(n, m, theta, phi) + + # TODO Add more simplififcation here + + def _eval_expand_func(self, **hints): + n, m, theta, phi = self.args + rv = (sqrt((2*n + 1)/(4*pi) * factorial(n - m)/factorial(n + m)) * + exp(I*m*phi) * assoc_legendre(n, m, cos(theta))) + # We can do this because of the range of theta + return rv.subs(sqrt(-cos(theta)**2 + 1), sin(theta)) + + def fdiff(self, argindex=4): + if argindex == 1: + # Diff wrt n + raise ArgumentIndexError(self, argindex) + elif argindex == 2: + # Diff wrt m + raise ArgumentIndexError(self, argindex) + elif argindex == 3: + # Diff wrt theta + n, m, theta, phi = self.args + return (m * cot(theta) * Ynm(n, m, theta, phi) + + sqrt((n - m)*(n + m + 1)) * exp(-I*phi) * Ynm(n, m + 1, theta, phi)) + elif argindex == 4: + # Diff wrt phi + n, m, theta, phi = self.args + return I * m * Ynm(n, m, theta, phi) + else: + raise ArgumentIndexError(self, argindex) + + def _eval_rewrite_as_polynomial(self, n, m, theta, phi, **kwargs): + # TODO: Make sure n \in N + # TODO: Assert |m| <= n ortherwise we should return 0 + return self.expand(func=True) + + def _eval_rewrite_as_sin(self, n, m, theta, phi, **kwargs): + return self.rewrite(cos) + + def _eval_rewrite_as_cos(self, n, m, theta, phi, **kwargs): + # This method can be expensive due to extensive use of simplification! + from sympy.simplify import simplify, trigsimp + # TODO: Make sure n \in N + # TODO: Assert |m| <= n ortherwise we should return 0 + term = simplify(self.expand(func=True)) + # We can do this because of the range of theta + term = term.xreplace({Abs(sin(theta)):sin(theta)}) + return simplify(trigsimp(term)) + + def _eval_conjugate(self): + # TODO: Make sure theta \in R and phi \in R + n, m, theta, phi = self.args + return S.NegativeOne**m * self.func(n, -m, theta, phi) + + def as_real_imag(self, deep=True, **hints): + # TODO: Handle deep and hints + n, m, theta, phi = self.args + re = (sqrt((2*n + 1)/(4*pi) * factorial(n - m)/factorial(n + m)) * + cos(m*phi) * assoc_legendre(n, m, cos(theta))) + im = (sqrt((2*n + 1)/(4*pi) * factorial(n - m)/factorial(n + m)) * + sin(m*phi) * assoc_legendre(n, m, cos(theta))) + return (re, im) + + def _eval_evalf(self, prec): + # Note: works without this function by just calling + # mpmath for Legendre polynomials. But using + # the dedicated function directly is cleaner. + from mpmath import mp, workprec + n = self.args[0]._to_mpmath(prec) + m = self.args[1]._to_mpmath(prec) + theta = self.args[2]._to_mpmath(prec) + phi = self.args[3]._to_mpmath(prec) + with workprec(prec): + res = mp.spherharm(n, m, theta, phi) + return Expr._from_mpmath(res, prec) + + +def Ynm_c(n, m, theta, phi): + r""" + Conjugate spherical harmonics defined as + + .. math:: + \overline{Y_n^m(\theta, \varphi)} := (-1)^m Y_n^{-m}(\theta, \varphi). + + Examples + ======== + + >>> from sympy import Ynm_c, Symbol, simplify + >>> from sympy.abc import n,m + >>> theta = Symbol("theta") + >>> phi = Symbol("phi") + >>> Ynm_c(n, m, theta, phi) + (-1)**(2*m)*exp(-2*I*m*phi)*Ynm(n, m, theta, phi) + >>> Ynm_c(n, m, -theta, phi) + (-1)**(2*m)*exp(-2*I*m*phi)*Ynm(n, m, theta, phi) + + For specific integers $n$ and $m$ we can evaluate the harmonics + to more useful expressions: + + >>> simplify(Ynm_c(0, 0, theta, phi).expand(func=True)) + 1/(2*sqrt(pi)) + >>> simplify(Ynm_c(1, -1, theta, phi).expand(func=True)) + sqrt(6)*exp(I*(-phi + 2*conjugate(phi)))*sin(theta)/(4*sqrt(pi)) + + See Also + ======== + + Ynm, Znm + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Spherical_harmonics + .. [2] https://mathworld.wolfram.com/SphericalHarmonic.html + .. [3] https://functions.wolfram.com/Polynomials/SphericalHarmonicY/ + + """ + return conjugate(Ynm(n, m, theta, phi)) + + +class Znm(DefinedFunction): + r""" + Real spherical harmonics defined as + + .. math:: + + Z_n^m(\theta, \varphi) := + \begin{cases} + \frac{Y_n^m(\theta, \varphi) + \overline{Y_n^m(\theta, \varphi)}}{\sqrt{2}} &\quad m > 0 \\ + Y_n^m(\theta, \varphi) &\quad m = 0 \\ + \frac{Y_n^m(\theta, \varphi) - \overline{Y_n^m(\theta, \varphi)}}{i \sqrt{2}} &\quad m < 0 \\ + \end{cases} + + which gives in simplified form + + .. math:: + + Z_n^m(\theta, \varphi) = + \begin{cases} + \frac{Y_n^m(\theta, \varphi) + (-1)^m Y_n^{-m}(\theta, \varphi)}{\sqrt{2}} &\quad m > 0 \\ + Y_n^m(\theta, \varphi) &\quad m = 0 \\ + \frac{Y_n^m(\theta, \varphi) - (-1)^m Y_n^{-m}(\theta, \varphi)}{i \sqrt{2}} &\quad m < 0 \\ + \end{cases} + + Examples + ======== + + >>> from sympy import Znm, Symbol, simplify + >>> from sympy.abc import n, m + >>> theta = Symbol("theta") + >>> phi = Symbol("phi") + >>> Znm(n, m, theta, phi) + Znm(n, m, theta, phi) + + For specific integers n and m we can evaluate the harmonics + to more useful expressions: + + >>> simplify(Znm(0, 0, theta, phi).expand(func=True)) + 1/(2*sqrt(pi)) + >>> simplify(Znm(1, 1, theta, phi).expand(func=True)) + -sqrt(3)*sin(theta)*cos(phi)/(2*sqrt(pi)) + >>> simplify(Znm(2, 1, theta, phi).expand(func=True)) + -sqrt(15)*sin(2*theta)*cos(phi)/(4*sqrt(pi)) + + See Also + ======== + + Ynm, Ynm_c + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Spherical_harmonics + .. [2] https://mathworld.wolfram.com/SphericalHarmonic.html + .. [3] https://functions.wolfram.com/Polynomials/SphericalHarmonicY/ + + """ + + @classmethod + def eval(cls, n, m, theta, phi): + if m.is_positive: + zz = (Ynm(n, m, theta, phi) + Ynm_c(n, m, theta, phi)) / sqrt(2) + return zz + elif m.is_zero: + return Ynm(n, m, theta, phi) + elif m.is_negative: + zz = (Ynm(n, m, theta, phi) - Ynm_c(n, m, theta, phi)) / (sqrt(2)*I) + return zz diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tensor_functions.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tensor_functions.py new file mode 100644 index 0000000000000000000000000000000000000000..6d996a58cbc8320620c9a1f6e68529c3b5e99aef --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tensor_functions.py @@ -0,0 +1,474 @@ +from math import prod + +from sympy.core import S, Integer +from sympy.core.function import DefinedFunction +from sympy.core.logic import fuzzy_not +from sympy.core.relational import Ne +from sympy.core.sorting import default_sort_key +from sympy.external.gmpy import SYMPY_INTS +from sympy.functions.combinatorial.factorials import factorial +from sympy.functions.elementary.piecewise import Piecewise +from sympy.utilities.iterables import has_dups + +############################################################################### +###################### Kronecker Delta, Levi-Civita etc. ###################### +############################################################################### + + +def Eijk(*args, **kwargs): + """ + Represent the Levi-Civita symbol. + + This is a compatibility wrapper to ``LeviCivita()``. + + See Also + ======== + + LeviCivita + + """ + return LeviCivita(*args, **kwargs) + + +def eval_levicivita(*args): + """Evaluate Levi-Civita symbol.""" + n = len(args) + return prod( + prod(args[j] - args[i] for j in range(i + 1, n)) + / factorial(i) for i in range(n)) + # converting factorial(i) to int is slightly faster + + +class LeviCivita(DefinedFunction): + """ + Represent the Levi-Civita symbol. + + Explanation + =========== + + For even permutations of indices it returns 1, for odd permutations -1, and + for everything else (a repeated index) it returns 0. + + Thus it represents an alternating pseudotensor. + + Examples + ======== + + >>> from sympy import LeviCivita + >>> from sympy.abc import i, j, k + >>> LeviCivita(1, 2, 3) + 1 + >>> LeviCivita(1, 3, 2) + -1 + >>> LeviCivita(1, 2, 2) + 0 + >>> LeviCivita(i, j, k) + LeviCivita(i, j, k) + >>> LeviCivita(i, j, i) + 0 + + See Also + ======== + + Eijk + + """ + + is_integer = True + + @classmethod + def eval(cls, *args): + if all(isinstance(a, (SYMPY_INTS, Integer)) for a in args): + return eval_levicivita(*args) + if has_dups(args): + return S.Zero + + def doit(self, **hints): + return eval_levicivita(*self.args) + + +class KroneckerDelta(DefinedFunction): + """ + The discrete, or Kronecker, delta function. + + Explanation + =========== + + A function that takes in two integers $i$ and $j$. It returns $0$ if $i$ + and $j$ are not equal, or it returns $1$ if $i$ and $j$ are equal. + + Examples + ======== + + An example with integer indices: + + >>> from sympy import KroneckerDelta + >>> KroneckerDelta(1, 2) + 0 + >>> KroneckerDelta(3, 3) + 1 + + Symbolic indices: + + >>> from sympy.abc import i, j, k + >>> KroneckerDelta(i, j) + KroneckerDelta(i, j) + >>> KroneckerDelta(i, i) + 1 + >>> KroneckerDelta(i, i + 1) + 0 + >>> KroneckerDelta(i, i + 1 + k) + KroneckerDelta(i, i + k + 1) + + Parameters + ========== + + i : Number, Symbol + The first index of the delta function. + j : Number, Symbol + The second index of the delta function. + + See Also + ======== + + eval + DiracDelta + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Kronecker_delta + + """ + + is_integer = True + + @classmethod + def eval(cls, i, j, delta_range=None): + """ + Evaluates the discrete delta function. + + Examples + ======== + + >>> from sympy import KroneckerDelta + >>> from sympy.abc import i, j, k + + >>> KroneckerDelta(i, j) + KroneckerDelta(i, j) + >>> KroneckerDelta(i, i) + 1 + >>> KroneckerDelta(i, i + 1) + 0 + >>> KroneckerDelta(i, i + 1 + k) + KroneckerDelta(i, i + k + 1) + + # indirect doctest + + """ + + if delta_range is not None: + dinf, dsup = delta_range + if (dinf - i > 0) == True: + return S.Zero + if (dinf - j > 0) == True: + return S.Zero + if (dsup - i < 0) == True: + return S.Zero + if (dsup - j < 0) == True: + return S.Zero + + diff = i - j + if diff.is_zero: + return S.One + elif fuzzy_not(diff.is_zero): + return S.Zero + + if i.assumptions0.get("below_fermi") and \ + j.assumptions0.get("above_fermi"): + return S.Zero + if j.assumptions0.get("below_fermi") and \ + i.assumptions0.get("above_fermi"): + return S.Zero + # to make KroneckerDelta canonical + # following lines will check if inputs are in order + # if not, will return KroneckerDelta with correct order + if default_sort_key(j) < default_sort_key(i): + if delta_range: + return cls(j, i, delta_range) + else: + return cls(j, i) + + @property + def delta_range(self): + if len(self.args) > 2: + return self.args[2] + + def _eval_power(self, expt): + if expt.is_positive: + return self + if expt.is_negative and expt is not S.NegativeOne: + return 1/self + + @property + def is_above_fermi(self): + """ + True if Delta can be non-zero above fermi. + + Examples + ======== + + >>> from sympy import KroneckerDelta, Symbol + >>> a = Symbol('a', above_fermi=True) + >>> i = Symbol('i', below_fermi=True) + >>> p = Symbol('p') + >>> q = Symbol('q') + >>> KroneckerDelta(p, a).is_above_fermi + True + >>> KroneckerDelta(p, i).is_above_fermi + False + >>> KroneckerDelta(p, q).is_above_fermi + True + + See Also + ======== + + is_below_fermi, is_only_below_fermi, is_only_above_fermi + + """ + if self.args[0].assumptions0.get("below_fermi"): + return False + if self.args[1].assumptions0.get("below_fermi"): + return False + return True + + @property + def is_below_fermi(self): + """ + True if Delta can be non-zero below fermi. + + Examples + ======== + + >>> from sympy import KroneckerDelta, Symbol + >>> a = Symbol('a', above_fermi=True) + >>> i = Symbol('i', below_fermi=True) + >>> p = Symbol('p') + >>> q = Symbol('q') + >>> KroneckerDelta(p, a).is_below_fermi + False + >>> KroneckerDelta(p, i).is_below_fermi + True + >>> KroneckerDelta(p, q).is_below_fermi + True + + See Also + ======== + + is_above_fermi, is_only_above_fermi, is_only_below_fermi + + """ + if self.args[0].assumptions0.get("above_fermi"): + return False + if self.args[1].assumptions0.get("above_fermi"): + return False + return True + + @property + def is_only_above_fermi(self): + """ + True if Delta is restricted to above fermi. + + Examples + ======== + + >>> from sympy import KroneckerDelta, Symbol + >>> a = Symbol('a', above_fermi=True) + >>> i = Symbol('i', below_fermi=True) + >>> p = Symbol('p') + >>> q = Symbol('q') + >>> KroneckerDelta(p, a).is_only_above_fermi + True + >>> KroneckerDelta(p, q).is_only_above_fermi + False + >>> KroneckerDelta(p, i).is_only_above_fermi + False + + See Also + ======== + + is_above_fermi, is_below_fermi, is_only_below_fermi + + """ + return ( self.args[0].assumptions0.get("above_fermi") + or + self.args[1].assumptions0.get("above_fermi") + ) or False + + @property + def is_only_below_fermi(self): + """ + True if Delta is restricted to below fermi. + + Examples + ======== + + >>> from sympy import KroneckerDelta, Symbol + >>> a = Symbol('a', above_fermi=True) + >>> i = Symbol('i', below_fermi=True) + >>> p = Symbol('p') + >>> q = Symbol('q') + >>> KroneckerDelta(p, i).is_only_below_fermi + True + >>> KroneckerDelta(p, q).is_only_below_fermi + False + >>> KroneckerDelta(p, a).is_only_below_fermi + False + + See Also + ======== + + is_above_fermi, is_below_fermi, is_only_above_fermi + + """ + return ( self.args[0].assumptions0.get("below_fermi") + or + self.args[1].assumptions0.get("below_fermi") + ) or False + + @property + def indices_contain_equal_information(self): + """ + Returns True if indices are either both above or below fermi. + + Examples + ======== + + >>> from sympy import KroneckerDelta, Symbol + >>> a = Symbol('a', above_fermi=True) + >>> i = Symbol('i', below_fermi=True) + >>> p = Symbol('p') + >>> q = Symbol('q') + >>> KroneckerDelta(p, q).indices_contain_equal_information + True + >>> KroneckerDelta(p, q+1).indices_contain_equal_information + True + >>> KroneckerDelta(i, p).indices_contain_equal_information + False + + """ + if (self.args[0].assumptions0.get("below_fermi") and + self.args[1].assumptions0.get("below_fermi")): + return True + if (self.args[0].assumptions0.get("above_fermi") + and self.args[1].assumptions0.get("above_fermi")): + return True + + # if both indices are general we are True, else false + return self.is_below_fermi and self.is_above_fermi + + @property + def preferred_index(self): + """ + Returns the index which is preferred to keep in the final expression. + + Explanation + =========== + + The preferred index is the index with more information regarding fermi + level. If indices contain the same information, 'a' is preferred before + 'b'. + + Examples + ======== + + >>> from sympy import KroneckerDelta, Symbol + >>> a = Symbol('a', above_fermi=True) + >>> i = Symbol('i', below_fermi=True) + >>> j = Symbol('j', below_fermi=True) + >>> p = Symbol('p') + >>> KroneckerDelta(p, i).preferred_index + i + >>> KroneckerDelta(p, a).preferred_index + a + >>> KroneckerDelta(i, j).preferred_index + i + + See Also + ======== + + killable_index + + """ + if self._get_preferred_index(): + return self.args[1] + else: + return self.args[0] + + @property + def killable_index(self): + """ + Returns the index which is preferred to substitute in the final + expression. + + Explanation + =========== + + The index to substitute is the index with less information regarding + fermi level. If indices contain the same information, 'a' is preferred + before 'b'. + + Examples + ======== + + >>> from sympy import KroneckerDelta, Symbol + >>> a = Symbol('a', above_fermi=True) + >>> i = Symbol('i', below_fermi=True) + >>> j = Symbol('j', below_fermi=True) + >>> p = Symbol('p') + >>> KroneckerDelta(p, i).killable_index + p + >>> KroneckerDelta(p, a).killable_index + p + >>> KroneckerDelta(i, j).killable_index + j + + See Also + ======== + + preferred_index + + """ + if self._get_preferred_index(): + return self.args[0] + else: + return self.args[1] + + def _get_preferred_index(self): + """ + Returns the index which is preferred to keep in the final expression. + + The preferred index is the index with more information regarding fermi + level. If indices contain the same information, index 0 is returned. + + """ + if not self.is_above_fermi: + if self.args[0].assumptions0.get("below_fermi"): + return 0 + else: + return 1 + elif not self.is_below_fermi: + if self.args[0].assumptions0.get("above_fermi"): + return 0 + else: + return 1 + else: + return 0 + + @property + def indices(self): + return self.args[0:2] + + def _eval_rewrite_as_Piecewise(self, *args, **kwargs): + i, j = args + return Piecewise((0, Ne(i, j)), (1, True)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6077c7a209f19cc6412cd0ab442dccfe40caa6e0 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_bessel.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_bessel.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..989676ae934176a31595c28ed29973ded75049ec Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_bessel.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_beta_functions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_beta_functions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f45b69af58c8cb651be40d05ebcd58086e6a2344 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_beta_functions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_bsplines.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_bsplines.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..85983817f8e0e6f145bf3e5c776e2c66b20ecf8e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_bsplines.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_delta_functions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_delta_functions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4990ec4e5f71b91f95bb7da3e6c3546a946cf990 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_delta_functions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_elliptic_integrals.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_elliptic_integrals.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ab8d6b2351f9dae44a6d490612a9e70bfad35483 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_elliptic_integrals.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_gamma_functions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_gamma_functions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..477e3706a802325f1411de9e73291487f60263bc Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_gamma_functions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_hyper.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_hyper.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1b0073240e84f65b96a869d280e8988fa23b5e66 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_hyper.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_mathieu.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_mathieu.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..94c1504efbbbc20a290882da3657890d08716716 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_mathieu.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_singularity_functions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_singularity_functions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d6294fa0c2c071fcd6eb5b4f6c7988660e2e20ff Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_singularity_functions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_spec_polynomials.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_spec_polynomials.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a5cf4e0247c0c1f7cb8371f54188944213a3b44c Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_spec_polynomials.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_spherical_harmonics.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_spherical_harmonics.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2e43607bdc235e2c714121b728b7d7315dbe754a Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_spherical_harmonics.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_tensor_functions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_tensor_functions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..58f50ab890b98edb09db760082142884cd857414 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_tensor_functions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_zeta_functions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_zeta_functions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..08d2357ca7a2dc83306d06cfccca046788bfe6e9 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/__pycache__/test_zeta_functions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_bessel.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_bessel.py new file mode 100644 index 0000000000000000000000000000000000000000..ccd1ce88ca9dea15f065e7c57d488498b8f79f4e --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_bessel.py @@ -0,0 +1,807 @@ +from itertools import product + +from sympy.concrete.summations import Sum +from sympy.core.function import (diff, expand_func) +from sympy.core.numbers import (I, Rational, oo, pi) +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.elementary.complexes import (conjugate, polar_lift) +from sympy.functions.elementary.exponential import (exp, exp_polar, log) +from sympy.functions.elementary.hyperbolic import (cosh, sinh) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.functions.special.bessel import (besseli, besselj, besselk, bessely, hankel1, hankel2, hn1, hn2, jn, jn_zeros, yn) +from sympy.functions.special.gamma_functions import (gamma, uppergamma) +from sympy.functions.special.hyper import hyper +from sympy.integrals.integrals import Integral +from sympy.series.order import O +from sympy.series.series import series +from sympy.functions.special.bessel import (airyai, airybi, + airyaiprime, airybiprime, marcumq) +from sympy.core.random import (random_complex_number as randcplx, + verify_numerically as tn, + test_derivative_numerically as td, + _randint) +from sympy.simplify import besselsimp +from sympy.testing.pytest import raises, slow + +from sympy.abc import z, n, k, x + +randint = _randint() + + +def test_bessel_rand(): + for f in [besselj, bessely, besseli, besselk, hankel1, hankel2]: + assert td(f(randcplx(), z), z) + + for f in [jn, yn, hn1, hn2]: + assert td(f(randint(-10, 10), z), z) + + +def test_bessel_twoinputs(): + for f in [besselj, bessely, besseli, besselk, hankel1, hankel2, jn, yn]: + raises(TypeError, lambda: f(1)) + raises(TypeError, lambda: f(1, 2, 3)) + + +def test_besselj_leading_term(): + assert besselj(0, x).as_leading_term(x) == 1 + assert besselj(1, sin(x)).as_leading_term(x) == x/2 + assert besselj(1, 2*sqrt(x)).as_leading_term(x) == sqrt(x) + + # https://github.com/sympy/sympy/issues/21701 + assert (besselj(z, x)/x**z).as_leading_term(x) == 1/(2**z*gamma(z + 1)) + + +def test_bessely_leading_term(): + assert bessely(0, x).as_leading_term(x) == (2*log(x) - 2*log(2) + 2*S.EulerGamma)/pi + assert bessely(1, sin(x)).as_leading_term(x) == -2/(pi*x) + assert bessely(1, 2*sqrt(x)).as_leading_term(x) == -1/(pi*sqrt(x)) + + +def test_besseli_leading_term(): + assert besseli(0, x).as_leading_term(x) == 1 + assert besseli(1, sin(x)).as_leading_term(x) == x/2 + assert besseli(1, 2*sqrt(x)).as_leading_term(x) == sqrt(x) + + +def test_besselk_leading_term(): + assert besselk(0, x).as_leading_term(x) == -log(x) - S.EulerGamma + log(2) + assert besselk(1, sin(x)).as_leading_term(x) == 1/x + assert besselk(1, 2*sqrt(x)).as_leading_term(x) == 1/(2*sqrt(x)) + assert besselk(S(5)/3, x).as_leading_term(x) == 2**(S(2)/3)*gamma(S(5)/3)/x**(S(5)/3) + assert besselk(S(2)/3, x).as_leading_term(x) == besselk(-S(2)/3, x).as_leading_term(x) + assert besselk(1,cos(x)).as_leading_term(x) == besselk(1,1) + assert besselk(3,1/x).as_leading_term(x) == sqrt(pi)*exp(-(1/x))/sqrt(2/x) + assert besselk(3,1/sin(x)).as_leading_term(x) == sqrt(pi)*exp(-(1/x))/sqrt(2/x) + + nz = Symbol("nz", nonzero=True) + assert besselk(nz, x).as_leading_term(x).subs({nz:S(5)/7}) == besselk(S(5)/7, x).series(x).as_leading_term(x) + assert besselk(nz, x).as_leading_term(x).subs({nz:S(-15)/7}) == besselk(S(-15)/7, x).series(x).as_leading_term(x) + assert besselk(nz, x).as_leading_term(x).subs({nz:3}) == besselk(3, x).series(x).as_leading_term(x) + assert besselk(nz, x).as_leading_term(x).subs({nz:-2}) == besselk(-2, x).series(x).as_leading_term(x) + + +def test_besselj_series(): + assert besselj(0, x).series(x) == 1 - x**2/4 + x**4/64 + O(x**6) + assert besselj(0, x**(1.1)).series(x) == 1 + x**4.4/64 - x**2.2/4 + O(x**6) + assert besselj(0, x**2 + x).series(x) == 1 - x**2/4 - x**3/2\ + - 15*x**4/64 + x**5/16 + O(x**6) + assert besselj(0, sqrt(x) + x).series(x, n=4) == 1 - x/4 - 15*x**2/64\ + + 215*x**3/2304 - x**Rational(3, 2)/2 + x**Rational(5, 2)/16\ + + 23*x**Rational(7, 2)/384 + O(x**4) + assert besselj(0, x/(1 - x)).series(x) == 1 - x**2/4 - x**3/2 - 47*x**4/64\ + - 15*x**5/16 + O(x**6) + assert besselj(0, log(1 + x)).series(x) == 1 - x**2/4 + x**3/4\ + - 41*x**4/192 + 17*x**5/96 + O(x**6) + assert besselj(1, sin(x)).series(x) == x/2 - 7*x**3/48 + 73*x**5/1920 + O(x**6) + assert besselj(1, 2*sqrt(x)).series(x) == sqrt(x) - x**Rational(3, 2)/2\ + + x**Rational(5, 2)/12 - x**Rational(7, 2)/144 + x**Rational(9, 2)/2880\ + - x**Rational(11, 2)/86400 + O(x**6) + assert besselj(-2, sin(x)).series(x, n=4) == besselj(2, sin(x)).series(x, n=4) + + +def test_bessely_series(): + const = 2*S.EulerGamma/pi - 2*log(2)/pi + 2*log(x)/pi + assert bessely(0, x).series(x, n=4) == const + x**2*(-log(x)/(2*pi)\ + + (2 - 2*S.EulerGamma)/(4*pi) + log(2)/(2*pi)) + O(x**4*log(x)) + assert bessely(1, x).series(x, n=4) == -2/(pi*x) + x*(log(x)/pi - log(2)/pi - \ + (1 - 2*S.EulerGamma)/(2*pi)) + x**3*(-log(x)/(8*pi) + \ + (S(5)/2 - 2*S.EulerGamma)/(16*pi) + log(2)/(8*pi)) + O(x**4*log(x)) + assert bessely(2, x).series(x, n=4) == -4/(pi*x**2) - 1/pi + x**2*(log(x)/(4*pi) - \ + log(2)/(4*pi) - (S(3)/2 - 2*S.EulerGamma)/(8*pi)) + O(x**4*log(x)) + assert bessely(3, x).series(x, n=4) == -16/(pi*x**3) - 2/(pi*x) - \ + x/(4*pi) + x**3*(log(x)/(24*pi) - log(2)/(24*pi) - \ + (S(11)/6 - 2*S.EulerGamma)/(48*pi)) + O(x**4*log(x)) + assert bessely(0, x**(1.1)).series(x, n=4) == 2*S.EulerGamma/pi\ + - 2*log(2)/pi + 2.2*log(x)/pi + x**2.2*(-0.55*log(x)/pi\ + + (2 - 2*S.EulerGamma)/(4*pi) + log(2)/(2*pi)) + O(x**4*log(x)) + assert bessely(0, x**2 + x).series(x, n=4) == \ + const - (2 - 2*S.EulerGamma)*(-x**3/(2*pi) - x**2/(4*pi)) + 2*x/pi\ + + x**2*(-log(x)/(2*pi) - 1/pi + log(2)/(2*pi))\ + + x**3*(-log(x)/pi + 1/(6*pi) + log(2)/pi) + O(x**4*log(x)) + assert bessely(0, x/(1 - x)).series(x, n=3) == const\ + + 2*x/pi + x**2*(-log(x)/(2*pi) + (2 - 2*S.EulerGamma)/(4*pi)\ + + log(2)/(2*pi) + 1/pi) + O(x**3*log(x)) + assert bessely(0, log(1 + x)).series(x, n=3) == const\ + - x/pi + x**2*(-log(x)/(2*pi) + (2 - 2*S.EulerGamma)/(4*pi)\ + + log(2)/(2*pi) + 5/(12*pi)) + O(x**3*log(x)) + assert bessely(1, sin(x)).series(x, n=4) == -1/(pi*(-x**3/12 + x/2)) - \ + (1 - 2*S.EulerGamma)*(-x**3/12 + x/2)/pi + x*(log(x)/pi - log(2)/pi) + \ + x**3*(-7*log(x)/(24*pi) - 1/(6*pi) + (S(5)/2 - 2*S.EulerGamma)/(16*pi) + + 7*log(2)/(24*pi)) + O(x**4*log(x)) + assert bessely(1, 2*sqrt(x)).series(x, n=3) == -1/(pi*sqrt(x)) + \ + sqrt(x)*(log(x)/pi - (1 - 2*S.EulerGamma)/pi) + x**(S(3)/2)*(-log(x)/(2*pi) + \ + (S(5)/2 - 2*S.EulerGamma)/(2*pi)) + x**(S(5)/2)*(log(x)/(12*pi) - \ + (S(10)/3 - 2*S.EulerGamma)/(12*pi)) + O(x**3*log(x)) + assert bessely(-2, sin(x)).series(x, n=4) == bessely(2, sin(x)).series(x, n=4) + + +def test_besseli_series(): + assert besseli(0, x).series(x) == 1 + x**2/4 + x**4/64 + O(x**6) + assert besseli(0, x**(1.1)).series(x) == 1 + x**4.4/64 + x**2.2/4 + O(x**6) + assert besseli(0, x**2 + x).series(x) == 1 + x**2/4 + x**3/2 + 17*x**4/64 + \ + x**5/16 + O(x**6) + assert besseli(0, sqrt(x) + x).series(x, n=4) == 1 + x/4 + 17*x**2/64 + \ + 217*x**3/2304 + x**(S(3)/2)/2 + x**(S(5)/2)/16 + 25*x**(S(7)/2)/384 + O(x**4) + assert besseli(0, x/(1 - x)).series(x) == 1 + x**2/4 + x**3/2 + 49*x**4/64 + \ + 17*x**5/16 + O(x**6) + assert besseli(0, log(1 + x)).series(x) == 1 + x**2/4 - x**3/4 + 47*x**4/192 - \ + 23*x**5/96 + O(x**6) + assert besseli(1, sin(x)).series(x) == x/2 - x**3/48 - 47*x**5/1920 + O(x**6) + assert besseli(1, 2*sqrt(x)).series(x) == sqrt(x) + x**(S(3)/2)/2 + x**(S(5)/2)/12 + \ + x**(S(7)/2)/144 + x**(S(9)/2)/2880 + x**(S(11)/2)/86400 + O(x**6) + assert besseli(-2, sin(x)).series(x, n=4) == besseli(2, sin(x)).series(x, n=4) + + #test for aseries + assert besseli(0,x).series(x, oo, n=4) == sqrt(2)*(sqrt(1/x) - (1/x)**(S(3)/2)/8 - \ + 3*(1/x)**(S(5)/2)/128 - 15*(1/x)**(S(7)/2)/1024 + O((1/x)**(S(9)/2), (x, oo)))*exp(x)/(2*sqrt(pi)) + assert besseli(0,x).series(x,-oo, n=4) == sqrt(2)*(sqrt(-1/x) - (-1/x)**(S(3)/2)/8 - 3*(-1/x)**(S(5)/2)/128 - \ + 15*(-1/x)**(S(7)/2)/1024 + O((-1/x)**(S(9)/2), (x, -oo)))*exp(-x)/(2*sqrt(pi)) + + +def test_besselk_series(): + const = log(2) - S.EulerGamma - log(x) + assert besselk(0, x).series(x, n=4) == const + \ + x**2*(-log(x)/4 - S.EulerGamma/4 + log(2)/4 + S(1)/4) + O(x**4*log(x)) + assert besselk(1, x).series(x, n=4) == 1/x + x*(log(x)/2 - log(2)/2 - \ + S(1)/4 + S.EulerGamma/2) + x**3*(log(x)/16 - S(5)/64 - log(2)/16 + \ + S.EulerGamma/16) + O(x**4*log(x)) + assert besselk(2, x).series(x, n=4) == 2/x**2 - S(1)/2 + x**2*(-log(x)/8 - \ + S.EulerGamma/8 + log(2)/8 + S(3)/32) + O(x**4*log(x)) + assert besselk(2, x).series(x, n=1) == 2/x**2 - S(1)/2 + O(x) #edge case for series truncation + assert besselk(0, x**(1.1)).series(x, n=4) == log(2) - S.EulerGamma - \ + 1.1*log(x) + x**2.2*(-0.275*log(x) - S.EulerGamma/4 + \ + log(2)/4 + S(1)/4) + O(x**4*log(x)) + assert besselk(0, x**2 + x).series(x, n=4) == const + \ + (2 - 2*S.EulerGamma)*(x**3/4 + x**2/8) - x + x**2*(-log(x)/4 + \ + log(2)/4 + S(1)/2) + x**3*(-log(x)/2 - S(7)/12 + log(2)/2) + O(x**4*log(x)) + assert besselk(0, x/(1 - x)).series(x, n=3) == const - x + x**2*(-log(x)/4 - \ + S(1)/4 - S.EulerGamma/4 + log(2)/4) + O(x**3*log(x)) + assert besselk(0, log(1 + x)).series(x, n=3) == const + x/2 + \ + x**2*(-log(x)/4 - S.EulerGamma/4 + S(1)/24 + log(2)/4) + O(x**3*log(x)) + assert besselk(1, 2*sqrt(x)).series(x, n=3) == 1/(2*sqrt(x)) + \ + sqrt(x)*(log(x)/2 - S(1)/2 + S.EulerGamma) + x**(S(3)/2)*(log(x)/4 - S(5)/8 + \ + S.EulerGamma/2) + x**(S(5)/2)*(log(x)/24 - S(5)/36 + S.EulerGamma/12) + O(x**3*log(x)) + assert besselk(-2, sin(x)).series(x, n=4) == besselk(2, sin(x)).series(x, n=4) + assert besselk(2, x**2).series(x, n=2) == 2/x**4 - S(1)/2 + O(x**2) #edge case for series truncation + assert besselk(2, x**2).series(x, n=6) == 2/x**4 - S(1)/2 + x**4*(-log(x)/4 - S.EulerGamma/8 + log(2)/8 + S(3)/32) + O(x**6*log(x)) + assert (x**2*besselk(2, x)).series(x, n=2) == 2 + O(x**2) + + #test for aseries + assert besselk(0,x).series(x, oo, n=4) == sqrt(2)*sqrt(pi)*(sqrt(1/x) + (1/x)**(S(3)/2)/8 - \ + 3*(1/x)**(S(5)/2)/128 + 15*(1/x)**(S(7)/2)/1024 + O((1/x)**(S(9)/2), (x, oo)))*exp(-x)/2 + assert besselk(0,x).series(x, -oo, n=4) == sqrt(2)*sqrt(pi)*(-I*sqrt(-1/x) + I*(-1/x)**(S(3)/2)/8 + \ + 3*I*(-1/x)**(S(5)/2)/128 + 15*I*(-1/x)**(S(7)/2)/1024 + O((-1/x)**(S(9)/2), (x, -oo)))*exp(-x)/2 + + +def test_besselk_frac_order_series(): + assert besselk(S(5)/3, x).series(x, n=2) == 2**(S(2)/3)*gamma(S(5)/3)/x**(S(5)/3) - \ + 3*gamma(S(5)/3)*x**(S(1)/3)/(4*2**(S(1)/3)) + \ + gamma(-S(5)/3)*x**(S(5)/3)/(4*2**(S(2)/3)) + O(x**2) + assert besselk(S(1)/2, x).series(x, n=2) == sqrt(pi/2)/sqrt(x) - \ + sqrt(pi*x/2) + x**(S(3)/2)*sqrt(pi/2)/2 + O(x**2) + assert besselk(S(1)/2, sqrt(x)).series(x, n=2) == sqrt(pi/2)/x**(S(1)/4) - \ + sqrt(pi/2)*x**(S(1)/4) + sqrt(pi/2)*x**(S(3)/4)/2 - \ + sqrt(pi/2)*x**(S(5)/4)/6 + sqrt(pi/2)*x**(S(7)/4)/24 + O(x**2) + assert besselk(S(1)/2, x**2).series(x, n=2) == sqrt(pi/2)/x \ + - sqrt(pi/2)*x + O(x**2) + assert besselk(-S(1)/2, x).series(x) == besselk(S(1)/2, x).series(x) + assert besselk(-S(7)/6, x).series(x) == besselk(S(7)/6, x).series(x) + + +def test_diff(): + assert besselj(n, z).diff(z) == besselj(n - 1, z)/2 - besselj(n + 1, z)/2 + assert bessely(n, z).diff(z) == bessely(n - 1, z)/2 - bessely(n + 1, z)/2 + assert besseli(n, z).diff(z) == besseli(n - 1, z)/2 + besseli(n + 1, z)/2 + assert besselk(n, z).diff(z) == -besselk(n - 1, z)/2 - besselk(n + 1, z)/2 + assert hankel1(n, z).diff(z) == hankel1(n - 1, z)/2 - hankel1(n + 1, z)/2 + assert hankel2(n, z).diff(z) == hankel2(n - 1, z)/2 - hankel2(n + 1, z)/2 + + +def test_rewrite(): + assert besselj(n, z).rewrite(jn) == sqrt(2*z/pi)*jn(n - S.Half, z) + assert bessely(n, z).rewrite(yn) == sqrt(2*z/pi)*yn(n - S.Half, z) + assert besseli(n, z).rewrite(besselj) == \ + exp(-I*n*pi/2)*besselj(n, polar_lift(I)*z) + assert besselj(n, z).rewrite(besseli) == \ + exp(I*n*pi/2)*besseli(n, polar_lift(-I)*z) + + nu = randcplx() + + assert tn(besselj(nu, z), besselj(nu, z).rewrite(besseli), z) + assert tn(besselj(nu, z), besselj(nu, z).rewrite(bessely), z) + + assert tn(besseli(nu, z), besseli(nu, z).rewrite(besselj), z) + assert tn(besseli(nu, z), besseli(nu, z).rewrite(bessely), z) + + assert tn(bessely(nu, z), bessely(nu, z).rewrite(besselj), z) + assert tn(bessely(nu, z), bessely(nu, z).rewrite(besseli), z) + + assert tn(besselk(nu, z), besselk(nu, z).rewrite(besselj), z) + assert tn(besselk(nu, z), besselk(nu, z).rewrite(besseli), z) + assert tn(besselk(nu, z), besselk(nu, z).rewrite(bessely), z) + + # check that a rewrite was triggered, when the order is set to a generic + # symbol 'nu' + assert yn(nu, z) != yn(nu, z).rewrite(jn) + assert hn1(nu, z) != hn1(nu, z).rewrite(jn) + assert hn2(nu, z) != hn2(nu, z).rewrite(jn) + assert jn(nu, z) != jn(nu, z).rewrite(yn) + assert hn1(nu, z) != hn1(nu, z).rewrite(yn) + assert hn2(nu, z) != hn2(nu, z).rewrite(yn) + + # rewriting spherical bessel functions (SBFs) w.r.t. besselj, bessely is + # not allowed if a generic symbol 'nu' is used as the order of the SBFs + # to avoid inconsistencies (the order of bessel[jy] is allowed to be + # complex-valued, whereas SBFs are defined only for integer orders) + order = nu + for f in (besselj, bessely): + assert hn1(order, z) == hn1(order, z).rewrite(f) + assert hn2(order, z) == hn2(order, z).rewrite(f) + + assert jn(order, z).rewrite(besselj) == sqrt(2)*sqrt(pi)*sqrt(1/z)*besselj(order + S.Half, z)/2 + assert jn(order, z).rewrite(bessely) == (-1)**nu*sqrt(2)*sqrt(pi)*sqrt(1/z)*bessely(-order - S.Half, z)/2 + + # for integral orders rewriting SBFs w.r.t bessel[jy] is allowed + N = Symbol('n', integer=True) + ri = randint(-11, 10) + for order in (ri, N): + for f in (besselj, bessely): + assert yn(order, z) != yn(order, z).rewrite(f) + assert jn(order, z) != jn(order, z).rewrite(f) + assert hn1(order, z) != hn1(order, z).rewrite(f) + assert hn2(order, z) != hn2(order, z).rewrite(f) + + for func, refunc in product((yn, jn, hn1, hn2), + (jn, yn, besselj, bessely)): + assert tn(func(ri, z), func(ri, z).rewrite(refunc), z) + + +def test_expand(): + assert expand_func(besselj(S.Half, z).rewrite(jn)) == \ + sqrt(2)*sin(z)/(sqrt(pi)*sqrt(z)) + assert expand_func(bessely(S.Half, z).rewrite(yn)) == \ + -sqrt(2)*cos(z)/(sqrt(pi)*sqrt(z)) + + # XXX: teach sin/cos to work around arguments like + # x*exp_polar(I*pi*n/2). Then change besselsimp -> expand_func + assert besselsimp(besselj(S.Half, z)) == sqrt(2)*sin(z)/(sqrt(pi)*sqrt(z)) + assert besselsimp(besselj(Rational(-1, 2), z)) == sqrt(2)*cos(z)/(sqrt(pi)*sqrt(z)) + assert besselsimp(besselj(Rational(5, 2), z)) == \ + -sqrt(2)*(z**2*sin(z) + 3*z*cos(z) - 3*sin(z))/(sqrt(pi)*z**Rational(5, 2)) + assert besselsimp(besselj(Rational(-5, 2), z)) == \ + -sqrt(2)*(z**2*cos(z) - 3*z*sin(z) - 3*cos(z))/(sqrt(pi)*z**Rational(5, 2)) + + assert besselsimp(bessely(S.Half, z)) == \ + -(sqrt(2)*cos(z))/(sqrt(pi)*sqrt(z)) + assert besselsimp(bessely(Rational(-1, 2), z)) == sqrt(2)*sin(z)/(sqrt(pi)*sqrt(z)) + assert besselsimp(bessely(Rational(5, 2), z)) == \ + sqrt(2)*(z**2*cos(z) - 3*z*sin(z) - 3*cos(z))/(sqrt(pi)*z**Rational(5, 2)) + assert besselsimp(bessely(Rational(-5, 2), z)) == \ + -sqrt(2)*(z**2*sin(z) + 3*z*cos(z) - 3*sin(z))/(sqrt(pi)*z**Rational(5, 2)) + + assert besselsimp(besseli(S.Half, z)) == sqrt(2)*sinh(z)/(sqrt(pi)*sqrt(z)) + assert besselsimp(besseli(Rational(-1, 2), z)) == \ + sqrt(2)*cosh(z)/(sqrt(pi)*sqrt(z)) + assert besselsimp(besseli(Rational(5, 2), z)) == \ + sqrt(2)*(z**2*sinh(z) - 3*z*cosh(z) + 3*sinh(z))/(sqrt(pi)*z**Rational(5, 2)) + assert besselsimp(besseli(Rational(-5, 2), z)) == \ + sqrt(2)*(z**2*cosh(z) - 3*z*sinh(z) + 3*cosh(z))/(sqrt(pi)*z**Rational(5, 2)) + + assert besselsimp(besselk(S.Half, z)) == \ + besselsimp(besselk(Rational(-1, 2), z)) == sqrt(pi)*exp(-z)/(sqrt(2)*sqrt(z)) + assert besselsimp(besselk(Rational(5, 2), z)) == \ + besselsimp(besselk(Rational(-5, 2), z)) == \ + sqrt(2)*sqrt(pi)*(z**2 + 3*z + 3)*exp(-z)/(2*z**Rational(5, 2)) + + n = Symbol('n', integer=True, positive=True) + + assert expand_func(besseli(n + 2, z)) == \ + besseli(n, z) + (-2*n - 2)*(-2*n*besseli(n, z)/z + besseli(n - 1, z))/z + assert expand_func(besselj(n + 2, z)) == \ + -besselj(n, z) + (2*n + 2)*(2*n*besselj(n, z)/z - besselj(n - 1, z))/z + assert expand_func(besselk(n + 2, z)) == \ + besselk(n, z) + (2*n + 2)*(2*n*besselk(n, z)/z + besselk(n - 1, z))/z + assert expand_func(bessely(n + 2, z)) == \ + -bessely(n, z) + (2*n + 2)*(2*n*bessely(n, z)/z - bessely(n - 1, z))/z + + assert expand_func(besseli(n + S.Half, z).rewrite(jn)) == \ + (sqrt(2)*sqrt(z)*exp(-I*pi*(n + S.Half)/2) * + exp_polar(I*pi/4)*jn(n, z*exp_polar(I*pi/2))/sqrt(pi)) + assert expand_func(besselj(n + S.Half, z).rewrite(jn)) == \ + sqrt(2)*sqrt(z)*jn(n, z)/sqrt(pi) + + r = Symbol('r', real=True) + p = Symbol('p', positive=True) + i = Symbol('i', integer=True) + + for besselx in [besselj, bessely, besseli, besselk]: + assert besselx(i, p).is_extended_real is True + assert besselx(i, x).is_extended_real is None + assert besselx(x, z).is_extended_real is None + + for besselx in [besselj, besseli]: + assert besselx(i, r).is_extended_real is True + for besselx in [bessely, besselk]: + assert besselx(i, r).is_extended_real is None + + for besselx in [besselj, bessely, besseli, besselk]: + assert expand_func(besselx(oo, x)) == besselx(oo, x, evaluate=False) + assert expand_func(besselx(-oo, x)) == besselx(-oo, x, evaluate=False) + + +# Quite varying time, but often really slow +@slow +def test_slow_expand(): + def check(eq, ans): + return tn(eq, ans) and eq == ans + + rn = randcplx(a=1, b=0, d=0, c=2) + + for besselx in [besselj, bessely, besseli, besselk]: + ri = S(2*randint(-11, 10) + 1) / 2 # half integer in [-21/2, 21/2] + assert tn(besselsimp(besselx(ri, z)), besselx(ri, z)) + + assert check(expand_func(besseli(rn, x)), + besseli(rn - 2, x) - 2*(rn - 1)*besseli(rn - 1, x)/x) + assert check(expand_func(besseli(-rn, x)), + besseli(-rn + 2, x) + 2*(-rn + 1)*besseli(-rn + 1, x)/x) + + assert check(expand_func(besselj(rn, x)), + -besselj(rn - 2, x) + 2*(rn - 1)*besselj(rn - 1, x)/x) + assert check(expand_func(besselj(-rn, x)), + -besselj(-rn + 2, x) + 2*(-rn + 1)*besselj(-rn + 1, x)/x) + + assert check(expand_func(besselk(rn, x)), + besselk(rn - 2, x) + 2*(rn - 1)*besselk(rn - 1, x)/x) + assert check(expand_func(besselk(-rn, x)), + besselk(-rn + 2, x) - 2*(-rn + 1)*besselk(-rn + 1, x)/x) + + assert check(expand_func(bessely(rn, x)), + -bessely(rn - 2, x) + 2*(rn - 1)*bessely(rn - 1, x)/x) + assert check(expand_func(bessely(-rn, x)), + -bessely(-rn + 2, x) + 2*(-rn + 1)*bessely(-rn + 1, x)/x) + + +def mjn(n, z): + return expand_func(jn(n, z)) + + +def myn(n, z): + return expand_func(yn(n, z)) + + +def test_jn(): + z = symbols("z") + assert jn(0, 0) == 1 + assert jn(1, 0) == 0 + assert jn(-1, 0) == S.ComplexInfinity + assert jn(z, 0) == jn(z, 0, evaluate=False) + assert jn(0, oo) == 0 + assert jn(0, -oo) == 0 + + assert mjn(0, z) == sin(z)/z + assert mjn(1, z) == sin(z)/z**2 - cos(z)/z + assert mjn(2, z) == (3/z**3 - 1/z)*sin(z) - (3/z**2) * cos(z) + assert mjn(3, z) == (15/z**4 - 6/z**2)*sin(z) + (1/z - 15/z**3)*cos(z) + assert mjn(4, z) == (1/z + 105/z**5 - 45/z**3)*sin(z) + \ + (-105/z**4 + 10/z**2)*cos(z) + assert mjn(5, z) == (945/z**6 - 420/z**4 + 15/z**2)*sin(z) + \ + (-1/z - 945/z**5 + 105/z**3)*cos(z) + assert mjn(6, z) == (-1/z + 10395/z**7 - 4725/z**5 + 210/z**3)*sin(z) + \ + (-10395/z**6 + 1260/z**4 - 21/z**2)*cos(z) + + assert expand_func(jn(n, z)) == jn(n, z) + + # SBFs not defined for complex-valued orders + assert jn(2+3j, 5.2+0.3j).evalf() == jn(2+3j, 5.2+0.3j) + + assert eq([jn(2, 5.2+0.3j).evalf(10)], + [0.09941975672 - 0.05452508024*I]) + + +def test_yn(): + z = symbols("z") + assert myn(0, z) == -cos(z)/z + assert myn(1, z) == -cos(z)/z**2 - sin(z)/z + assert myn(2, z) == -((3/z**3 - 1/z)*cos(z) + (3/z**2)*sin(z)) + assert expand_func(yn(n, z)) == yn(n, z) + + # SBFs not defined for complex-valued orders + assert yn(2+3j, 5.2+0.3j).evalf() == yn(2+3j, 5.2+0.3j) + + assert eq([yn(2, 5.2+0.3j).evalf(10)], + [0.185250342 + 0.01489557397*I]) + + +def test_sympify_yn(): + assert S(15) in myn(3, pi).atoms() + assert myn(3, pi) == 15/pi**4 - 6/pi**2 + + +def eq(a, b, tol=1e-6): + for u, v in zip(a, b): + if not (abs(u - v) < tol): + return False + return True + + +def test_jn_zeros(): + assert eq(jn_zeros(0, 4), [3.141592, 6.283185, 9.424777, 12.566370]) + assert eq(jn_zeros(1, 4), [4.493409, 7.725251, 10.904121, 14.066193]) + assert eq(jn_zeros(2, 4), [5.763459, 9.095011, 12.322940, 15.514603]) + assert eq(jn_zeros(3, 4), [6.987932, 10.417118, 13.698023, 16.923621]) + assert eq(jn_zeros(4, 4), [8.182561, 11.704907, 15.039664, 18.301255]) + + +def test_bessel_eval(): + n, m, k = Symbol('n', integer=True), Symbol('m'), Symbol('k', integer=True, zero=False) + + for f in [besselj, besseli]: + assert f(0, 0) is S.One + assert f(2.1, 0) is S.Zero + assert f(-3, 0) is S.Zero + assert f(-10.2, 0) is S.ComplexInfinity + assert f(1 + 3*I, 0) is S.Zero + assert f(-3 + I, 0) is S.ComplexInfinity + assert f(-2*I, 0) is S.NaN + assert f(n, 0) != S.One and f(n, 0) != S.Zero + assert f(m, 0) != S.One and f(m, 0) != S.Zero + assert f(k, 0) is S.Zero + + assert bessely(0, 0) is S.NegativeInfinity + assert besselk(0, 0) is S.Infinity + for f in [bessely, besselk]: + assert f(1 + I, 0) is S.ComplexInfinity + assert f(I, 0) is S.NaN + + for f in [besselj, bessely]: + assert f(m, S.Infinity) is S.Zero + assert f(m, S.NegativeInfinity) is S.Zero + + for f in [besseli, besselk]: + assert f(m, I*S.Infinity) is S.Zero + assert f(m, I*S.NegativeInfinity) is S.Zero + + for f in [besseli, besselk]: + assert f(-4, z) == f(4, z) + assert f(-3, z) == f(3, z) + assert f(-n, z) == f(n, z) + assert f(-m, z) != f(m, z) + + for f in [besselj, bessely]: + assert f(-4, z) == f(4, z) + assert f(-3, z) == -f(3, z) + assert f(-n, z) == (-1)**n*f(n, z) + assert f(-m, z) != (-1)**m*f(m, z) + + for f in [besselj, besseli]: + assert f(m, -z) == (-z)**m*z**(-m)*f(m, z) + + assert besseli(2, -z) == besseli(2, z) + assert besseli(3, -z) == -besseli(3, z) + + assert besselj(0, -z) == besselj(0, z) + assert besselj(1, -z) == -besselj(1, z) + + assert besseli(0, I*z) == besselj(0, z) + assert besseli(1, I*z) == I*besselj(1, z) + assert besselj(3, I*z) == -I*besseli(3, z) + + +def test_bessel_nan(): + # FIXME: could have these return NaN; for now just fix infinite recursion + for f in [besselj, bessely, besseli, besselk, hankel1, hankel2, yn, jn]: + assert f(1, S.NaN) == f(1, S.NaN, evaluate=False) + + +def test_meromorphic(): + assert besselj(2, x).is_meromorphic(x, 1) == True + assert besselj(2, x).is_meromorphic(x, 0) == True + assert besselj(2, x).is_meromorphic(x, oo) == False + assert besselj(S(2)/3, x).is_meromorphic(x, 1) == True + assert besselj(S(2)/3, x).is_meromorphic(x, 0) == False + assert besselj(S(2)/3, x).is_meromorphic(x, oo) == False + assert besselj(x, 2*x).is_meromorphic(x, 2) == False + assert besselk(0, x).is_meromorphic(x, 1) == True + assert besselk(2, x).is_meromorphic(x, 0) == True + assert besseli(0, x).is_meromorphic(x, 1) == True + assert besseli(2, x).is_meromorphic(x, 0) == True + assert bessely(0, x).is_meromorphic(x, 1) == True + assert bessely(0, x).is_meromorphic(x, 0) == False + assert bessely(2, x).is_meromorphic(x, 0) == True + assert hankel1(3, x**2 + 2*x).is_meromorphic(x, 1) == True + assert hankel1(0, x).is_meromorphic(x, 0) == False + assert hankel2(11, 4).is_meromorphic(x, 5) == True + assert hn1(6, 7*x**3 + 4).is_meromorphic(x, 7) == True + assert hn2(3, 2*x).is_meromorphic(x, 9) == True + assert jn(5, 2*x + 7).is_meromorphic(x, 4) == True + assert yn(8, x**2 + 11).is_meromorphic(x, 6) == True + + +def test_conjugate(): + n = Symbol('n') + z = Symbol('z', extended_real=False) + x = Symbol('x', extended_real=True) + y = Symbol('y', positive=True) + t = Symbol('t', negative=True) + + for f in [besseli, besselj, besselk, bessely, hankel1, hankel2]: + assert f(n, -1).conjugate() != f(conjugate(n), -1) + assert f(n, x).conjugate() != f(conjugate(n), x) + assert f(n, t).conjugate() != f(conjugate(n), t) + + rz = randcplx(b=0.5) + + for f in [besseli, besselj, besselk, bessely]: + assert f(n, 1 + I).conjugate() == f(conjugate(n), 1 - I) + assert f(n, 0).conjugate() == f(conjugate(n), 0) + assert f(n, 1).conjugate() == f(conjugate(n), 1) + assert f(n, z).conjugate() == f(conjugate(n), conjugate(z)) + assert f(n, y).conjugate() == f(conjugate(n), y) + assert tn(f(n, rz).conjugate(), f(conjugate(n), conjugate(rz))) + + assert hankel1(n, 1 + I).conjugate() == hankel2(conjugate(n), 1 - I) + assert hankel1(n, 0).conjugate() == hankel2(conjugate(n), 0) + assert hankel1(n, 1).conjugate() == hankel2(conjugate(n), 1) + assert hankel1(n, y).conjugate() == hankel2(conjugate(n), y) + assert hankel1(n, z).conjugate() == hankel2(conjugate(n), conjugate(z)) + assert tn(hankel1(n, rz).conjugate(), hankel2(conjugate(n), conjugate(rz))) + + assert hankel2(n, 1 + I).conjugate() == hankel1(conjugate(n), 1 - I) + assert hankel2(n, 0).conjugate() == hankel1(conjugate(n), 0) + assert hankel2(n, 1).conjugate() == hankel1(conjugate(n), 1) + assert hankel2(n, y).conjugate() == hankel1(conjugate(n), y) + assert hankel2(n, z).conjugate() == hankel1(conjugate(n), conjugate(z)) + assert tn(hankel2(n, rz).conjugate(), hankel1(conjugate(n), conjugate(rz))) + + +def test_branching(): + assert besselj(polar_lift(k), x) == besselj(k, x) + assert besseli(polar_lift(k), x) == besseli(k, x) + + n = Symbol('n', integer=True) + assert besselj(n, exp_polar(2*pi*I)*x) == besselj(n, x) + assert besselj(n, polar_lift(x)) == besselj(n, x) + assert besseli(n, exp_polar(2*pi*I)*x) == besseli(n, x) + assert besseli(n, polar_lift(x)) == besseli(n, x) + + def tn(func, s): + from sympy.core.random import uniform + c = uniform(1, 5) + expr = func(s, c*exp_polar(I*pi)) - func(s, c*exp_polar(-I*pi)) + eps = 1e-15 + expr2 = func(s + eps, -c + eps*I) - func(s + eps, -c - eps*I) + return abs(expr.n() - expr2.n()).n() < 1e-10 + + nu = Symbol('nu') + assert besselj(nu, exp_polar(2*pi*I)*x) == exp(2*pi*I*nu)*besselj(nu, x) + assert besseli(nu, exp_polar(2*pi*I)*x) == exp(2*pi*I*nu)*besseli(nu, x) + assert tn(besselj, 2) + assert tn(besselj, pi) + assert tn(besselj, I) + assert tn(besseli, 2) + assert tn(besseli, pi) + assert tn(besseli, I) + + +def test_airy_base(): + z = Symbol('z') + x = Symbol('x', real=True) + y = Symbol('y', real=True) + + assert conjugate(airyai(z)) == airyai(conjugate(z)) + assert airyai(x).is_extended_real + + assert airyai(x+I*y).as_real_imag() == ( + airyai(x - I*y)/2 + airyai(x + I*y)/2, + I*(airyai(x - I*y) - airyai(x + I*y))/2) + + +def test_airyai(): + z = Symbol('z', real=False) + t = Symbol('t', negative=True) + p = Symbol('p', positive=True) + + assert isinstance(airyai(z), airyai) + + assert airyai(0) == 3**Rational(1, 3)/(3*gamma(Rational(2, 3))) + assert airyai(oo) == 0 + assert airyai(-oo) == 0 + + assert diff(airyai(z), z) == airyaiprime(z) + + assert series(airyai(z), z, 0, 3) == ( + 3**Rational(5, 6)*gamma(Rational(1, 3))/(6*pi) - 3**Rational(1, 6)*z*gamma(Rational(2, 3))/(2*pi) + O(z**3)) + + assert airyai(z).rewrite(hyper) == ( + -3**Rational(2, 3)*z*hyper((), (Rational(4, 3),), z**3/9)/(3*gamma(Rational(1, 3))) + + 3**Rational(1, 3)*hyper((), (Rational(2, 3),), z**3/9)/(3*gamma(Rational(2, 3)))) + + assert isinstance(airyai(z).rewrite(besselj), airyai) + assert airyai(t).rewrite(besselj) == ( + sqrt(-t)*(besselj(Rational(-1, 3), 2*(-t)**Rational(3, 2)/3) + + besselj(Rational(1, 3), 2*(-t)**Rational(3, 2)/3))/3) + assert airyai(z).rewrite(besseli) == ( + -z*besseli(Rational(1, 3), 2*z**Rational(3, 2)/3)/(3*(z**Rational(3, 2))**Rational(1, 3)) + + (z**Rational(3, 2))**Rational(1, 3)*besseli(Rational(-1, 3), 2*z**Rational(3, 2)/3)/3) + assert airyai(p).rewrite(besseli) == ( + sqrt(p)*(besseli(Rational(-1, 3), 2*p**Rational(3, 2)/3) - + besseli(Rational(1, 3), 2*p**Rational(3, 2)/3))/3) + + assert expand_func(airyai(2*(3*z**5)**Rational(1, 3))) == ( + -sqrt(3)*(-1 + (z**5)**Rational(1, 3)/z**Rational(5, 3))*airybi(2*3**Rational(1, 3)*z**Rational(5, 3))/6 + + (1 + (z**5)**Rational(1, 3)/z**Rational(5, 3))*airyai(2*3**Rational(1, 3)*z**Rational(5, 3))/2) + + +def test_airybi(): + z = Symbol('z', real=False) + t = Symbol('t', negative=True) + p = Symbol('p', positive=True) + + assert isinstance(airybi(z), airybi) + + assert airybi(0) == 3**Rational(5, 6)/(3*gamma(Rational(2, 3))) + assert airybi(oo) is oo + assert airybi(-oo) == 0 + + assert diff(airybi(z), z) == airybiprime(z) + + assert series(airybi(z), z, 0, 3) == ( + 3**Rational(1, 3)*gamma(Rational(1, 3))/(2*pi) + 3**Rational(2, 3)*z*gamma(Rational(2, 3))/(2*pi) + O(z**3)) + + assert airybi(z).rewrite(hyper) == ( + 3**Rational(1, 6)*z*hyper((), (Rational(4, 3),), z**3/9)/gamma(Rational(1, 3)) + + 3**Rational(5, 6)*hyper((), (Rational(2, 3),), z**3/9)/(3*gamma(Rational(2, 3)))) + + assert isinstance(airybi(z).rewrite(besselj), airybi) + assert airyai(t).rewrite(besselj) == ( + sqrt(-t)*(besselj(Rational(-1, 3), 2*(-t)**Rational(3, 2)/3) + + besselj(Rational(1, 3), 2*(-t)**Rational(3, 2)/3))/3) + assert airybi(z).rewrite(besseli) == ( + sqrt(3)*(z*besseli(Rational(1, 3), 2*z**Rational(3, 2)/3)/(z**Rational(3, 2))**Rational(1, 3) + + (z**Rational(3, 2))**Rational(1, 3)*besseli(Rational(-1, 3), 2*z**Rational(3, 2)/3))/3) + assert airybi(p).rewrite(besseli) == ( + sqrt(3)*sqrt(p)*(besseli(Rational(-1, 3), 2*p**Rational(3, 2)/3) + + besseli(Rational(1, 3), 2*p**Rational(3, 2)/3))/3) + + assert expand_func(airybi(2*(3*z**5)**Rational(1, 3))) == ( + sqrt(3)*(1 - (z**5)**Rational(1, 3)/z**Rational(5, 3))*airyai(2*3**Rational(1, 3)*z**Rational(5, 3))/2 + + (1 + (z**5)**Rational(1, 3)/z**Rational(5, 3))*airybi(2*3**Rational(1, 3)*z**Rational(5, 3))/2) + + +def test_airyaiprime(): + z = Symbol('z', real=False) + t = Symbol('t', negative=True) + p = Symbol('p', positive=True) + + assert isinstance(airyaiprime(z), airyaiprime) + + assert airyaiprime(0) == -3**Rational(2, 3)/(3*gamma(Rational(1, 3))) + assert airyaiprime(oo) == 0 + + assert diff(airyaiprime(z), z) == z*airyai(z) + + assert series(airyaiprime(z), z, 0, 3) == ( + -3**Rational(2, 3)/(3*gamma(Rational(1, 3))) + 3**Rational(1, 3)*z**2/(6*gamma(Rational(2, 3))) + O(z**3)) + + assert airyaiprime(z).rewrite(hyper) == ( + 3**Rational(1, 3)*z**2*hyper((), (Rational(5, 3),), z**3/9)/(6*gamma(Rational(2, 3))) - + 3**Rational(2, 3)*hyper((), (Rational(1, 3),), z**3/9)/(3*gamma(Rational(1, 3)))) + + assert isinstance(airyaiprime(z).rewrite(besselj), airyaiprime) + assert airyai(t).rewrite(besselj) == ( + sqrt(-t)*(besselj(Rational(-1, 3), 2*(-t)**Rational(3, 2)/3) + + besselj(Rational(1, 3), 2*(-t)**Rational(3, 2)/3))/3) + assert airyaiprime(z).rewrite(besseli) == ( + z**2*besseli(Rational(2, 3), 2*z**Rational(3, 2)/3)/(3*(z**Rational(3, 2))**Rational(2, 3)) - + (z**Rational(3, 2))**Rational(2, 3)*besseli(Rational(-1, 3), 2*z**Rational(3, 2)/3)/3) + assert airyaiprime(p).rewrite(besseli) == ( + p*(-besseli(Rational(-2, 3), 2*p**Rational(3, 2)/3) + besseli(Rational(2, 3), 2*p**Rational(3, 2)/3))/3) + + assert expand_func(airyaiprime(2*(3*z**5)**Rational(1, 3))) == ( + sqrt(3)*(z**Rational(5, 3)/(z**5)**Rational(1, 3) - 1)*airybiprime(2*3**Rational(1, 3)*z**Rational(5, 3))/6 + + (z**Rational(5, 3)/(z**5)**Rational(1, 3) + 1)*airyaiprime(2*3**Rational(1, 3)*z**Rational(5, 3))/2) + + +def test_airybiprime(): + z = Symbol('z', real=False) + t = Symbol('t', negative=True) + p = Symbol('p', positive=True) + + assert isinstance(airybiprime(z), airybiprime) + + assert airybiprime(0) == 3**Rational(1, 6)/gamma(Rational(1, 3)) + assert airybiprime(oo) is oo + assert airybiprime(-oo) == 0 + + assert diff(airybiprime(z), z) == z*airybi(z) + + assert series(airybiprime(z), z, 0, 3) == ( + 3**Rational(1, 6)/gamma(Rational(1, 3)) + 3**Rational(5, 6)*z**2/(6*gamma(Rational(2, 3))) + O(z**3)) + + assert airybiprime(z).rewrite(hyper) == ( + 3**Rational(5, 6)*z**2*hyper((), (Rational(5, 3),), z**3/9)/(6*gamma(Rational(2, 3))) + + 3**Rational(1, 6)*hyper((), (Rational(1, 3),), z**3/9)/gamma(Rational(1, 3))) + + assert isinstance(airybiprime(z).rewrite(besselj), airybiprime) + assert airyai(t).rewrite(besselj) == ( + sqrt(-t)*(besselj(Rational(-1, 3), 2*(-t)**Rational(3, 2)/3) + + besselj(Rational(1, 3), 2*(-t)**Rational(3, 2)/3))/3) + assert airybiprime(z).rewrite(besseli) == ( + sqrt(3)*(z**2*besseli(Rational(2, 3), 2*z**Rational(3, 2)/3)/(z**Rational(3, 2))**Rational(2, 3) + + (z**Rational(3, 2))**Rational(2, 3)*besseli(Rational(-2, 3), 2*z**Rational(3, 2)/3))/3) + assert airybiprime(p).rewrite(besseli) == ( + sqrt(3)*p*(besseli(Rational(-2, 3), 2*p**Rational(3, 2)/3) + besseli(Rational(2, 3), 2*p**Rational(3, 2)/3))/3) + + assert expand_func(airybiprime(2*(3*z**5)**Rational(1, 3))) == ( + sqrt(3)*(z**Rational(5, 3)/(z**5)**Rational(1, 3) - 1)*airyaiprime(2*3**Rational(1, 3)*z**Rational(5, 3))/2 + + (z**Rational(5, 3)/(z**5)**Rational(1, 3) + 1)*airybiprime(2*3**Rational(1, 3)*z**Rational(5, 3))/2) + + +def test_marcumq(): + m = Symbol('m') + a = Symbol('a') + b = Symbol('b') + + assert marcumq(0, 0, 0) == 0 + assert marcumq(m, 0, b) == uppergamma(m, b**2/2)/gamma(m) + assert marcumq(2, 0, 5) == 27*exp(Rational(-25, 2))/2 + assert marcumq(0, a, 0) == 1 - exp(-a**2/2) + assert marcumq(0, pi, 0) == 1 - exp(-pi**2/2) + assert marcumq(1, a, a) == S.Half + exp(-a**2)*besseli(0, a**2)/2 + assert marcumq(2, a, a) == S.Half + exp(-a**2)*besseli(0, a**2)/2 + exp(-a**2)*besseli(1, a**2) + + assert diff(marcumq(1, a, 3), a) == a*(-marcumq(1, a, 3) + marcumq(2, a, 3)) + assert diff(marcumq(2, 3, b), b) == -b**2*exp(-b**2/2 - Rational(9, 2))*besseli(1, 3*b)/3 + + x = Symbol('x') + assert marcumq(2, 3, 4).rewrite(Integral, x=x) == \ + Integral(x**2*exp(-x**2/2 - Rational(9, 2))*besseli(1, 3*x), (x, 4, oo))/3 + assert eq([marcumq(5, -2, 3).rewrite(Integral).evalf(10)], + [0.7905769565]) + + k = Symbol('k') + assert marcumq(-3, -5, -7).rewrite(Sum, k=k) == \ + exp(-37)*Sum((Rational(5, 7))**k*besseli(k, 35), (k, 4, oo)) + assert eq([marcumq(1, 3, 1).rewrite(Sum).evalf(10)], + [0.9891705502]) + + assert marcumq(1, a, a, evaluate=False).rewrite(besseli) == S.Half + exp(-a**2)*besseli(0, a**2)/2 + assert marcumq(2, a, a, evaluate=False).rewrite(besseli) == S.Half + exp(-a**2)*besseli(0, a**2)/2 + \ + exp(-a**2)*besseli(1, a**2) + assert marcumq(3, a, a).rewrite(besseli) == (besseli(1, a**2) + besseli(2, a**2))*exp(-a**2) + \ + S.Half + exp(-a**2)*besseli(0, a**2)/2 + assert marcumq(5, 8, 8).rewrite(besseli) == exp(-64)*besseli(0, 64)/2 + \ + (besseli(4, 64) + besseli(3, 64) + besseli(2, 64) + besseli(1, 64))*exp(-64) + S.Half + assert marcumq(m, a, a).rewrite(besseli) == marcumq(m, a, a) + + x = Symbol('x', integer=True) + assert marcumq(x, a, a).rewrite(besseli) == marcumq(x, a, a) + + +def test_issue_26134(): + x = Symbol('x') + assert marcumq(2, 3, 4).rewrite(Integral, x=x).dummy_eq( + Integral(x**2*exp(-x**2/2 - Rational(9, 2))*besseli(1, 3*x), (x, 4, oo))/3) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_beta_functions.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_beta_functions.py new file mode 100644 index 0000000000000000000000000000000000000000..b34cb2febf9e2746d869cd878525d2794535aea5 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_beta_functions.py @@ -0,0 +1,89 @@ +from sympy.core.function import (diff, expand_func) +from sympy.core.numbers import I, Rational, pi +from sympy.core.singleton import S +from sympy.core.symbol import (Dummy, symbols) +from sympy.functions.combinatorial.numbers import catalan +from sympy.functions.elementary.complexes import conjugate +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.special.beta_functions import (beta, betainc, betainc_regularized) +from sympy.functions.special.gamma_functions import gamma, polygamma +from sympy.functions.special.hyper import hyper +from sympy.integrals.integrals import Integral +from sympy.core.function import ArgumentIndexError +from sympy.core.expr import unchanged +from sympy.testing.pytest import raises + + +def test_beta(): + x, y = symbols('x y') + t = Dummy('t') + + assert unchanged(beta, x, y) + assert unchanged(beta, x, x) + + assert beta(5, -3).is_real == True + assert beta(3, y).is_real is None + + assert expand_func(beta(x, y)) == gamma(x)*gamma(y)/gamma(x + y) + assert expand_func(beta(x, y) - beta(y, x)) == 0 # Symmetric + assert expand_func(beta(x, y)) == expand_func(beta(x, y + 1) + beta(x + 1, y)).simplify() + + assert diff(beta(x, y), x) == beta(x, y)*(polygamma(0, x) - polygamma(0, x + y)) + assert diff(beta(x, y), y) == beta(x, y)*(polygamma(0, y) - polygamma(0, x + y)) + + assert conjugate(beta(x, y)) == beta(conjugate(x), conjugate(y)) + + raises(ArgumentIndexError, lambda: beta(x, y).fdiff(3)) + + assert beta(x, y).rewrite(gamma) == gamma(x)*gamma(y)/gamma(x + y) + assert beta(x).rewrite(gamma) == gamma(x)**2/gamma(2*x) + assert beta(x, y).rewrite(Integral).dummy_eq(Integral(t**(x - 1) * (1 - t)**(y - 1), (t, 0, 1))) + assert beta(Rational(-19, 10), Rational(-1, 10)) == S.Zero + assert beta(Rational(-19, 10), Rational(-9, 10)) == \ + 800*2**(S(4)/5)*sqrt(pi)*gamma(S.One/10)/(171*gamma(-S(7)/5)) + assert beta(Rational(19, 10), Rational(29, 10)) == 100/(551*catalan(Rational(19, 10))) + assert beta(1, 0) == S.ComplexInfinity + assert beta(0, 1) == S.ComplexInfinity + assert beta(2, 3) == S.One/12 + assert unchanged(beta, x, x + 1) + assert unchanged(beta, x, 1) + assert unchanged(beta, 1, y) + assert beta(x, x + 1).doit() == 1/(x*(x+1)*catalan(x)) + assert beta(1, y).doit() == 1/y + assert beta(x, 1).doit() == 1/x + assert beta(Rational(-19, 10), Rational(-1, 10), evaluate=False).doit() == S.Zero + assert beta(2) == beta(2, 2) + assert beta(x, evaluate=False) != beta(x, x) + assert beta(x, evaluate=False).doit() == beta(x, x) + + +def test_betainc(): + a, b, x1, x2 = symbols('a b x1 x2') + + assert unchanged(betainc, a, b, x1, x2) + assert unchanged(betainc, a, b, 0, x1) + + assert betainc(1, 2, 0, -5).is_real == True + assert betainc(1, 2, 0, x2).is_real is None + assert conjugate(betainc(I, 2, 3 - I, 1 + 4*I)) == betainc(-I, 2, 3 + I, 1 - 4*I) + + assert betainc(a, b, 0, 1).rewrite(Integral).dummy_eq(beta(a, b).rewrite(Integral)) + assert betainc(1, 2, 0, x2).rewrite(hyper) == x2*hyper((1, -1), (2,), x2) + + assert betainc(1, 2, 3, 3).evalf() == 0 + + +def test_betainc_regularized(): + a, b, x1, x2 = symbols('a b x1 x2') + + assert unchanged(betainc_regularized, a, b, x1, x2) + assert unchanged(betainc_regularized, a, b, 0, x1) + + assert betainc_regularized(3, 5, 0, -1).is_real == True + assert betainc_regularized(3, 5, 0, x2).is_real is None + assert conjugate(betainc_regularized(3*I, 1, 2 + I, 1 + 2*I)) == betainc_regularized(-3*I, 1, 2 - I, 1 - 2*I) + + assert betainc_regularized(a, b, 0, 1).rewrite(Integral) == 1 + assert betainc_regularized(1, 2, x1, x2).rewrite(hyper) == 2*x2*hyper((1, -1), (2,), x2) - 2*x1*hyper((1, -1), (2,), x1) + + assert betainc_regularized(4, 1, 5, 5).evalf() == 0 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_bsplines.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_bsplines.py new file mode 100644 index 0000000000000000000000000000000000000000..136831b96ba16c95edba12ecd47b6f1566b68427 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_bsplines.py @@ -0,0 +1,167 @@ +from sympy.functions import bspline_basis_set, interpolating_spline +from sympy.core.numbers import Rational +from sympy.core.singleton import S +from sympy.core.symbol import symbols +from sympy.functions.elementary.piecewise import Piecewise +from sympy.logic.boolalg import And +from sympy.sets.sets import Interval +from sympy.testing.pytest import slow + +x, y = symbols('x,y') + + +def test_basic_degree_0(): + d = 0 + knots = range(5) + splines = bspline_basis_set(d, knots, x) + for i in range(len(splines)): + assert splines[i] == Piecewise((1, Interval(i, i + 1).contains(x)), + (0, True)) + + +def test_basic_degree_1(): + d = 1 + knots = range(5) + splines = bspline_basis_set(d, knots, x) + assert splines[0] == Piecewise((x, Interval(0, 1).contains(x)), + (2 - x, Interval(1, 2).contains(x)), + (0, True)) + assert splines[1] == Piecewise((-1 + x, Interval(1, 2).contains(x)), + (3 - x, Interval(2, 3).contains(x)), + (0, True)) + assert splines[2] == Piecewise((-2 + x, Interval(2, 3).contains(x)), + (4 - x, Interval(3, 4).contains(x)), + (0, True)) + + +def test_basic_degree_2(): + d = 2 + knots = range(5) + splines = bspline_basis_set(d, knots, x) + b0 = Piecewise((x**2/2, Interval(0, 1).contains(x)), + (Rational(-3, 2) + 3*x - x**2, Interval(1, 2).contains(x)), + (Rational(9, 2) - 3*x + x**2/2, Interval(2, 3).contains(x)), + (0, True)) + b1 = Piecewise((S.Half - x + x**2/2, Interval(1, 2).contains(x)), + (Rational(-11, 2) + 5*x - x**2, Interval(2, 3).contains(x)), + (8 - 4*x + x**2/2, Interval(3, 4).contains(x)), + (0, True)) + assert splines[0] == b0 + assert splines[1] == b1 + + +def test_basic_degree_3(): + d = 3 + knots = range(5) + splines = bspline_basis_set(d, knots, x) + b0 = Piecewise( + (x**3/6, Interval(0, 1).contains(x)), + (Rational(2, 3) - 2*x + 2*x**2 - x**3/2, Interval(1, 2).contains(x)), + (Rational(-22, 3) + 10*x - 4*x**2 + x**3/2, Interval(2, 3).contains(x)), + (Rational(32, 3) - 8*x + 2*x**2 - x**3/6, Interval(3, 4).contains(x)), + (0, True) + ) + assert splines[0] == b0 + + +def test_repeated_degree_1(): + d = 1 + knots = [0, 0, 1, 2, 2, 3, 4, 4] + splines = bspline_basis_set(d, knots, x) + assert splines[0] == Piecewise((1 - x, Interval(0, 1).contains(x)), + (0, True)) + assert splines[1] == Piecewise((x, Interval(0, 1).contains(x)), + (2 - x, Interval(1, 2).contains(x)), + (0, True)) + assert splines[2] == Piecewise((-1 + x, Interval(1, 2).contains(x)), + (0, True)) + assert splines[3] == Piecewise((3 - x, Interval(2, 3).contains(x)), + (0, True)) + assert splines[4] == Piecewise((-2 + x, Interval(2, 3).contains(x)), + (4 - x, Interval(3, 4).contains(x)), + (0, True)) + assert splines[5] == Piecewise((-3 + x, Interval(3, 4).contains(x)), + (0, True)) + + +def test_repeated_degree_2(): + d = 2 + knots = [0, 0, 1, 2, 2, 3, 4, 4] + splines = bspline_basis_set(d, knots, x) + + assert splines[0] == Piecewise(((-3*x**2/2 + 2*x), And(x <= 1, x >= 0)), + (x**2/2 - 2*x + 2, And(x <= 2, x >= 1)), + (0, True)) + assert splines[1] == Piecewise((x**2/2, And(x <= 1, x >= 0)), + (-3*x**2/2 + 4*x - 2, And(x <= 2, x >= 1)), + (0, True)) + assert splines[2] == Piecewise((x**2 - 2*x + 1, And(x <= 2, x >= 1)), + (x**2 - 6*x + 9, And(x <= 3, x >= 2)), + (0, True)) + assert splines[3] == Piecewise((-3*x**2/2 + 8*x - 10, And(x <= 3, x >= 2)), + (x**2/2 - 4*x + 8, And(x <= 4, x >= 3)), + (0, True)) + assert splines[4] == Piecewise((x**2/2 - 2*x + 2, And(x <= 3, x >= 2)), + (-3*x**2/2 + 10*x - 16, And(x <= 4, x >= 3)), + (0, True)) + +# Tests for interpolating_spline + + +def test_10_points_degree_1(): + d = 1 + X = [-5, 2, 3, 4, 7, 9, 10, 30, 31, 34] + Y = [-10, -2, 2, 4, 7, 6, 20, 45, 19, 25] + spline = interpolating_spline(d, x, X, Y) + + assert spline == Piecewise((x*Rational(8, 7) - Rational(30, 7), (x >= -5) & (x <= 2)), (4*x - 10, (x >= 2) & (x <= 3)), + (2*x - 4, (x >= 3) & (x <= 4)), (x, (x >= 4) & (x <= 7)), + (-x/2 + Rational(21, 2), (x >= 7) & (x <= 9)), (14*x - 120, (x >= 9) & (x <= 10)), + (x*Rational(5, 4) + Rational(15, 2), (x >= 10) & (x <= 30)), (-26*x + 825, (x >= 30) & (x <= 31)), + (2*x - 43, (x >= 31) & (x <= 34))) + + +def test_3_points_degree_2(): + d = 2 + X = [-3, 10, 19] + Y = [3, -4, 30] + spline = interpolating_spline(d, x, X, Y) + + assert spline == Piecewise((505*x**2/2574 - x*Rational(4921, 2574) - Rational(1931, 429), (x >= -3) & (x <= 19))) + + +def test_5_points_degree_2(): + d = 2 + X = [-3, 2, 4, 5, 10] + Y = [-1, 2, 5, 10, 14] + spline = interpolating_spline(d, x, X, Y) + + assert spline == Piecewise((4*x**2/329 + x*Rational(1007, 1645) + Rational(1196, 1645), (x >= -3) & (x <= 3)), + (2701*x**2/1645 - x*Rational(15079, 1645) + Rational(5065, 329), (x >= 3) & (x <= Rational(9, 2))), + (-1319*x**2/1645 + x*Rational(21101, 1645) - Rational(11216, 329), (x >= Rational(9, 2)) & (x <= 10))) + + +@slow +def test_6_points_degree_3(): + d = 3 + X = [-1, 0, 2, 3, 9, 12] + Y = [-4, 3, 3, 7, 9, 20] + spline = interpolating_spline(d, x, X, Y) + + assert spline == Piecewise((6058*x**3/5301 - 18427*x**2/5301 + x*Rational(12622, 5301) + 3, (x >= -1) & (x <= 2)), + (-8327*x**3/5301 + 67883*x**2/5301 - x*Rational(159998, 5301) + Rational(43661, 1767), (x >= 2) & (x <= 3)), + (5414*x**3/47709 - 1386*x**2/589 + x*Rational(4267, 279) - Rational(12232, 589), (x >= 3) & (x <= 12))) + + +def test_issue_19262(): + Delta = symbols('Delta', positive=True) + knots = [i*Delta for i in range(4)] + basis = bspline_basis_set(1, knots, x) + y = symbols('y', nonnegative=True) + basis2 = bspline_basis_set(1, knots, y) + assert basis[0].subs(x, y) == basis2[0] + assert interpolating_spline(1, x, + [Delta*i for i in [1, 2, 4, 7]], [3, 6, 5, 7] + ) == Piecewise((3*x/Delta, (Delta <= x) & (x <= 2*Delta)), + (7 - x/(2*Delta), (x >= 2*Delta) & (x <= 4*Delta)), + (Rational(7, 3) + 2*x/(3*Delta), (x >= 4*Delta) & (x <= 7*Delta))) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_delta_functions.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_delta_functions.py new file mode 100644 index 0000000000000000000000000000000000000000..d5a39d9e352143cf878cf69fa42f454f58be65c9 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_delta_functions.py @@ -0,0 +1,165 @@ +from sympy.core.numbers import (I, nan, oo, pi) +from sympy.core.relational import (Eq, Ne) +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.elementary.complexes import (adjoint, conjugate, sign, transpose) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.piecewise import Piecewise +from sympy.functions.special.delta_functions import (DiracDelta, Heaviside) +from sympy.functions.special.singularity_functions import SingularityFunction +from sympy.simplify.simplify import signsimp + + +from sympy.testing.pytest import raises + +from sympy.core.expr import unchanged + +from sympy.core.function import ArgumentIndexError + + +x, y = symbols('x y') +i = symbols('t', nonzero=True) +j = symbols('j', positive=True) +k = symbols('k', negative=True) + +def test_DiracDelta(): + assert DiracDelta(1) == 0 + assert DiracDelta(5.1) == 0 + assert DiracDelta(-pi) == 0 + assert DiracDelta(5, 7) == 0 + assert DiracDelta(x, 0) == DiracDelta(x) + assert DiracDelta(i) == 0 + assert DiracDelta(j) == 0 + assert DiracDelta(k) == 0 + assert DiracDelta(nan) is nan + assert DiracDelta(0).func is DiracDelta + assert DiracDelta(x).func is DiracDelta + # FIXME: this is generally undefined @ x=0 + # But then limit(Delta(c)*Heaviside(x),x,-oo) + # need's to be implemented. + # assert 0*DiracDelta(x) == 0 + + assert adjoint(DiracDelta(x)) == DiracDelta(x) + assert adjoint(DiracDelta(x - y)) == DiracDelta(x - y) + assert conjugate(DiracDelta(x)) == DiracDelta(x) + assert conjugate(DiracDelta(x - y)) == DiracDelta(x - y) + assert transpose(DiracDelta(x)) == DiracDelta(x) + assert transpose(DiracDelta(x - y)) == DiracDelta(x - y) + + assert DiracDelta(x).diff(x) == DiracDelta(x, 1) + assert DiracDelta(x, 1).diff(x) == DiracDelta(x, 2) + + assert DiracDelta(x).is_simple(x) is True + assert DiracDelta(3*x).is_simple(x) is True + assert DiracDelta(x**2).is_simple(x) is False + assert DiracDelta(sqrt(x)).is_simple(x) is False + assert DiracDelta(x).is_simple(y) is False + + assert DiracDelta(x*y).expand(diracdelta=True, wrt=x) == DiracDelta(x)/abs(y) + assert DiracDelta(x*y).expand(diracdelta=True, wrt=y) == DiracDelta(y)/abs(x) + assert DiracDelta(x**2*y).expand(diracdelta=True, wrt=x) == DiracDelta(x**2*y) + assert DiracDelta(y).expand(diracdelta=True, wrt=x) == DiracDelta(y) + assert DiracDelta((x - 1)*(x - 2)*(x - 3)).expand(diracdelta=True, wrt=x) == ( + DiracDelta(x - 3)/2 + DiracDelta(x - 2) + DiracDelta(x - 1)/2) + + assert DiracDelta(2*x) != DiracDelta(x) # scaling property + assert DiracDelta(x) == DiracDelta(-x) # even function + assert DiracDelta(-x, 2) == DiracDelta(x, 2) + assert DiracDelta(-x, 1) == -DiracDelta(x, 1) # odd deriv is odd + assert DiracDelta(-oo*x) == DiracDelta(oo*x) + assert DiracDelta(x - y) != DiracDelta(y - x) + assert signsimp(DiracDelta(x - y) - DiracDelta(y - x)) == 0 + + assert DiracDelta(x*y).expand(diracdelta=True, wrt=x) == DiracDelta(x)/abs(y) + assert DiracDelta(x*y).expand(diracdelta=True, wrt=y) == DiracDelta(y)/abs(x) + assert DiracDelta(x**2*y).expand(diracdelta=True, wrt=x) == DiracDelta(x**2*y) + assert DiracDelta(y).expand(diracdelta=True, wrt=x) == DiracDelta(y) + assert DiracDelta((x - 1)*(x - 2)*(x - 3)).expand(diracdelta=True) == ( + DiracDelta(x - 3)/2 + DiracDelta(x - 2) + DiracDelta(x - 1)/2) + + raises(ArgumentIndexError, lambda: DiracDelta(x).fdiff(2)) + raises(ValueError, lambda: DiracDelta(x, -1)) + raises(ValueError, lambda: DiracDelta(I)) + raises(ValueError, lambda: DiracDelta(2 + 3*I)) + + +def test_heaviside(): + assert Heaviside(-5) == 0 + assert Heaviside(1) == 1 + assert Heaviside(0) == S.Half + + assert Heaviside(0, x) == x + assert unchanged(Heaviside,x, nan) + assert Heaviside(0, nan) == nan + + h0 = Heaviside(x, 0) + h12 = Heaviside(x, S.Half) + h1 = Heaviside(x, 1) + + assert h0.args == h0.pargs == (x, 0) + assert h1.args == h1.pargs == (x, 1) + assert h12.args == (x, S.Half) + assert h12.pargs == (x,) # default 1/2 suppressed + + assert adjoint(Heaviside(x)) == Heaviside(x) + assert adjoint(Heaviside(x - y)) == Heaviside(x - y) + assert conjugate(Heaviside(x)) == Heaviside(x) + assert conjugate(Heaviside(x - y)) == Heaviside(x - y) + assert transpose(Heaviside(x)) == Heaviside(x) + assert transpose(Heaviside(x - y)) == Heaviside(x - y) + + assert Heaviside(x).diff(x) == DiracDelta(x) + assert Heaviside(x + I).is_Function is True + assert Heaviside(I*x).is_Function is True + + raises(ArgumentIndexError, lambda: Heaviside(x).fdiff(2)) + raises(ValueError, lambda: Heaviside(I)) + raises(ValueError, lambda: Heaviside(2 + 3*I)) + + +def test_rewrite(): + x, y = Symbol('x', real=True), Symbol('y') + assert Heaviside(x).rewrite(Piecewise) == ( + Piecewise((0, x < 0), (Heaviside(0), Eq(x, 0)), (1, True))) + assert Heaviside(y).rewrite(Piecewise) == ( + Piecewise((0, y < 0), (Heaviside(0), Eq(y, 0)), (1, True))) + assert Heaviside(x, y).rewrite(Piecewise) == ( + Piecewise((0, x < 0), (y, Eq(x, 0)), (1, True))) + assert Heaviside(x, 0).rewrite(Piecewise) == ( + Piecewise((0, x <= 0), (1, True))) + assert Heaviside(x, 1).rewrite(Piecewise) == ( + Piecewise((0, x < 0), (1, True))) + assert Heaviside(x, nan).rewrite(Piecewise) == ( + Piecewise((0, x < 0), (nan, Eq(x, 0)), (1, True))) + + assert Heaviside(x).rewrite(sign) == \ + Heaviside(x, H0=Heaviside(0)).rewrite(sign) == \ + Piecewise( + (sign(x)/2 + S(1)/2, Eq(Heaviside(0), S(1)/2)), + (Piecewise( + (sign(x)/2 + S(1)/2, Ne(x, 0)), (Heaviside(0), True)), True) + ) + + assert Heaviside(y).rewrite(sign) == Heaviside(y) + assert Heaviside(x, S.Half).rewrite(sign) == (sign(x)+1)/2 + assert Heaviside(x, y).rewrite(sign) == \ + Piecewise( + (sign(x)/2 + S(1)/2, Eq(y, S(1)/2)), + (Piecewise( + (sign(x)/2 + S(1)/2, Ne(x, 0)), (y, True)), True) + ) + + assert DiracDelta(y).rewrite(Piecewise) == Piecewise((DiracDelta(0), Eq(y, 0)), (0, True)) + assert DiracDelta(y, 1).rewrite(Piecewise) == DiracDelta(y, 1) + assert DiracDelta(x - 5).rewrite(Piecewise) == ( + Piecewise((DiracDelta(0), Eq(x - 5, 0)), (0, True))) + + assert (x*DiracDelta(x - 10)).rewrite(SingularityFunction) == x*SingularityFunction(x, 10, -1) + assert 5*x*y*DiracDelta(y, 1).rewrite(SingularityFunction) == 5*x*y*SingularityFunction(y, 0, -2) + assert DiracDelta(0).rewrite(SingularityFunction) == SingularityFunction(0, 0, -1) + assert DiracDelta(0, 1).rewrite(SingularityFunction) == SingularityFunction(0, 0, -2) + + assert Heaviside(x).rewrite(SingularityFunction) == SingularityFunction(x, 0, 0) + assert 5*x*y*Heaviside(y + 1).rewrite(SingularityFunction) == 5*x*y*SingularityFunction(y, -1, 0) + assert ((x - 3)**3*Heaviside(x - 3)).rewrite(SingularityFunction) == (x - 3)**3*SingularityFunction(x, 3, 0) + assert Heaviside(0).rewrite(SingularityFunction) == S.Half diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_elliptic_integrals.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_elliptic_integrals.py new file mode 100644 index 0000000000000000000000000000000000000000..a11e531af32301a00b6fc864064d02f9318929e1 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_elliptic_integrals.py @@ -0,0 +1,181 @@ +from sympy.core.numbers import (I, Rational, oo, pi, zoo) +from sympy.core.singleton import S +from sympy.core.symbol import (Dummy, Symbol) +from sympy.functions.elementary.hyperbolic import atanh +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (sin, tan) +from sympy.functions.special.gamma_functions import gamma +from sympy.functions.special.hyper import (hyper, meijerg) +from sympy.integrals.integrals import Integral +from sympy.series.order import O +from sympy.functions.special.elliptic_integrals import (elliptic_k as K, + elliptic_f as F, elliptic_e as E, elliptic_pi as P) +from sympy.core.random import (test_derivative_numerically as td, + random_complex_number as randcplx, + verify_numerically as tn) +from sympy.abc import z, m, n + +i = Symbol('i', integer=True) +j = Symbol('k', integer=True, positive=True) +t = Dummy('t') + +def test_K(): + assert K(0) == pi/2 + assert K(S.Half) == 8*pi**Rational(3, 2)/gamma(Rational(-1, 4))**2 + assert K(1) is zoo + assert K(-1) == gamma(Rational(1, 4))**2/(4*sqrt(2*pi)) + assert K(oo) == 0 + assert K(-oo) == 0 + assert K(I*oo) == 0 + assert K(-I*oo) == 0 + assert K(zoo) == 0 + + assert K(z).diff(z) == (E(z) - (1 - z)*K(z))/(2*z*(1 - z)) + assert td(K(z), z) + + zi = Symbol('z', real=False) + assert K(zi).conjugate() == K(zi.conjugate()) + zr = Symbol('z', negative=True) + assert K(zr).conjugate() == K(zr) + + assert K(z).rewrite(hyper) == \ + (pi/2)*hyper((S.Half, S.Half), (S.One,), z) + assert tn(K(z), (pi/2)*hyper((S.Half, S.Half), (S.One,), z)) + assert K(z).rewrite(meijerg) == \ + meijerg(((S.Half, S.Half), []), ((S.Zero,), (S.Zero,)), -z)/2 + assert tn(K(z), meijerg(((S.Half, S.Half), []), ((S.Zero,), (S.Zero,)), -z)/2) + + assert K(z).series(z) == pi/2 + pi*z/8 + 9*pi*z**2/128 + \ + 25*pi*z**3/512 + 1225*pi*z**4/32768 + 3969*pi*z**5/131072 + O(z**6) + + assert K(m).rewrite(Integral).dummy_eq( + Integral(1/sqrt(1 - m*sin(t)**2), (t, 0, pi/2))) + +def test_F(): + assert F(z, 0) == z + assert F(0, m) == 0 + assert F(pi*i/2, m) == i*K(m) + assert F(z, oo) == 0 + assert F(z, -oo) == 0 + + assert F(-z, m) == -F(z, m) + + assert F(z, m).diff(z) == 1/sqrt(1 - m*sin(z)**2) + assert F(z, m).diff(m) == E(z, m)/(2*m*(1 - m)) - F(z, m)/(2*m) - \ + sin(2*z)/(4*(1 - m)*sqrt(1 - m*sin(z)**2)) + r = randcplx() + assert td(F(z, r), z) + assert td(F(r, m), m) + + mi = Symbol('m', real=False) + assert F(z, mi).conjugate() == F(z.conjugate(), mi.conjugate()) + mr = Symbol('m', negative=True) + assert F(z, mr).conjugate() == F(z.conjugate(), mr) + + assert F(z, m).series(z) == \ + z + z**5*(3*m**2/40 - m/30) + m*z**3/6 + O(z**6) + + assert F(z, m).rewrite(Integral).dummy_eq( + Integral(1/sqrt(1 - m*sin(t)**2), (t, 0, z))) + +def test_E(): + assert E(z, 0) == z + assert E(0, m) == 0 + assert E(i*pi/2, m) == i*E(m) + assert E(z, oo) is zoo + assert E(z, -oo) is zoo + assert E(0) == pi/2 + assert E(1) == 1 + assert E(oo) == I*oo + assert E(-oo) is oo + assert E(zoo) is zoo + + assert E(-z, m) == -E(z, m) + + assert E(z, m).diff(z) == sqrt(1 - m*sin(z)**2) + assert E(z, m).diff(m) == (E(z, m) - F(z, m))/(2*m) + assert E(z).diff(z) == (E(z) - K(z))/(2*z) + r = randcplx() + assert td(E(r, m), m) + assert td(E(z, r), z) + assert td(E(z), z) + + mi = Symbol('m', real=False) + assert E(z, mi).conjugate() == E(z.conjugate(), mi.conjugate()) + assert E(mi).conjugate() == E(mi.conjugate()) + mr = Symbol('m', negative=True) + assert E(z, mr).conjugate() == E(z.conjugate(), mr) + assert E(mr).conjugate() == E(mr) + + assert E(z).rewrite(hyper) == (pi/2)*hyper((Rational(-1, 2), S.Half), (S.One,), z) + assert tn(E(z), (pi/2)*hyper((Rational(-1, 2), S.Half), (S.One,), z)) + assert E(z).rewrite(meijerg) == \ + -meijerg(((S.Half, Rational(3, 2)), []), ((S.Zero,), (S.Zero,)), -z)/4 + assert tn(E(z), -meijerg(((S.Half, Rational(3, 2)), []), ((S.Zero,), (S.Zero,)), -z)/4) + + assert E(z, m).series(z) == \ + z + z**5*(-m**2/40 + m/30) - m*z**3/6 + O(z**6) + assert E(z).series(z) == pi/2 - pi*z/8 - 3*pi*z**2/128 - \ + 5*pi*z**3/512 - 175*pi*z**4/32768 - 441*pi*z**5/131072 + O(z**6) + assert E(4*z/(z+1)).series(z) == \ + pi/2 - pi*z/2 + pi*z**2/8 - 3*pi*z**3/8 - 15*pi*z**4/128 - 93*pi*z**5/128 + O(z**6) + + assert E(z, m).rewrite(Integral).dummy_eq( + Integral(sqrt(1 - m*sin(t)**2), (t, 0, z))) + assert E(m).rewrite(Integral).dummy_eq( + Integral(sqrt(1 - m*sin(t)**2), (t, 0, pi/2))) + +def test_P(): + assert P(0, z, m) == F(z, m) + assert P(1, z, m) == F(z, m) + \ + (sqrt(1 - m*sin(z)**2)*tan(z) - E(z, m))/(1 - m) + assert P(n, i*pi/2, m) == i*P(n, m) + assert P(n, z, 0) == atanh(sqrt(n - 1)*tan(z))/sqrt(n - 1) + assert P(n, z, n) == F(z, n) - P(1, z, n) + tan(z)/sqrt(1 - n*sin(z)**2) + assert P(oo, z, m) == 0 + assert P(-oo, z, m) == 0 + assert P(n, z, oo) == 0 + assert P(n, z, -oo) == 0 + assert P(0, m) == K(m) + assert P(1, m) is zoo + assert P(n, 0) == pi/(2*sqrt(1 - n)) + assert P(2, 1) is -oo + assert P(-1, 1) is oo + assert P(n, n) == E(n)/(1 - n) + + assert P(n, -z, m) == -P(n, z, m) + + ni, mi = Symbol('n', real=False), Symbol('m', real=False) + assert P(ni, z, mi).conjugate() == \ + P(ni.conjugate(), z.conjugate(), mi.conjugate()) + nr, mr = Symbol('n', negative=True), \ + Symbol('m', negative=True) + assert P(nr, z, mr).conjugate() == P(nr, z.conjugate(), mr) + assert P(n, m).conjugate() == P(n.conjugate(), m.conjugate()) + + assert P(n, z, m).diff(n) == (E(z, m) + (m - n)*F(z, m)/n + + (n**2 - m)*P(n, z, m)/n - n*sqrt(1 - + m*sin(z)**2)*sin(2*z)/(2*(1 - n*sin(z)**2)))/(2*(m - n)*(n - 1)) + assert P(n, z, m).diff(z) == 1/(sqrt(1 - m*sin(z)**2)*(1 - n*sin(z)**2)) + assert P(n, z, m).diff(m) == (E(z, m)/(m - 1) + P(n, z, m) - + m*sin(2*z)/(2*(m - 1)*sqrt(1 - m*sin(z)**2)))/(2*(n - m)) + assert P(n, m).diff(n) == (E(m) + (m - n)*K(m)/n + + (n**2 - m)*P(n, m)/n)/(2*(m - n)*(n - 1)) + assert P(n, m).diff(m) == (E(m)/(m - 1) + P(n, m))/(2*(n - m)) + + # These tests fail due to + # https://github.com/fredrik-johansson/mpmath/issues/571#issuecomment-777201962 + # https://github.com/sympy/sympy/issues/20933#issuecomment-777080385 + # + # rx, ry = randcplx(), randcplx() + # assert td(P(n, rx, ry), n) + # assert td(P(rx, z, ry), z) + # assert td(P(rx, ry, m), m) + + assert P(n, z, m).series(z) == z + z**3*(m/6 + n/3) + \ + z**5*(3*m**2/40 + m*n/10 - m/30 + n**2/5 - n/15) + O(z**6) + + assert P(n, z, m).rewrite(Integral).dummy_eq( + Integral(1/((1 - n*sin(t)**2)*sqrt(1 - m*sin(t)**2)), (t, 0, z))) + assert P(n, m).rewrite(Integral).dummy_eq( + Integral(1/((1 - n*sin(t)**2)*sqrt(1 - m*sin(t)**2)), (t, 0, pi/2))) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_error_functions.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_error_functions.py new file mode 100644 index 0000000000000000000000000000000000000000..073371d3d584b97936729dc2e39c833ac347559b --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_error_functions.py @@ -0,0 +1,860 @@ +from sympy.core.function import (diff, expand, expand_func) +from sympy.core import EulerGamma +from sympy.core.numbers import (E, Float, I, Rational, nan, oo, pi) +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols, Dummy) +from sympy.functions.elementary.complexes import (conjugate, im, polar_lift, re) +from sympy.functions.elementary.exponential import (exp, exp_polar, log) +from sympy.functions.elementary.hyperbolic import (cosh, sinh) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (cos, sin, sinc) +from sympy.functions.special.error_functions import (Chi, Ci, E1, Ei, Li, Shi, Si, erf, erf2, erf2inv, erfc, erfcinv, erfi, erfinv, expint, fresnelc, fresnels, li) +from sympy.functions.special.gamma_functions import (gamma, uppergamma) +from sympy.functions.special.hyper import (hyper, meijerg) +from sympy.integrals.integrals import (Integral, integrate) +from sympy.series.gruntz import gruntz +from sympy.series.limits import limit +from sympy.series.order import O +from sympy.core.expr import unchanged +from sympy.core.function import ArgumentIndexError +from sympy.functions.special.error_functions import _erfs, _eis +from sympy.testing.pytest import raises + +x, y, z = symbols('x,y,z') +w = Symbol("w", real=True) +n = Symbol("n", integer=True) +t = Dummy('t') + + +def test_erf(): + assert erf(nan) is nan + + assert erf(oo) == 1 + assert erf(-oo) == -1 + + assert erf(0) is S.Zero + + assert erf(I*oo) == oo*I + assert erf(-I*oo) == -oo*I + + assert erf(-2) == -erf(2) + assert erf(-x*y) == -erf(x*y) + assert erf(-x - y) == -erf(x + y) + + assert erf(erfinv(x)) == x + assert erf(erfcinv(x)) == 1 - x + assert erf(erf2inv(0, x)) == x + assert erf(erf2inv(0, x, evaluate=False)) == x # To cover code in erf + assert erf(erf2inv(0, erf(erfcinv(1 - erf(erfinv(x)))))) == x + + alpha = symbols('alpha', extended_real=True) + assert erf(alpha).is_real is True + assert erf(alpha).is_finite is True + alpha = symbols('alpha', extended_real=False) + assert erf(alpha).is_real is None + assert erf(alpha).is_finite is None + assert erf(alpha).is_zero is None + assert erf(alpha).is_positive is None + assert erf(alpha).is_negative is None + alpha = symbols('alpha', extended_positive=True) + assert erf(alpha).is_positive is True + alpha = symbols('alpha', extended_negative=True) + assert erf(alpha).is_negative is True + assert erf(I).is_real is False + assert erf(0, evaluate=False).is_real + assert erf(0, evaluate=False).is_zero + + assert conjugate(erf(z)) == erf(conjugate(z)) + + assert erf(x).as_leading_term(x) == 2*x/sqrt(pi) + assert erf(x*y).as_leading_term(y) == 2*x*y/sqrt(pi) + assert (erf(x*y)/erf(y)).as_leading_term(y) == x + assert erf(1/x).as_leading_term(x) == S.One + + assert erf(z).rewrite('uppergamma') == sqrt(z**2)*(1 - erfc(sqrt(z**2)))/z + assert erf(z).rewrite('erfc') == S.One - erfc(z) + assert erf(z).rewrite('erfi') == -I*erfi(I*z) + assert erf(z).rewrite('fresnels') == (1 + I)*(fresnelc(z*(1 - I)/sqrt(pi)) - + I*fresnels(z*(1 - I)/sqrt(pi))) + assert erf(z).rewrite('fresnelc') == (1 + I)*(fresnelc(z*(1 - I)/sqrt(pi)) - + I*fresnels(z*(1 - I)/sqrt(pi))) + assert erf(z).rewrite('hyper') == 2*z*hyper([S.Half], [3*S.Half], -z**2)/sqrt(pi) + assert erf(z).rewrite('meijerg') == z*meijerg([S.Half], [], [0], [Rational(-1, 2)], z**2)/sqrt(pi) + assert erf(z).rewrite('expint') == sqrt(z**2)/z - z*expint(S.Half, z**2)/sqrt(S.Pi) + + assert limit(exp(x)*exp(x**2)*(erf(x + 1/exp(x)) - erf(x)), x, oo) == \ + 2/sqrt(pi) + assert limit((1 - erf(z))*exp(z**2)*z, z, oo) == 1/sqrt(pi) + assert limit((1 - erf(x))*exp(x**2)*sqrt(pi)*x, x, oo) == 1 + assert limit(((1 - erf(x))*exp(x**2)*sqrt(pi)*x - 1)*2*x**2, x, oo) == -1 + assert limit(erf(x)/x, x, 0) == 2/sqrt(pi) + assert limit(x**(-4) - sqrt(pi)*erf(x**2) / (2*x**6), x, 0) == S(1)/3 + + assert erf(x).as_real_imag() == \ + (erf(re(x) - I*im(x))/2 + erf(re(x) + I*im(x))/2, + -I*(-erf(re(x) - I*im(x)) + erf(re(x) + I*im(x)))/2) + + assert erf(x).as_real_imag(deep=False) == \ + (erf(re(x) - I*im(x))/2 + erf(re(x) + I*im(x))/2, + -I*(-erf(re(x) - I*im(x)) + erf(re(x) + I*im(x)))/2) + + assert erf(w).as_real_imag() == (erf(w), 0) + assert erf(w).as_real_imag(deep=False) == (erf(w), 0) + # issue 13575 + assert erf(I).as_real_imag() == (0, -I*erf(I)) + + raises(ArgumentIndexError, lambda: erf(x).fdiff(2)) + + assert erf(x).inverse() == erfinv + + +def test_erf_series(): + assert erf(x).series(x, 0, 7) == 2*x/sqrt(pi) - \ + 2*x**3/3/sqrt(pi) + x**5/5/sqrt(pi) + O(x**7) + + assert erf(x).series(x, oo) == \ + -exp(-x**2)*(3/(4*x**5) - 1/(2*x**3) + 1/x + O(x**(-6), (x, oo)))/sqrt(pi) + 1 + assert erf(x**2).series(x, oo, n=8) == \ + (-1/(2*x**6) + x**(-2) + O(x**(-8), (x, oo)))*exp(-x**4)/sqrt(pi)*-1 + 1 + assert erf(sqrt(x)).series(x, oo, n=3) == (sqrt(1/x) - (1/x)**(S(3)/2)/2\ + + 3*(1/x)**(S(5)/2)/4 + O(x**(-3), (x, oo)))*exp(-x)/sqrt(pi)*-1 + 1 + + +def test_erf_evalf(): + assert abs( erf(Float(2.0)) - 0.995322265 ) < 1E-8 # XXX + + +def test__erfs(): + assert _erfs(z).diff(z) == -2/sqrt(S.Pi) + 2*z*_erfs(z) + + assert _erfs(1/z).series(z) == \ + z/sqrt(pi) - z**3/(2*sqrt(pi)) + 3*z**5/(4*sqrt(pi)) + O(z**6) + + assert expand(erf(z).rewrite('tractable').diff(z).rewrite('intractable')) \ + == erf(z).diff(z) + assert _erfs(z).rewrite("intractable") == (-erf(z) + 1)*exp(z**2) + raises(ArgumentIndexError, lambda: _erfs(z).fdiff(2)) + + +def test_erfc(): + assert erfc(nan) is nan + + assert erfc(oo) is S.Zero + assert erfc(-oo) == 2 + + assert erfc(0) == 1 + + assert erfc(I*oo) == -oo*I + assert erfc(-I*oo) == oo*I + + assert erfc(-x) == S(2) - erfc(x) + assert erfc(erfcinv(x)) == x + + alpha = symbols('alpha', extended_real=True) + assert erfc(alpha).is_real is True + alpha = symbols('alpha', extended_real=False) + assert erfc(alpha).is_real is None + assert erfc(I).is_real is False + assert erfc(0, evaluate=False).is_real + assert erfc(0, evaluate=False).is_zero is False + + assert erfc(erfinv(x)) == 1 - x + + assert conjugate(erfc(z)) == erfc(conjugate(z)) + + assert erfc(x).as_leading_term(x) is S.One + assert erfc(1/x).as_leading_term(x) == S.Zero + + assert erfc(z).rewrite('erf') == 1 - erf(z) + assert erfc(z).rewrite('erfi') == 1 + I*erfi(I*z) + assert erfc(z).rewrite('fresnels') == 1 - (1 + I)*(fresnelc(z*(1 - I)/sqrt(pi)) - + I*fresnels(z*(1 - I)/sqrt(pi))) + assert erfc(z).rewrite('fresnelc') == 1 - (1 + I)*(fresnelc(z*(1 - I)/sqrt(pi)) - + I*fresnels(z*(1 - I)/sqrt(pi))) + assert erfc(z).rewrite('hyper') == 1 - 2*z*hyper([S.Half], [3*S.Half], -z**2)/sqrt(pi) + assert erfc(z).rewrite('meijerg') == 1 - z*meijerg([S.Half], [], [0], [Rational(-1, 2)], z**2)/sqrt(pi) + assert erfc(z).rewrite('uppergamma') == 1 - sqrt(z**2)*(1 - erfc(sqrt(z**2)))/z + assert erfc(z).rewrite('expint') == S.One - sqrt(z**2)/z + z*expint(S.Half, z**2)/sqrt(S.Pi) + assert erfc(z).rewrite('tractable') == _erfs(z)*exp(-z**2) + assert expand_func(erf(x) + erfc(x)) is S.One + + assert erfc(x).as_real_imag() == \ + (erfc(re(x) - I*im(x))/2 + erfc(re(x) + I*im(x))/2, + -I*(-erfc(re(x) - I*im(x)) + erfc(re(x) + I*im(x)))/2) + + assert erfc(x).as_real_imag(deep=False) == \ + (erfc(re(x) - I*im(x))/2 + erfc(re(x) + I*im(x))/2, + -I*(-erfc(re(x) - I*im(x)) + erfc(re(x) + I*im(x)))/2) + + assert erfc(w).as_real_imag() == (erfc(w), 0) + assert erfc(w).as_real_imag(deep=False) == (erfc(w), 0) + raises(ArgumentIndexError, lambda: erfc(x).fdiff(2)) + + assert erfc(x).inverse() == erfcinv + + +def test_erfc_series(): + assert erfc(x).series(x, 0, 7) == 1 - 2*x/sqrt(pi) + \ + 2*x**3/3/sqrt(pi) - x**5/5/sqrt(pi) + O(x**7) + + assert erfc(x).series(x, oo) == \ + (3/(4*x**5) - 1/(2*x**3) + 1/x + O(x**(-6), (x, oo)))*exp(-x**2)/sqrt(pi) + + +def test_erfc_evalf(): + assert abs( erfc(Float(2.0)) - 0.00467773 ) < 1E-8 # XXX + + +def test_erfi(): + assert erfi(nan) is nan + + assert erfi(oo) is S.Infinity + assert erfi(-oo) is S.NegativeInfinity + + assert erfi(0) is S.Zero + + assert erfi(I*oo) == I + assert erfi(-I*oo) == -I + + assert erfi(-x) == -erfi(x) + + assert erfi(I*erfinv(x)) == I*x + assert erfi(I*erfcinv(x)) == I*(1 - x) + assert erfi(I*erf2inv(0, x)) == I*x + assert erfi(I*erf2inv(0, x, evaluate=False)) == I*x # To cover code in erfi + + assert erfi(I).is_real is False + assert erfi(0, evaluate=False).is_real + assert erfi(0, evaluate=False).is_zero + + assert conjugate(erfi(z)) == erfi(conjugate(z)) + + assert erfi(x).as_leading_term(x) == 2*x/sqrt(pi) + assert erfi(x*y).as_leading_term(y) == 2*x*y/sqrt(pi) + assert (erfi(x*y)/erfi(y)).as_leading_term(y) == x + assert erfi(1/x).as_leading_term(x) == erfi(1/x) + + assert erfi(z).rewrite('erf') == -I*erf(I*z) + assert erfi(z).rewrite('erfc') == I*erfc(I*z) - I + assert erfi(z).rewrite('fresnels') == (1 - I)*(fresnelc(z*(1 + I)/sqrt(pi)) - + I*fresnels(z*(1 + I)/sqrt(pi))) + assert erfi(z).rewrite('fresnelc') == (1 - I)*(fresnelc(z*(1 + I)/sqrt(pi)) - + I*fresnels(z*(1 + I)/sqrt(pi))) + assert erfi(z).rewrite('hyper') == 2*z*hyper([S.Half], [3*S.Half], z**2)/sqrt(pi) + assert erfi(z).rewrite('meijerg') == z*meijerg([S.Half], [], [0], [Rational(-1, 2)], -z**2)/sqrt(pi) + assert erfi(z).rewrite('uppergamma') == (sqrt(-z**2)/z*(uppergamma(S.Half, + -z**2)/sqrt(S.Pi) - S.One)) + assert erfi(z).rewrite('expint') == sqrt(-z**2)/z - z*expint(S.Half, -z**2)/sqrt(S.Pi) + assert erfi(z).rewrite('tractable') == -I*(-_erfs(I*z)*exp(z**2) + 1) + assert expand_func(erfi(I*z)) == I*erf(z) + + assert erfi(x).as_real_imag() == \ + (erfi(re(x) - I*im(x))/2 + erfi(re(x) + I*im(x))/2, + -I*(-erfi(re(x) - I*im(x)) + erfi(re(x) + I*im(x)))/2) + assert erfi(x).as_real_imag(deep=False) == \ + (erfi(re(x) - I*im(x))/2 + erfi(re(x) + I*im(x))/2, + -I*(-erfi(re(x) - I*im(x)) + erfi(re(x) + I*im(x)))/2) + + assert erfi(w).as_real_imag() == (erfi(w), 0) + assert erfi(w).as_real_imag(deep=False) == (erfi(w), 0) + + raises(ArgumentIndexError, lambda: erfi(x).fdiff(2)) + + +def test_erfi_series(): + assert erfi(x).series(x, 0, 7) == 2*x/sqrt(pi) + \ + 2*x**3/3/sqrt(pi) + x**5/5/sqrt(pi) + O(x**7) + + assert erfi(x).series(x, oo) == \ + (3/(4*x**5) + 1/(2*x**3) + 1/x + O(x**(-6), (x, oo)))*exp(x**2)/sqrt(pi) - I + + +def test_erfi_evalf(): + assert abs( erfi(Float(2.0)) - 18.5648024145756 ) < 1E-13 # XXX + + +def test_erf2(): + + assert erf2(0, 0) is S.Zero + assert erf2(x, x) is S.Zero + assert erf2(nan, 0) is nan + + assert erf2(-oo, y) == erf(y) + 1 + assert erf2( oo, y) == erf(y) - 1 + assert erf2( x, oo) == 1 - erf(x) + assert erf2( x,-oo) == -1 - erf(x) + assert erf2(x, erf2inv(x, y)) == y + + assert erf2(-x, -y) == -erf2(x,y) + assert erf2(-x, y) == erf(y) + erf(x) + assert erf2( x, -y) == -erf(y) - erf(x) + assert erf2(x, y).rewrite('fresnels') == erf(y).rewrite(fresnels)-erf(x).rewrite(fresnels) + assert erf2(x, y).rewrite('fresnelc') == erf(y).rewrite(fresnelc)-erf(x).rewrite(fresnelc) + assert erf2(x, y).rewrite('hyper') == erf(y).rewrite(hyper)-erf(x).rewrite(hyper) + assert erf2(x, y).rewrite('meijerg') == erf(y).rewrite(meijerg)-erf(x).rewrite(meijerg) + assert erf2(x, y).rewrite('uppergamma') == erf(y).rewrite(uppergamma) - erf(x).rewrite(uppergamma) + assert erf2(x, y).rewrite('expint') == erf(y).rewrite(expint)-erf(x).rewrite(expint) + + assert erf2(I, 0).is_real is False + assert erf2(0, 0, evaluate=False).is_real + assert erf2(0, 0, evaluate=False).is_zero + assert erf2(x, x, evaluate=False).is_zero + assert erf2(x, y).is_zero is None + + assert expand_func(erf(x) + erf2(x, y)) == erf(y) + + assert conjugate(erf2(x, y)) == erf2(conjugate(x), conjugate(y)) + + assert erf2(x, y).rewrite('erf') == erf(y) - erf(x) + assert erf2(x, y).rewrite('erfc') == erfc(x) - erfc(y) + assert erf2(x, y).rewrite('erfi') == I*(erfi(I*x) - erfi(I*y)) + + assert erf2(x, y).diff(x) == erf2(x, y).fdiff(1) + assert erf2(x, y).diff(y) == erf2(x, y).fdiff(2) + assert erf2(x, y).diff(x) == -2*exp(-x**2)/sqrt(pi) + assert erf2(x, y).diff(y) == 2*exp(-y**2)/sqrt(pi) + raises(ArgumentIndexError, lambda: erf2(x, y).fdiff(3)) + + assert erf2(x, y).is_extended_real is None + xr, yr = symbols('xr yr', extended_real=True) + assert erf2(xr, yr).is_extended_real is True + + +def test_erfinv(): + assert erfinv(0) is S.Zero + assert erfinv(1) is S.Infinity + assert erfinv(nan) is S.NaN + assert erfinv(-1) is S.NegativeInfinity + + assert erfinv(erf(w)) == w + assert erfinv(erf(-w)) == -w + + assert erfinv(x).diff() == sqrt(pi)*exp(erfinv(x)**2)/2 + raises(ArgumentIndexError, lambda: erfinv(x).fdiff(2)) + + assert erfinv(z).rewrite('erfcinv') == erfcinv(1-z) + assert erfinv(z).inverse() == erf + + +def test_erfinv_evalf(): + assert abs( erfinv(Float(0.2)) - 0.179143454621292 ) < 1E-13 + + +def test_erfcinv(): + assert erfcinv(1) is S.Zero + assert erfcinv(0) is S.Infinity + assert erfcinv(0, evaluate=False).is_infinite is True + assert erfcinv(2, evaluate=False).is_infinite is True + assert erfcinv(nan) is S.NaN + + assert erfcinv(x).diff() == -sqrt(pi)*exp(erfcinv(x)**2)/2 + raises(ArgumentIndexError, lambda: erfcinv(x).fdiff(2)) + + assert erfcinv(z).rewrite('erfinv') == erfinv(1-z) + assert erfcinv(z).inverse() == erfc + + +def test_erf2inv(): + assert erf2inv(0, 0) is S.Zero + assert erf2inv(0, 1) is S.Infinity + assert erf2inv(1, 0) is S.One + assert erf2inv(0, y) == erfinv(y) + assert erf2inv(oo, y) == erfcinv(-y) + assert erf2inv(x, 0) == x + assert erf2inv(x, oo) == erfinv(x) + assert erf2inv(nan, 0) is nan + assert erf2inv(0, nan) is nan + + assert erf2inv(x, y).diff(x) == exp(-x**2 + erf2inv(x, y)**2) + assert erf2inv(x, y).diff(y) == sqrt(pi)*exp(erf2inv(x, y)**2)/2 + raises(ArgumentIndexError, lambda: erf2inv(x, y).fdiff(3)) + + +# NOTE we multiply by exp_polar(I*pi) and need this to be on the principal +# branch, hence take x in the lower half plane (d=0). + + +def mytn(expr1, expr2, expr3, x, d=0): + from sympy.core.random import verify_numerically, random_complex_number + subs = {} + for a in expr1.free_symbols: + if a != x: + subs[a] = random_complex_number() + return expr2 == expr3 and verify_numerically(expr1.subs(subs), + expr2.subs(subs), x, d=d) + + +def mytd(expr1, expr2, x): + from sympy.core.random import test_derivative_numerically, \ + random_complex_number + subs = {} + for a in expr1.free_symbols: + if a != x: + subs[a] = random_complex_number() + return expr1.diff(x) == expr2 and test_derivative_numerically(expr1.subs(subs), x) + + +def tn_branch(func, s=None): + from sympy.core.random import uniform + + def fn(x): + if s is None: + return func(x) + return func(s, x) + c = uniform(1, 5) + expr = fn(c*exp_polar(I*pi)) - fn(c*exp_polar(-I*pi)) + eps = 1e-15 + expr2 = fn(-c + eps*I) - fn(-c - eps*I) + return abs(expr.n() - expr2.n()).n() < 1e-10 + + +def test_ei(): + assert Ei(0) is S.NegativeInfinity + assert Ei(oo) is S.Infinity + assert Ei(-oo) is S.Zero + + assert tn_branch(Ei) + assert mytd(Ei(x), exp(x)/x, x) + assert mytn(Ei(x), Ei(x).rewrite(uppergamma), + -uppergamma(0, x*polar_lift(-1)) - I*pi, x) + assert mytn(Ei(x), Ei(x).rewrite(expint), + -expint(1, x*polar_lift(-1)) - I*pi, x) + assert Ei(x).rewrite(expint).rewrite(Ei) == Ei(x) + assert Ei(x*exp_polar(2*I*pi)) == Ei(x) + 2*I*pi + assert Ei(x*exp_polar(-2*I*pi)) == Ei(x) - 2*I*pi + + assert mytn(Ei(x), Ei(x).rewrite(Shi), Chi(x) + Shi(x), x) + assert mytn(Ei(x*polar_lift(I)), Ei(x*polar_lift(I)).rewrite(Si), + Ci(x) + I*Si(x) + I*pi/2, x) + + assert Ei(log(x)).rewrite(li) == li(x) + assert Ei(2*log(x)).rewrite(li) == li(x**2) + + assert gruntz(Ei(x+exp(-x))*exp(-x)*x, x, oo) == 1 + + assert Ei(x).series(x) == EulerGamma + log(x) + x + x**2/4 + \ + x**3/18 + x**4/96 + x**5/600 + O(x**6) + assert Ei(x).series(x, 1, 3) == Ei(1) + E*(x - 1) + O((x - 1)**3, (x, 1)) + assert Ei(x).series(x, oo) == \ + (120/x**5 + 24/x**4 + 6/x**3 + 2/x**2 + 1/x + 1 + O(x**(-6), (x, oo)))*exp(x)/x + assert Ei(x).series(x, -oo) == \ + (120/x**5 + 24/x**4 + 6/x**3 + 2/x**2 + 1/x + 1 + O(x**(-6), (x, -oo)))*exp(x)/x + assert Ei(-x).series(x, oo) == \ + -((-120/x**5 + 24/x**4 - 6/x**3 + 2/x**2 - 1/x + 1 + O(x**(-6), (x, oo)))*exp(-x)/x) + + assert str(Ei(cos(2)).evalf(n=10)) == '-0.6760647401' + raises(ArgumentIndexError, lambda: Ei(x).fdiff(2)) + + +def test_expint(): + assert mytn(expint(x, y), expint(x, y).rewrite(uppergamma), + y**(x - 1)*uppergamma(1 - x, y), x) + assert mytd( + expint(x, y), -y**(x - 1)*meijerg([], [1, 1], [0, 0, 1 - x], [], y), x) + assert mytd(expint(x, y), -expint(x - 1, y), y) + assert mytn(expint(1, x), expint(1, x).rewrite(Ei), + -Ei(x*polar_lift(-1)) + I*pi, x) + + assert expint(-4, x) == exp(-x)/x + 4*exp(-x)/x**2 + 12*exp(-x)/x**3 \ + + 24*exp(-x)/x**4 + 24*exp(-x)/x**5 + assert expint(Rational(-3, 2), x) == \ + exp(-x)/x + 3*exp(-x)/(2*x**2) + 3*sqrt(pi)*erfc(sqrt(x))/(4*x**S('5/2')) + + assert tn_branch(expint, 1) + assert tn_branch(expint, 2) + assert tn_branch(expint, 3) + assert tn_branch(expint, 1.7) + assert tn_branch(expint, pi) + + assert expint(y, x*exp_polar(2*I*pi)) == \ + x**(y - 1)*(exp(2*I*pi*y) - 1)*gamma(-y + 1) + expint(y, x) + assert expint(y, x*exp_polar(-2*I*pi)) == \ + x**(y - 1)*(exp(-2*I*pi*y) - 1)*gamma(-y + 1) + expint(y, x) + assert expint(2, x*exp_polar(2*I*pi)) == 2*I*pi*x + expint(2, x) + assert expint(2, x*exp_polar(-2*I*pi)) == -2*I*pi*x + expint(2, x) + assert expint(1, x).rewrite(Ei).rewrite(expint) == expint(1, x) + assert expint(x, y).rewrite(Ei) == expint(x, y) + assert expint(x, y).rewrite(Ci) == expint(x, y) + + assert mytn(E1(x), E1(x).rewrite(Shi), Shi(x) - Chi(x), x) + assert mytn(E1(polar_lift(I)*x), E1(polar_lift(I)*x).rewrite(Si), + -Ci(x) + I*Si(x) - I*pi/2, x) + + assert mytn(expint(2, x), expint(2, x).rewrite(Ei).rewrite(expint), + -x*E1(x) + exp(-x), x) + assert mytn(expint(3, x), expint(3, x).rewrite(Ei).rewrite(expint), + x**2*E1(x)/2 + (1 - x)*exp(-x)/2, x) + + assert expint(Rational(3, 2), z).nseries(z) == \ + 2 + 2*z - z**2/3 + z**3/15 - z**4/84 + z**5/540 - \ + 2*sqrt(pi)*sqrt(z) + O(z**6) + + assert E1(z).series(z) == -EulerGamma - log(z) + z - \ + z**2/4 + z**3/18 - z**4/96 + z**5/600 + O(z**6) + + assert expint(4, z).series(z) == Rational(1, 3) - z/2 + z**2/2 + \ + z**3*(log(z)/6 - Rational(11, 36) + EulerGamma/6 - I*pi/6) - z**4/24 + \ + z**5/240 + O(z**6) + + assert expint(n, x).series(x, oo, n=3) == \ + (n*(n + 1)/x**2 - n/x + 1 + O(x**(-3), (x, oo)))*exp(-x)/x + + assert expint(z, y).series(z, 0, 2) == exp(-y)/y - z*meijerg(((), (1, 1)), + ((0, 0, 1), ()), y)/y + O(z**2) + raises(ArgumentIndexError, lambda: expint(x, y).fdiff(3)) + + neg = Symbol('neg', negative=True) + assert Ei(neg).rewrite(Si) == Shi(neg) + Chi(neg) - I*pi + + +def test__eis(): + assert _eis(z).diff(z) == -_eis(z) + 1/z + + assert _eis(1/z).series(z) == \ + z + z**2 + 2*z**3 + 6*z**4 + 24*z**5 + O(z**6) + + assert Ei(z).rewrite('tractable') == exp(z)*_eis(z) + assert li(z).rewrite('tractable') == z*_eis(log(z)) + + assert _eis(z).rewrite('intractable') == exp(-z)*Ei(z) + + assert expand(li(z).rewrite('tractable').diff(z).rewrite('intractable')) \ + == li(z).diff(z) + + assert expand(Ei(z).rewrite('tractable').diff(z).rewrite('intractable')) \ + == Ei(z).diff(z) + + assert _eis(z).series(z, n=3) == EulerGamma + log(z) + z*(-log(z) - \ + EulerGamma + 1) + z**2*(log(z)/2 - Rational(3, 4) + EulerGamma/2)\ + + O(z**3*log(z)) + raises(ArgumentIndexError, lambda: _eis(z).fdiff(2)) + + +def tn_arg(func): + def test(arg, e1, e2): + from sympy.core.random import uniform + v = uniform(1, 5) + v1 = func(arg*x).subs(x, v).n() + v2 = func(e1*v + e2*1e-15).n() + return abs(v1 - v2).n() < 1e-10 + return test(exp_polar(I*pi/2), I, 1) and \ + test(exp_polar(-I*pi/2), -I, 1) and \ + test(exp_polar(I*pi), -1, I) and \ + test(exp_polar(-I*pi), -1, -I) + + +def test_li(): + z = Symbol("z") + zr = Symbol("z", real=True) + zp = Symbol("z", positive=True) + zn = Symbol("z", negative=True) + + assert li(0) is S.Zero + assert li(1) is -oo + assert li(oo) is oo + + assert isinstance(li(z), li) + assert unchanged(li, -zp) + assert unchanged(li, zn) + + assert diff(li(z), z) == 1/log(z) + + assert conjugate(li(z)) == li(conjugate(z)) + assert conjugate(li(-zr)) == li(-zr) + assert unchanged(conjugate, li(-zp)) + assert unchanged(conjugate, li(zn)) + + assert li(z).rewrite(Li) == Li(z) + li(2) + assert li(z).rewrite(Ei) == Ei(log(z)) + assert li(z).rewrite(uppergamma) == (-log(1/log(z))/2 - log(-log(z)) + + log(log(z))/2 - expint(1, -log(z))) + assert li(z).rewrite(Si) == (-log(I*log(z)) - log(1/log(z))/2 + + log(log(z))/2 + Ci(I*log(z)) + Shi(log(z))) + assert li(z).rewrite(Ci) == (-log(I*log(z)) - log(1/log(z))/2 + + log(log(z))/2 + Ci(I*log(z)) + Shi(log(z))) + assert li(z).rewrite(Shi) == (-log(1/log(z))/2 + log(log(z))/2 + + Chi(log(z)) - Shi(log(z))) + assert li(z).rewrite(Chi) == (-log(1/log(z))/2 + log(log(z))/2 + + Chi(log(z)) - Shi(log(z))) + assert li(z).rewrite(hyper) ==(log(z)*hyper((1, 1), (2, 2), log(z)) - + log(1/log(z))/2 + log(log(z))/2 + EulerGamma) + assert li(z).rewrite(meijerg) == (-log(1/log(z))/2 - log(-log(z)) + log(log(z))/2 - + meijerg(((), (1,)), ((0, 0), ()), -log(z))) + + assert gruntz(1/li(z), z, oo) is S.Zero + assert li(z).series(z) == log(z)**5/600 + log(z)**4/96 + log(z)**3/18 + log(z)**2/4 + \ + log(z) + log(log(z)) + EulerGamma + raises(ArgumentIndexError, lambda: li(z).fdiff(2)) + + +def test_Li(): + assert Li(2) is S.Zero + assert Li(oo) is oo + + assert isinstance(Li(z), Li) + + assert diff(Li(z), z) == 1/log(z) + + assert gruntz(1/Li(z), z, oo) is S.Zero + assert Li(z).rewrite(li) == li(z) - li(2) + assert Li(z).series(z) == \ + log(z)**5/600 + log(z)**4/96 + log(z)**3/18 + log(z)**2/4 + log(z) + log(log(z)) - li(2) + EulerGamma + raises(ArgumentIndexError, lambda: Li(z).fdiff(2)) + + +def test_si(): + assert Si(I*x) == I*Shi(x) + assert Shi(I*x) == I*Si(x) + assert Si(-I*x) == -I*Shi(x) + assert Shi(-I*x) == -I*Si(x) + assert Si(-x) == -Si(x) + assert Shi(-x) == -Shi(x) + assert Si(exp_polar(2*pi*I)*x) == Si(x) + assert Si(exp_polar(-2*pi*I)*x) == Si(x) + assert Shi(exp_polar(2*pi*I)*x) == Shi(x) + assert Shi(exp_polar(-2*pi*I)*x) == Shi(x) + + assert Si(oo) == pi/2 + assert Si(-oo) == -pi/2 + assert Shi(oo) is oo + assert Shi(-oo) is -oo + + assert mytd(Si(x), sin(x)/x, x) + assert mytd(Shi(x), sinh(x)/x, x) + + assert mytn(Si(x), Si(x).rewrite(Ei), + -I*(-Ei(x*exp_polar(-I*pi/2))/2 + + Ei(x*exp_polar(I*pi/2))/2 - I*pi) + pi/2, x) + assert mytn(Si(x), Si(x).rewrite(expint), + -I*(-expint(1, x*exp_polar(-I*pi/2))/2 + + expint(1, x*exp_polar(I*pi/2))/2) + pi/2, x) + assert mytn(Shi(x), Shi(x).rewrite(Ei), + Ei(x)/2 - Ei(x*exp_polar(I*pi))/2 + I*pi/2, x) + assert mytn(Shi(x), Shi(x).rewrite(expint), + expint(1, x)/2 - expint(1, x*exp_polar(I*pi))/2 - I*pi/2, x) + + assert tn_arg(Si) + assert tn_arg(Shi) + + assert Si(x)._eval_as_leading_term(x, None, 1) == x + assert Si(2*x)._eval_as_leading_term(x, None, 1) == 2*x + assert Si(sin(x))._eval_as_leading_term(x, None, 1) == x + assert Si(x + 1)._eval_as_leading_term(x, None, 1) == Si(1) + assert Si(1/x)._eval_as_leading_term(x, None, 1) == \ + Si(1/x)._eval_as_leading_term(x, None, -1) == Si(1/x) + + assert Si(x).nseries(x, n=8) == \ + x - x**3/18 + x**5/600 - x**7/35280 + O(x**8) + assert Shi(x).nseries(x, n=8) == \ + x + x**3/18 + x**5/600 + x**7/35280 + O(x**8) + assert Si(sin(x)).nseries(x, n=5) == x - 2*x**3/9 + O(x**5) + assert Si(x).nseries(x, 1, n=3) == \ + Si(1) + (x - 1)*sin(1) + (x - 1)**2*(-sin(1)/2 + cos(1)/2) + O((x - 1)**3, (x, 1)) + + assert Si(x).series(x, oo) == -sin(x)*(-6/x**4 + x**(-2) + O(x**(-6), (x, oo))) - \ + cos(x)*(24/x**5 - 2/x**3 + 1/x + O(x**(-6), (x, oo))) + pi/2 + + t = Symbol('t', Dummy=True) + assert Si(x).rewrite(sinc).dummy_eq(Integral(sinc(t), (t, 0, x))) + + assert limit(Shi(x), x, S.Infinity) == S.Infinity + assert limit(Shi(x), x, S.NegativeInfinity) == S.NegativeInfinity + + +def test_ci(): + m1 = exp_polar(I*pi) + m1_ = exp_polar(-I*pi) + pI = exp_polar(I*pi/2) + mI = exp_polar(-I*pi/2) + + assert Ci(m1*x) == Ci(x) + I*pi + assert Ci(m1_*x) == Ci(x) - I*pi + assert Ci(pI*x) == Chi(x) + I*pi/2 + assert Ci(mI*x) == Chi(x) - I*pi/2 + assert Chi(m1*x) == Chi(x) + I*pi + assert Chi(m1_*x) == Chi(x) - I*pi + assert Chi(pI*x) == Ci(x) + I*pi/2 + assert Chi(mI*x) == Ci(x) - I*pi/2 + assert Ci(exp_polar(2*I*pi)*x) == Ci(x) + 2*I*pi + assert Chi(exp_polar(-2*I*pi)*x) == Chi(x) - 2*I*pi + assert Chi(exp_polar(2*I*pi)*x) == Chi(x) + 2*I*pi + assert Ci(exp_polar(-2*I*pi)*x) == Ci(x) - 2*I*pi + + assert Ci(oo) is S.Zero + assert Ci(-oo) == I*pi + assert Chi(oo) is oo + assert Chi(-oo) is oo + + assert mytd(Ci(x), cos(x)/x, x) + assert mytd(Chi(x), cosh(x)/x, x) + + assert mytn(Ci(x), Ci(x).rewrite(Ei), + Ei(x*exp_polar(-I*pi/2))/2 + Ei(x*exp_polar(I*pi/2))/2, x) + assert mytn(Chi(x), Chi(x).rewrite(Ei), + Ei(x)/2 + Ei(x*exp_polar(I*pi))/2 - I*pi/2, x) + + assert tn_arg(Ci) + assert tn_arg(Chi) + + assert Ci(x).nseries(x, n=4) == \ + EulerGamma + log(x) - x**2/4 + O(x**4) + assert Chi(x).nseries(x, n=4) == \ + EulerGamma + log(x) + x**2/4 + O(x**4) + + assert Ci(x).series(x, oo) == -cos(x)*(-6/x**4 + x**(-2) + O(x**(-6), (x, oo))) + \ + sin(x)*(24/x**5 - 2/x**3 + 1/x + O(x**(-6), (x, oo))) + + assert Ci(x).series(x, -oo) == -cos(x)*(-6/x**4 + x**(-2) + O(x**(-6), (x, -oo))) + \ + sin(x)*(24/x**5 - 2/x**3 + 1/x + O(x**(-6), (x, -oo))) + I*pi + + assert limit(log(x) - Ci(2*x), x, 0) == -log(2) - EulerGamma + assert Ci(x).rewrite(uppergamma) == -expint(1, x*exp_polar(-I*pi/2))/2 -\ + expint(1, x*exp_polar(I*pi/2))/2 + assert Ci(x).rewrite(expint) == -expint(1, x*exp_polar(-I*pi/2))/2 -\ + expint(1, x*exp_polar(I*pi/2))/2 + raises(ArgumentIndexError, lambda: Ci(x).fdiff(2)) + + +def test_fresnel(): + assert fresnels(0) is S.Zero + assert fresnels(oo) is S.Half + assert fresnels(-oo) == Rational(-1, 2) + assert fresnels(I*oo) == -I*S.Half + + assert unchanged(fresnels, z) + assert fresnels(-z) == -fresnels(z) + assert fresnels(I*z) == -I*fresnels(z) + assert fresnels(-I*z) == I*fresnels(z) + + assert conjugate(fresnels(z)) == fresnels(conjugate(z)) + + assert fresnels(z).diff(z) == sin(pi*z**2/2) + + assert fresnels(z).rewrite(erf) == (S.One + I)/4 * ( + erf((S.One + I)/2*sqrt(pi)*z) - I*erf((S.One - I)/2*sqrt(pi)*z)) + + assert fresnels(z).rewrite(hyper) == \ + pi*z**3/6 * hyper([Rational(3, 4)], [Rational(3, 2), Rational(7, 4)], -pi**2*z**4/16) + + assert fresnels(z).series(z, n=15) == \ + pi*z**3/6 - pi**3*z**7/336 + pi**5*z**11/42240 + O(z**15) + + assert fresnels(w).is_extended_real is True + assert fresnels(w).is_finite is True + + assert fresnels(z).is_extended_real is None + assert fresnels(z).is_finite is None + + assert fresnels(z).as_real_imag() == (fresnels(re(z) - I*im(z))/2 + + fresnels(re(z) + I*im(z))/2, + -I*(-fresnels(re(z) - I*im(z)) + fresnels(re(z) + I*im(z)))/2) + + assert fresnels(z).as_real_imag(deep=False) == (fresnels(re(z) - I*im(z))/2 + + fresnels(re(z) + I*im(z))/2, + -I*(-fresnels(re(z) - I*im(z)) + fresnels(re(z) + I*im(z)))/2) + + assert fresnels(w).as_real_imag() == (fresnels(w), 0) + assert fresnels(w).as_real_imag(deep=True) == (fresnels(w), 0) + + assert fresnels(2 + 3*I).as_real_imag() == ( + fresnels(2 + 3*I)/2 + fresnels(2 - 3*I)/2, + -I*(fresnels(2 + 3*I) - fresnels(2 - 3*I))/2 + ) + + assert expand_func(integrate(fresnels(z), z)) == \ + z*fresnels(z) + cos(pi*z**2/2)/pi + + assert fresnels(z).rewrite(meijerg) == sqrt(2)*pi*z**Rational(9, 4) * \ + meijerg(((), (1,)), ((Rational(3, 4),), + (Rational(1, 4), 0)), -pi**2*z**4/16)/(2*(-z)**Rational(3, 4)*(z**2)**Rational(3, 4)) + + assert fresnelc(0) is S.Zero + assert fresnelc(oo) == S.Half + assert fresnelc(-oo) == Rational(-1, 2) + assert fresnelc(I*oo) == I*S.Half + + assert unchanged(fresnelc, z) + assert fresnelc(-z) == -fresnelc(z) + assert fresnelc(I*z) == I*fresnelc(z) + assert fresnelc(-I*z) == -I*fresnelc(z) + + assert conjugate(fresnelc(z)) == fresnelc(conjugate(z)) + + assert fresnelc(z).diff(z) == cos(pi*z**2/2) + + assert fresnelc(z).rewrite(erf) == (S.One - I)/4 * ( + erf((S.One + I)/2*sqrt(pi)*z) + I*erf((S.One - I)/2*sqrt(pi)*z)) + + assert fresnelc(z).rewrite(hyper) == \ + z * hyper([Rational(1, 4)], [S.Half, Rational(5, 4)], -pi**2*z**4/16) + + assert fresnelc(w).is_extended_real is True + + assert fresnelc(z).as_real_imag() == \ + (fresnelc(re(z) - I*im(z))/2 + fresnelc(re(z) + I*im(z))/2, + -I*(-fresnelc(re(z) - I*im(z)) + fresnelc(re(z) + I*im(z)))/2) + + assert fresnelc(z).as_real_imag(deep=False) == \ + (fresnelc(re(z) - I*im(z))/2 + fresnelc(re(z) + I*im(z))/2, + -I*(-fresnelc(re(z) - I*im(z)) + fresnelc(re(z) + I*im(z)))/2) + + assert fresnelc(2 + 3*I).as_real_imag() == ( + fresnelc(2 - 3*I)/2 + fresnelc(2 + 3*I)/2, + -I*(fresnelc(2 + 3*I) - fresnelc(2 - 3*I))/2 + ) + + assert expand_func(integrate(fresnelc(z), z)) == \ + z*fresnelc(z) - sin(pi*z**2/2)/pi + + assert fresnelc(z).rewrite(meijerg) == sqrt(2)*pi*z**Rational(3, 4) * \ + meijerg(((), (1,)), ((Rational(1, 4),), + (Rational(3, 4), 0)), -pi**2*z**4/16)/(2*(-z)**Rational(1, 4)*(z**2)**Rational(1, 4)) + + from sympy.core.random import verify_numerically + + verify_numerically(re(fresnels(z)), fresnels(z).as_real_imag()[0], z) + verify_numerically(im(fresnels(z)), fresnels(z).as_real_imag()[1], z) + verify_numerically(fresnels(z), fresnels(z).rewrite(hyper), z) + verify_numerically(fresnels(z), fresnels(z).rewrite(meijerg), z) + + verify_numerically(re(fresnelc(z)), fresnelc(z).as_real_imag()[0], z) + verify_numerically(im(fresnelc(z)), fresnelc(z).as_real_imag()[1], z) + verify_numerically(fresnelc(z), fresnelc(z).rewrite(hyper), z) + verify_numerically(fresnelc(z), fresnelc(z).rewrite(meijerg), z) + + raises(ArgumentIndexError, lambda: fresnels(z).fdiff(2)) + raises(ArgumentIndexError, lambda: fresnelc(z).fdiff(2)) + + assert fresnels(x).taylor_term(-1, x) is S.Zero + assert fresnelc(x).taylor_term(-1, x) is S.Zero + assert fresnelc(x).taylor_term(1, x) == -pi**2*x**5/40 + + +def test_fresnel_series(): + assert fresnelc(z).series(z, n=15) == \ + z - pi**2*z**5/40 + pi**4*z**9/3456 - pi**6*z**13/599040 + O(z**15) + + # issues 6510, 10102 + fs = (S.Half - sin(pi*z**2/2)/(pi**2*z**3) + + (-1/(pi*z) + 3/(pi**3*z**5))*cos(pi*z**2/2)) + fc = (S.Half - cos(pi*z**2/2)/(pi**2*z**3) + + (1/(pi*z) - 3/(pi**3*z**5))*sin(pi*z**2/2)) + assert fresnels(z).series(z, oo) == fs + O(z**(-6), (z, oo)) + assert fresnelc(z).series(z, oo) == fc + O(z**(-6), (z, oo)) + assert (fresnels(z).series(z, -oo) + fs.subs(z, -z)).expand().is_Order + assert (fresnelc(z).series(z, -oo) + fc.subs(z, -z)).expand().is_Order + assert (fresnels(1/z).series(z) - fs.subs(z, 1/z)).expand().is_Order + assert (fresnelc(1/z).series(z) - fc.subs(z, 1/z)).expand().is_Order + assert ((2*fresnels(3*z)).series(z, oo) - 2*fs.subs(z, 3*z)).expand().is_Order + assert ((3*fresnelc(2*z)).series(z, oo) - 3*fc.subs(z, 2*z)).expand().is_Order + + +def test_integral_rewrites(): #issues 26134, 26144, 26306 + assert expint(n, x).rewrite(Integral).dummy_eq(Integral(t**-n * exp(-t*x), (t, 1, oo))) + assert Si(x).rewrite(Integral).dummy_eq(Integral(sinc(t), (t, 0, x))) + assert Ci(x).rewrite(Integral).dummy_eq(log(x) - Integral((1 - cos(t))/t, (t, 0, x)) + EulerGamma) + assert fresnels(x).rewrite(Integral).dummy_eq(Integral(sin(pi*t**2/2), (t, 0, x))) + assert fresnelc(x).rewrite(Integral).dummy_eq(Integral(cos(pi*t**2/2), (t, 0, x))) + assert Ei(x).rewrite(Integral).dummy_eq(Integral(exp(t)/t, (t, -oo, x))) + assert fresnels(x).diff(x) == fresnels(x).rewrite(Integral).diff(x) + assert fresnelc(x).diff(x) == fresnelc(x).rewrite(Integral).diff(x) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_gamma_functions.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_gamma_functions.py new file mode 100644 index 0000000000000000000000000000000000000000..14c57a31ce2edaa60fd5efc8bcbc95668961fd41 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_gamma_functions.py @@ -0,0 +1,741 @@ +from sympy.core.function import expand_func, Subs +from sympy.core import EulerGamma +from sympy.core.numbers import (I, Rational, nan, oo, pi, zoo) +from sympy.core.singleton import S +from sympy.core.symbol import (Dummy, Symbol) +from sympy.functions.combinatorial.factorials import factorial +from sympy.functions.combinatorial.numbers import harmonic +from sympy.functions.elementary.complexes import (Abs, conjugate, im, re) +from sympy.functions.elementary.exponential import (exp, exp_polar, log) +from sympy.functions.elementary.hyperbolic import tanh +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (cos, sin, atan) +from sympy.functions.special.error_functions import (Ei, erf, erfc) +from sympy.functions.special.gamma_functions import (digamma, gamma, loggamma, lowergamma, multigamma, polygamma, trigamma, uppergamma) +from sympy.functions.special.zeta_functions import zeta +from sympy.series.order import O + +from sympy.core.expr import unchanged +from sympy.core.function import ArgumentIndexError +from sympy.testing.pytest import raises +from sympy.core.random import (test_derivative_numerically as td, + random_complex_number as randcplx, + verify_numerically as tn) + +x = Symbol('x') +y = Symbol('y') +n = Symbol('n', integer=True) +w = Symbol('w', real=True) + +def test_gamma(): + assert gamma(nan) is nan + assert gamma(oo) is oo + + assert gamma(-100) is zoo + assert gamma(0) is zoo + assert gamma(-100.0) is zoo + + assert gamma(1) == 1 + assert gamma(2) == 1 + assert gamma(3) == 2 + + assert gamma(102) == factorial(101) + + assert gamma(S.Half) == sqrt(pi) + + assert gamma(Rational(3, 2)) == sqrt(pi)*S.Half + assert gamma(Rational(5, 2)) == sqrt(pi)*Rational(3, 4) + assert gamma(Rational(7, 2)) == sqrt(pi)*Rational(15, 8) + + assert gamma(Rational(-1, 2)) == -2*sqrt(pi) + assert gamma(Rational(-3, 2)) == sqrt(pi)*Rational(4, 3) + assert gamma(Rational(-5, 2)) == sqrt(pi)*Rational(-8, 15) + + assert gamma(Rational(-15, 2)) == sqrt(pi)*Rational(256, 2027025) + + assert gamma(Rational( + -11, 8)).expand(func=True) == Rational(64, 33)*gamma(Rational(5, 8)) + assert gamma(Rational( + -10, 3)).expand(func=True) == Rational(81, 280)*gamma(Rational(2, 3)) + assert gamma(Rational( + 14, 3)).expand(func=True) == Rational(880, 81)*gamma(Rational(2, 3)) + assert gamma(Rational( + 17, 7)).expand(func=True) == Rational(30, 49)*gamma(Rational(3, 7)) + assert gamma(Rational( + 19, 8)).expand(func=True) == Rational(33, 64)*gamma(Rational(3, 8)) + + assert gamma(x).diff(x) == gamma(x)*polygamma(0, x) + + assert gamma(x - 1).expand(func=True) == gamma(x)/(x - 1) + assert gamma(x + 2).expand(func=True, mul=False) == x*(x + 1)*gamma(x) + + assert conjugate(gamma(x)) == gamma(conjugate(x)) + + assert expand_func(gamma(x + Rational(3, 2))) == \ + (x + S.Half)*gamma(x + S.Half) + + assert expand_func(gamma(x - S.Half)) == \ + gamma(S.Half + x)/(x - S.Half) + + # Test a bug: + assert expand_func(gamma(x + Rational(3, 4))) == gamma(x + Rational(3, 4)) + + # XXX: Not sure about these tests. I can fix them by defining e.g. + # exp_polar.is_integer but I'm not sure if that makes sense. + assert gamma(3*exp_polar(I*pi)/4).is_nonnegative is False + assert gamma(3*exp_polar(I*pi)/4).is_extended_nonpositive is True + + y = Symbol('y', nonpositive=True, integer=True) + assert gamma(y).is_real == False + y = Symbol('y', positive=True, noninteger=True) + assert gamma(y).is_real == True + + assert gamma(-1.0, evaluate=False).is_real == False + assert gamma(0, evaluate=False).is_real == False + assert gamma(-2, evaluate=False).is_real == False + + +def test_gamma_rewrite(): + assert gamma(n).rewrite(factorial) == factorial(n - 1) + + +def test_gamma_series(): + assert gamma(x + 1).series(x, 0, 3) == \ + 1 - EulerGamma*x + x**2*(EulerGamma**2/2 + pi**2/12) + O(x**3) + assert gamma(x).series(x, -1, 3) == \ + -1/(x + 1) + EulerGamma - 1 + (x + 1)*(-1 - pi**2/12 - EulerGamma**2/2 + \ + EulerGamma) + (x + 1)**2*(-1 - pi**2/12 - EulerGamma**2/2 + EulerGamma**3/6 - \ + polygamma(2, 1)/6 + EulerGamma*pi**2/12 + EulerGamma) + O((x + 1)**3, (x, -1)) + + +def tn_branch(s, func): + from sympy.core.random import uniform + c = uniform(1, 5) + expr = func(s, c*exp_polar(I*pi)) - func(s, c*exp_polar(-I*pi)) + eps = 1e-15 + expr2 = func(s + eps, -c + eps*I) - func(s + eps, -c - eps*I) + return abs(expr.n() - expr2.n()).n() < 1e-10 + + +def test_lowergamma(): + from sympy.functions.special.error_functions import expint + from sympy.functions.special.hyper import meijerg + assert lowergamma(x, 0) == 0 + assert lowergamma(x, y).diff(y) == y**(x - 1)*exp(-y) + assert td(lowergamma(randcplx(), y), y) + assert td(lowergamma(x, randcplx()), x) + assert lowergamma(x, y).diff(x) == \ + gamma(x)*digamma(x) - uppergamma(x, y)*log(y) \ + - meijerg([], [1, 1], [0, 0, x], [], y) + + assert lowergamma(S.Half, x) == sqrt(pi)*erf(sqrt(x)) + assert not lowergamma(S.Half - 3, x).has(lowergamma) + assert not lowergamma(S.Half + 3, x).has(lowergamma) + assert lowergamma(S.Half, x, evaluate=False).has(lowergamma) + assert tn(lowergamma(S.Half + 3, x, evaluate=False), + lowergamma(S.Half + 3, x), x) + assert tn(lowergamma(S.Half - 3, x, evaluate=False), + lowergamma(S.Half - 3, x), x) + + assert tn_branch(-3, lowergamma) + assert tn_branch(-4, lowergamma) + assert tn_branch(Rational(1, 3), lowergamma) + assert tn_branch(pi, lowergamma) + assert lowergamma(3, exp_polar(4*pi*I)*x) == lowergamma(3, x) + assert lowergamma(y, exp_polar(5*pi*I)*x) == \ + exp(4*I*pi*y)*lowergamma(y, x*exp_polar(pi*I)) + assert lowergamma(-2, exp_polar(5*pi*I)*x) == \ + lowergamma(-2, x*exp_polar(I*pi)) + 2*pi*I + + assert conjugate(lowergamma(x, y)) == lowergamma(conjugate(x), conjugate(y)) + assert conjugate(lowergamma(x, 0)) == 0 + assert unchanged(conjugate, lowergamma(x, -oo)) + + assert lowergamma(0, x)._eval_is_meromorphic(x, 0) == False + assert lowergamma(S(1)/3, x)._eval_is_meromorphic(x, 0) == False + assert lowergamma(1, x, evaluate=False)._eval_is_meromorphic(x, 0) == True + assert lowergamma(x, x)._eval_is_meromorphic(x, 0) == False + assert lowergamma(x + 1, x)._eval_is_meromorphic(x, 0) == False + assert lowergamma(1/x, x)._eval_is_meromorphic(x, 0) == False + assert lowergamma(0, x + 1)._eval_is_meromorphic(x, 0) == False + assert lowergamma(S(1)/3, x + 1)._eval_is_meromorphic(x, 0) == True + assert lowergamma(1, x + 1, evaluate=False)._eval_is_meromorphic(x, 0) == True + assert lowergamma(x, x + 1)._eval_is_meromorphic(x, 0) == True + assert lowergamma(x + 1, x + 1)._eval_is_meromorphic(x, 0) == True + assert lowergamma(1/x, x + 1)._eval_is_meromorphic(x, 0) == False + assert lowergamma(0, 1/x)._eval_is_meromorphic(x, 0) == False + assert lowergamma(S(1)/3, 1/x)._eval_is_meromorphic(x, 0) == False + assert lowergamma(1, 1/x, evaluate=False)._eval_is_meromorphic(x, 0) == False + assert lowergamma(x, 1/x)._eval_is_meromorphic(x, 0) == False + assert lowergamma(x + 1, 1/x)._eval_is_meromorphic(x, 0) == False + assert lowergamma(1/x, 1/x)._eval_is_meromorphic(x, 0) == False + + assert lowergamma(x, 2).series(x, oo, 3) == \ + 2**x*(1 + 2/(x + 1))*exp(-2)/x + O(exp(x*log(2))/x**3, (x, oo)) + + assert lowergamma( + x, y).rewrite(expint) == -y**x*expint(-x + 1, y) + gamma(x) + k = Symbol('k', integer=True) + assert lowergamma( + k, y).rewrite(expint) == -y**k*expint(-k + 1, y) + gamma(k) + k = Symbol('k', integer=True, positive=False) + assert lowergamma(k, y).rewrite(expint) == lowergamma(k, y) + assert lowergamma(x, y).rewrite(uppergamma) == gamma(x) - uppergamma(x, y) + + assert lowergamma(70, 6) == factorial(69) - 69035724522603011058660187038367026272747334489677105069435923032634389419656200387949342530805432320 * exp(-6) + assert (lowergamma(S(77) / 2, 6) - lowergamma(S(77) / 2, 6, evaluate=False)).evalf() < 1e-16 + assert (lowergamma(-S(77) / 2, 6) - lowergamma(-S(77) / 2, 6, evaluate=False)).evalf() < 1e-16 + + +def test_uppergamma(): + from sympy.functions.special.error_functions import expint + from sympy.functions.special.hyper import meijerg + assert uppergamma(4, 0) == 6 + assert uppergamma(x, y).diff(y) == -y**(x - 1)*exp(-y) + assert td(uppergamma(randcplx(), y), y) + assert uppergamma(x, y).diff(x) == \ + uppergamma(x, y)*log(y) + meijerg([], [1, 1], [0, 0, x], [], y) + assert td(uppergamma(x, randcplx()), x) + + p = Symbol('p', positive=True) + assert uppergamma(0, p) == -Ei(-p) + assert uppergamma(p, 0) == gamma(p) + assert uppergamma(S.Half, x) == sqrt(pi)*erfc(sqrt(x)) + assert not uppergamma(S.Half - 3, x).has(uppergamma) + assert not uppergamma(S.Half + 3, x).has(uppergamma) + assert uppergamma(S.Half, x, evaluate=False).has(uppergamma) + assert tn(uppergamma(S.Half + 3, x, evaluate=False), + uppergamma(S.Half + 3, x), x) + assert tn(uppergamma(S.Half - 3, x, evaluate=False), + uppergamma(S.Half - 3, x), x) + + assert unchanged(uppergamma, x, -oo) + assert unchanged(uppergamma, x, 0) + + assert tn_branch(-3, uppergamma) + assert tn_branch(-4, uppergamma) + assert tn_branch(Rational(1, 3), uppergamma) + assert tn_branch(pi, uppergamma) + assert uppergamma(3, exp_polar(4*pi*I)*x) == uppergamma(3, x) + assert uppergamma(y, exp_polar(5*pi*I)*x) == \ + exp(4*I*pi*y)*uppergamma(y, x*exp_polar(pi*I)) + \ + gamma(y)*(1 - exp(4*pi*I*y)) + assert uppergamma(-2, exp_polar(5*pi*I)*x) == \ + uppergamma(-2, x*exp_polar(I*pi)) - 2*pi*I + + assert uppergamma(-2, x) == expint(3, x)/x**2 + + assert conjugate(uppergamma(x, y)) == uppergamma(conjugate(x), conjugate(y)) + assert unchanged(conjugate, uppergamma(x, -oo)) + + assert uppergamma(x, y).rewrite(expint) == y**x*expint(-x + 1, y) + assert uppergamma(x, y).rewrite(lowergamma) == gamma(x) - lowergamma(x, y) + + assert uppergamma(70, 6) == 69035724522603011058660187038367026272747334489677105069435923032634389419656200387949342530805432320*exp(-6) + assert (uppergamma(S(77) / 2, 6) - uppergamma(S(77) / 2, 6, evaluate=False)).evalf() < 1e-16 + assert (uppergamma(-S(77) / 2, 6) - uppergamma(-S(77) / 2, 6, evaluate=False)).evalf() < 1e-16 + + +def test_polygamma(): + assert polygamma(n, nan) is nan + + assert polygamma(0, oo) is oo + assert polygamma(0, -oo) is oo + assert polygamma(0, I*oo) is oo + assert polygamma(0, -I*oo) is oo + assert polygamma(1, oo) == 0 + assert polygamma(5, oo) == 0 + + assert polygamma(0, -9) is zoo + + assert polygamma(0, -9) is zoo + assert polygamma(0, -1) is zoo + assert polygamma(Rational(3, 2), -1) is zoo + + assert polygamma(0, 0) is zoo + + assert polygamma(0, 1) == -EulerGamma + assert polygamma(0, 7) == Rational(49, 20) - EulerGamma + + assert polygamma(1, 1) == pi**2/6 + assert polygamma(1, 2) == pi**2/6 - 1 + assert polygamma(1, 3) == pi**2/6 - Rational(5, 4) + assert polygamma(3, 1) == pi**4 / 15 + assert polygamma(3, 5) == 6*(Rational(-22369, 20736) + pi**4/90) + assert polygamma(5, 1) == 8 * pi**6 / 63 + + assert polygamma(1, S.Half) == pi**2 / 2 + assert polygamma(2, S.Half) == -14*zeta(3) + assert polygamma(11, S.Half) == 176896*pi**12 + + def t(m, n): + x = S(m)/n + r = polygamma(0, x) + if r.has(polygamma): + return False + return abs(polygamma(0, x.n()).n() - r.n()).n() < 1e-10 + assert t(1, 2) + assert t(3, 2) + assert t(-1, 2) + assert t(1, 4) + assert t(-3, 4) + assert t(1, 3) + assert t(4, 3) + assert t(3, 4) + assert t(2, 3) + assert t(123, 5) + + assert polygamma(0, x).rewrite(zeta) == polygamma(0, x) + assert polygamma(1, x).rewrite(zeta) == zeta(2, x) + assert polygamma(2, x).rewrite(zeta) == -2*zeta(3, x) + assert polygamma(I, 2).rewrite(zeta) == polygamma(I, 2) + n1 = Symbol('n1') + n2 = Symbol('n2', real=True) + n3 = Symbol('n3', integer=True) + n4 = Symbol('n4', positive=True) + n5 = Symbol('n5', positive=True, integer=True) + assert polygamma(n1, x).rewrite(zeta) == polygamma(n1, x) + assert polygamma(n2, x).rewrite(zeta) == polygamma(n2, x) + assert polygamma(n3, x).rewrite(zeta) == polygamma(n3, x) + assert polygamma(n4, x).rewrite(zeta) == polygamma(n4, x) + assert polygamma(n5, x).rewrite(zeta) == (-1)**(n5 + 1) * factorial(n5) * zeta(n5 + 1, x) + + assert polygamma(3, 7*x).diff(x) == 7*polygamma(4, 7*x) + + assert polygamma(0, x).rewrite(harmonic) == harmonic(x - 1) - EulerGamma + assert polygamma(2, x).rewrite(harmonic) == 2*harmonic(x - 1, 3) - 2*zeta(3) + ni = Symbol("n", integer=True) + assert polygamma(ni, x).rewrite(harmonic) == (-1)**(ni + 1)*(-harmonic(x - 1, ni + 1) + + zeta(ni + 1))*factorial(ni) + + # Polygamma of non-negative integer order is unbranched: + k = Symbol('n', integer=True, nonnegative=True) + assert polygamma(k, exp_polar(2*I*pi)*x) == polygamma(k, x) + + # but negative integers are branched! + k = Symbol('n', integer=True) + assert polygamma(k, exp_polar(2*I*pi)*x).args == (k, exp_polar(2*I*pi)*x) + + # Polygamma of order -1 is loggamma: + assert polygamma(-1, x) == loggamma(x) - log(2*pi) / 2 + + # But smaller orders are iterated integrals and don't have a special name + assert polygamma(-2, x).func is polygamma + + # Test a bug + assert polygamma(0, -x).expand(func=True) == polygamma(0, -x) + + assert polygamma(2, 2.5).is_positive == False + assert polygamma(2, -2.5).is_positive == False + assert polygamma(3, 2.5).is_positive == True + assert polygamma(3, -2.5).is_positive is True + assert polygamma(-2, -2.5).is_positive is None + assert polygamma(-3, -2.5).is_positive is None + + assert polygamma(2, 2.5).is_negative == True + assert polygamma(3, 2.5).is_negative == False + assert polygamma(3, -2.5).is_negative == False + assert polygamma(2, -2.5).is_negative is True + assert polygamma(-2, -2.5).is_negative is None + assert polygamma(-3, -2.5).is_negative is None + + assert polygamma(I, 2).is_positive is None + assert polygamma(I, 3).is_negative is None + + # issue 17350 + assert (I*polygamma(I, pi)).as_real_imag() == \ + (-im(polygamma(I, pi)), re(polygamma(I, pi))) + assert (tanh(polygamma(I, 1))).rewrite(exp) == \ + (exp(polygamma(I, 1)) - exp(-polygamma(I, 1)))/(exp(polygamma(I, 1)) + exp(-polygamma(I, 1))) + assert (I / polygamma(I, 4)).rewrite(exp) == \ + I*exp(-I*atan(im(polygamma(I, 4))/re(polygamma(I, 4))))/Abs(polygamma(I, 4)) + + # issue 12569 + assert unchanged(im, polygamma(0, I)) + assert polygamma(Symbol('a', positive=True), Symbol('b', positive=True)).is_real is True + assert polygamma(0, I).is_real is None + + assert str(polygamma(pi, 3).evalf(n=10)) == "0.1169314564" + assert str(polygamma(2.3, 1.0).evalf(n=10)) == "-3.003302909" + assert str(polygamma(-1, 1).evalf(n=10)) == "-0.9189385332" # not zero + assert str(polygamma(I, 1).evalf(n=10)) == "-3.109856569 + 1.89089016*I" + assert str(polygamma(1, I).evalf(n=10)) == "-0.5369999034 - 0.7942335428*I" + assert str(polygamma(I, I).evalf(n=10)) == "6.332362889 + 45.92828268*I" + + +def test_polygamma_expand_func(): + assert polygamma(0, x).expand(func=True) == polygamma(0, x) + assert polygamma(0, 2*x).expand(func=True) == \ + polygamma(0, x)/2 + polygamma(0, S.Half + x)/2 + log(2) + assert polygamma(1, 2*x).expand(func=True) == \ + polygamma(1, x)/4 + polygamma(1, S.Half + x)/4 + assert polygamma(2, x).expand(func=True) == \ + polygamma(2, x) + assert polygamma(0, -1 + x).expand(func=True) == \ + polygamma(0, x) - 1/(x - 1) + assert polygamma(0, 1 + x).expand(func=True) == \ + 1/x + polygamma(0, x ) + assert polygamma(0, 2 + x).expand(func=True) == \ + 1/x + 1/(1 + x) + polygamma(0, x) + assert polygamma(0, 3 + x).expand(func=True) == \ + polygamma(0, x) + 1/x + 1/(1 + x) + 1/(2 + x) + assert polygamma(0, 4 + x).expand(func=True) == \ + polygamma(0, x) + 1/x + 1/(1 + x) + 1/(2 + x) + 1/(3 + x) + assert polygamma(1, 1 + x).expand(func=True) == \ + polygamma(1, x) - 1/x**2 + assert polygamma(1, 2 + x).expand(func=True, multinomial=False) == \ + polygamma(1, x) - 1/x**2 - 1/(1 + x)**2 + assert polygamma(1, 3 + x).expand(func=True, multinomial=False) == \ + polygamma(1, x) - 1/x**2 - 1/(1 + x)**2 - 1/(2 + x)**2 + assert polygamma(1, 4 + x).expand(func=True, multinomial=False) == \ + polygamma(1, x) - 1/x**2 - 1/(1 + x)**2 - \ + 1/(2 + x)**2 - 1/(3 + x)**2 + assert polygamma(0, x + y).expand(func=True) == \ + polygamma(0, x + y) + assert polygamma(1, x + y).expand(func=True) == \ + polygamma(1, x + y) + assert polygamma(1, 3 + 4*x + y).expand(func=True, multinomial=False) == \ + polygamma(1, y + 4*x) - 1/(y + 4*x)**2 - \ + 1/(1 + y + 4*x)**2 - 1/(2 + y + 4*x)**2 + assert polygamma(3, 3 + 4*x + y).expand(func=True, multinomial=False) == \ + polygamma(3, y + 4*x) - 6/(y + 4*x)**4 - \ + 6/(1 + y + 4*x)**4 - 6/(2 + y + 4*x)**4 + assert polygamma(3, 4*x + y + 1).expand(func=True, multinomial=False) == \ + polygamma(3, y + 4*x) - 6/(y + 4*x)**4 + e = polygamma(3, 4*x + y + Rational(3, 2)) + assert e.expand(func=True) == e + e = polygamma(3, x + y + Rational(3, 4)) + assert e.expand(func=True, basic=False) == e + + assert polygamma(-1, x, evaluate=False).expand(func=True) == \ + loggamma(x) - log(pi)/2 - log(2)/2 + p2 = polygamma(-2, x).expand(func=True) + x**2/2 - x/2 + S(1)/12 + assert isinstance(p2, Subs) + assert p2.point == (-1,) + + +def test_digamma(): + assert digamma(nan) == nan + + assert digamma(oo) == oo + assert digamma(-oo) == oo + assert digamma(I*oo) == oo + assert digamma(-I*oo) == oo + + assert digamma(-9) == zoo + + assert digamma(-9) == zoo + assert digamma(-1) == zoo + + assert digamma(0) == zoo + + assert digamma(1) == -EulerGamma + assert digamma(7) == Rational(49, 20) - EulerGamma + + def t(m, n): + x = S(m)/n + r = digamma(x) + if r.has(digamma): + return False + return abs(digamma(x.n()).n() - r.n()).n() < 1e-10 + assert t(1, 2) + assert t(3, 2) + assert t(-1, 2) + assert t(1, 4) + assert t(-3, 4) + assert t(1, 3) + assert t(4, 3) + assert t(3, 4) + assert t(2, 3) + assert t(123, 5) + + assert digamma(x).rewrite(zeta) == polygamma(0, x) + + assert digamma(x).rewrite(harmonic) == harmonic(x - 1) - EulerGamma + + assert digamma(I).is_real is None + + assert digamma(x,evaluate=False).fdiff() == polygamma(1, x) + + assert digamma(x,evaluate=False).is_real is None + + assert digamma(x,evaluate=False).is_positive is None + + assert digamma(x,evaluate=False).is_negative is None + + assert digamma(x,evaluate=False).rewrite(polygamma) == polygamma(0, x) + + +def test_digamma_expand_func(): + assert digamma(x).expand(func=True) == polygamma(0, x) + assert digamma(2*x).expand(func=True) == \ + polygamma(0, x)/2 + polygamma(0, Rational(1, 2) + x)/2 + log(2) + assert digamma(-1 + x).expand(func=True) == \ + polygamma(0, x) - 1/(x - 1) + assert digamma(1 + x).expand(func=True) == \ + 1/x + polygamma(0, x ) + assert digamma(2 + x).expand(func=True) == \ + 1/x + 1/(1 + x) + polygamma(0, x) + assert digamma(3 + x).expand(func=True) == \ + polygamma(0, x) + 1/x + 1/(1 + x) + 1/(2 + x) + assert digamma(4 + x).expand(func=True) == \ + polygamma(0, x) + 1/x + 1/(1 + x) + 1/(2 + x) + 1/(3 + x) + assert digamma(x + y).expand(func=True) == \ + polygamma(0, x + y) + +def test_trigamma(): + assert trigamma(nan) == nan + + assert trigamma(oo) == 0 + + assert trigamma(1) == pi**2/6 + assert trigamma(2) == pi**2/6 - 1 + assert trigamma(3) == pi**2/6 - Rational(5, 4) + + assert trigamma(x, evaluate=False).rewrite(zeta) == zeta(2, x) + assert trigamma(x, evaluate=False).rewrite(harmonic) == \ + trigamma(x).rewrite(polygamma).rewrite(harmonic) + + assert trigamma(x,evaluate=False).fdiff() == polygamma(2, x) + + assert trigamma(x,evaluate=False).is_real is None + + assert trigamma(x,evaluate=False).is_positive is None + + assert trigamma(x,evaluate=False).is_negative is None + + assert trigamma(x,evaluate=False).rewrite(polygamma) == polygamma(1, x) + +def test_trigamma_expand_func(): + assert trigamma(2*x).expand(func=True) == \ + polygamma(1, x)/4 + polygamma(1, Rational(1, 2) + x)/4 + assert trigamma(1 + x).expand(func=True) == \ + polygamma(1, x) - 1/x**2 + assert trigamma(2 + x).expand(func=True, multinomial=False) == \ + polygamma(1, x) - 1/x**2 - 1/(1 + x)**2 + assert trigamma(3 + x).expand(func=True, multinomial=False) == \ + polygamma(1, x) - 1/x**2 - 1/(1 + x)**2 - 1/(2 + x)**2 + assert trigamma(4 + x).expand(func=True, multinomial=False) == \ + polygamma(1, x) - 1/x**2 - 1/(1 + x)**2 - \ + 1/(2 + x)**2 - 1/(3 + x)**2 + assert trigamma(x + y).expand(func=True) == \ + polygamma(1, x + y) + assert trigamma(3 + 4*x + y).expand(func=True, multinomial=False) == \ + polygamma(1, y + 4*x) - 1/(y + 4*x)**2 - \ + 1/(1 + y + 4*x)**2 - 1/(2 + y + 4*x)**2 + +def test_loggamma(): + raises(TypeError, lambda: loggamma(2, 3)) + raises(ArgumentIndexError, lambda: loggamma(x).fdiff(2)) + + assert loggamma(-1) is oo + assert loggamma(-2) is oo + assert loggamma(0) is oo + assert loggamma(1) == 0 + assert loggamma(2) == 0 + assert loggamma(3) == log(2) + assert loggamma(4) == log(6) + + n = Symbol("n", integer=True, positive=True) + assert loggamma(n) == log(gamma(n)) + assert loggamma(-n) is oo + assert loggamma(n/2) == log(2**(-n + 1)*sqrt(pi)*gamma(n)/gamma(n/2 + S.Half)) + + assert loggamma(oo) is oo + assert loggamma(-oo) is zoo + assert loggamma(I*oo) is zoo + assert loggamma(-I*oo) is zoo + assert loggamma(zoo) is zoo + assert loggamma(nan) is nan + + L = loggamma(Rational(16, 3)) + E = -5*log(3) + loggamma(Rational(1, 3)) + log(4) + log(7) + log(10) + log(13) + assert expand_func(L).doit() == E + assert L.n() == E.n() + + L = loggamma(Rational(19, 4)) + E = -4*log(4) + loggamma(Rational(3, 4)) + log(3) + log(7) + log(11) + log(15) + assert expand_func(L).doit() == E + assert L.n() == E.n() + + L = loggamma(Rational(23, 7)) + E = -3*log(7) + log(2) + loggamma(Rational(2, 7)) + log(9) + log(16) + assert expand_func(L).doit() == E + assert L.n() == E.n() + + L = loggamma(Rational(19, 4) - 7) + E = -log(9) - log(5) + loggamma(Rational(3, 4)) + 3*log(4) - 3*I*pi + assert expand_func(L).doit() == E + assert L.n() == E.n() + + L = loggamma(Rational(23, 7) - 6) + E = -log(19) - log(12) - log(5) + loggamma(Rational(2, 7)) + 3*log(7) - 3*I*pi + assert expand_func(L).doit() == E + assert L.n() == E.n() + + assert loggamma(x).diff(x) == polygamma(0, x) + s1 = loggamma(1/(x + sin(x)) + cos(x)).nseries(x, n=4) + s2 = (-log(2*x) - 1)/(2*x) - log(x/pi)/2 + (4 - log(2*x))*x/24 + O(x**2) + \ + log(x)*x**2/2 + assert (s1 - s2).expand(force=True).removeO() == 0 + s1 = loggamma(1/x).series(x) + s2 = (1/x - S.Half)*log(1/x) - 1/x + log(2*pi)/2 + \ + x/12 - x**3/360 + x**5/1260 + O(x**7) + assert ((s1 - s2).expand(force=True)).removeO() == 0 + + assert loggamma(x).rewrite('intractable') == log(gamma(x)) + + s1 = loggamma(x).series(x).cancel() + assert s1 == -log(x) - EulerGamma*x + pi**2*x**2/12 + x**3*polygamma(2, 1)/6 + \ + pi**4*x**4/360 + x**5*polygamma(4, 1)/120 + O(x**6) + assert s1 == loggamma(x).rewrite('intractable').series(x).cancel() + + assert conjugate(loggamma(x)) == loggamma(conjugate(x)) + assert conjugate(loggamma(0)) is oo + assert conjugate(loggamma(1)) == loggamma(conjugate(1)) + assert conjugate(loggamma(-oo)) == conjugate(zoo) + + assert loggamma(Symbol('v', positive=True)).is_real is True + assert loggamma(Symbol('v', zero=True)).is_real is False + assert loggamma(Symbol('v', negative=True)).is_real is False + assert loggamma(Symbol('v', nonpositive=True)).is_real is False + assert loggamma(Symbol('v', nonnegative=True)).is_real is None + assert loggamma(Symbol('v', imaginary=True)).is_real is None + assert loggamma(Symbol('v', real=True)).is_real is None + assert loggamma(Symbol('v')).is_real is None + + assert loggamma(S.Half).is_real is True + assert loggamma(0).is_real is False + assert loggamma(Rational(-1, 2)).is_real is False + assert loggamma(I).is_real is None + assert loggamma(2 + 3*I).is_real is None + + def tN(N, M): + assert loggamma(1/x)._eval_nseries(x, n=N).getn() == M + tN(0, 0) + tN(1, 1) + tN(2, 2) + tN(3, 3) + tN(4, 4) + tN(5, 5) + + +def test_polygamma_expansion(): + # A. & S., pa. 259 and 260 + assert polygamma(0, 1/x).nseries(x, n=3) == \ + -log(x) - x/2 - x**2/12 + O(x**3) + assert polygamma(1, 1/x).series(x, n=5) == \ + x + x**2/2 + x**3/6 + O(x**5) + assert polygamma(3, 1/x).nseries(x, n=11) == \ + 2*x**3 + 3*x**4 + 2*x**5 - x**7 + 4*x**9/3 + O(x**11) + + +def test_polygamma_leading_term(): + expr = -log(1/x) + polygamma(0, 1 + 1/x) + S.EulerGamma + assert expr.as_leading_term(x, logx=-y) == S.EulerGamma + + +def test_issue_8657(): + n = Symbol('n', negative=True, integer=True) + m = Symbol('m', integer=True) + o = Symbol('o', positive=True) + p = Symbol('p', negative=True, integer=False) + assert gamma(n).is_real is False + assert gamma(m).is_real is None + assert gamma(o).is_real is True + assert gamma(p).is_real is True + assert gamma(w).is_real is None + + +def test_issue_8524(): + x = Symbol('x', positive=True) + y = Symbol('y', negative=True) + z = Symbol('z', positive=False) + p = Symbol('p', negative=False) + q = Symbol('q', integer=True) + r = Symbol('r', integer=False) + e = Symbol('e', even=True, negative=True) + assert gamma(x).is_positive is True + assert gamma(y).is_positive is None + assert gamma(z).is_positive is None + assert gamma(p).is_positive is None + assert gamma(q).is_positive is None + assert gamma(r).is_positive is None + assert gamma(e + S.Half).is_positive is True + assert gamma(e - S.Half).is_positive is False + +def test_issue_14450(): + assert uppergamma(Rational(3, 8), x).evalf() == uppergamma(Rational(3, 8), x) + assert lowergamma(x, Rational(3, 8)).evalf() == lowergamma(x, Rational(3, 8)) + # some values from Wolfram Alpha for comparison + assert abs(uppergamma(Rational(3, 8), 2).evalf() - 0.07105675881) < 1e-9 + assert abs(lowergamma(Rational(3, 8), 2).evalf() - 2.2993794256) < 1e-9 + +def test_issue_14528(): + k = Symbol('k', integer=True, nonpositive=True) + assert isinstance(gamma(k), gamma) + +def test_multigamma(): + from sympy.concrete.products import Product + p = Symbol('p') + _k = Dummy('_k') + + assert multigamma(x, p).dummy_eq(pi**(p*(p - 1)/4)*\ + Product(gamma(x + (1 - _k)/2), (_k, 1, p))) + + assert conjugate(multigamma(x, p)).dummy_eq(pi**((conjugate(p) - 1)*\ + conjugate(p)/4)*Product(gamma(conjugate(x) + (1-conjugate(_k))/2), (_k, 1, p))) + assert conjugate(multigamma(x, 1)) == gamma(conjugate(x)) + + p = Symbol('p', positive=True) + assert conjugate(multigamma(x, p)).dummy_eq(pi**((p - 1)*p/4)*\ + Product(gamma(conjugate(x) + (1-conjugate(_k))/2), (_k, 1, p))) + + assert multigamma(nan, 1) is nan + assert multigamma(oo, 1).doit() is oo + + assert multigamma(1, 1) == 1 + assert multigamma(2, 1) == 1 + assert multigamma(3, 1) == 2 + + assert multigamma(102, 1) == factorial(101) + assert multigamma(S.Half, 1) == sqrt(pi) + + assert multigamma(1, 2) == pi + assert multigamma(2, 2) == pi/2 + + assert multigamma(1, 3) is zoo + assert multigamma(2, 3) == pi**2/2 + assert multigamma(3, 3) == 3*pi**2/2 + + assert multigamma(x, 1).diff(x) == gamma(x)*polygamma(0, x) + assert multigamma(x, 2).diff(x) == sqrt(pi)*gamma(x)*gamma(x - S.Half)*\ + polygamma(0, x) + sqrt(pi)*gamma(x)*gamma(x - S.Half)*polygamma(0, x - S.Half) + + assert multigamma(x - 1, 1).expand(func=True) == gamma(x)/(x - 1) + assert multigamma(x + 2, 1).expand(func=True, mul=False) == x*(x + 1)*\ + gamma(x) + assert multigamma(x - 1, 2).expand(func=True) == sqrt(pi)*gamma(x)*\ + gamma(x + S.Half)/(x**3 - 3*x**2 + x*Rational(11, 4) - Rational(3, 4)) + assert multigamma(x - 1, 3).expand(func=True) == pi**Rational(3, 2)*gamma(x)**2*\ + gamma(x + S.Half)/(x**5 - 6*x**4 + 55*x**3/4 - 15*x**2 + x*Rational(31, 4) - Rational(3, 2)) + + assert multigamma(n, 1).rewrite(factorial) == factorial(n - 1) + assert multigamma(n, 2).rewrite(factorial) == sqrt(pi)*\ + factorial(n - Rational(3, 2))*factorial(n - 1) + assert multigamma(n, 3).rewrite(factorial) == pi**Rational(3, 2)*\ + factorial(n - 2)*factorial(n - Rational(3, 2))*factorial(n - 1) + + assert multigamma(Rational(-1, 2), 3, evaluate=False).is_real == False + assert multigamma(S.Half, 3, evaluate=False).is_real == False + assert multigamma(0, 1, evaluate=False).is_real == False + assert multigamma(1, 3, evaluate=False).is_real == False + assert multigamma(-1.0, 3, evaluate=False).is_real == False + assert multigamma(0.7, 3, evaluate=False).is_real == True + assert multigamma(3, 3, evaluate=False).is_real == True + +def test_gamma_as_leading_term(): + assert gamma(x).as_leading_term(x) == 1/x + assert gamma(2 + x).as_leading_term(x) == S(1) + assert gamma(cos(x)).as_leading_term(x) == S(1) + assert gamma(sin(x)).as_leading_term(x) == 1/x diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_hyper.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_hyper.py new file mode 100644 index 0000000000000000000000000000000000000000..f1be5b5f0db158ff76173e180ed8d88bd59461b9 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_hyper.py @@ -0,0 +1,403 @@ +from sympy.core.containers import Tuple +from sympy.core.function import Derivative +from sympy.core.numbers import (I, Rational, oo, pi) +from sympy.core.singleton import S +from sympy.core.symbol import symbols +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import cos +from sympy.functions.special.gamma_functions import gamma +from sympy.functions.special.hyper import (appellf1, hyper, meijerg) +from sympy.series.order import O +from sympy.abc import x, z, k +from sympy.series.limits import limit +from sympy.testing.pytest import raises, slow +from sympy.core.random import ( + random_complex_number as randcplx, + verify_numerically as tn, + test_derivative_numerically as td) + + +def test_TupleParametersBase(): + # test that our implementation of the chain rule works + p = hyper((), (), z**2) + assert p.diff(z) == p*2*z + + +def test_hyper(): + raises(TypeError, lambda: hyper(1, 2, z)) + + assert hyper((2, 1), (1,), z) == hyper(Tuple(1, 2), Tuple(1), z) + assert hyper((2, 1, 2), (1, 2, 1, 3), z) == hyper((2,), (1, 3), z) + u = hyper((2, 1, 2), (1, 2, 1, 3), z, evaluate=False) + assert u.ap == Tuple(1, 2, 2) + assert u.bq == Tuple(1, 1, 2, 3) + + h = hyper((1, 2), (3, 4, 5), z) + assert h.ap == Tuple(1, 2) + assert h.bq == Tuple(3, 4, 5) + assert h.argument == z + assert h.is_commutative is True + h = hyper((2, 1), (4, 3, 5), z) + assert h.ap == Tuple(1, 2) + assert h.bq == Tuple(3, 4, 5) + assert h.argument == z + assert h.is_commutative is True + + # just a few checks to make sure that all arguments go where they should + assert tn(hyper(Tuple(), Tuple(), z), exp(z), z) + assert tn(z*hyper((1, 1), Tuple(2), -z), log(1 + z), z) + + # differentiation + h = hyper( + (randcplx(), randcplx(), randcplx()), (randcplx(), randcplx()), z) + assert td(h, z) + + a1, a2, b1, b2, b3 = symbols('a1:3, b1:4') + assert hyper((a1, a2), (b1, b2, b3), z).diff(z) == \ + a1*a2/(b1*b2*b3) * hyper((a1 + 1, a2 + 1), (b1 + 1, b2 + 1, b3 + 1), z) + + # differentiation wrt parameters is not supported + assert hyper([z], [], z).diff(z) == Derivative(hyper([z], [], z), z) + + # hyper is unbranched wrt parameters + from sympy.functions.elementary.complexes import polar_lift + assert hyper([polar_lift(z)], [polar_lift(k)], polar_lift(x)) == \ + hyper([z], [k], polar_lift(x)) + + # hyper does not automatically evaluate anyway, but the test is to make + # sure that the evaluate keyword is accepted + assert hyper((1, 2), (1,), z, evaluate=False).func is hyper + + +def test_expand_func(): + # evaluation at 1 of Gauss' hypergeometric function: + from sympy.abc import a, b, c + from sympy.core.function import expand_func + a1, b1, c1 = randcplx(), randcplx(), randcplx() + 5 + assert expand_func(hyper([a, b], [c], 1)) == \ + gamma(c)*gamma(-a - b + c)/(gamma(-a + c)*gamma(-b + c)) + assert abs(expand_func(hyper([a1, b1], [c1], 1)).n() + - hyper([a1, b1], [c1], 1).n()) < 1e-10 + + # hyperexpand wrapper for hyper: + assert expand_func(hyper([], [], z)) == exp(z) + assert expand_func(hyper([1, 2, 3], [], z)) == hyper([1, 2, 3], [], z) + assert expand_func(meijerg([[1, 1], []], [[1], [0]], z)) == log(z + 1) + assert expand_func(meijerg([[1, 1], []], [[], []], z)) == \ + meijerg([[1, 1], []], [[], []], z) + + +def replace_dummy(expr, sym): + from sympy.core.symbol import Dummy + dum = expr.atoms(Dummy) + if not dum: + return expr + assert len(dum) == 1 + return expr.xreplace({dum.pop(): sym}) + + +def test_hyper_rewrite_sum(): + from sympy.concrete.summations import Sum + from sympy.core.symbol import Dummy + from sympy.functions.combinatorial.factorials import (RisingFactorial, factorial) + _k = Dummy("k") + assert replace_dummy(hyper((1, 2), (1, 3), x).rewrite(Sum), _k) == \ + Sum(x**_k / factorial(_k) * RisingFactorial(2, _k) / + RisingFactorial(3, _k), (_k, 0, oo)) + + assert hyper((1, 2, 3), (-1, 3), z).rewrite(Sum) == \ + hyper((1, 2, 3), (-1, 3), z) + + +def test_radius_of_convergence(): + assert hyper((1, 2), [3], z).radius_of_convergence == 1 + assert hyper((1, 2), [3, 4], z).radius_of_convergence is oo + assert hyper((1, 2, 3), [4], z).radius_of_convergence == 0 + assert hyper((0, 1, 2), [4], z).radius_of_convergence is oo + assert hyper((-1, 1, 2), [-4], z).radius_of_convergence == 0 + assert hyper((-1, -2, 2), [-1], z).radius_of_convergence is oo + assert hyper((-1, 2), [-1, -2], z).radius_of_convergence == 0 + assert hyper([-1, 1, 3], [-2, 2], z).radius_of_convergence == 1 + assert hyper([-1, 1], [-2, 2], z).radius_of_convergence is oo + assert hyper([-1, 1, 3], [-2], z).radius_of_convergence == 0 + assert hyper((-1, 2, 3, 4), [], z).radius_of_convergence is oo + + assert hyper([1, 1], [3], 1).convergence_statement == True + assert hyper([1, 1], [2], 1).convergence_statement == False + assert hyper([1, 1], [2], -1).convergence_statement == True + assert hyper([1, 1], [1], -1).convergence_statement == False + + +def test_meijer(): + raises(TypeError, lambda: meijerg(1, z)) + raises(TypeError, lambda: meijerg(((1,), (2,)), (3,), (4,), z)) + + assert meijerg(((1, 2), (3,)), ((4,), (5,)), z) == \ + meijerg(Tuple(1, 2), Tuple(3), Tuple(4), Tuple(5), z) + + g = meijerg((1, 2), (3, 4, 5), (6, 7, 8, 9), (10, 11, 12, 13, 14), z) + assert g.an == Tuple(1, 2) + assert g.ap == Tuple(1, 2, 3, 4, 5) + assert g.aother == Tuple(3, 4, 5) + assert g.bm == Tuple(6, 7, 8, 9) + assert g.bq == Tuple(6, 7, 8, 9, 10, 11, 12, 13, 14) + assert g.bother == Tuple(10, 11, 12, 13, 14) + assert g.argument == z + assert g.nu == 75 + assert g.delta == -1 + assert g.is_commutative is True + assert g.is_number is False + #issue 13071 + assert meijerg([[],[]], [[S.Half],[0]], 1).is_number is True + + assert meijerg([1, 2], [3], [4], [5], z).delta == S.Half + + # just a few checks to make sure that all arguments go where they should + assert tn(meijerg(Tuple(), Tuple(), Tuple(0), Tuple(), -z), exp(z), z) + assert tn(sqrt(pi)*meijerg(Tuple(), Tuple(), + Tuple(0), Tuple(S.Half), z**2/4), cos(z), z) + assert tn(meijerg(Tuple(1, 1), Tuple(), Tuple(1), Tuple(0), z), + log(1 + z), z) + + # test exceptions + raises(ValueError, lambda: meijerg(((3, 1), (2,)), ((oo,), (2, 0)), x)) + raises(ValueError, lambda: meijerg(((3, 1), (2,)), ((1,), (2, 0)), x)) + + # differentiation + g = meijerg((randcplx(),), (randcplx() + 2*I,), Tuple(), + (randcplx(), randcplx()), z) + assert td(g, z) + + g = meijerg(Tuple(), (randcplx(),), Tuple(), + (randcplx(), randcplx()), z) + assert td(g, z) + + g = meijerg(Tuple(), Tuple(), Tuple(randcplx()), + Tuple(randcplx(), randcplx()), z) + assert td(g, z) + + a1, a2, b1, b2, c1, c2, d1, d2 = symbols('a1:3, b1:3, c1:3, d1:3') + assert meijerg((a1, a2), (b1, b2), (c1, c2), (d1, d2), z).diff(z) == \ + (meijerg((a1 - 1, a2), (b1, b2), (c1, c2), (d1, d2), z) + + (a1 - 1)*meijerg((a1, a2), (b1, b2), (c1, c2), (d1, d2), z))/z + + assert meijerg([z, z], [], [], [], z).diff(z) == \ + Derivative(meijerg([z, z], [], [], [], z), z) + + # meijerg is unbranched wrt parameters + from sympy.functions.elementary.complexes import polar_lift as pl + assert meijerg([pl(a1)], [pl(a2)], [pl(b1)], [pl(b2)], pl(z)) == \ + meijerg([a1], [a2], [b1], [b2], pl(z)) + + # integrand + from sympy.abc import a, b, c, d, s + assert meijerg([a], [b], [c], [d], z).integrand(s) == \ + z**s*gamma(c - s)*gamma(-a + s + 1)/(gamma(b - s)*gamma(-d + s + 1)) + + +def test_meijerg_derivative(): + assert meijerg([], [1, 1], [0, 0, x], [], z).diff(x) == \ + log(z)*meijerg([], [1, 1], [0, 0, x], [], z) \ + + 2*meijerg([], [1, 1, 1], [0, 0, x, 0], [], z) + + y = randcplx() + a = 5 # mpmath chokes with non-real numbers, and Mod1 with floats + assert td(meijerg([x], [], [], [], y), x) + assert td(meijerg([x**2], [], [], [], y), x) + assert td(meijerg([], [x], [], [], y), x) + assert td(meijerg([], [], [x], [], y), x) + assert td(meijerg([], [], [], [x], y), x) + assert td(meijerg([x], [a], [a + 1], [], y), x) + assert td(meijerg([x], [a + 1], [a], [], y), x) + assert td(meijerg([x, a], [], [], [a + 1], y), x) + assert td(meijerg([x, a + 1], [], [], [a], y), x) + b = Rational(3, 2) + assert td(meijerg([a + 2], [b], [b - 3, x], [a], y), x) + + +def test_meijerg_period(): + assert meijerg([], [1], [0], [], x).get_period() == 2*pi + assert meijerg([1], [], [], [0], x).get_period() == 2*pi + assert meijerg([], [], [0], [], x).get_period() == 2*pi # exp(x) + assert meijerg( + [], [], [0], [S.Half], x).get_period() == 2*pi # cos(sqrt(x)) + assert meijerg( + [], [], [S.Half], [0], x).get_period() == 4*pi # sin(sqrt(x)) + assert meijerg([1, 1], [], [1], [0], x).get_period() is oo # log(1 + x) + + +def test_hyper_unpolarify(): + from sympy.functions.elementary.exponential import exp_polar + a = exp_polar(2*pi*I)*x + b = x + assert hyper([], [], a).argument == b + assert hyper([0], [], a).argument == a + assert hyper([0], [0], a).argument == b + assert hyper([0, 1], [0], a).argument == a + assert hyper([0, 1], [0], exp_polar(2*pi*I)).argument == 1 + + +@slow +def test_hyperrep(): + from sympy.functions.special.hyper import (HyperRep, HyperRep_atanh, + HyperRep_power1, HyperRep_power2, HyperRep_log1, HyperRep_asin1, + HyperRep_asin2, HyperRep_sqrts1, HyperRep_sqrts2, HyperRep_log2, + HyperRep_cosasin, HyperRep_sinasin) + # First test the base class works. + from sympy.functions.elementary.exponential import exp_polar + from sympy.functions.elementary.piecewise import Piecewise + a, b, c, d, z = symbols('a b c d z') + + class myrep(HyperRep): + @classmethod + def _expr_small(cls, x): + return a + + @classmethod + def _expr_small_minus(cls, x): + return b + + @classmethod + def _expr_big(cls, x, n): + return c*n + + @classmethod + def _expr_big_minus(cls, x, n): + return d*n + assert myrep(z).rewrite('nonrep') == Piecewise((0, abs(z) > 1), (a, True)) + assert myrep(exp_polar(I*pi)*z).rewrite('nonrep') == \ + Piecewise((0, abs(z) > 1), (b, True)) + assert myrep(exp_polar(2*I*pi)*z).rewrite('nonrep') == \ + Piecewise((c, abs(z) > 1), (a, True)) + assert myrep(exp_polar(3*I*pi)*z).rewrite('nonrep') == \ + Piecewise((d, abs(z) > 1), (b, True)) + assert myrep(exp_polar(4*I*pi)*z).rewrite('nonrep') == \ + Piecewise((2*c, abs(z) > 1), (a, True)) + assert myrep(exp_polar(5*I*pi)*z).rewrite('nonrep') == \ + Piecewise((2*d, abs(z) > 1), (b, True)) + assert myrep(z).rewrite('nonrepsmall') == a + assert myrep(exp_polar(I*pi)*z).rewrite('nonrepsmall') == b + + def t(func, hyp, z): + """ Test that func is a valid representation of hyp. """ + # First test that func agrees with hyp for small z + if not tn(func.rewrite('nonrepsmall'), hyp, z, + a=Rational(-1, 2), b=Rational(-1, 2), c=S.Half, d=S.Half): + return False + # Next check that the two small representations agree. + if not tn( + func.rewrite('nonrepsmall').subs( + z, exp_polar(I*pi)*z).replace(exp_polar, exp), + func.subs(z, exp_polar(I*pi)*z).rewrite('nonrepsmall'), + z, a=Rational(-1, 2), b=Rational(-1, 2), c=S.Half, d=S.Half): + return False + # Next check continuity along exp_polar(I*pi)*t + expr = func.subs(z, exp_polar(I*pi)*z).rewrite('nonrep') + if abs(expr.subs(z, 1 + 1e-15).n() - expr.subs(z, 1 - 1e-15).n()) > 1e-10: + return False + # Finally check continuity of the big reps. + + def dosubs(func, a, b): + rv = func.subs(z, exp_polar(a)*z).rewrite('nonrep') + return rv.subs(z, exp_polar(b)*z).replace(exp_polar, exp) + for n in [0, 1, 2, 3, 4, -1, -2, -3, -4]: + expr1 = dosubs(func, 2*I*pi*n, I*pi/2) + expr2 = dosubs(func, 2*I*pi*n + I*pi, -I*pi/2) + if not tn(expr1, expr2, z): + return False + expr1 = dosubs(func, 2*I*pi*(n + 1), -I*pi/2) + expr2 = dosubs(func, 2*I*pi*n + I*pi, I*pi/2) + if not tn(expr1, expr2, z): + return False + return True + + # Now test the various representatives. + a = Rational(1, 3) + assert t(HyperRep_atanh(z), hyper([S.Half, 1], [Rational(3, 2)], z), z) + assert t(HyperRep_power1(a, z), hyper([-a], [], z), z) + assert t(HyperRep_power2(a, z), hyper([a, a - S.Half], [2*a], z), z) + assert t(HyperRep_log1(z), -z*hyper([1, 1], [2], z), z) + assert t(HyperRep_asin1(z), hyper([S.Half, S.Half], [Rational(3, 2)], z), z) + assert t(HyperRep_asin2(z), hyper([1, 1], [Rational(3, 2)], z), z) + assert t(HyperRep_sqrts1(a, z), hyper([-a, S.Half - a], [S.Half], z), z) + assert t(HyperRep_sqrts2(a, z), + -2*z/(2*a + 1)*hyper([-a - S.Half, -a], [S.Half], z).diff(z), z) + assert t(HyperRep_log2(z), -z/4*hyper([Rational(3, 2), 1, 1], [2, 2], z), z) + assert t(HyperRep_cosasin(a, z), hyper([-a, a], [S.Half], z), z) + assert t(HyperRep_sinasin(a, z), 2*a*z*hyper([1 - a, 1 + a], [Rational(3, 2)], z), z) + + +@slow +def test_meijerg_eval(): + from sympy.functions.elementary.exponential import exp_polar + from sympy.functions.special.bessel import besseli + from sympy.abc import l + a = randcplx() + arg = x*exp_polar(k*pi*I) + expr1 = pi*meijerg([[], [(a + 1)/2]], [[a/2], [-a/2, (a + 1)/2]], arg**2/4) + expr2 = besseli(a, arg) + + # Test that the two expressions agree for all arguments. + for x_ in [0.5, 1.5]: + for k_ in [0.0, 0.1, 0.3, 0.5, 0.8, 1, 5.751, 15.3]: + assert abs((expr1 - expr2).n(subs={x: x_, k: k_})) < 1e-10 + assert abs((expr1 - expr2).n(subs={x: x_, k: -k_})) < 1e-10 + + # Test continuity independently + eps = 1e-13 + expr2 = expr1.subs(k, l) + for x_ in [0.5, 1.5]: + for k_ in [0.5, Rational(1, 3), 0.25, 0.75, Rational(2, 3), 1.0, 1.5]: + assert abs((expr1 - expr2).n( + subs={x: x_, k: k_ + eps, l: k_ - eps})) < 1e-10 + assert abs((expr1 - expr2).n( + subs={x: x_, k: -k_ + eps, l: -k_ - eps})) < 1e-10 + + expr = (meijerg(((0.5,), ()), ((0.5, 0, 0.5), ()), exp_polar(-I*pi)/4) + + meijerg(((0.5,), ()), ((0.5, 0, 0.5), ()), exp_polar(I*pi)/4)) \ + /(2*sqrt(pi)) + assert (expr - pi/exp(1)).n(chop=True) == 0 + + +def test_limits(): + k, x = symbols('k, x') + assert hyper((1,), (Rational(4, 3), Rational(5, 3)), k**2).series(k) == \ + 1 + 9*k**2/20 + 81*k**4/1120 + O(k**6) # issue 6350 + + # https://github.com/sympy/sympy/issues/11465 + assert limit(1/hyper((1, ), (1, ), x), x, 0) == 1 + + +def test_appellf1(): + a, b1, b2, c, x, y = symbols('a b1 b2 c x y') + assert appellf1(a, b2, b1, c, y, x) == appellf1(a, b1, b2, c, x, y) + assert appellf1(a, b1, b1, c, y, x) == appellf1(a, b1, b1, c, x, y) + assert appellf1(a, b1, b2, c, S.Zero, S.Zero) is S.One + + f = appellf1(a, b1, b2, c, S.Zero, S.Zero, evaluate=False) + assert f.func is appellf1 + assert f.doit() is S.One + + +def test_derivative_appellf1(): + from sympy.core.function import diff + a, b1, b2, c, x, y, z = symbols('a b1 b2 c x y z') + assert diff(appellf1(a, b1, b2, c, x, y), x) == a*b1*appellf1(a + 1, b2, b1 + 1, c + 1, y, x)/c + assert diff(appellf1(a, b1, b2, c, x, y), y) == a*b2*appellf1(a + 1, b1, b2 + 1, c + 1, x, y)/c + assert diff(appellf1(a, b1, b2, c, x, y), z) == 0 + assert diff(appellf1(a, b1, b2, c, x, y), a) == Derivative(appellf1(a, b1, b2, c, x, y), a) + + +def test_eval_nseries(): + a1, b1, a2, b2 = symbols('a1 b1 a2 b2') + assert hyper((1,2), (1,2,3), x**2)._eval_nseries(x, 7, None) == \ + 1 + x**2/3 + x**4/24 + x**6/360 + O(x**7) + assert exp(x)._eval_nseries(x,7,None) == \ + hyper((a1, b1), (a1, b1), x)._eval_nseries(x, 7, None) + assert hyper((a1, a2), (b1, b2), x)._eval_nseries(z, 7, None) ==\ + hyper((a1, a2), (b1, b2), x) + O(z**7) + assert hyper((-S(1)/2, S(1)/2), (1,), 4*x/(x + 1)).nseries(x) == \ + 1 - x + x**2/4 - 3*x**3/4 - 15*x**4/64 - 93*x**5/64 + O(x**6) + assert (pi/2*hyper((-S(1)/2, S(1)/2), (1,), 4*x/(x + 1))).nseries(x) == \ + pi/2 - pi*x/2 + pi*x**2/8 - 3*pi*x**3/8 - 15*pi*x**4/128 - 93*pi*x**5/128 + O(x**6) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_mathieu.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_mathieu.py new file mode 100644 index 0000000000000000000000000000000000000000..b9296f0657d920c8d297f820fb3ab8b6a53129ab --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_mathieu.py @@ -0,0 +1,29 @@ +from sympy.core.function import diff +from sympy.functions.elementary.complexes import conjugate +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.functions.special.mathieu_functions import (mathieuc, mathieucprime, mathieus, mathieusprime) + +from sympy.abc import a, q, z + + +def test_mathieus(): + assert isinstance(mathieus(a, q, z), mathieus) + assert mathieus(a, 0, z) == sin(sqrt(a)*z) + assert conjugate(mathieus(a, q, z)) == mathieus(conjugate(a), conjugate(q), conjugate(z)) + assert diff(mathieus(a, q, z), z) == mathieusprime(a, q, z) + +def test_mathieuc(): + assert isinstance(mathieuc(a, q, z), mathieuc) + assert mathieuc(a, 0, z) == cos(sqrt(a)*z) + assert diff(mathieuc(a, q, z), z) == mathieucprime(a, q, z) + +def test_mathieusprime(): + assert isinstance(mathieusprime(a, q, z), mathieusprime) + assert mathieusprime(a, 0, z) == sqrt(a)*cos(sqrt(a)*z) + assert diff(mathieusprime(a, q, z), z) == (-a + 2*q*cos(2*z))*mathieus(a, q, z) + +def test_mathieucprime(): + assert isinstance(mathieucprime(a, q, z), mathieucprime) + assert mathieucprime(a, 0, z) == -sqrt(a)*sin(sqrt(a)*z) + assert diff(mathieucprime(a, q, z), z) == (-a + 2*q*cos(2*z))*mathieuc(a, q, z) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_singularity_functions.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_singularity_functions.py new file mode 100644 index 0000000000000000000000000000000000000000..dbd85cb0c7e5524d4fe1441615879b9776ad1693 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_singularity_functions.py @@ -0,0 +1,129 @@ +from sympy.core.function import (Derivative, diff) +from sympy.core.numbers import (Float, I, nan, oo, pi) +from sympy.core.relational import Eq +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.elementary.piecewise import Piecewise +from sympy.functions.special.delta_functions import (DiracDelta, Heaviside) +from sympy.functions.special.singularity_functions import SingularityFunction +from sympy.series.order import O + + +from sympy.core.expr import unchanged +from sympy.core.function import ArgumentIndexError +from sympy.testing.pytest import raises + +x, y, a, n = symbols('x y a n') + + +def test_fdiff(): + assert SingularityFunction(x, 4, 5).fdiff() == 5*SingularityFunction(x, 4, 4) + assert SingularityFunction(x, 4, -1).fdiff() == SingularityFunction(x, 4, -2) + assert SingularityFunction(x, 4, -2).fdiff() == SingularityFunction(x, 4, -3) + assert SingularityFunction(x, 4, -3).fdiff() == SingularityFunction(x, 4, -4) + assert SingularityFunction(x, 4, 0).fdiff() == SingularityFunction(x, 4, -1) + + assert SingularityFunction(y, 6, 2).diff(y) == 2*SingularityFunction(y, 6, 1) + assert SingularityFunction(y, -4, -1).diff(y) == SingularityFunction(y, -4, -2) + assert SingularityFunction(y, 4, 0).diff(y) == SingularityFunction(y, 4, -1) + assert SingularityFunction(y, 4, 0).diff(y, 2) == SingularityFunction(y, 4, -2) + + n = Symbol('n', positive=True) + assert SingularityFunction(x, a, n).fdiff() == n*SingularityFunction(x, a, n - 1) + assert SingularityFunction(y, a, n).diff(y) == n*SingularityFunction(y, a, n - 1) + + expr_in = 4*SingularityFunction(x, a, n) + 3*SingularityFunction(x, a, -1) + -10*SingularityFunction(x, a, 0) + expr_out = n*4*SingularityFunction(x, a, n - 1) + 3*SingularityFunction(x, a, -2) - 10*SingularityFunction(x, a, -1) + assert diff(expr_in, x) == expr_out + + assert SingularityFunction(x, -10, 5).diff(evaluate=False) == ( + Derivative(SingularityFunction(x, -10, 5), x)) + + raises(ArgumentIndexError, lambda: SingularityFunction(x, 4, 5).fdiff(2)) + + +def test_eval(): + assert SingularityFunction(x, a, n).func == SingularityFunction + assert unchanged(SingularityFunction, x, 5, n) + assert SingularityFunction(5, 3, 2) == 4 + assert SingularityFunction(3, 5, 1) == 0 + assert SingularityFunction(3, 3, 0) == 1 + assert SingularityFunction(3, 3, 1) == 0 + assert SingularityFunction(Symbol('z', zero=True), 0, 1) == 0 # like sin(z) == 0 + assert SingularityFunction(4, 4, -1) is oo + assert SingularityFunction(4, 2, -1) == 0 + assert SingularityFunction(4, 7, -1) == 0 + assert SingularityFunction(5, 6, -2) == 0 + assert SingularityFunction(4, 2, -2) == 0 + assert SingularityFunction(4, 4, -2) is oo + assert SingularityFunction(4, 2, -3) == 0 + assert SingularityFunction(8, 8, -3) is oo + assert SingularityFunction(4, 2, -4) == 0 + assert SingularityFunction(8, 8, -4) is oo + assert (SingularityFunction(6.1, 4, 5)).evalf(5) == Float('40.841', '5') + assert SingularityFunction(6.1, pi, 2) == (-pi + 6.1)**2 + assert SingularityFunction(x, a, nan) is nan + assert SingularityFunction(x, nan, 1) is nan + assert SingularityFunction(nan, a, n) is nan + + raises(ValueError, lambda: SingularityFunction(x, a, I)) + raises(ValueError, lambda: SingularityFunction(2*I, I, n)) + raises(ValueError, lambda: SingularityFunction(x, a, -5)) + + +def test_leading_term(): + l = Symbol('l', positive=True) + assert SingularityFunction(x, 3, 2).as_leading_term(x) == 0 + assert SingularityFunction(x, -2, 1).as_leading_term(x) == 2 + assert SingularityFunction(x, 0, 0).as_leading_term(x) == 1 + assert SingularityFunction(x, 0, 0).as_leading_term(x, cdir=-1) == 0 + assert SingularityFunction(x, 0, -1).as_leading_term(x) == 0 + assert SingularityFunction(x, 0, -2).as_leading_term(x) == 0 + assert SingularityFunction(x, 0, -3).as_leading_term(x) == 0 + assert SingularityFunction(x, 0, -4).as_leading_term(x) == 0 + assert (SingularityFunction(x + l, 0, 1)/2\ + - SingularityFunction(x + l, l/2, 1)\ + + SingularityFunction(x + l, l, 1)/2).as_leading_term(x) == -x/2 + + +def test_series(): + l = Symbol('l', positive=True) + assert SingularityFunction(x, -3, 2).series(x) == x**2 + 6*x + 9 + assert SingularityFunction(x, -2, 1).series(x) == x + 2 + assert SingularityFunction(x, 0, 0).series(x) == 1 + assert SingularityFunction(x, 0, 0).series(x, dir='-') == 0 + assert SingularityFunction(x, 0, -1).series(x) == 0 + assert SingularityFunction(x, 0, -2).series(x) == 0 + assert SingularityFunction(x, 0, -3).series(x) == 0 + assert SingularityFunction(x, 0, -4).series(x) == 0 + assert (SingularityFunction(x + l, 0, 1)/2\ + - SingularityFunction(x + l, l/2, 1)\ + + SingularityFunction(x + l, l, 1)/2).nseries(x) == -x/2 + O(x**6) + + +def test_rewrite(): + assert SingularityFunction(x, 4, 5).rewrite(Piecewise) == ( + Piecewise(((x - 4)**5, x - 4 >= 0), (0, True))) + assert SingularityFunction(x, -10, 0).rewrite(Piecewise) == ( + Piecewise((1, x + 10 >= 0), (0, True))) + assert SingularityFunction(x, 2, -1).rewrite(Piecewise) == ( + Piecewise((oo, Eq(x - 2, 0)), (0, True))) + assert SingularityFunction(x, 0, -2).rewrite(Piecewise) == ( + Piecewise((oo, Eq(x, 0)), (0, True))) + + n = Symbol('n', nonnegative=True) + p = SingularityFunction(x, a, n).rewrite(Piecewise) + assert p == ( + Piecewise(((x - a)**n, x - a >= 0), (0, True))) + assert p.subs(x, a).subs(n, 0) == 1 + + expr_in = SingularityFunction(x, 4, 5) + SingularityFunction(x, -3, -1) - SingularityFunction(x, 0, -2) + expr_out = (x - 4)**5*Heaviside(x - 4, 1) + DiracDelta(x + 3) - DiracDelta(x, 1) + assert expr_in.rewrite(Heaviside) == expr_out + assert expr_in.rewrite(DiracDelta) == expr_out + assert expr_in.rewrite('HeavisideDiracDelta') == expr_out + + expr_in = SingularityFunction(x, a, n) + SingularityFunction(x, a, -1) - SingularityFunction(x, a, -2) + expr_out = (x - a)**n*Heaviside(x - a, 1) + DiracDelta(x - a) + DiracDelta(a - x, 1) + assert expr_in.rewrite(Heaviside) == expr_out + assert expr_in.rewrite(DiracDelta) == expr_out + assert expr_in.rewrite('HeavisideDiracDelta') == expr_out diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_spec_polynomials.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_spec_polynomials.py new file mode 100644 index 0000000000000000000000000000000000000000..584ad3cf97df8b9d92da9fc7805ab4296f40671c --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_spec_polynomials.py @@ -0,0 +1,475 @@ +from sympy.concrete.summations import Sum +from sympy.core.function import (Derivative, diff) +from sympy.core.numbers import (Rational, oo, pi, zoo) +from sympy.core.singleton import S +from sympy.core.symbol import (Dummy, Symbol) +from sympy.functions.combinatorial.factorials import (RisingFactorial, binomial, factorial) +from sympy.functions.elementary.complexes import conjugate +from sympy.functions.elementary.exponential import exp +from sympy.functions.elementary.integers import floor +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import cos +from sympy.functions.special.gamma_functions import gamma +from sympy.functions.special.hyper import hyper +from sympy.functions.special.polynomials import (assoc_laguerre, assoc_legendre, chebyshevt, chebyshevt_root, chebyshevu, chebyshevu_root, gegenbauer, hermite, hermite_prob, jacobi, jacobi_normalized, laguerre, legendre) +from sympy.polys.orthopolys import laguerre_poly +from sympy.polys.polyroots import roots + +from sympy.core.expr import unchanged +from sympy.core.function import ArgumentIndexError +from sympy.testing.pytest import raises + + +x = Symbol('x') + + +def test_jacobi(): + n = Symbol("n") + a = Symbol("a") + b = Symbol("b") + + assert jacobi(0, a, b, x) == 1 + assert jacobi(1, a, b, x) == a/2 - b/2 + x*(a/2 + b/2 + 1) + + assert jacobi(n, a, a, x) == RisingFactorial( + a + 1, n)*gegenbauer(n, a + S.Half, x)/RisingFactorial(2*a + 1, n) + assert jacobi(n, a, -a, x) == ((-1)**a*(-x + 1)**(-a/2)*(x + 1)**(a/2)*assoc_legendre(n, a, x)* + factorial(-a + n)*gamma(a + n + 1)/(factorial(a + n)*gamma(n + 1))) + assert jacobi(n, -b, b, x) == ((-x + 1)**(b/2)*(x + 1)**(-b/2)*assoc_legendre(n, b, x)* + gamma(-b + n + 1)/gamma(n + 1)) + assert jacobi(n, 0, 0, x) == legendre(n, x) + assert jacobi(n, S.Half, S.Half, x) == RisingFactorial( + Rational(3, 2), n)*chebyshevu(n, x)/factorial(n + 1) + assert jacobi(n, Rational(-1, 2), Rational(-1, 2), x) == RisingFactorial( + S.Half, n)*chebyshevt(n, x)/factorial(n) + + X = jacobi(n, a, b, x) + assert isinstance(X, jacobi) + + assert jacobi(n, a, b, -x) == (-1)**n*jacobi(n, b, a, x) + assert jacobi(n, a, b, 0) == 2**(-n)*gamma(a + n + 1)*hyper( + (-b - n, -n), (a + 1,), -1)/(factorial(n)*gamma(a + 1)) + assert jacobi(n, a, b, 1) == RisingFactorial(a + 1, n)/factorial(n) + + m = Symbol("m", positive=True) + assert jacobi(m, a, b, oo) == oo*RisingFactorial(a + b + m + 1, m) + assert unchanged(jacobi, n, a, b, oo) + + assert conjugate(jacobi(m, a, b, x)) == \ + jacobi(m, conjugate(a), conjugate(b), conjugate(x)) + + _k = Dummy('k') + assert diff(jacobi(n, a, b, x), n) == Derivative(jacobi(n, a, b, x), n) + assert diff(jacobi(n, a, b, x), a).dummy_eq(Sum((jacobi(n, a, b, x) + + (2*_k + a + b + 1)*RisingFactorial(_k + b + 1, -_k + n)*jacobi(_k, a, + b, x)/((-_k + n)*RisingFactorial(_k + a + b + 1, -_k + n)))/(_k + a + + b + n + 1), (_k, 0, n - 1))) + assert diff(jacobi(n, a, b, x), b).dummy_eq(Sum(((-1)**(-_k + n)*(2*_k + + a + b + 1)*RisingFactorial(_k + a + 1, -_k + n)*jacobi(_k, a, b, x)/ + ((-_k + n)*RisingFactorial(_k + a + b + 1, -_k + n)) + jacobi(n, a, + b, x))/(_k + a + b + n + 1), (_k, 0, n - 1))) + assert diff(jacobi(n, a, b, x), x) == \ + (a/2 + b/2 + n/2 + S.Half)*jacobi(n - 1, a + 1, b + 1, x) + + assert jacobi_normalized(n, a, b, x) == \ + (jacobi(n, a, b, x)/sqrt(2**(a + b + 1)*gamma(a + n + 1)*gamma(b + n + 1) + /((a + b + 2*n + 1)*factorial(n)*gamma(a + b + n + 1)))) + + raises(ValueError, lambda: jacobi(-2.1, a, b, x)) + raises(ValueError, lambda: jacobi(Dummy(positive=True, integer=True), 1, 2, oo)) + + assert jacobi(n, a, b, x).rewrite(Sum).dummy_eq(Sum((S.Half - x/2) + **_k*RisingFactorial(-n, _k)*RisingFactorial(_k + a + 1, -_k + n)* + RisingFactorial(a + b + n + 1, _k)/factorial(_k), (_k, 0, n))/factorial(n)) + assert jacobi(n, a, b, x).rewrite("polynomial").dummy_eq(Sum((S.Half - x/2) + **_k*RisingFactorial(-n, _k)*RisingFactorial(_k + a + 1, -_k + n)* + RisingFactorial(a + b + n + 1, _k)/factorial(_k), (_k, 0, n))/factorial(n)) + raises(ArgumentIndexError, lambda: jacobi(n, a, b, x).fdiff(5)) + + +def test_gegenbauer(): + n = Symbol("n") + a = Symbol("a") + + assert gegenbauer(0, a, x) == 1 + assert gegenbauer(1, a, x) == 2*a*x + assert gegenbauer(2, a, x) == -a + x**2*(2*a**2 + 2*a) + assert gegenbauer(3, a, x) == \ + x**3*(4*a**3/3 + 4*a**2 + a*Rational(8, 3)) + x*(-2*a**2 - 2*a) + + assert gegenbauer(-1, a, x) == 0 + assert gegenbauer(n, S.Half, x) == legendre(n, x) + assert gegenbauer(n, 1, x) == chebyshevu(n, x) + assert gegenbauer(n, -1, x) == 0 + + X = gegenbauer(n, a, x) + assert isinstance(X, gegenbauer) + + assert gegenbauer(n, a, -x) == (-1)**n*gegenbauer(n, a, x) + assert gegenbauer(n, a, 0) == 2**n*sqrt(pi) * \ + gamma(a + n/2)/(gamma(a)*gamma(-n/2 + S.Half)*gamma(n + 1)) + assert gegenbauer(n, a, 1) == gamma(2*a + n)/(gamma(2*a)*gamma(n + 1)) + + assert gegenbauer(n, Rational(3, 4), -1) is zoo + assert gegenbauer(n, Rational(1, 4), -1) == (sqrt(2)*cos(pi*(n + S.One/4))* + gamma(n + S.Half)/(sqrt(pi)*gamma(n + 1))) + + m = Symbol("m", positive=True) + assert gegenbauer(m, a, oo) == oo*RisingFactorial(a, m) + assert unchanged(gegenbauer, n, a, oo) + + assert conjugate(gegenbauer(n, a, x)) == gegenbauer(n, conjugate(a), conjugate(x)) + + _k = Dummy('k') + + assert diff(gegenbauer(n, a, x), n) == Derivative(gegenbauer(n, a, x), n) + assert diff(gegenbauer(n, a, x), a).dummy_eq(Sum((2*(-1)**(-_k + n) + 2)* + (_k + a)*gegenbauer(_k, a, x)/((-_k + n)*(_k + 2*a + n)) + ((2*_k + + 2)/((_k + 2*a)*(2*_k + 2*a + 1)) + 2/(_k + 2*a + n))*gegenbauer(n, a + , x), (_k, 0, n - 1))) + assert diff(gegenbauer(n, a, x), x) == 2*a*gegenbauer(n - 1, a + 1, x) + + assert gegenbauer(n, a, x).rewrite(Sum).dummy_eq( + Sum((-1)**_k*(2*x)**(-2*_k + n)*RisingFactorial(a, -_k + n) + /(factorial(_k)*factorial(-2*_k + n)), (_k, 0, floor(n/2)))) + assert gegenbauer(n, a, x).rewrite("polynomial").dummy_eq( + Sum((-1)**_k*(2*x)**(-2*_k + n)*RisingFactorial(a, -_k + n) + /(factorial(_k)*factorial(-2*_k + n)), (_k, 0, floor(n/2)))) + + raises(ArgumentIndexError, lambda: gegenbauer(n, a, x).fdiff(4)) + + +def test_legendre(): + assert legendre(0, x) == 1 + assert legendre(1, x) == x + assert legendre(2, x) == ((3*x**2 - 1)/2).expand() + assert legendre(3, x) == ((5*x**3 - 3*x)/2).expand() + assert legendre(4, x) == ((35*x**4 - 30*x**2 + 3)/8).expand() + assert legendre(5, x) == ((63*x**5 - 70*x**3 + 15*x)/8).expand() + assert legendre(6, x) == ((231*x**6 - 315*x**4 + 105*x**2 - 5)/16).expand() + + assert legendre(10, -1) == 1 + assert legendre(11, -1) == -1 + assert legendre(10, 1) == 1 + assert legendre(11, 1) == 1 + assert legendre(10, 0) != 0 + assert legendre(11, 0) == 0 + + assert legendre(-1, x) == 1 + k = Symbol('k') + assert legendre(5 - k, x).subs(k, 2) == ((5*x**3 - 3*x)/2).expand() + + assert roots(legendre(4, x), x) == { + sqrt(Rational(3, 7) - Rational(2, 35)*sqrt(30)): 1, + -sqrt(Rational(3, 7) - Rational(2, 35)*sqrt(30)): 1, + sqrt(Rational(3, 7) + Rational(2, 35)*sqrt(30)): 1, + -sqrt(Rational(3, 7) + Rational(2, 35)*sqrt(30)): 1, + } + + n = Symbol("n") + + X = legendre(n, x) + assert isinstance(X, legendre) + assert unchanged(legendre, n, x) + + assert legendre(n, 0) == sqrt(pi)/(gamma(S.Half - n/2)*gamma(n/2 + 1)) + assert legendre(n, 1) == 1 + assert legendre(n, oo) is oo + assert legendre(-n, x) == legendre(n - 1, x) + assert legendre(n, -x) == (-1)**n*legendre(n, x) + assert unchanged(legendre, -n + k, x) + + assert conjugate(legendre(n, x)) == legendre(n, conjugate(x)) + + assert diff(legendre(n, x), x) == \ + n*(x*legendre(n, x) - legendre(n - 1, x))/(x**2 - 1) + assert diff(legendre(n, x), n) == Derivative(legendre(n, x), n) + + _k = Dummy('k') + assert legendre(n, x).rewrite(Sum).dummy_eq(Sum((-1)**_k*(S.Half - + x/2)**_k*(x/2 + S.Half)**(-_k + n)*binomial(n, _k)**2, (_k, 0, n))) + assert legendre(n, x).rewrite("polynomial").dummy_eq(Sum((-1)**_k*(S.Half - + x/2)**_k*(x/2 + S.Half)**(-_k + n)*binomial(n, _k)**2, (_k, 0, n))) + raises(ArgumentIndexError, lambda: legendre(n, x).fdiff(1)) + raises(ArgumentIndexError, lambda: legendre(n, x).fdiff(3)) + + +def test_assoc_legendre(): + Plm = assoc_legendre + Q = sqrt(1 - x**2) + + assert Plm(0, 0, x) == 1 + assert Plm(1, 0, x) == x + assert Plm(1, 1, x) == -Q + assert Plm(2, 0, x) == (3*x**2 - 1)/2 + assert Plm(2, 1, x) == -3*x*Q + assert Plm(2, 2, x) == 3*Q**2 + assert Plm(3, 0, x) == (5*x**3 - 3*x)/2 + assert Plm(3, 1, x).expand() == (( 3*(1 - 5*x**2)/2 ).expand() * Q).expand() + assert Plm(3, 2, x) == 15*x * Q**2 + assert Plm(3, 3, x) == -15 * Q**3 + + # negative m + assert Plm(1, -1, x) == -Plm(1, 1, x)/2 + assert Plm(2, -2, x) == Plm(2, 2, x)/24 + assert Plm(2, -1, x) == -Plm(2, 1, x)/6 + assert Plm(3, -3, x) == -Plm(3, 3, x)/720 + assert Plm(3, -2, x) == Plm(3, 2, x)/120 + assert Plm(3, -1, x) == -Plm(3, 1, x)/12 + + n = Symbol("n") + m = Symbol("m") + X = Plm(n, m, x) + assert isinstance(X, assoc_legendre) + + assert Plm(n, 0, x) == legendre(n, x) + assert Plm(n, m, 0) == 2**m*sqrt(pi)/(gamma(-m/2 - n/2 + + S.Half)*gamma(-m/2 + n/2 + 1)) + + assert diff(Plm(m, n, x), x) == (m*x*assoc_legendre(m, n, x) - + (m + n)*assoc_legendre(m - 1, n, x))/(x**2 - 1) + + _k = Dummy('k') + assert Plm(m, n, x).rewrite(Sum).dummy_eq( + (1 - x**2)**(n/2)*Sum((-1)**_k*2**(-m)*x**(-2*_k + m - n)*factorial + (-2*_k + 2*m)/(factorial(_k)*factorial(-_k + m)*factorial(-2*_k + m + - n)), (_k, 0, floor(m/2 - n/2)))) + assert Plm(m, n, x).rewrite("polynomial").dummy_eq( + (1 - x**2)**(n/2)*Sum((-1)**_k*2**(-m)*x**(-2*_k + m - n)*factorial + (-2*_k + 2*m)/(factorial(_k)*factorial(-_k + m)*factorial(-2*_k + m + - n)), (_k, 0, floor(m/2 - n/2)))) + assert conjugate(assoc_legendre(n, m, x)) == \ + assoc_legendre(n, conjugate(m), conjugate(x)) + raises(ValueError, lambda: Plm(0, 1, x)) + raises(ValueError, lambda: Plm(-1, 1, x)) + raises(ArgumentIndexError, lambda: Plm(n, m, x).fdiff(1)) + raises(ArgumentIndexError, lambda: Plm(n, m, x).fdiff(2)) + raises(ArgumentIndexError, lambda: Plm(n, m, x).fdiff(4)) + + +def test_chebyshev(): + assert chebyshevt(0, x) == 1 + assert chebyshevt(1, x) == x + assert chebyshevt(2, x) == 2*x**2 - 1 + assert chebyshevt(3, x) == 4*x**3 - 3*x + + for n in range(1, 4): + for k in range(n): + z = chebyshevt_root(n, k) + assert chebyshevt(n, z) == 0 + raises(ValueError, lambda: chebyshevt_root(n, n)) + + for n in range(1, 4): + for k in range(n): + z = chebyshevu_root(n, k) + assert chebyshevu(n, z) == 0 + raises(ValueError, lambda: chebyshevu_root(n, n)) + + n = Symbol("n") + X = chebyshevt(n, x) + assert isinstance(X, chebyshevt) + assert unchanged(chebyshevt, n, x) + assert chebyshevt(n, -x) == (-1)**n*chebyshevt(n, x) + assert chebyshevt(-n, x) == chebyshevt(n, x) + + assert chebyshevt(n, 0) == cos(pi*n/2) + assert chebyshevt(n, 1) == 1 + assert chebyshevt(n, oo) is oo + + assert conjugate(chebyshevt(n, x)) == chebyshevt(n, conjugate(x)) + + assert diff(chebyshevt(n, x), x) == n*chebyshevu(n - 1, x) + + X = chebyshevu(n, x) + assert isinstance(X, chebyshevu) + + y = Symbol('y') + assert chebyshevu(n, -x) == (-1)**n*chebyshevu(n, x) + assert chebyshevu(-n, x) == -chebyshevu(n - 2, x) + assert unchanged(chebyshevu, -n + y, x) + + assert chebyshevu(n, 0) == cos(pi*n/2) + assert chebyshevu(n, 1) == n + 1 + assert chebyshevu(n, oo) is oo + + assert conjugate(chebyshevu(n, x)) == chebyshevu(n, conjugate(x)) + + assert diff(chebyshevu(n, x), x) == \ + (-x*chebyshevu(n, x) + (n + 1)*chebyshevt(n + 1, x))/(x**2 - 1) + + _k = Dummy('k') + assert chebyshevt(n, x).rewrite(Sum).dummy_eq(Sum(x**(-2*_k + n) + *(x**2 - 1)**_k*binomial(n, 2*_k), (_k, 0, floor(n/2)))) + assert chebyshevt(n, x).rewrite("polynomial").dummy_eq(Sum(x**(-2*_k + n) + *(x**2 - 1)**_k*binomial(n, 2*_k), (_k, 0, floor(n/2)))) + assert chebyshevu(n, x).rewrite(Sum).dummy_eq(Sum((-1)**_k*(2*x) + **(-2*_k + n)*factorial(-_k + n)/(factorial(_k)* + factorial(-2*_k + n)), (_k, 0, floor(n/2)))) + assert chebyshevu(n, x).rewrite("polynomial").dummy_eq(Sum((-1)**_k*(2*x) + **(-2*_k + n)*factorial(-_k + n)/(factorial(_k)* + factorial(-2*_k + n)), (_k, 0, floor(n/2)))) + raises(ArgumentIndexError, lambda: chebyshevt(n, x).fdiff(1)) + raises(ArgumentIndexError, lambda: chebyshevt(n, x).fdiff(3)) + raises(ArgumentIndexError, lambda: chebyshevu(n, x).fdiff(1)) + raises(ArgumentIndexError, lambda: chebyshevu(n, x).fdiff(3)) + + +def test_hermite(): + assert hermite(0, x) == 1 + assert hermite(1, x) == 2*x + assert hermite(2, x) == 4*x**2 - 2 + assert hermite(3, x) == 8*x**3 - 12*x + assert hermite(4, x) == 16*x**4 - 48*x**2 + 12 + assert hermite(6, x) == 64*x**6 - 480*x**4 + 720*x**2 - 120 + + n = Symbol("n") + assert unchanged(hermite, n, x) + assert hermite(n, -x) == (-1)**n*hermite(n, x) + assert unchanged(hermite, -n, x) + + assert hermite(n, 0) == 2**n*sqrt(pi)/gamma(S.Half - n/2) + assert hermite(n, oo) is oo + + assert conjugate(hermite(n, x)) == hermite(n, conjugate(x)) + + _k = Dummy('k') + assert hermite(n, x).rewrite(Sum).dummy_eq(factorial(n)*Sum((-1) + **_k*(2*x)**(-2*_k + n)/(factorial(_k)*factorial(-2*_k + n)), (_k, + 0, floor(n/2)))) + assert hermite(n, x).rewrite("polynomial").dummy_eq(factorial(n)*Sum((-1) + **_k*(2*x)**(-2*_k + n)/(factorial(_k)*factorial(-2*_k + n)), (_k, + 0, floor(n/2)))) + + assert diff(hermite(n, x), x) == 2*n*hermite(n - 1, x) + assert diff(hermite(n, x), n) == Derivative(hermite(n, x), n) + raises(ArgumentIndexError, lambda: hermite(n, x).fdiff(3)) + + assert hermite(n, x).rewrite(hermite_prob) == \ + sqrt(2)**n * hermite_prob(n, x*sqrt(2)) + + +def test_hermite_prob(): + assert hermite_prob(0, x) == 1 + assert hermite_prob(1, x) == x + assert hermite_prob(2, x) == x**2 - 1 + assert hermite_prob(3, x) == x**3 - 3*x + assert hermite_prob(4, x) == x**4 - 6*x**2 + 3 + assert hermite_prob(6, x) == x**6 - 15*x**4 + 45*x**2 - 15 + + n = Symbol("n") + assert unchanged(hermite_prob, n, x) + assert hermite_prob(n, -x) == (-1)**n*hermite_prob(n, x) + assert unchanged(hermite_prob, -n, x) + + assert hermite_prob(n, 0) == sqrt(pi)/gamma(S.Half - n/2) + assert hermite_prob(n, oo) is oo + + assert conjugate(hermite_prob(n, x)) == hermite_prob(n, conjugate(x)) + + _k = Dummy('k') + assert hermite_prob(n, x).rewrite(Sum).dummy_eq(factorial(n) * + Sum((-S.Half)**_k * x**(n-2*_k) / (factorial(_k) * factorial(n-2*_k)), + (_k, 0, floor(n/2)))) + assert hermite_prob(n, x).rewrite("polynomial").dummy_eq(factorial(n) * + Sum((-S.Half)**_k * x**(n-2*_k) / (factorial(_k) * factorial(n-2*_k)), + (_k, 0, floor(n/2)))) + + assert diff(hermite_prob(n, x), x) == n*hermite_prob(n-1, x) + assert diff(hermite_prob(n, x), n) == Derivative(hermite_prob(n, x), n) + raises(ArgumentIndexError, lambda: hermite_prob(n, x).fdiff(3)) + + assert hermite_prob(n, x).rewrite(hermite) == \ + sqrt(2)**(-n) * hermite(n, x/sqrt(2)) + + +def test_laguerre(): + n = Symbol("n") + m = Symbol("m", negative=True) + + # Laguerre polynomials: + assert laguerre(0, x) == 1 + assert laguerre(1, x) == -x + 1 + assert laguerre(2, x) == x**2/2 - 2*x + 1 + assert laguerre(3, x) == -x**3/6 + 3*x**2/2 - 3*x + 1 + assert laguerre(-2, x) == (x + 1)*exp(x) + + X = laguerre(n, x) + assert isinstance(X, laguerre) + + assert laguerre(n, 0) == 1 + assert laguerre(n, oo) == (-1)**n*oo + assert laguerre(n, -oo) is oo + + assert conjugate(laguerre(n, x)) == laguerre(n, conjugate(x)) + + _k = Dummy('k') + + assert laguerre(n, x).rewrite(Sum).dummy_eq( + Sum(x**_k*RisingFactorial(-n, _k)/factorial(_k)**2, (_k, 0, n))) + assert laguerre(n, x).rewrite("polynomial").dummy_eq( + Sum(x**_k*RisingFactorial(-n, _k)/factorial(_k)**2, (_k, 0, n))) + assert laguerre(m, x).rewrite(Sum).dummy_eq( + exp(x)*Sum((-x)**_k*RisingFactorial(m + 1, _k)/factorial(_k)**2, + (_k, 0, -m - 1))) + assert laguerre(m, x).rewrite("polynomial").dummy_eq( + exp(x)*Sum((-x)**_k*RisingFactorial(m + 1, _k)/factorial(_k)**2, + (_k, 0, -m - 1))) + + assert diff(laguerre(n, x), x) == -assoc_laguerre(n - 1, 1, x) + + k = Symbol('k') + assert laguerre(-n, x) == exp(x)*laguerre(n - 1, -x) + assert laguerre(-3, x) == exp(x)*laguerre(2, -x) + assert unchanged(laguerre, -n + k, x) + + raises(ValueError, lambda: laguerre(-2.1, x)) + raises(ValueError, lambda: laguerre(Rational(5, 2), x)) + raises(ArgumentIndexError, lambda: laguerre(n, x).fdiff(1)) + raises(ArgumentIndexError, lambda: laguerre(n, x).fdiff(3)) + + +def test_assoc_laguerre(): + n = Symbol("n") + m = Symbol("m") + alpha = Symbol("alpha") + + # generalized Laguerre polynomials: + assert assoc_laguerre(0, alpha, x) == 1 + assert assoc_laguerre(1, alpha, x) == -x + alpha + 1 + assert assoc_laguerre(2, alpha, x).expand() == \ + (x**2/2 - (alpha + 2)*x + (alpha + 2)*(alpha + 1)/2).expand() + assert assoc_laguerre(3, alpha, x).expand() == \ + (-x**3/6 + (alpha + 3)*x**2/2 - (alpha + 2)*(alpha + 3)*x/2 + + (alpha + 1)*(alpha + 2)*(alpha + 3)/6).expand() + + # Test the lowest 10 polynomials with laguerre_poly, to make sure it works: + for i in range(10): + assert assoc_laguerre(i, 0, x).expand() == laguerre_poly(i, x) + + X = assoc_laguerre(n, m, x) + assert isinstance(X, assoc_laguerre) + + assert assoc_laguerre(n, 0, x) == laguerre(n, x) + assert assoc_laguerre(n, alpha, 0) == binomial(alpha + n, alpha) + p = Symbol("p", positive=True) + assert assoc_laguerre(p, alpha, oo) == (-1)**p*oo + assert assoc_laguerre(p, alpha, -oo) is oo + + assert diff(assoc_laguerre(n, alpha, x), x) == \ + -assoc_laguerre(n - 1, alpha + 1, x) + _k = Dummy('k') + assert diff(assoc_laguerre(n, alpha, x), alpha).dummy_eq( + Sum(assoc_laguerre(_k, alpha, x)/(-alpha + n), (_k, 0, n - 1))) + + assert conjugate(assoc_laguerre(n, alpha, x)) == \ + assoc_laguerre(n, conjugate(alpha), conjugate(x)) + + assert assoc_laguerre(n, alpha, x).rewrite(Sum).dummy_eq( + gamma(alpha + n + 1)*Sum(x**_k*RisingFactorial(-n, _k)/ + (factorial(_k)*gamma(_k + alpha + 1)), (_k, 0, n))/factorial(n)) + assert assoc_laguerre(n, alpha, x).rewrite("polynomial").dummy_eq( + gamma(alpha + n + 1)*Sum(x**_k*RisingFactorial(-n, _k)/ + (factorial(_k)*gamma(_k + alpha + 1)), (_k, 0, n))/factorial(n)) + raises(ValueError, lambda: assoc_laguerre(-2.1, alpha, x)) + raises(ArgumentIndexError, lambda: assoc_laguerre(n, alpha, x).fdiff(1)) + raises(ArgumentIndexError, lambda: assoc_laguerre(n, alpha, x).fdiff(4)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_spherical_harmonics.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_spherical_harmonics.py new file mode 100644 index 0000000000000000000000000000000000000000..2e0d4ffebabb62c13d3fc2996e8ba23866467720 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_spherical_harmonics.py @@ -0,0 +1,66 @@ +from sympy.core.function import diff +from sympy.core.numbers import (I, pi) +from sympy.core.symbol import Symbol +from sympy.functions.elementary.complexes import conjugate +from sympy.functions.elementary.exponential import exp +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (cos, cot, sin) +from sympy.functions.special.spherical_harmonics import Ynm, Znm, Ynm_c + + +def test_Ynm(): + # https://en.wikipedia.org/wiki/Spherical_harmonics + th, ph = Symbol("theta", real=True), Symbol("phi", real=True) + from sympy.abc import n,m + + assert Ynm(0, 0, th, ph).expand(func=True) == 1/(2*sqrt(pi)) + assert Ynm(1, -1, th, ph) == -exp(-2*I*ph)*Ynm(1, 1, th, ph) + assert Ynm(1, -1, th, ph).expand(func=True) == sqrt(6)*sin(th)*exp(-I*ph)/(4*sqrt(pi)) + assert Ynm(1, 0, th, ph).expand(func=True) == sqrt(3)*cos(th)/(2*sqrt(pi)) + assert Ynm(1, 1, th, ph).expand(func=True) == -sqrt(6)*sin(th)*exp(I*ph)/(4*sqrt(pi)) + assert Ynm(2, 0, th, ph).expand(func=True) == 3*sqrt(5)*cos(th)**2/(4*sqrt(pi)) - sqrt(5)/(4*sqrt(pi)) + assert Ynm(2, 1, th, ph).expand(func=True) == -sqrt(30)*sin(th)*exp(I*ph)*cos(th)/(4*sqrt(pi)) + assert Ynm(2, -2, th, ph).expand(func=True) == (-sqrt(30)*exp(-2*I*ph)*cos(th)**2/(8*sqrt(pi)) + + sqrt(30)*exp(-2*I*ph)/(8*sqrt(pi))) + assert Ynm(2, 2, th, ph).expand(func=True) == (-sqrt(30)*exp(2*I*ph)*cos(th)**2/(8*sqrt(pi)) + + sqrt(30)*exp(2*I*ph)/(8*sqrt(pi))) + + assert diff(Ynm(n, m, th, ph), th) == (m*cot(th)*Ynm(n, m, th, ph) + + sqrt((-m + n)*(m + n + 1))*exp(-I*ph)*Ynm(n, m + 1, th, ph)) + assert diff(Ynm(n, m, th, ph), ph) == I*m*Ynm(n, m, th, ph) + + assert conjugate(Ynm(n, m, th, ph)) == (-1)**(2*m)*exp(-2*I*m*ph)*Ynm(n, m, th, ph) + + assert Ynm(n, m, -th, ph) == Ynm(n, m, th, ph) + assert Ynm(n, m, th, -ph) == exp(-2*I*m*ph)*Ynm(n, m, th, ph) + assert Ynm(n, -m, th, ph) == (-1)**m*exp(-2*I*m*ph)*Ynm(n, m, th, ph) + + +def test_Ynm_c(): + th, ph = Symbol("theta", real=True), Symbol("phi", real=True) + from sympy.abc import n,m + + assert Ynm_c(n, m, th, ph) == (-1)**(2*m)*exp(-2*I*m*ph)*Ynm(n, m, th, ph) + + +def test_Znm(): + # https://en.wikipedia.org/wiki/Solid_harmonics#List_of_lowest_functions + th, ph = Symbol("theta", real=True), Symbol("phi", real=True) + + assert Znm(0, 0, th, ph) == Ynm(0, 0, th, ph) + assert Znm(1, -1, th, ph) == (-sqrt(2)*I*(Ynm(1, 1, th, ph) + - exp(-2*I*ph)*Ynm(1, 1, th, ph))/2) + assert Znm(1, 0, th, ph) == Ynm(1, 0, th, ph) + assert Znm(1, 1, th, ph) == (sqrt(2)*(Ynm(1, 1, th, ph) + + exp(-2*I*ph)*Ynm(1, 1, th, ph))/2) + assert Znm(0, 0, th, ph).expand(func=True) == 1/(2*sqrt(pi)) + assert Znm(1, -1, th, ph).expand(func=True) == (sqrt(3)*I*sin(th)*exp(I*ph)/(4*sqrt(pi)) + - sqrt(3)*I*sin(th)*exp(-I*ph)/(4*sqrt(pi))) + assert Znm(1, 0, th, ph).expand(func=True) == sqrt(3)*cos(th)/(2*sqrt(pi)) + assert Znm(1, 1, th, ph).expand(func=True) == (-sqrt(3)*sin(th)*exp(I*ph)/(4*sqrt(pi)) + - sqrt(3)*sin(th)*exp(-I*ph)/(4*sqrt(pi))) + assert Znm(2, -1, th, ph).expand(func=True) == (sqrt(15)*I*sin(th)*exp(I*ph)*cos(th)/(4*sqrt(pi)) + - sqrt(15)*I*sin(th)*exp(-I*ph)*cos(th)/(4*sqrt(pi))) + assert Znm(2, 0, th, ph).expand(func=True) == 3*sqrt(5)*cos(th)**2/(4*sqrt(pi)) - sqrt(5)/(4*sqrt(pi)) + assert Znm(2, 1, th, ph).expand(func=True) == (-sqrt(15)*sin(th)*exp(I*ph)*cos(th)/(4*sqrt(pi)) + - sqrt(15)*sin(th)*exp(-I*ph)*cos(th)/(4*sqrt(pi))) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_tensor_functions.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_tensor_functions.py new file mode 100644 index 0000000000000000000000000000000000000000..7d4f31c45ae0a60a6f72dc5551794b2110f5ab99 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_tensor_functions.py @@ -0,0 +1,145 @@ +from sympy.core.relational import Ne +from sympy.core.symbol import (Dummy, Symbol, symbols) +from sympy.functions.elementary.complexes import (adjoint, conjugate, transpose) +from sympy.functions.elementary.piecewise import Piecewise +from sympy.functions.special.tensor_functions import (Eijk, KroneckerDelta, LeviCivita) + +from sympy.physics.secondquant import evaluate_deltas, F + +x, y = symbols('x y') + + +def test_levicivita(): + assert Eijk(1, 2, 3) == LeviCivita(1, 2, 3) + assert LeviCivita(1, 2, 3) == 1 + assert LeviCivita(int(1), int(2), int(3)) == 1 + assert LeviCivita(1, 3, 2) == -1 + assert LeviCivita(1, 2, 2) == 0 + i, j, k = symbols('i j k') + assert LeviCivita(i, j, k) == LeviCivita(i, j, k, evaluate=False) + assert LeviCivita(i, j, i) == 0 + assert LeviCivita(1, i, i) == 0 + assert LeviCivita(i, j, k).doit() == (j - i)*(k - i)*(k - j)/2 + assert LeviCivita(1, 2, 3, 1) == 0 + assert LeviCivita(4, 5, 1, 2, 3) == 1 + assert LeviCivita(4, 5, 2, 1, 3) == -1 + + assert LeviCivita(i, j, k).is_integer is True + + assert adjoint(LeviCivita(i, j, k)) == LeviCivita(i, j, k) + assert conjugate(LeviCivita(i, j, k)) == LeviCivita(i, j, k) + assert transpose(LeviCivita(i, j, k)) == LeviCivita(i, j, k) + + +def test_kronecker_delta(): + i, j = symbols('i j') + k = Symbol('k', nonzero=True) + assert KroneckerDelta(1, 1) == 1 + assert KroneckerDelta(1, 2) == 0 + assert KroneckerDelta(k, 0) == 0 + assert KroneckerDelta(x, x) == 1 + assert KroneckerDelta(x**2 - y**2, x**2 - y**2) == 1 + assert KroneckerDelta(i, i) == 1 + assert KroneckerDelta(i, i + 1) == 0 + assert KroneckerDelta(0, 0) == 1 + assert KroneckerDelta(0, 1) == 0 + assert KroneckerDelta(i + k, i) == 0 + assert KroneckerDelta(i + k, i + k) == 1 + assert KroneckerDelta(i + k, i + 1 + k) == 0 + assert KroneckerDelta(i, j).subs({"i": 1, "j": 0}) == 0 + assert KroneckerDelta(i, j).subs({"i": 3, "j": 3}) == 1 + + assert KroneckerDelta(i, j)**0 == 1 + for n in range(1, 10): + assert KroneckerDelta(i, j)**n == KroneckerDelta(i, j) + assert KroneckerDelta(i, j)**-n == 1/KroneckerDelta(i, j) + + assert KroneckerDelta(i, j).is_integer is True + + assert adjoint(KroneckerDelta(i, j)) == KroneckerDelta(i, j) + assert conjugate(KroneckerDelta(i, j)) == KroneckerDelta(i, j) + assert transpose(KroneckerDelta(i, j)) == KroneckerDelta(i, j) + # to test if canonical + assert (KroneckerDelta(i, j) == KroneckerDelta(j, i)) == True + + assert KroneckerDelta(i, j).rewrite(Piecewise) == Piecewise((0, Ne(i, j)), (1, True)) + + # Tests with range: + assert KroneckerDelta(i, j, (0, i)).args == (i, j, (0, i)) + assert KroneckerDelta(i, j, (-j, i)).delta_range == (-j, i) + + # If index is out of range, return zero: + assert KroneckerDelta(i, j, (0, i-1)) == 0 + assert KroneckerDelta(-1, j, (0, i-1)) == 0 + assert KroneckerDelta(j, -1, (0, i-1)) == 0 + assert KroneckerDelta(j, i, (0, i-1)) == 0 + + +def test_kronecker_delta_secondquant(): + """secondquant-specific methods""" + D = KroneckerDelta + i, j, v, w = symbols('i j v w', below_fermi=True, cls=Dummy) + a, b, t, u = symbols('a b t u', above_fermi=True, cls=Dummy) + p, q, r, s = symbols('p q r s', cls=Dummy) + + assert D(i, a) == 0 + assert D(i, t) == 0 + + assert D(i, j).is_above_fermi is False + assert D(a, b).is_above_fermi is True + assert D(p, q).is_above_fermi is True + assert D(i, q).is_above_fermi is False + assert D(q, i).is_above_fermi is False + assert D(q, v).is_above_fermi is False + assert D(a, q).is_above_fermi is True + + assert D(i, j).is_below_fermi is True + assert D(a, b).is_below_fermi is False + assert D(p, q).is_below_fermi is True + assert D(p, j).is_below_fermi is True + assert D(q, b).is_below_fermi is False + + assert D(i, j).is_only_above_fermi is False + assert D(a, b).is_only_above_fermi is True + assert D(p, q).is_only_above_fermi is False + assert D(i, q).is_only_above_fermi is False + assert D(q, i).is_only_above_fermi is False + assert D(a, q).is_only_above_fermi is True + + assert D(i, j).is_only_below_fermi is True + assert D(a, b).is_only_below_fermi is False + assert D(p, q).is_only_below_fermi is False + assert D(p, j).is_only_below_fermi is True + assert D(q, b).is_only_below_fermi is False + + assert not D(i, q).indices_contain_equal_information + assert not D(a, q).indices_contain_equal_information + assert D(p, q).indices_contain_equal_information + assert D(a, b).indices_contain_equal_information + assert D(i, j).indices_contain_equal_information + + assert D(q, b).preferred_index == b + assert D(q, b).killable_index == q + assert D(q, t).preferred_index == t + assert D(q, t).killable_index == q + assert D(q, i).preferred_index == i + assert D(q, i).killable_index == q + assert D(q, v).preferred_index == v + assert D(q, v).killable_index == q + assert D(q, p).preferred_index == p + assert D(q, p).killable_index == q + + EV = evaluate_deltas + assert EV(D(a, q)*F(q)) == F(a) + assert EV(D(i, q)*F(q)) == F(i) + assert EV(D(a, q)*F(a)) == D(a, q)*F(a) + assert EV(D(i, q)*F(i)) == D(i, q)*F(i) + assert EV(D(a, b)*F(a)) == F(b) + assert EV(D(a, b)*F(b)) == F(a) + assert EV(D(i, j)*F(i)) == F(j) + assert EV(D(i, j)*F(j)) == F(i) + assert EV(D(p, q)*F(q)) == F(p) + assert EV(D(p, q)*F(p)) == F(q) + assert EV(D(p, j)*D(p, i)*F(i)) == F(j) + assert EV(D(p, j)*D(p, i)*F(j)) == F(i) + assert EV(D(p, q)*D(p, i))*F(i) == D(q, i)*F(i) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_zeta_functions.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_zeta_functions.py new file mode 100644 index 0000000000000000000000000000000000000000..c2083b0b6e8cb38fde17fb1ede2a34be6338b1dc --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/tests/test_zeta_functions.py @@ -0,0 +1,286 @@ +from sympy.concrete.summations import Sum +from sympy.core.function import expand_func +from sympy.core.numbers import (Float, I, Rational, nan, oo, pi, zoo) +from sympy.core.singleton import S +from sympy.core.symbol import Symbol +from sympy.functions.elementary.complexes import (Abs, polar_lift) +from sympy.functions.elementary.exponential import (exp, exp_polar, log) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.special.zeta_functions import (dirichlet_eta, lerchphi, polylog, riemann_xi, stieltjes, zeta) +from sympy.series.order import O +from sympy.core.function import ArgumentIndexError +from sympy.functions.combinatorial.numbers import bernoulli, factorial, genocchi, harmonic +from sympy.testing.pytest import raises +from sympy.core.random import (test_derivative_numerically as td, + random_complex_number as randcplx, verify_numerically) + +x = Symbol('x') +a = Symbol('a') +b = Symbol('b', negative=True) +z = Symbol('z') +s = Symbol('s') + + +def test_zeta_eval(): + + assert zeta(nan) is nan + assert zeta(x, nan) is nan + + assert zeta(0) == Rational(-1, 2) + assert zeta(0, x) == S.Half - x + assert zeta(0, b) == S.Half - b + + assert zeta(1) is zoo + assert zeta(1, 2) is zoo + assert zeta(1, -7) is zoo + assert zeta(1, x) is zoo + + assert zeta(2, 1) == pi**2/6 + assert zeta(3, 1) == zeta(3) + + assert zeta(2) == pi**2/6 + assert zeta(4) == pi**4/90 + assert zeta(6) == pi**6/945 + + assert zeta(4, 3) == pi**4/90 - Rational(17, 16) + assert zeta(7, 4) == zeta(7) - Rational(282251, 279936) + assert zeta(S.Half, 2).func == zeta + assert expand_func(zeta(S.Half, 2)) == zeta(S.Half) - 1 + assert zeta(x, 3).func == zeta + assert expand_func(zeta(x, 3)) == zeta(x) - 1 - 1/2**x + + assert zeta(2, 0) is nan + assert zeta(3, -1) is nan + assert zeta(4, -2) is nan + + assert zeta(oo) == 1 + + assert zeta(-1) == Rational(-1, 12) + assert zeta(-2) == 0 + assert zeta(-3) == Rational(1, 120) + assert zeta(-4) == 0 + assert zeta(-5) == Rational(-1, 252) + + assert zeta(-1, 3) == Rational(-37, 12) + assert zeta(-1, 7) == Rational(-253, 12) + assert zeta(-1, -4) == Rational(-121, 12) + assert zeta(-1, -9) == Rational(-541, 12) + + assert zeta(-4, 3) == -17 + assert zeta(-4, -8) == 8772 + + assert zeta(0, 1) == Rational(-1, 2) + assert zeta(0, -1) == Rational(3, 2) + + assert zeta(0, 2) == Rational(-3, 2) + assert zeta(0, -2) == Rational(5, 2) + + assert zeta( + 3).evalf(20).epsilon_eq(Float("1.2020569031595942854", 20), 1e-19) + + +def test_zeta_series(): + assert zeta(x, a).series(a, z, 2) == \ + zeta(x, z) - x*(a-z)*zeta(x+1, z) + O((a-z)**2, (a, z)) + + +def test_dirichlet_eta_eval(): + assert dirichlet_eta(0) == S.Half + assert dirichlet_eta(-1) == Rational(1, 4) + assert dirichlet_eta(1) == log(2) + assert dirichlet_eta(1, S.Half).simplify() == pi/2 + assert dirichlet_eta(1, 2) == 1 - log(2) + assert dirichlet_eta(2) == pi**2/12 + assert dirichlet_eta(4) == pi**4*Rational(7, 720) + assert str(dirichlet_eta(I).evalf(n=10)) == '0.5325931818 + 0.2293848577*I' + assert str(dirichlet_eta(I, I).evalf(n=10)) == '3.462349253 + 0.220285771*I' + + +def test_riemann_xi_eval(): + assert riemann_xi(2) == pi/6 + assert riemann_xi(0) == Rational(1, 2) + assert riemann_xi(1) == Rational(1, 2) + assert riemann_xi(3).rewrite(zeta) == 3*zeta(3)/(2*pi) + assert riemann_xi(4) == pi**2/15 + + +def test_rewriting(): + from sympy.functions.elementary.piecewise import Piecewise + assert isinstance(dirichlet_eta(x).rewrite(zeta), Piecewise) + assert isinstance(dirichlet_eta(x).rewrite(genocchi), Piecewise) + assert zeta(x).rewrite(dirichlet_eta) == dirichlet_eta(x)/(1 - 2**(1 - x)) + assert zeta(x).rewrite(dirichlet_eta, a=2) == zeta(x) + assert verify_numerically(dirichlet_eta(x), dirichlet_eta(x).rewrite(zeta), x) + assert verify_numerically(dirichlet_eta(x), dirichlet_eta(x).rewrite(genocchi), x) + assert verify_numerically(zeta(x), zeta(x).rewrite(dirichlet_eta), x) + + assert zeta(x, a).rewrite(lerchphi) == lerchphi(1, x, a) + assert polylog(s, z).rewrite(lerchphi) == lerchphi(z, s, 1)*z + + assert lerchphi(1, x, a).rewrite(zeta) == zeta(x, a) + assert z*lerchphi(z, s, 1).rewrite(polylog) == polylog(s, z) + + +def test_derivatives(): + from sympy.core.function import Derivative + assert zeta(x, a).diff(x) == Derivative(zeta(x, a), x) + assert zeta(x, a).diff(a) == -x*zeta(x + 1, a) + assert lerchphi( + z, s, a).diff(z) == (lerchphi(z, s - 1, a) - a*lerchphi(z, s, a))/z + assert lerchphi(z, s, a).diff(a) == -s*lerchphi(z, s + 1, a) + assert polylog(s, z).diff(z) == polylog(s - 1, z)/z + + b = randcplx() + c = randcplx() + assert td(zeta(b, x), x) + assert td(polylog(b, z), z) + assert td(lerchphi(c, b, x), x) + assert td(lerchphi(x, b, c), x) + raises(ArgumentIndexError, lambda: lerchphi(c, b, x).fdiff(2)) + raises(ArgumentIndexError, lambda: lerchphi(c, b, x).fdiff(4)) + raises(ArgumentIndexError, lambda: polylog(b, z).fdiff(1)) + raises(ArgumentIndexError, lambda: polylog(b, z).fdiff(3)) + + +def myexpand(func, target): + expanded = expand_func(func) + if target is not None: + return expanded == target + if expanded == func: # it didn't expand + return False + + # check to see that the expanded and original evaluate to the same value + subs = {} + for a in func.free_symbols: + subs[a] = randcplx() + return abs(func.subs(subs).n() + - expanded.replace(exp_polar, exp).subs(subs).n()) < 1e-10 + + +def test_polylog_expansion(): + assert polylog(s, 0) == 0 + assert polylog(s, 1) == zeta(s) + assert polylog(s, -1) == -dirichlet_eta(s) + assert polylog(s, exp_polar(I*pi*Rational(4, 3))) == polylog(s, exp(I*pi*Rational(4, 3))) + assert polylog(s, exp_polar(I*pi)/3) == polylog(s, exp(I*pi)/3) + + assert myexpand(polylog(1, z), -log(1 - z)) + assert myexpand(polylog(0, z), z/(1 - z)) + assert myexpand(polylog(-1, z), z/(1 - z)**2) + assert ((1-z)**3 * expand_func(polylog(-2, z))).simplify() == z*(1 + z) + assert myexpand(polylog(-5, z), None) + + +def test_polylog_series(): + assert polylog(1, z).series(z, n=5) == z + z**2/2 + z**3/3 + z**4/4 + O(z**5) + assert polylog(1, sqrt(z)).series(z, n=3) == z/2 + z**2/4 + sqrt(z)\ + + z**(S(3)/2)/3 + z**(S(5)/2)/5 + O(z**3) + + # https://github.com/sympy/sympy/issues/9497 + assert polylog(S(3)/2, -z).series(z, 0, 5) == -z + sqrt(2)*z**2/4\ + - sqrt(3)*z**3/9 + z**4/8 + O(z**5) + + +def test_issue_8404(): + i = Symbol('i', integer=True) + assert Abs(Sum(1/(3*i + 1)**2, (i, 0, S.Infinity)).doit().n(4) + - 1.122) < 0.001 + + +def test_polylog_values(): + assert polylog(2, 2) == pi**2/4 - I*pi*log(2) + assert polylog(2, S.Half) == pi**2/12 - log(2)**2/2 + for z in [S.Half, 2, (sqrt(5)-1)/2, -(sqrt(5)-1)/2, -(sqrt(5)+1)/2, (3-sqrt(5))/2]: + assert Abs(polylog(2, z).evalf() - polylog(2, z, evaluate=False).evalf()) < 1e-15 + z = Symbol("z") + for s in [-1, 0]: + for _ in range(10): + assert verify_numerically(polylog(s, z), polylog(s, z, evaluate=False), + z, a=-3, b=-2, c=S.Half, d=2) + assert verify_numerically(polylog(s, z), polylog(s, z, evaluate=False), + z, a=2, b=-2, c=5, d=2) + + from sympy.integrals.integrals import Integral + assert polylog(0, Integral(1, (x, 0, 1))) == -S.Half + + +def test_lerchphi_expansion(): + assert myexpand(lerchphi(1, s, a), zeta(s, a)) + assert myexpand(lerchphi(z, s, 1), polylog(s, z)/z) + + # direct summation + assert myexpand(lerchphi(z, -1, a), a/(1 - z) + z/(1 - z)**2) + assert myexpand(lerchphi(z, -3, a), None) + # polylog reduction + assert myexpand(lerchphi(z, s, S.Half), + 2**(s - 1)*(polylog(s, sqrt(z))/sqrt(z) + - polylog(s, polar_lift(-1)*sqrt(z))/sqrt(z))) + assert myexpand(lerchphi(z, s, 2), -1/z + polylog(s, z)/z**2) + assert myexpand(lerchphi(z, s, Rational(3, 2)), None) + assert myexpand(lerchphi(z, s, Rational(7, 3)), None) + assert myexpand(lerchphi(z, s, Rational(-1, 3)), None) + assert myexpand(lerchphi(z, s, Rational(-5, 2)), None) + + # hurwitz zeta reduction + assert myexpand(lerchphi(-1, s, a), + 2**(-s)*zeta(s, a/2) - 2**(-s)*zeta(s, (a + 1)/2)) + assert myexpand(lerchphi(I, s, a), None) + assert myexpand(lerchphi(-I, s, a), None) + assert myexpand(lerchphi(exp(I*pi*Rational(2, 5)), s, a), None) + + +def test_stieltjes(): + assert isinstance(stieltjes(x), stieltjes) + assert isinstance(stieltjes(x, a), stieltjes) + + # Zero'th constant EulerGamma + assert stieltjes(0) == S.EulerGamma + assert stieltjes(0, 1) == S.EulerGamma + + # Not defined + assert stieltjes(nan) is nan + assert stieltjes(0, nan) is nan + assert stieltjes(-1) is S.ComplexInfinity + assert stieltjes(1.5) is S.ComplexInfinity + assert stieltjes(z, 0) is S.ComplexInfinity + assert stieltjes(z, -1) is S.ComplexInfinity + + +def test_stieltjes_evalf(): + assert abs(stieltjes(0).evalf() - 0.577215664) < 1E-9 + assert abs(stieltjes(0, 0.5).evalf() - 1.963510026) < 1E-9 + assert abs(stieltjes(1, 2).evalf() + 0.072815845) < 1E-9 + + +def test_issue_10475(): + a = Symbol('a', extended_real=True) + b = Symbol('b', extended_positive=True) + s = Symbol('s', zero=False) + + assert zeta(2 + I).is_finite + assert zeta(1).is_finite is False + assert zeta(x).is_finite is None + assert zeta(x + I).is_finite is None + assert zeta(a).is_finite is None + assert zeta(b).is_finite is None + assert zeta(-b).is_finite is True + assert zeta(b**2 - 2*b + 1).is_finite is None + assert zeta(a + I).is_finite is True + assert zeta(b + 1).is_finite is True + assert zeta(s + 1).is_finite is True + + +def test_issue_14177(): + n = Symbol('n', nonnegative=True, integer=True) + + assert zeta(-n).rewrite(bernoulli) == bernoulli(n+1) / (-n-1) + assert zeta(-n, a).rewrite(bernoulli) == bernoulli(n+1, a) / (-n-1) + z2n = -(2*I*pi)**(2*n)*bernoulli(2*n) / (2*factorial(2*n)) + assert zeta(2*n).rewrite(bernoulli) == z2n + assert expand_func(zeta(s, n+1)) == zeta(s) - harmonic(n, s) + assert expand_func(zeta(-b, -n)) is nan + assert expand_func(zeta(-b, n)) == zeta(-b, n) + + n = Symbol('n') + + assert zeta(2*n) == zeta(2*n) # As sign of z (= 2*n) is not determined diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/zeta_functions.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/zeta_functions.py new file mode 100644 index 0000000000000000000000000000000000000000..8f410f0f1086de91490c714cd3becf11df9ab189 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/functions/special/zeta_functions.py @@ -0,0 +1,786 @@ +""" Riemann zeta and related function. """ + +from sympy.core.add import Add +from sympy.core.cache import cacheit +from sympy.core.function import ArgumentIndexError, expand_mul, DefinedFunction +from sympy.core.logic import fuzzy_not +from sympy.core.numbers import pi, I, Integer +from sympy.core.relational import Eq +from sympy.core.singleton import S +from sympy.core.symbol import Dummy +from sympy.core.sympify import sympify +from sympy.functions.combinatorial.numbers import bernoulli, factorial, genocchi, harmonic +from sympy.functions.elementary.complexes import re, unpolarify, Abs, polar_lift +from sympy.functions.elementary.exponential import log, exp_polar, exp +from sympy.functions.elementary.integers import ceiling, floor +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.piecewise import Piecewise +from sympy.polys.polytools import Poly + +############################################################################### +###################### LERCH TRANSCENDENT ##################################### +############################################################################### + + +class lerchphi(DefinedFunction): + r""" + Lerch transcendent (Lerch phi function). + + Explanation + =========== + + For $\operatorname{Re}(a) > 0$, $|z| < 1$ and $s \in \mathbb{C}$, the + Lerch transcendent is defined as + + .. math :: \Phi(z, s, a) = \sum_{n=0}^\infty \frac{z^n}{(n + a)^s}, + + where the standard branch of the argument is used for $n + a$, + and by analytic continuation for other values of the parameters. + + A commonly used related function is the Lerch zeta function, defined by + + .. math:: L(q, s, a) = \Phi(e^{2\pi i q}, s, a). + + **Analytic Continuation and Branching Behavior** + + It can be shown that + + .. math:: \Phi(z, s, a) = z\Phi(z, s, a+1) + a^{-s}. + + This provides the analytic continuation to $\operatorname{Re}(a) \le 0$. + + Assume now $\operatorname{Re}(a) > 0$. The integral representation + + .. math:: \Phi_0(z, s, a) = \int_0^\infty \frac{t^{s-1} e^{-at}}{1 - ze^{-t}} + \frac{\mathrm{d}t}{\Gamma(s)} + + provides an analytic continuation to $\mathbb{C} - [1, \infty)$. + Finally, for $x \in (1, \infty)$ we find + + .. math:: \lim_{\epsilon \to 0^+} \Phi_0(x + i\epsilon, s, a) + -\lim_{\epsilon \to 0^+} \Phi_0(x - i\epsilon, s, a) + = \frac{2\pi i \log^{s-1}{x}}{x^a \Gamma(s)}, + + using the standard branch for both $\log{x}$ and + $\log{\log{x}}$ (a branch of $\log{\log{x}}$ is needed to + evaluate $\log{x}^{s-1}$). + This concludes the analytic continuation. The Lerch transcendent is thus + branched at $z \in \{0, 1, \infty\}$ and + $a \in \mathbb{Z}_{\le 0}$. For fixed $z, a$ outside these + branch points, it is an entire function of $s$. + + Examples + ======== + + The Lerch transcendent is a fairly general function, for this reason it does + not automatically evaluate to simpler functions. Use ``expand_func()`` to + achieve this. + + If $z=1$, the Lerch transcendent reduces to the Hurwitz zeta function: + + >>> from sympy import lerchphi, expand_func + >>> from sympy.abc import z, s, a + >>> expand_func(lerchphi(1, s, a)) + zeta(s, a) + + More generally, if $z$ is a root of unity, the Lerch transcendent + reduces to a sum of Hurwitz zeta functions: + + >>> expand_func(lerchphi(-1, s, a)) + zeta(s, a/2)/2**s - zeta(s, a/2 + 1/2)/2**s + + If $a=1$, the Lerch transcendent reduces to the polylogarithm: + + >>> expand_func(lerchphi(z, s, 1)) + polylog(s, z)/z + + More generally, if $a$ is rational, the Lerch transcendent reduces + to a sum of polylogarithms: + + >>> from sympy import S + >>> expand_func(lerchphi(z, s, S(1)/2)) + 2**(s - 1)*(polylog(s, sqrt(z))/sqrt(z) - + polylog(s, sqrt(z)*exp_polar(I*pi))/sqrt(z)) + >>> expand_func(lerchphi(z, s, S(3)/2)) + -2**s/z + 2**(s - 1)*(polylog(s, sqrt(z))/sqrt(z) - + polylog(s, sqrt(z)*exp_polar(I*pi))/sqrt(z))/z + + The derivatives with respect to $z$ and $a$ can be computed in + closed form: + + >>> lerchphi(z, s, a).diff(z) + (-a*lerchphi(z, s, a) + lerchphi(z, s - 1, a))/z + >>> lerchphi(z, s, a).diff(a) + -s*lerchphi(z, s + 1, a) + + See Also + ======== + + polylog, zeta + + References + ========== + + .. [1] Bateman, H.; Erdelyi, A. (1953), Higher Transcendental Functions, + Vol. I, New York: McGraw-Hill. Section 1.11. + .. [2] https://dlmf.nist.gov/25.14 + .. [3] https://en.wikipedia.org/wiki/Lerch_transcendent + + """ + + def _eval_expand_func(self, **hints): + z, s, a = self.args + if z == 1: + return zeta(s, a) + if s.is_Integer and s <= 0: + t = Dummy('t') + p = Poly((t + a)**(-s), t) + start = 1/(1 - t) + res = S.Zero + for c in reversed(p.all_coeffs()): + res += c*start + start = t*start.diff(t) + return res.subs(t, z) + + if a.is_Rational: + # See section 18 of + # Kelly B. Roach. Hypergeometric Function Representations. + # In: Proceedings of the 1997 International Symposium on Symbolic and + # Algebraic Computation, pages 205-211, New York, 1997. ACM. + # TODO should something be polarified here? + add = S.Zero + mul = S.One + # First reduce a to the interaval (0, 1] + if a > 1: + n = floor(a) + if n == a: + n -= 1 + a -= n + mul = z**(-n) + add = Add(*[-z**(k - n)/(a + k)**s for k in range(n)]) + elif a <= 0: + n = floor(-a) + 1 + a += n + mul = z**n + add = Add(*[z**(n - 1 - k)/(a - k - 1)**s for k in range(n)]) + + m, n = S([a.p, a.q]) + zet = exp_polar(2*pi*I/n) + root = z**(1/n) + up_zet = unpolarify(zet) + addargs = [] + for k in range(n): + p = polylog(s, zet**k*root) + if isinstance(p, polylog): + p = p._eval_expand_func(**hints) + addargs.append(p/(up_zet**k*root)**m) + return add + mul*n**(s - 1)*Add(*addargs) + + # TODO use minpoly instead of ad-hoc methods when issue 5888 is fixed + if isinstance(z, exp) and (z.args[0]/(pi*I)).is_Rational or z in [-1, I, -I]: + # TODO reference? + if z == -1: + p, q = S([1, 2]) + elif z == I: + p, q = S([1, 4]) + elif z == -I: + p, q = S([-1, 4]) + else: + arg = z.args[0]/(2*pi*I) + p, q = S([arg.p, arg.q]) + return Add(*[exp(2*pi*I*k*p/q)/q**s*zeta(s, (k + a)/q) + for k in range(q)]) + + return lerchphi(z, s, a) + + def fdiff(self, argindex=1): + z, s, a = self.args + if argindex == 3: + return -s*lerchphi(z, s + 1, a) + elif argindex == 1: + return (lerchphi(z, s - 1, a) - a*lerchphi(z, s, a))/z + else: + raise ArgumentIndexError + + def _eval_rewrite_helper(self, target): + res = self._eval_expand_func() + if res.has(target): + return res + else: + return self + + def _eval_rewrite_as_zeta(self, z, s, a, **kwargs): + return self._eval_rewrite_helper(zeta) + + def _eval_rewrite_as_polylog(self, z, s, a, **kwargs): + return self._eval_rewrite_helper(polylog) + +############################################################################### +###################### POLYLOGARITHM ########################################## +############################################################################### + + +class polylog(DefinedFunction): + r""" + Polylogarithm function. + + Explanation + =========== + + For $|z| < 1$ and $s \in \mathbb{C}$, the polylogarithm is + defined by + + .. math:: \operatorname{Li}_s(z) = \sum_{n=1}^\infty \frac{z^n}{n^s}, + + where the standard branch of the argument is used for $n$. It admits + an analytic continuation which is branched at $z=1$ (notably not on the + sheet of initial definition), $z=0$ and $z=\infty$. + + The name polylogarithm comes from the fact that for $s=1$, the + polylogarithm is related to the ordinary logarithm (see examples), and that + + .. math:: \operatorname{Li}_{s+1}(z) = + \int_0^z \frac{\operatorname{Li}_s(t)}{t} \mathrm{d}t. + + The polylogarithm is a special case of the Lerch transcendent: + + .. math:: \operatorname{Li}_{s}(z) = z \Phi(z, s, 1). + + Examples + ======== + + For $z \in \{0, 1, -1\}$, the polylogarithm is automatically expressed + using other functions: + + >>> from sympy import polylog + >>> from sympy.abc import s + >>> polylog(s, 0) + 0 + >>> polylog(s, 1) + zeta(s) + >>> polylog(s, -1) + -dirichlet_eta(s) + + If $s$ is a negative integer, $0$ or $1$, the polylogarithm can be + expressed using elementary functions. This can be done using + ``expand_func()``: + + >>> from sympy import expand_func + >>> from sympy.abc import z + >>> expand_func(polylog(1, z)) + -log(1 - z) + >>> expand_func(polylog(0, z)) + z/(1 - z) + + The derivative with respect to $z$ can be computed in closed form: + + >>> polylog(s, z).diff(z) + polylog(s - 1, z)/z + + The polylogarithm can be expressed in terms of the lerch transcendent: + + >>> from sympy import lerchphi + >>> polylog(s, z).rewrite(lerchphi) + z*lerchphi(z, s, 1) + + See Also + ======== + + zeta, lerchphi + + """ + + @classmethod + def eval(cls, s, z): + if z.is_number: + if z is S.One: + return zeta(s) + elif z is S.NegativeOne: + return -dirichlet_eta(s) + elif z is S.Zero: + return S.Zero + elif s == 2: + dilogtable = _dilogtable() + if z in dilogtable: + return dilogtable[z] + + if z.is_zero: + return S.Zero + + # Make an effort to determine if z is 1 to avoid replacing into + # expression with singularity + zone = z.equals(S.One) + + if zone: + return zeta(s) + elif zone is False: + # For s = 0 or -1 use explicit formulas to evaluate, but + # automatically expanding polylog(1, z) to -log(1-z) seems + # undesirable for summation methods based on hypergeometric + # functions + if s is S.Zero: + return z/(1 - z) + elif s is S.NegativeOne: + return z/(1 - z)**2 + if s.is_zero: + return z/(1 - z) + + # polylog is branched, but not over the unit disk + if z.has(exp_polar, polar_lift) and (zone or (Abs(z) <= S.One) == True): + return cls(s, unpolarify(z)) + + def fdiff(self, argindex=1): + s, z = self.args + if argindex == 2: + return polylog(s - 1, z)/z + raise ArgumentIndexError + + def _eval_rewrite_as_lerchphi(self, s, z, **kwargs): + return z*lerchphi(z, s, 1) + + def _eval_expand_func(self, **hints): + s, z = self.args + if s == 1: + return -log(1 - z) + if s.is_Integer and s <= 0: + u = Dummy('u') + start = u/(1 - u) + for _ in range(-s): + start = u*start.diff(u) + return expand_mul(start).subs(u, z) + return polylog(s, z) + + def _eval_is_zero(self): + z = self.args[1] + if z.is_zero: + return True + + def _eval_nseries(self, x, n, logx, cdir=0): + from sympy.series.order import Order + nu, z = self.args + + z0 = z.subs(x, 0) + if z0 is S.NaN: + z0 = z.limit(x, 0, dir='-' if re(cdir).is_negative else '+') + + if z0.is_zero: + # In case of powers less than 1, number of terms need to be computed + # separately to avoid repeated callings of _eval_nseries with wrong n + try: + _, exp = z.leadterm(x) + except (ValueError, NotImplementedError): + return self + + if exp.is_positive: + newn = ceiling(n/exp) + o = Order(x**n, x) + r = z._eval_nseries(x, n, logx, cdir).removeO() + if r is S.Zero: + return o + + term = r + s = [term] + for k in range(2, newn): + term *= r + s.append(term/k**nu) + return Add(*s) + o + + return super(polylog, self)._eval_nseries(x, n, logx, cdir) + +############################################################################### +###################### HURWITZ GENERALIZED ZETA FUNCTION ###################### +############################################################################### + + +class zeta(DefinedFunction): + r""" + Hurwitz zeta function (or Riemann zeta function). + + Explanation + =========== + + For $\operatorname{Re}(a) > 0$ and $\operatorname{Re}(s) > 1$, this + function is defined as + + .. math:: \zeta(s, a) = \sum_{n=0}^\infty \frac{1}{(n + a)^s}, + + where the standard choice of argument for $n + a$ is used. For fixed + $a$ not a nonpositive integer the Hurwitz zeta function admits a + meromorphic continuation to all of $\mathbb{C}$; it is an unbranched + function with a simple pole at $s = 1$. + + The Hurwitz zeta function is a special case of the Lerch transcendent: + + .. math:: \zeta(s, a) = \Phi(1, s, a). + + This formula defines an analytic continuation for all possible values of + $s$ and $a$ (also $\operatorname{Re}(a) < 0$), see the documentation of + :class:`lerchphi` for a description of the branching behavior. + + If no value is passed for $a$ a default value of $a = 1$ is assumed, + yielding the Riemann zeta function. + + Examples + ======== + + For $a = 1$ the Hurwitz zeta function reduces to the famous Riemann + zeta function: + + .. math:: \zeta(s, 1) = \zeta(s) = \sum_{n=1}^\infty \frac{1}{n^s}. + + >>> from sympy import zeta + >>> from sympy.abc import s + >>> zeta(s, 1) + zeta(s) + >>> zeta(s) + zeta(s) + + The Riemann zeta function can also be expressed using the Dirichlet eta + function: + + >>> from sympy import dirichlet_eta + >>> zeta(s).rewrite(dirichlet_eta) + dirichlet_eta(s)/(1 - 2**(1 - s)) + + The Riemann zeta function at nonnegative even and negative integer + values is related to the Bernoulli numbers and polynomials: + + >>> zeta(2) + pi**2/6 + >>> zeta(4) + pi**4/90 + >>> zeta(0) + -1/2 + >>> zeta(-1) + -1/12 + >>> zeta(-4) + 0 + + The specific formulae are: + + .. math:: \zeta(2n) = -\frac{(2\pi i)^{2n} B_{2n}}{2(2n)!} + .. math:: \zeta(-n,a) = -\frac{B_{n+1}(a)}{n+1} + + No closed-form expressions are known at positive odd integers, but + numerical evaluation is possible: + + >>> zeta(3).n() + 1.20205690315959 + + The derivative of $\zeta(s, a)$ with respect to $a$ can be computed: + + >>> from sympy.abc import a + >>> zeta(s, a).diff(a) + -s*zeta(s + 1, a) + + However the derivative with respect to $s$ has no useful closed form + expression: + + >>> zeta(s, a).diff(s) + Derivative(zeta(s, a), s) + + The Hurwitz zeta function can be expressed in terms of the Lerch + transcendent, :class:`~.lerchphi`: + + >>> from sympy import lerchphi + >>> zeta(s, a).rewrite(lerchphi) + lerchphi(1, s, a) + + See Also + ======== + + dirichlet_eta, lerchphi, polylog + + References + ========== + + .. [1] https://dlmf.nist.gov/25.11 + .. [2] https://en.wikipedia.org/wiki/Hurwitz_zeta_function + + """ + + @classmethod + def eval(cls, s, a=None): + if a is S.One: + return cls(s) + elif s is S.NaN or a is S.NaN: + return S.NaN + elif s is S.One: + return S.ComplexInfinity + elif s is S.Infinity: + return S.One + elif a is S.Infinity: + return S.Zero + + sint = s.is_Integer + if a is None: + a = S.One + if sint and s.is_nonpositive: + return bernoulli(1-s, a) / (s-1) + elif a is S.One: + if sint and s.is_even: + return -(2*pi*I)**s * bernoulli(s) / (2*factorial(s)) + elif sint and a.is_Integer and a.is_positive: + return cls(s) - harmonic(a-1, s) + elif a.is_Integer and a.is_nonpositive and \ + (s.is_integer is False or s.is_nonpositive is False): + return S.NaN + + def _eval_rewrite_as_bernoulli(self, s, a=1, **kwargs): + if a == 1 and s.is_integer and s.is_nonnegative and s.is_even: + return -(2*pi*I)**s * bernoulli(s) / (2*factorial(s)) + return bernoulli(1-s, a) / (s-1) + + def _eval_rewrite_as_dirichlet_eta(self, s, a=1, **kwargs): + if a != 1: + return self + s = self.args[0] + return dirichlet_eta(s)/(1 - 2**(1 - s)) + + def _eval_rewrite_as_lerchphi(self, s, a=1, **kwargs): + return lerchphi(1, s, a) + + def _eval_is_finite(self): + return fuzzy_not((self.args[0] - 1).is_zero) + + def _eval_expand_func(self, **hints): + s = self.args[0] + a = self.args[1] if len(self.args) > 1 else S.One + if a.is_integer: + if a.is_positive: + return zeta(s) - harmonic(a-1, s) + if a.is_nonpositive and (s.is_integer is False or + s.is_nonpositive is False): + return S.NaN + return self + + def fdiff(self, argindex=1): + if len(self.args) == 2: + s, a = self.args + else: + s, a = self.args + (1,) + if argindex == 2: + return -s*zeta(s + 1, a) + else: + raise ArgumentIndexError + + def _eval_as_leading_term(self, x, logx, cdir): + if len(self.args) == 2: + s, a = self.args + else: + s, a = self.args + (S.One,) + + try: + c, e = a.leadterm(x) + except NotImplementedError: + return self + + if e.is_negative and not s.is_positive: + raise NotImplementedError + + return super(zeta, self)._eval_as_leading_term(x, logx=logx, cdir=cdir) + + +class dirichlet_eta(DefinedFunction): + r""" + Dirichlet eta function. + + Explanation + =========== + + For $\operatorname{Re}(s) > 0$ and $0 < x \le 1$, this function is defined as + + .. math:: \eta(s, a) = \sum_{n=0}^\infty \frac{(-1)^n}{(n+a)^s}. + + It admits a unique analytic continuation to all of $\mathbb{C}$ for any + fixed $a$ not a nonpositive integer. It is an entire, unbranched function. + + It can be expressed using the Hurwitz zeta function as + + .. math:: \eta(s, a) = \zeta(s,a) - 2^{1-s} \zeta\left(s, \frac{a+1}{2}\right) + + and using the generalized Genocchi function as + + .. math:: \eta(s, a) = \frac{G(1-s, a)}{2(s-1)}. + + In both cases the limiting value of $\log2 - \psi(a) + \psi\left(\frac{a+1}{2}\right)$ + is used when $s = 1$. + + Examples + ======== + + >>> from sympy import dirichlet_eta, zeta + >>> from sympy.abc import s + >>> dirichlet_eta(s).rewrite(zeta) + Piecewise((log(2), Eq(s, 1)), ((1 - 2**(1 - s))*zeta(s), True)) + + See Also + ======== + + zeta + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Dirichlet_eta_function + .. [2] Peter Luschny, "An introduction to the Bernoulli function", + https://arxiv.org/abs/2009.06743 + + """ + + @classmethod + def eval(cls, s, a=None): + if a is S.One: + return cls(s) + if a is None: + if s == 1: + return log(2) + z = zeta(s) + if not z.has(zeta): + return (1 - 2**(1-s)) * z + return + elif s == 1: + from sympy.functions.special.gamma_functions import digamma + return log(2) - digamma(a) + digamma((a+1)/2) + z1 = zeta(s, a) + z2 = zeta(s, (a+1)/2) + if not z1.has(zeta) and not z2.has(zeta): + return z1 - 2**(1-s) * z2 + + def _eval_rewrite_as_zeta(self, s, a=1, **kwargs): + from sympy.functions.special.gamma_functions import digamma + if a == 1: + return Piecewise((log(2), Eq(s, 1)), ((1 - 2**(1-s)) * zeta(s), True)) + return Piecewise((log(2) - digamma(a) + digamma((a+1)/2), Eq(s, 1)), + (zeta(s, a) - 2**(1-s) * zeta(s, (a+1)/2), True)) + + def _eval_rewrite_as_genocchi(self, s, a=S.One, **kwargs): + from sympy.functions.special.gamma_functions import digamma + return Piecewise((log(2) - digamma(a) + digamma((a+1)/2), Eq(s, 1)), + (genocchi(1-s, a) / (2 * (s-1)), True)) + + def _eval_evalf(self, prec): + if all(i.is_number for i in self.args): + return self.rewrite(zeta)._eval_evalf(prec) + + +class riemann_xi(DefinedFunction): + r""" + Riemann Xi function. + + Examples + ======== + + The Riemann Xi function is closely related to the Riemann zeta function. + The zeros of Riemann Xi function are precisely the non-trivial zeros + of the zeta function. + + >>> from sympy import riemann_xi, zeta + >>> from sympy.abc import s + >>> riemann_xi(s).rewrite(zeta) + s*(s - 1)*gamma(s/2)*zeta(s)/(2*pi**(s/2)) + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Riemann_Xi_function + + """ + + + @classmethod + def eval(cls, s): + from sympy.functions.special.gamma_functions import gamma + z = zeta(s) + if s in (S.Zero, S.One): + return S.Half + + if not isinstance(z, zeta): + return s*(s - 1)*gamma(s/2)*z/(2*pi**(s/2)) + + def _eval_rewrite_as_zeta(self, s, **kwargs): + from sympy.functions.special.gamma_functions import gamma + return s*(s - 1)*gamma(s/2)*zeta(s)/(2*pi**(s/2)) + + +class stieltjes(DefinedFunction): + r""" + Represents Stieltjes constants, $\gamma_{k}$ that occur in + Laurent Series expansion of the Riemann zeta function. + + Examples + ======== + + >>> from sympy import stieltjes + >>> from sympy.abc import n, m + >>> stieltjes(n) + stieltjes(n) + + The zero'th stieltjes constant: + + >>> stieltjes(0) + EulerGamma + >>> stieltjes(0, 1) + EulerGamma + + For generalized stieltjes constants: + + >>> stieltjes(n, m) + stieltjes(n, m) + + Constants are only defined for integers >= 0: + + >>> stieltjes(-1) + zoo + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Stieltjes_constants + + """ + + @classmethod + def eval(cls, n, a=None): + if a is not None: + a = sympify(a) + if a is S.NaN: + return S.NaN + if a.is_Integer and a.is_nonpositive: + return S.ComplexInfinity + + if n.is_Number: + if n is S.NaN: + return S.NaN + elif n < 0: + return S.ComplexInfinity + elif not n.is_Integer: + return S.ComplexInfinity + elif n is S.Zero and a in [None, 1]: + return S.EulerGamma + + if n.is_extended_negative: + return S.ComplexInfinity + + if n.is_zero and a in [None, 1]: + return S.EulerGamma + + if n.is_integer == False: + return S.ComplexInfinity + + +@cacheit +def _dilogtable(): + return { + S.Half: pi**2/12 - log(2)**2/2, + Integer(2) : pi**2/4 - I*pi*log(2), + -(sqrt(5) - 1)/2 : -pi**2/15 + log((sqrt(5)-1)/2)**2/2, + -(sqrt(5) + 1)/2 : -pi**2/10 - log((sqrt(5)+1)/2)**2, + (3 - sqrt(5))/2 : pi**2/15 - log((sqrt(5)-1)/2)**2, + (sqrt(5) - 1)/2 : pi**2/10 - log((sqrt(5)-1)/2)**2, + I : I*S.Catalan - pi**2/48, + -I : -I*S.Catalan - pi**2/48, + 1 - I : pi**2/16 - I*S.Catalan - pi*I/4*log(2), + 1 + I : pi**2/16 + I*S.Catalan + pi*I/4*log(2), + (1 - I)/2 : -log(2)**2/8 + pi*I*log(2)/8 + 5*pi**2/96 - I*S.Catalan + } diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8563ed03dd1c04d8c2ab67a8ab9a4e8adbc87f42 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/curve.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/curve.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e7e7e8778b95c4c1fd79d98de458659deb2d824d Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/curve.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/ellipse.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/ellipse.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8d09e184fa3ef3397af1129ccbb5c5437741174d Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/ellipse.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/entity.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/entity.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3e490e7cc9c05587a560081ac909505695e44f19 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/entity.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/exceptions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/exceptions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6258cc3ca023ddb74fe8bc35138137078ac68c76 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/exceptions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/line.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/line.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1e0941d50efe37f0507683c02422b3a2dc530895 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/line.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/parabola.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/parabola.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7c746f7665ff8c4147bf3cb0a958d7274aea4a5f Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/parabola.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/plane.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/plane.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e7628776cdb727e23050a56decf08f47d5dc0f39 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/plane.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/point.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/point.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4efa48d03012072409ab4b3338cfcf2336a8d28a Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/point.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/util.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/util.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..298e2beefc40284558ab77a09d3a61c9cb22bc0c Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/__pycache__/util.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..49956fc8852224db6d4150f206cc965ca08bf6b5 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_curve.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_curve.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b541369881159e0b1c11bfa9ac8375cf6efe53e3 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_curve.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_ellipse.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_ellipse.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2fb436f1389d8e71f350185f66c5796e78d838fc Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_ellipse.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_entity.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_entity.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..12a65af5cac7b47785f8431bbfe9449f89bf61ac Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_entity.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_geometrysets.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_geometrysets.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..90b6839fbd6d6729d21975c97f163075e2d6c845 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_geometrysets.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_line.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_line.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c1838251d764c1600fcd628c4fdba00bfcc7aec2 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_line.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_parabola.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_parabola.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b43b4df75c0084f6043050ebf1886b279ae4ac65 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_parabola.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_plane.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_plane.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5d7dccef67946dd6938c9dc0a3f444340e5ad91b Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_plane.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_point.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_point.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a0154784d36e1e87009e3b8c6bf59096318935c1 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_point.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_polygon.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_polygon.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d8f97b73c34c1ecbc6544a5ed7bb44d768138d4d Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_polygon.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_util.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_util.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..006b21abae9bf4c09d84cb65f7f23aa6d3b073a1 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/__pycache__/test_util.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_curve.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_curve.py new file mode 100644 index 0000000000000000000000000000000000000000..50aa80273a1d8eb9e414a8d591571f3127352dad --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_curve.py @@ -0,0 +1,120 @@ +from sympy.core.containers import Tuple +from sympy.core.numbers import (Rational, pi) +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.elementary.hyperbolic import asinh +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.geometry import Curve, Line, Point, Ellipse, Ray, Segment, Circle, Polygon, RegularPolygon +from sympy.testing.pytest import raises, slow + + +def test_curve(): + x = Symbol('x', real=True) + s = Symbol('s') + z = Symbol('z') + + # this curve is independent of the indicated parameter + c = Curve([2*s, s**2], (z, 0, 2)) + + assert c.parameter == z + assert c.functions == (2*s, s**2) + assert c.arbitrary_point() == Point(2*s, s**2) + assert c.arbitrary_point(z) == Point(2*s, s**2) + + # this is how it is normally used + c = Curve([2*s, s**2], (s, 0, 2)) + + assert c.parameter == s + assert c.functions == (2*s, s**2) + t = Symbol('t') + # the t returned as assumptions + assert c.arbitrary_point() != Point(2*t, t**2) + t = Symbol('t', real=True) + # now t has the same assumptions so the test passes + assert c.arbitrary_point() == Point(2*t, t**2) + assert c.arbitrary_point(z) == Point(2*z, z**2) + assert c.arbitrary_point(c.parameter) == Point(2*s, s**2) + assert c.arbitrary_point(None) == Point(2*s, s**2) + assert c.plot_interval() == [t, 0, 2] + assert c.plot_interval(z) == [z, 0, 2] + + assert Curve([x, x], (x, 0, 1)).rotate(pi/2) == Curve([-x, x], (x, 0, 1)) + assert Curve([x, x], (x, 0, 1)).rotate(pi/2, (1, 2)).scale(2, 3).translate( + 1, 3).arbitrary_point(s) == \ + Line((0, 0), (1, 1)).rotate(pi/2, (1, 2)).scale(2, 3).translate( + 1, 3).arbitrary_point(s) == \ + Point(-2*s + 7, 3*s + 6) + + raises(ValueError, lambda: Curve((s), (s, 1, 2))) + raises(ValueError, lambda: Curve((x, x * 2), (1, x))) + + raises(ValueError, lambda: Curve((s, s + t), (s, 1, 2)).arbitrary_point()) + raises(ValueError, lambda: Curve((s, s + t), (t, 1, 2)).arbitrary_point(s)) + + +@slow +def test_free_symbols(): + a, b, c, d, e, f, s = symbols('a:f,s') + assert Point(a, b).free_symbols == {a, b} + assert Line((a, b), (c, d)).free_symbols == {a, b, c, d} + assert Ray((a, b), (c, d)).free_symbols == {a, b, c, d} + assert Ray((a, b), angle=c).free_symbols == {a, b, c} + assert Segment((a, b), (c, d)).free_symbols == {a, b, c, d} + assert Line((a, b), slope=c).free_symbols == {a, b, c} + assert Curve((a*s, b*s), (s, c, d)).free_symbols == {a, b, c, d} + assert Ellipse((a, b), c, d).free_symbols == {a, b, c, d} + assert Ellipse((a, b), c, eccentricity=d).free_symbols == \ + {a, b, c, d} + assert Ellipse((a, b), vradius=c, eccentricity=d).free_symbols == \ + {a, b, c, d} + assert Circle((a, b), c).free_symbols == {a, b, c} + assert Circle((a, b), (c, d), (e, f)).free_symbols == \ + {e, d, c, b, f, a} + assert Polygon((a, b), (c, d), (e, f)).free_symbols == \ + {e, b, d, f, a, c} + assert RegularPolygon((a, b), c, d, e).free_symbols == {e, a, b, c, d} + + +def test_transform(): + x = Symbol('x', real=True) + y = Symbol('y', real=True) + c = Curve((x, x**2), (x, 0, 1)) + cout = Curve((2*x - 4, 3*x**2 - 10), (x, 0, 1)) + pts = [Point(0, 0), Point(S.Half, Rational(1, 4)), Point(1, 1)] + pts_out = [Point(-4, -10), Point(-3, Rational(-37, 4)), Point(-2, -7)] + + assert c.scale(2, 3, (4, 5)) == cout + assert [c.subs(x, xi/2) for xi in Tuple(0, 1, 2)] == pts + assert [cout.subs(x, xi/2) for xi in Tuple(0, 1, 2)] == pts_out + assert Curve((x + y, 3*x), (x, 0, 1)).subs(y, S.Half) == \ + Curve((x + S.Half, 3*x), (x, 0, 1)) + assert Curve((x, 3*x), (x, 0, 1)).translate(4, 5) == \ + Curve((x + 4, 3*x + 5), (x, 0, 1)) + + +def test_length(): + t = Symbol('t', real=True) + + c1 = Curve((t, 0), (t, 0, 1)) + assert c1.length == 1 + + c2 = Curve((t, t), (t, 0, 1)) + assert c2.length == sqrt(2) + + c3 = Curve((t ** 2, t), (t, 2, 5)) + assert c3.length == -sqrt(17) - asinh(4) / 4 + asinh(10) / 4 + 5 * sqrt(101) / 2 + + +def test_parameter_value(): + t = Symbol('t') + C = Curve([2*t, t**2], (t, 0, 2)) + assert C.parameter_value((2, 1), t) == {t: 1} + raises(ValueError, lambda: C.parameter_value((2, 0), t)) + + +def test_issue_17997(): + t, s = symbols('t s') + c = Curve((t, t**2), (t, 0, 10)) + p = Curve([2*s, s**2], (s, 0, 2)) + assert c(2) == Point(2, 4) + assert p(1) == Point(2, 1) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_ellipse.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_ellipse.py new file mode 100644 index 0000000000000000000000000000000000000000..a79eba8c35771bda9f0980aca68d937f8e625c0a --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_ellipse.py @@ -0,0 +1,613 @@ +from sympy.core import expand +from sympy.core.numbers import (Rational, oo, pi) +from sympy.core.relational import Eq +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.elementary.complexes import Abs +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import sec +from sympy.geometry.line import Segment2D +from sympy.geometry.point import Point2D +from sympy.geometry import (Circle, Ellipse, GeometryError, Line, Point, + Polygon, Ray, RegularPolygon, Segment, + Triangle, intersection) +from sympy.testing.pytest import raises, slow +from sympy.integrals.integrals import integrate +from sympy.functions.special.elliptic_integrals import elliptic_e +from sympy.functions.elementary.miscellaneous import Max + + +def test_ellipse_equation_using_slope(): + from sympy.abc import x, y + + e1 = Ellipse(Point(1, 0), 3, 2) + assert str(e1.equation(_slope=1)) == str((-x + y + 1)**2/8 + (x + y - 1)**2/18 - 1) + + e2 = Ellipse(Point(0, 0), 4, 1) + assert str(e2.equation(_slope=1)) == str((-x + y)**2/2 + (x + y)**2/32 - 1) + + e3 = Ellipse(Point(1, 5), 6, 2) + assert str(e3.equation(_slope=2)) == str((-2*x + y - 3)**2/20 + (x + 2*y - 11)**2/180 - 1) + + +def test_object_from_equation(): + from sympy.abc import x, y, a, b, c, d, e + assert Circle(x**2 + y**2 + 3*x + 4*y - 8) == Circle(Point2D(S(-3) / 2, -2), sqrt(57) / 2) + assert Circle(x**2 + y**2 + 6*x + 8*y + 25) == Circle(Point2D(-3, -4), 0) + assert Circle(a**2 + b**2 + 6*a + 8*b + 25, x='a', y='b') == Circle(Point2D(-3, -4), 0) + assert Circle(x**2 + y**2 - 25) == Circle(Point2D(0, 0), 5) + assert Circle(x**2 + y**2) == Circle(Point2D(0, 0), 0) + assert Circle(a**2 + b**2, x='a', y='b') == Circle(Point2D(0, 0), 0) + assert Circle(x**2 + y**2 + 6*x + 8) == Circle(Point2D(-3, 0), 1) + assert Circle(x**2 + y**2 + 6*y + 8) == Circle(Point2D(0, -3), 1) + assert Circle((x - 1)**2 + y**2 - 9) == Circle(Point2D(1, 0), 3) + assert Circle(6*(x**2) + 6*(y**2) + 6*x + 8*y - 25) == Circle(Point2D(Rational(-1, 2), Rational(-2, 3)), 5*sqrt(7)/6) + assert Circle(Eq(a**2 + b**2, 25), x='a', y=b) == Circle(Point2D(0, 0), 5) + raises(GeometryError, lambda: Circle(x**2 + y**2 + 3*x + 4*y + 26)) + raises(GeometryError, lambda: Circle(x**2 + y**2 + 25)) + raises(GeometryError, lambda: Circle(a**2 + b**2 + 25, x='a', y='b')) + raises(GeometryError, lambda: Circle(x**2 + 6*y + 8)) + raises(GeometryError, lambda: Circle(6*(x ** 2) + 4*(y**2) + 6*x + 8*y + 25)) + raises(ValueError, lambda: Circle(a**2 + b**2 + 3*a + 4*b - 8)) + # .equation() adds 'real=True' assumption; '==' would fail if assumptions differed + x, y = symbols('x y', real=True) + eq = a*x**2 + a*y**2 + c*x + d*y + e + assert expand(Circle(eq).equation()*a) == eq + + +@slow +def test_ellipse_geom(): + x = Symbol('x', real=True) + y = Symbol('y', real=True) + t = Symbol('t', real=True) + y1 = Symbol('y1', real=True) + half = S.Half + p1 = Point(0, 0) + p2 = Point(1, 1) + p4 = Point(0, 1) + + e1 = Ellipse(p1, 1, 1) + e2 = Ellipse(p2, half, 1) + e3 = Ellipse(p1, y1, y1) + c1 = Circle(p1, 1) + c2 = Circle(p2, 1) + c3 = Circle(Point(sqrt(2), sqrt(2)), 1) + l1 = Line(p1, p2) + + # Test creation with three points + cen, rad = Point(3*half, 2), 5*half + assert Circle(Point(0, 0), Point(3, 0), Point(0, 4)) == Circle(cen, rad) + assert Circle(Point(0, 0), Point(1, 1), Point(2, 2)) == Segment2D(Point2D(0, 0), Point2D(2, 2)) + + raises(ValueError, lambda: Ellipse(None, None, None, 1)) + raises(ValueError, lambda: Ellipse()) + raises(GeometryError, lambda: Circle(Point(0, 0))) + raises(GeometryError, lambda: Circle(Symbol('x')*Symbol('y'))) + + # Basic Stuff + assert Ellipse(None, 1, 1).center == Point(0, 0) + assert e1 == c1 + assert e1 != e2 + assert e1 != l1 + assert p4 in e1 + assert e1 in e1 + assert e2 in e2 + assert 1 not in e2 + assert p2 not in e2 + assert e1.area == pi + assert e2.area == pi/2 + assert e3.area == pi*y1*abs(y1) + assert c1.area == e1.area + assert c1.circumference == e1.circumference + assert e3.circumference == 2*pi*y1 + assert e1.plot_interval() == e2.plot_interval() == [t, -pi, pi] + assert e1.plot_interval(x) == e2.plot_interval(x) == [x, -pi, pi] + + assert c1.minor == 1 + assert c1.major == 1 + assert c1.hradius == 1 + assert c1.vradius == 1 + + assert Ellipse((1, 1), 0, 0) == Point(1, 1) + assert Ellipse((1, 1), 1, 0) == Segment(Point(0, 1), Point(2, 1)) + assert Ellipse((1, 1), 0, 1) == Segment(Point(1, 0), Point(1, 2)) + + # Private Functions + assert hash(c1) == hash(Circle(Point(1, 0), Point(0, 1), Point(0, -1))) + assert c1 in e1 + assert (Line(p1, p2) in e1) is False + assert e1.__cmp__(e1) == 0 + assert e1.__cmp__(Point(0, 0)) > 0 + + # Encloses + assert e1.encloses(Segment(Point(-0.5, -0.5), Point(0.5, 0.5))) is True + assert e1.encloses(Line(p1, p2)) is False + assert e1.encloses(Ray(p1, p2)) is False + assert e1.encloses(e1) is False + assert e1.encloses( + Polygon(Point(-0.5, -0.5), Point(-0.5, 0.5), Point(0.5, 0.5))) is True + assert e1.encloses(RegularPolygon(p1, 0.5, 3)) is True + assert e1.encloses(RegularPolygon(p1, 5, 3)) is False + assert e1.encloses(RegularPolygon(p2, 5, 3)) is False + + assert e2.arbitrary_point() in e2 + raises(ValueError, lambda: Ellipse(Point(x, y), 1, 1).arbitrary_point(parameter='x')) + + # Foci + f1, f2 = Point(sqrt(12), 0), Point(-sqrt(12), 0) + ef = Ellipse(Point(0, 0), 4, 2) + assert ef.foci in [(f1, f2), (f2, f1)] + + # Tangents + v = sqrt(2) / 2 + p1_1 = Point(v, v) + p1_2 = p2 + Point(half, 0) + p1_3 = p2 + Point(0, 1) + assert e1.tangent_lines(p4) == c1.tangent_lines(p4) + assert e2.tangent_lines(p1_2) == [Line(Point(Rational(3, 2), 1), Point(Rational(3, 2), S.Half))] + assert e2.tangent_lines(p1_3) == [Line(Point(1, 2), Point(Rational(5, 4), 2))] + assert c1.tangent_lines(p1_1) != [Line(p1_1, Point(0, sqrt(2)))] + assert c1.tangent_lines(p1) == [] + assert e2.is_tangent(Line(p1_2, p2 + Point(half, 1))) + assert e2.is_tangent(Line(p1_3, p2 + Point(half, 1))) + assert c1.is_tangent(Line(p1_1, Point(0, sqrt(2)))) + assert e1.is_tangent(Line(Point(0, 0), Point(1, 1))) is False + assert c1.is_tangent(e1) is True + assert c1.is_tangent(Ellipse(Point(2, 0), 1, 1)) is True + assert c1.is_tangent( + Polygon(Point(1, 1), Point(1, -1), Point(2, 0))) is False + assert c1.is_tangent( + Polygon(Point(1, 1), Point(1, 0), Point(2, 0))) is False + assert Circle(Point(5, 5), 3).is_tangent(Circle(Point(0, 5), 1)) is False + + assert Ellipse(Point(5, 5), 2, 1).tangent_lines(Point(0, 0)) == \ + [Line(Point(0, 0), Point(Rational(77, 25), Rational(132, 25))), + Line(Point(0, 0), Point(Rational(33, 5), Rational(22, 5)))] + assert Ellipse(Point(5, 5), 2, 1).tangent_lines(Point(3, 4)) == \ + [Line(Point(3, 4), Point(4, 4)), Line(Point(3, 4), Point(3, 5))] + assert Circle(Point(5, 5), 2).tangent_lines(Point(3, 3)) == \ + [Line(Point(3, 3), Point(4, 3)), Line(Point(3, 3), Point(3, 4))] + assert Circle(Point(5, 5), 2).tangent_lines(Point(5 - 2*sqrt(2), 5)) == \ + [Line(Point(5 - 2*sqrt(2), 5), Point(5 - sqrt(2), 5 - sqrt(2))), + Line(Point(5 - 2*sqrt(2), 5), Point(5 - sqrt(2), 5 + sqrt(2))), ] + assert Circle(Point(5, 5), 5).tangent_lines(Point(4, 0)) == \ + [Line(Point(4, 0), Point(Rational(40, 13), Rational(5, 13))), + Line(Point(4, 0), Point(5, 0))] + assert Circle(Point(5, 5), 5).tangent_lines(Point(0, 6)) == \ + [Line(Point(0, 6), Point(0, 7)), + Line(Point(0, 6), Point(Rational(5, 13), Rational(90, 13)))] + + # for numerical calculations, we shouldn't demand exact equality, + # so only test up to the desired precision + def lines_close(l1, l2, prec): + """ tests whether l1 and 12 are within 10**(-prec) + of each other """ + return abs(l1.p1 - l2.p1) < 10**(-prec) and abs(l1.p2 - l2.p2) < 10**(-prec) + def line_list_close(ll1, ll2, prec): + return all(lines_close(l1, l2, prec) for l1, l2 in zip(ll1, ll2)) + + e = Ellipse(Point(0, 0), 2, 1) + assert e.normal_lines(Point(0, 0)) == \ + [Line(Point(0, 0), Point(0, 1)), Line(Point(0, 0), Point(1, 0))] + assert e.normal_lines(Point(1, 0)) == \ + [Line(Point(0, 0), Point(1, 0))] + assert e.normal_lines((0, 1)) == \ + [Line(Point(0, 0), Point(0, 1))] + assert line_list_close(e.normal_lines(Point(1, 1), 2), [ + Line(Point(Rational(-51, 26), Rational(-1, 5)), Point(Rational(-25, 26), Rational(17, 83))), + Line(Point(Rational(28, 29), Rational(-7, 8)), Point(Rational(57, 29), Rational(-9, 2)))], 2) + # test the failure of Poly.intervals and checks a point on the boundary + p = Point(sqrt(3), S.Half) + assert p in e + assert line_list_close(e.normal_lines(p, 2), [ + Line(Point(Rational(-341, 171), Rational(-1, 13)), Point(Rational(-170, 171), Rational(5, 64))), + Line(Point(Rational(26, 15), Rational(-1, 2)), Point(Rational(41, 15), Rational(-43, 26)))], 2) + # be sure to use the slope that isn't undefined on boundary + e = Ellipse((0, 0), 2, 2*sqrt(3)/3) + assert line_list_close(e.normal_lines((1, 1), 2), [ + Line(Point(Rational(-64, 33), Rational(-20, 71)), Point(Rational(-31, 33), Rational(2, 13))), + Line(Point(1, -1), Point(2, -4))], 2) + # general ellipse fails except under certain conditions + e = Ellipse((0, 0), x, 1) + assert e.normal_lines((x + 1, 0)) == [Line(Point(0, 0), Point(1, 0))] + raises(NotImplementedError, lambda: e.normal_lines((x + 1, 1))) + # Properties + major = 3 + minor = 1 + e4 = Ellipse(p2, minor, major) + assert e4.focus_distance == sqrt(major**2 - minor**2) + ecc = e4.focus_distance / major + assert e4.eccentricity == ecc + assert e4.periapsis == major*(1 - ecc) + assert e4.apoapsis == major*(1 + ecc) + assert e4.semilatus_rectum == major*(1 - ecc ** 2) + # independent of orientation + e4 = Ellipse(p2, major, minor) + assert e4.focus_distance == sqrt(major**2 - minor**2) + ecc = e4.focus_distance / major + assert e4.eccentricity == ecc + assert e4.periapsis == major*(1 - ecc) + assert e4.apoapsis == major*(1 + ecc) + + # Intersection + l1 = Line(Point(1, -5), Point(1, 5)) + l2 = Line(Point(-5, -1), Point(5, -1)) + l3 = Line(Point(-1, -1), Point(1, 1)) + l4 = Line(Point(-10, 0), Point(0, 10)) + pts_c1_l3 = [Point(sqrt(2)/2, sqrt(2)/2), Point(-sqrt(2)/2, -sqrt(2)/2)] + + assert intersection(e2, l4) == [] + assert intersection(c1, Point(1, 0)) == [Point(1, 0)] + assert intersection(c1, l1) == [Point(1, 0)] + assert intersection(c1, l2) == [Point(0, -1)] + assert intersection(c1, l3) in [pts_c1_l3, [pts_c1_l3[1], pts_c1_l3[0]]] + assert intersection(c1, c2) == [Point(0, 1), Point(1, 0)] + assert intersection(c1, c3) == [Point(sqrt(2)/2, sqrt(2)/2)] + assert e1.intersection(l1) == [Point(1, 0)] + assert e2.intersection(l4) == [] + assert e1.intersection(Circle(Point(0, 2), 1)) == [Point(0, 1)] + assert e1.intersection(Circle(Point(5, 0), 1)) == [] + assert e1.intersection(Ellipse(Point(2, 0), 1, 1)) == [Point(1, 0)] + assert e1.intersection(Ellipse(Point(5, 0), 1, 1)) == [] + assert e1.intersection(Point(2, 0)) == [] + assert e1.intersection(e1) == e1 + assert intersection(Ellipse(Point(0, 0), 2, 1), Ellipse(Point(3, 0), 1, 2)) == [Point(2, 0)] + assert intersection(Circle(Point(0, 0), 2), Circle(Point(3, 0), 1)) == [Point(2, 0)] + assert intersection(Circle(Point(0, 0), 2), Circle(Point(7, 0), 1)) == [] + assert intersection(Ellipse(Point(0, 0), 5, 17), Ellipse(Point(4, 0), 1, 0.2) + ) == [Point(5.0, 0, evaluate=False)] + assert intersection(Ellipse(Point(0, 0), 5, 17), Ellipse(Point(4, 0), 0.999, 0.2)) == [] + assert Circle((0, 0), S.Half).intersection( + Triangle((-1, 0), (1, 0), (0, 1))) == [ + Point(Rational(-1, 2), 0), Point(S.Half, 0)] + raises(TypeError, lambda: intersection(e2, Line((0, 0, 0), (0, 0, 1)))) + raises(TypeError, lambda: intersection(e2, Rational(12))) + raises(TypeError, lambda: Ellipse.intersection(e2, 1)) + # some special case intersections + csmall = Circle(p1, 3) + cbig = Circle(p1, 5) + cout = Circle(Point(5, 5), 1) + # one circle inside of another + assert csmall.intersection(cbig) == [] + # separate circles + assert csmall.intersection(cout) == [] + # coincident circles + assert csmall.intersection(csmall) == csmall + + v = sqrt(2) + t1 = Triangle(Point(0, v), Point(0, -v), Point(v, 0)) + points = intersection(t1, c1) + assert len(points) == 4 + assert Point(0, 1) in points + assert Point(0, -1) in points + assert Point(v/2, v/2) in points + assert Point(v/2, -v/2) in points + + circ = Circle(Point(0, 0), 5) + elip = Ellipse(Point(0, 0), 5, 20) + assert intersection(circ, elip) in \ + [[Point(5, 0), Point(-5, 0)], [Point(-5, 0), Point(5, 0)]] + assert elip.tangent_lines(Point(0, 0)) == [] + elip = Ellipse(Point(0, 0), 3, 2) + assert elip.tangent_lines(Point(3, 0)) == \ + [Line(Point(3, 0), Point(3, -12))] + + e1 = Ellipse(Point(0, 0), 5, 10) + e2 = Ellipse(Point(2, 1), 4, 8) + a = Rational(53, 17) + c = 2*sqrt(3991)/17 + ans = [Point(a - c/8, a/2 + c), Point(a + c/8, a/2 - c)] + assert e1.intersection(e2) == ans + e2 = Ellipse(Point(x, y), 4, 8) + c = sqrt(3991) + ans = [Point(-c/68 + a, c*Rational(2, 17) + a/2), Point(c/68 + a, c*Rational(-2, 17) + a/2)] + assert [p.subs({x: 2, y:1}) for p in e1.intersection(e2)] == ans + + # Combinations of above + assert e3.is_tangent(e3.tangent_lines(p1 + Point(y1, 0))[0]) + + e = Ellipse((1, 2), 3, 2) + assert e.tangent_lines(Point(10, 0)) == \ + [Line(Point(10, 0), Point(1, 0)), + Line(Point(10, 0), Point(Rational(14, 5), Rational(18, 5)))] + + # encloses_point + e = Ellipse((0, 0), 1, 2) + assert e.encloses_point(e.center) + assert e.encloses_point(e.center + Point(0, e.vradius - Rational(1, 10))) + assert e.encloses_point(e.center + Point(e.hradius - Rational(1, 10), 0)) + assert e.encloses_point(e.center + Point(e.hradius, 0)) is False + assert e.encloses_point( + e.center + Point(e.hradius + Rational(1, 10), 0)) is False + e = Ellipse((0, 0), 2, 1) + assert e.encloses_point(e.center) + assert e.encloses_point(e.center + Point(0, e.vradius - Rational(1, 10))) + assert e.encloses_point(e.center + Point(e.hradius - Rational(1, 10), 0)) + assert e.encloses_point(e.center + Point(e.hradius, 0)) is False + assert e.encloses_point( + e.center + Point(e.hradius + Rational(1, 10), 0)) is False + assert c1.encloses_point(Point(1, 0)) is False + assert c1.encloses_point(Point(0.3, 0.4)) is True + + assert e.scale(2, 3) == Ellipse((0, 0), 4, 3) + assert e.scale(3, 6) == Ellipse((0, 0), 6, 6) + assert e.rotate(pi) == e + assert e.rotate(pi, (1, 2)) == Ellipse(Point(2, 4), 2, 1) + raises(NotImplementedError, lambda: e.rotate(pi/3)) + + # Circle rotation tests (Issue #11743) + # Link - https://github.com/sympy/sympy/issues/11743 + cir = Circle(Point(1, 0), 1) + assert cir.rotate(pi/2) == Circle(Point(0, 1), 1) + assert cir.rotate(pi/3) == Circle(Point(S.Half, sqrt(3)/2), 1) + assert cir.rotate(pi/3, Point(1, 0)) == Circle(Point(1, 0), 1) + assert cir.rotate(pi/3, Point(0, 1)) == Circle(Point(S.Half + sqrt(3)/2, S.Half + sqrt(3)/2), 1) + + +def test_construction(): + e1 = Ellipse(hradius=2, vradius=1, eccentricity=None) + assert e1.eccentricity == sqrt(3)/2 + + e2 = Ellipse(hradius=2, vradius=None, eccentricity=sqrt(3)/2) + assert e2.vradius == 1 + + e3 = Ellipse(hradius=None, vradius=1, eccentricity=sqrt(3)/2) + assert e3.hradius == 2 + + # filter(None, iterator) filters out anything falsey, including 0 + # eccentricity would be filtered out in this case and the constructor would throw an error + e4 = Ellipse(Point(0, 0), hradius=1, eccentricity=0) + assert e4.vradius == 1 + + #tests for eccentricity > 1 + raises(GeometryError, lambda: Ellipse(Point(3, 1), hradius=3, eccentricity = S(3)/2)) + raises(GeometryError, lambda: Ellipse(Point(3, 1), hradius=3, eccentricity=sec(5))) + raises(GeometryError, lambda: Ellipse(Point(3, 1), hradius=3, eccentricity=S.Pi-S(2))) + + #tests for eccentricity = 1 + #if vradius is not defined + assert Ellipse(None, 1, None, 1).length == 2 + #if hradius is not defined + raises(GeometryError, lambda: Ellipse(None, None, 1, eccentricity = 1)) + + #tests for eccentricity < 0 + raises(GeometryError, lambda: Ellipse(Point(3, 1), hradius=3, eccentricity = -3)) + raises(GeometryError, lambda: Ellipse(Point(3, 1), hradius=3, eccentricity = -0.5)) + +def test_ellipse_random_point(): + y1 = Symbol('y1', real=True) + e3 = Ellipse(Point(0, 0), y1, y1) + rx, ry = Symbol('rx'), Symbol('ry') + for ind in range(0, 5): + r = e3.random_point() + # substitution should give zero*y1**2 + assert e3.equation(rx, ry).subs(zip((rx, ry), r.args)).equals(0) + # test for the case with seed + r = e3.random_point(seed=1) + assert e3.equation(rx, ry).subs(zip((rx, ry), r.args)).equals(0) + + +def test_repr(): + assert repr(Circle((0, 1), 2)) == 'Circle(Point2D(0, 1), 2)' + + +def test_transform(): + c = Circle((1, 1), 2) + assert c.scale(-1) == Circle((-1, 1), 2) + assert c.scale(y=-1) == Circle((1, -1), 2) + assert c.scale(2) == Ellipse((2, 1), 4, 2) + + assert Ellipse((0, 0), 2, 3).scale(2, 3, (4, 5)) == \ + Ellipse(Point(-4, -10), 4, 9) + assert Circle((0, 0), 2).scale(2, 3, (4, 5)) == \ + Ellipse(Point(-4, -10), 4, 6) + assert Ellipse((0, 0), 2, 3).scale(3, 3, (4, 5)) == \ + Ellipse(Point(-8, -10), 6, 9) + assert Circle((0, 0), 2).scale(3, 3, (4, 5)) == \ + Circle(Point(-8, -10), 6) + assert Circle(Point(-8, -10), 6).scale(Rational(1, 3), Rational(1, 3), (4, 5)) == \ + Circle((0, 0), 2) + assert Circle((0, 0), 2).translate(4, 5) == \ + Circle((4, 5), 2) + assert Circle((0, 0), 2).scale(3, 3) == \ + Circle((0, 0), 6) + + +def test_bounds(): + e1 = Ellipse(Point(0, 0), 3, 5) + e2 = Ellipse(Point(2, -2), 7, 7) + c1 = Circle(Point(2, -2), 7) + c2 = Circle(Point(-2, 0), Point(0, 2), Point(2, 0)) + assert e1.bounds == (-3, -5, 3, 5) + assert e2.bounds == (-5, -9, 9, 5) + assert c1.bounds == (-5, -9, 9, 5) + assert c2.bounds == (-2, -2, 2, 2) + + +def test_reflect(): + b = Symbol('b') + m = Symbol('m') + l = Line((0, b), slope=m) + t1 = Triangle((0, 0), (1, 0), (2, 3)) + assert t1.area == -t1.reflect(l).area + e = Ellipse((1, 0), 1, 2) + assert e.area == -e.reflect(Line((1, 0), slope=0)).area + assert e.area == -e.reflect(Line((1, 0), slope=oo)).area + raises(NotImplementedError, lambda: e.reflect(Line((1, 0), slope=m))) + assert Circle((0, 1), 1).reflect(Line((0, 0), (1, 1))) == Circle(Point2D(1, 0), -1) + + +def test_is_tangent(): + e1 = Ellipse(Point(0, 0), 3, 5) + c1 = Circle(Point(2, -2), 7) + assert e1.is_tangent(Point(0, 0)) is False + assert e1.is_tangent(Point(3, 0)) is False + assert e1.is_tangent(e1) is True + assert e1.is_tangent(Ellipse((0, 0), 1, 2)) is False + assert e1.is_tangent(Ellipse((0, 0), 3, 2)) is True + assert c1.is_tangent(Ellipse((2, -2), 7, 1)) is True + assert c1.is_tangent(Circle((11, -2), 2)) is True + assert c1.is_tangent(Circle((7, -2), 2)) is True + assert c1.is_tangent(Ray((-5, -2), (-15, -20))) is False + assert c1.is_tangent(Ray((-3, -2), (-15, -20))) is False + assert c1.is_tangent(Ray((-3, -22), (15, 20))) is False + assert c1.is_tangent(Ray((9, 20), (9, -20))) is True + assert c1.is_tangent(Ray((2, 5), (9, 5))) is True + assert c1.is_tangent(Segment((2, 5), (9, 5))) is True + assert e1.is_tangent(Segment((2, 2), (-7, 7))) is False + assert e1.is_tangent(Segment((0, 0), (1, 2))) is False + assert c1.is_tangent(Segment((0, 0), (-5, -2))) is False + assert e1.is_tangent(Segment((3, 0), (12, 12))) is False + assert e1.is_tangent(Segment((12, 12), (3, 0))) is False + assert e1.is_tangent(Segment((-3, 0), (3, 0))) is False + assert e1.is_tangent(Segment((-3, 5), (3, 5))) is True + assert e1.is_tangent(Line((10, 0), (10, 10))) is False + assert e1.is_tangent(Line((0, 0), (1, 1))) is False + assert e1.is_tangent(Line((-3, 0), (-2.99, -0.001))) is False + assert e1.is_tangent(Line((-3, 0), (-3, 1))) is True + assert e1.is_tangent(Polygon((0, 0), (5, 5), (5, -5))) is False + assert e1.is_tangent(Polygon((-100, -50), (-40, -334), (-70, -52))) is False + assert e1.is_tangent(Polygon((-3, 0), (3, 0), (0, 1))) is False + assert e1.is_tangent(Polygon((-3, 0), (3, 0), (0, 5))) is False + assert e1.is_tangent(Polygon((-3, 0), (0, -5), (3, 0), (0, 5))) is False + assert e1.is_tangent(Polygon((-3, -5), (-3, 5), (3, 5), (3, -5))) is True + assert c1.is_tangent(Polygon((-3, -5), (-3, 5), (3, 5), (3, -5))) is False + assert e1.is_tangent(Polygon((0, 0), (3, 0), (7, 7), (0, 5))) is False + assert e1.is_tangent(Polygon((3, 12), (3, -12), (6, 5))) is False + assert e1.is_tangent(Polygon((3, 12), (3, -12), (0, -5), (0, 5))) is False + assert e1.is_tangent(Polygon((3, 0), (5, 7), (6, -5))) is False + assert c1.is_tangent(Segment((0, 0), (-5, -2))) is False + assert e1.is_tangent(Segment((-3, 0), (3, 0))) is False + assert e1.is_tangent(Segment((-3, 5), (3, 5))) is True + assert e1.is_tangent(Polygon((0, 0), (5, 5), (5, -5))) is False + assert e1.is_tangent(Polygon((-100, -50), (-40, -334), (-70, -52))) is False + assert e1.is_tangent(Polygon((-3, -5), (-3, 5), (3, 5), (3, -5))) is True + assert c1.is_tangent(Polygon((-3, -5), (-3, 5), (3, 5), (3, -5))) is False + assert e1.is_tangent(Polygon((3, 12), (3, -12), (0, -5), (0, 5))) is False + assert e1.is_tangent(Polygon((3, 0), (5, 7), (6, -5))) is False + raises(TypeError, lambda: e1.is_tangent(Point(0, 0, 0))) + raises(TypeError, lambda: e1.is_tangent(Rational(5))) + + +def test_parameter_value(): + t = Symbol('t') + e = Ellipse(Point(0, 0), 3, 5) + assert e.parameter_value((3, 0), t) == {t: 0} + raises(ValueError, lambda: e.parameter_value((4, 0), t)) + + +@slow +def test_second_moment_of_area(): + x, y = symbols('x, y') + e = Ellipse(Point(0, 0), 5, 4) + I_yy = 2*4*integrate(sqrt(25 - x**2)*x**2, (x, -5, 5))/5 + I_xx = 2*5*integrate(sqrt(16 - y**2)*y**2, (y, -4, 4))/4 + Y = 3*sqrt(1 - x**2/5**2) + I_xy = integrate(integrate(y, (y, -Y, Y))*x, (x, -5, 5)) + assert I_yy == e.second_moment_of_area()[1] + assert I_xx == e.second_moment_of_area()[0] + assert I_xy == e.second_moment_of_area()[2] + #checking for other point + t1 = e.second_moment_of_area(Point(6,5)) + t2 = (580*pi, 845*pi, 600*pi) + assert t1==t2 + + +def test_section_modulus_and_polar_second_moment_of_area(): + d = Symbol('d', positive=True) + c = Circle((3, 7), 8) + assert c.polar_second_moment_of_area() == 2048*pi + assert c.section_modulus() == (128*pi, 128*pi) + c = Circle((2, 9), d/2) + assert c.polar_second_moment_of_area() == pi*d**3*Abs(d)/64 + pi*d*Abs(d)**3/64 + assert c.section_modulus() == (pi*d**3/S(32), pi*d**3/S(32)) + + a, b = symbols('a, b', positive=True) + e = Ellipse((4, 6), a, b) + assert e.section_modulus() == (pi*a*b**2/S(4), pi*a**2*b/S(4)) + assert e.polar_second_moment_of_area() == pi*a**3*b/S(4) + pi*a*b**3/S(4) + e = e.rotate(pi/2) # no change in polar and section modulus + assert e.section_modulus() == (pi*a**2*b/S(4), pi*a*b**2/S(4)) + assert e.polar_second_moment_of_area() == pi*a**3*b/S(4) + pi*a*b**3/S(4) + + e = Ellipse((a, b), 2, 6) + assert e.section_modulus() == (18*pi, 6*pi) + assert e.polar_second_moment_of_area() == 120*pi + + e = Ellipse(Point(0, 0), 2, 2) + assert e.section_modulus() == (2*pi, 2*pi) + assert e.section_modulus(Point(2, 2)) == (2*pi, 2*pi) + assert e.section_modulus((2, 2)) == (2*pi, 2*pi) + + +def test_circumference(): + M = Symbol('M') + m = Symbol('m') + assert Ellipse(Point(0, 0), M, m).circumference == 4 * M * elliptic_e((M ** 2 - m ** 2) / M**2) + + assert Ellipse(Point(0, 0), 5, 4).circumference == 20 * elliptic_e(S(9) / 25) + + # circle + assert Ellipse(None, 1, None, 0).circumference == 2*pi + + # test numerically + assert abs(Ellipse(None, hradius=5, vradius=3).circumference.evalf(16) - 25.52699886339813) < 1e-10 + + +def test_issue_15259(): + assert Circle((1, 2), 0) == Point(1, 2) + + +def test_issue_15797_equals(): + Ri = 0.024127189424130748 + Ci = (0.0864931002830291, 0.0819863295239654) + A = Point(0, 0.0578591400998346) + c = Circle(Ci, Ri) # evaluated + assert c.is_tangent(c.tangent_lines(A)[0]) == True + assert c.center.x.is_Rational + assert c.center.y.is_Rational + assert c.radius.is_Rational + u = Circle(Ci, Ri, evaluate=False) # unevaluated + assert u.center.x.is_Float + assert u.center.y.is_Float + assert u.radius.is_Float + + +def test_auxiliary_circle(): + x, y, a, b = symbols('x y a b') + e = Ellipse((x, y), a, b) + # the general result + assert e.auxiliary_circle() == Circle((x, y), Max(a, b)) + # a special case where Ellipse is a Circle + assert Circle((3, 4), 8).auxiliary_circle() == Circle((3, 4), 8) + + +def test_director_circle(): + x, y, a, b = symbols('x y a b') + e = Ellipse((x, y), a, b) + # the general result + assert e.director_circle() == Circle((x, y), sqrt(a**2 + b**2)) + # a special case where Ellipse is a Circle + assert Circle((3, 4), 8).director_circle() == Circle((3, 4), 8*sqrt(2)) + + +def test_evolute(): + #ellipse centered at h,k + x, y, h, k = symbols('x y h k',real = True) + a, b = symbols('a b') + e = Ellipse(Point(h, k), a, b) + t1 = (e.hradius*(x - e.center.x))**Rational(2, 3) + t2 = (e.vradius*(y - e.center.y))**Rational(2, 3) + E = t1 + t2 - (e.hradius**2 - e.vradius**2)**Rational(2, 3) + assert e.evolute() == E + #Numerical Example + e = Ellipse(Point(1, 1), 6, 3) + t1 = (6*(x - 1))**Rational(2, 3) + t2 = (3*(y - 1))**Rational(2, 3) + E = t1 + t2 - (27)**Rational(2, 3) + assert e.evolute() == E + + +def test_svg(): + e1 = Ellipse(Point(1, 0), 3, 2) + assert e1._svg(2, "#FFAAFF") == '' diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_entity.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_entity.py new file mode 100644 index 0000000000000000000000000000000000000000..0d440fd5dbd193c7c490b45a706fab2703e247ec --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_entity.py @@ -0,0 +1,120 @@ +from sympy.core.numbers import (Rational, pi) +from sympy.core.singleton import S +from sympy.core.symbol import Symbol +from sympy.geometry import (Circle, Ellipse, Point, Line, Parabola, + Polygon, Ray, RegularPolygon, Segment, Triangle, Plane, Curve) +from sympy.geometry.entity import scale, GeometryEntity +from sympy.testing.pytest import raises + + +def test_entity(): + x = Symbol('x', real=True) + y = Symbol('y', real=True) + + assert GeometryEntity(x, y) in GeometryEntity(x, y) + raises(NotImplementedError, lambda: Point(0, 0) in GeometryEntity(x, y)) + + assert GeometryEntity(x, y) == GeometryEntity(x, y) + assert GeometryEntity(x, y).equals(GeometryEntity(x, y)) + + c = Circle((0, 0), 5) + assert GeometryEntity.encloses(c, Point(0, 0)) + assert GeometryEntity.encloses(c, Segment((0, 0), (1, 1))) + assert GeometryEntity.encloses(c, Line((0, 0), (1, 1))) is False + assert GeometryEntity.encloses(c, Circle((0, 0), 4)) + assert GeometryEntity.encloses(c, Polygon(Point(0, 0), Point(1, 0), Point(0, 1))) + assert GeometryEntity.encloses(c, RegularPolygon(Point(8, 8), 1, 3)) is False + + +def test_svg(): + a = Symbol('a') + b = Symbol('b') + d = Symbol('d') + + entity = Circle(Point(a, b), d) + assert entity._repr_svg_() is None + + entity = Circle(Point(0, 0), S.Infinity) + assert entity._repr_svg_() is None + + +def test_subs(): + x = Symbol('x', real=True) + y = Symbol('y', real=True) + p = Point(x, 2) + q = Point(1, 1) + r = Point(3, 4) + for o in [p, + Segment(p, q), + Ray(p, q), + Line(p, q), + Triangle(p, q, r), + RegularPolygon(p, 3, 6), + Polygon(p, q, r, Point(5, 4)), + Circle(p, 3), + Ellipse(p, 3, 4)]: + assert 'y' in str(o.subs(x, y)) + assert p.subs({x: 1}) == Point(1, 2) + assert Point(1, 2).subs(Point(1, 2), Point(3, 4)) == Point(3, 4) + assert Point(1, 2).subs((1, 2), Point(3, 4)) == Point(3, 4) + assert Point(1, 2).subs(Point(1, 2), Point(3, 4)) == Point(3, 4) + assert Point(1, 2).subs({(1, 2)}) == Point(2, 2) + raises(ValueError, lambda: Point(1, 2).subs(1)) + raises(TypeError, lambda: Point(1, 1).subs((Point(1, 1), Point(1, + 2)), 1, 2)) + + +def test_transform(): + assert scale(1, 2, (3, 4)).tolist() == \ + [[1, 0, 0], [0, 2, 0], [0, -4, 1]] + + +def test_reflect_entity_overrides(): + x = Symbol('x', real=True) + y = Symbol('y', real=True) + b = Symbol('b') + m = Symbol('m') + l = Line((0, b), slope=m) + p = Point(x, y) + r = p.reflect(l) + c = Circle((x, y), 3) + cr = c.reflect(l) + assert cr == Circle(r, -3) + assert c.area == -cr.area + + pent = RegularPolygon((1, 2), 1, 5) + slope = S.ComplexInfinity + while slope is S.ComplexInfinity: + slope = Rational(*(x._random()/2).as_real_imag()) + l = Line(pent.vertices[1], slope=slope) + rpent = pent.reflect(l) + assert rpent.center == pent.center.reflect(l) + rvert = [i.reflect(l) for i in pent.vertices] + for v in rpent.vertices: + for i in range(len(rvert)): + ri = rvert[i] + if ri.equals(v): + rvert.remove(ri) + break + assert not rvert + assert pent.area.equals(-rpent.area) + + +def test_geometry_EvalfMixin(): + x = pi + t = Symbol('t') + for g in [ + Point(x, x), + Plane(Point(0, x, 0), (0, 0, x)), + Curve((x*t, x), (t, 0, x)), + Ellipse((x, x), x, -x), + Circle((x, x), x), + Line((0, x), (x, 0)), + Segment((0, x), (x, 0)), + Ray((0, x), (x, 0)), + Parabola((0, x), Line((-x, 0), (x, 0))), + Polygon((0, 0), (0, x), (x, 0), (x, x)), + RegularPolygon((0, x), x, 4, x), + Triangle((0, 0), (x, 0), (x, x)), + ]: + assert str(g).replace('pi', '3.1') == str(g.n(2)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_geometrysets.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_geometrysets.py new file mode 100644 index 0000000000000000000000000000000000000000..c52898b3c9ba4e9db80c244db3aebf88db2cc8b4 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_geometrysets.py @@ -0,0 +1,38 @@ +from sympy.core.numbers import Rational +from sympy.core.singleton import S +from sympy.geometry import Circle, Line, Point, Polygon, Segment +from sympy.sets import FiniteSet, Union, Intersection, EmptySet + + +def test_booleans(): + """ test basic unions and intersections """ + half = S.Half + + p1, p2, p3, p4 = map(Point, [(0, 0), (1, 0), (5, 1), (0, 1)]) + p5, p6, p7 = map(Point, [(3, 2), (1, -1), (0, 2)]) + l1 = Line(Point(0,0), Point(1,1)) + l2 = Line(Point(half, half), Point(5,5)) + l3 = Line(p2, p3) + l4 = Line(p3, p4) + poly1 = Polygon(p1, p2, p3, p4) + poly2 = Polygon(p5, p6, p7) + poly3 = Polygon(p1, p2, p5) + assert Union(l1, l2).equals(l1) + assert Intersection(l1, l2).equals(l1) + assert Intersection(l1, l4) == FiniteSet(Point(1,1)) + assert Intersection(Union(l1, l4), l3) == FiniteSet(Point(Rational(-1, 3), Rational(-1, 3)), Point(5, 1)) + assert Intersection(l1, FiniteSet(Point(7,-7))) == EmptySet + assert Intersection(Circle(Point(0,0), 3), Line(p1,p2)) == FiniteSet(Point(-3,0), Point(3,0)) + assert Intersection(l1, FiniteSet(p1)) == FiniteSet(p1) + assert Union(l1, FiniteSet(p1)) == l1 + + fs = FiniteSet(Point(Rational(1, 3), 1), Point(Rational(2, 3), 0), Point(Rational(9, 5), Rational(1, 5)), Point(Rational(7, 3), 1)) + # test the intersection of polygons + assert Intersection(poly1, poly2) == fs + # make sure if we union polygons with subsets, the subsets go away + assert Union(poly1, poly2, fs) == Union(poly1, poly2) + # make sure that if we union with a FiniteSet that isn't a subset, + # that the points in the intersection stop being listed + assert Union(poly1, FiniteSet(Point(0,0), Point(3,5))) == Union(poly1, FiniteSet(Point(3,5))) + # intersect two polygons that share an edge + assert Intersection(poly1, poly3) == Union(FiniteSet(Point(Rational(3, 2), 1), Point(2, 1)), Segment(Point(0, 0), Point(1, 0))) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_line.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_line.py new file mode 100644 index 0000000000000000000000000000000000000000..5158ec05ab414020fbbe2681a2658454dd15b6eb --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_line.py @@ -0,0 +1,861 @@ +from sympy.core.numbers import (Float, Rational, oo, pi) +from sympy.core.relational import Eq +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (acos, cos, sin) +from sympy.sets import EmptySet +from sympy.simplify.simplify import simplify +from sympy.functions.elementary.trigonometric import tan +from sympy.geometry import (Circle, GeometryError, Line, Point, Ray, + Segment, Triangle, intersection, Point3D, Line3D, Ray3D, Segment3D, + Point2D, Line2D, Plane) +from sympy.geometry.line import Undecidable +from sympy.geometry.polygon import _asa as asa +from sympy.utilities.iterables import cartes +from sympy.testing.pytest import raises, warns + + +x = Symbol('x', real=True) +y = Symbol('y', real=True) +z = Symbol('z', real=True) +k = Symbol('k', real=True) +x1 = Symbol('x1', real=True) +y1 = Symbol('y1', real=True) +t = Symbol('t', real=True) +a, b = symbols('a,b', real=True) +m = symbols('m', real=True) + + +def test_object_from_equation(): + from sympy.abc import x, y, a, b + assert Line(3*x + y + 18) == Line2D(Point2D(0, -18), Point2D(1, -21)) + assert Line(3*x + 5 * y + 1) == Line2D( + Point2D(0, Rational(-1, 5)), Point2D(1, Rational(-4, 5))) + assert Line(3*a + b + 18, x="a", y="b") == Line2D( + Point2D(0, -18), Point2D(1, -21)) + assert Line(3*x + y) == Line2D(Point2D(0, 0), Point2D(1, -3)) + assert Line(x + y) == Line2D(Point2D(0, 0), Point2D(1, -1)) + assert Line(Eq(3*a + b, -18), x="a", y=b) == Line2D( + Point2D(0, -18), Point2D(1, -21)) + # issue 22361 + assert Line(x - 1) == Line2D(Point2D(1, 0), Point2D(1, 1)) + assert Line(2*x - 2, y=x) == Line2D(Point2D(0, 1), Point2D(1, 1)) + assert Line(y) == Line2D(Point2D(0, 0), Point2D(1, 0)) + assert Line(2*y, x=y) == Line2D(Point2D(0, 0), Point2D(0, 1)) + assert Line(y, x=y) == Line2D(Point2D(0, 0), Point2D(0, 1)) + raises(ValueError, lambda: Line(x / y)) + raises(ValueError, lambda: Line(a / b, x='a', y='b')) + raises(ValueError, lambda: Line(y / x)) + raises(ValueError, lambda: Line(b / a, x='a', y='b')) + raises(ValueError, lambda: Line((x + 1)**2 + y)) + + +def feq(a, b): + """Test if two floating point values are 'equal'.""" + t_float = Float("1.0E-10") + return -t_float < a - b < t_float + + +def test_angle_between(): + a = Point(1, 2, 3, 4) + b = a.orthogonal_direction + o = a.origin + assert feq(Line.angle_between(Line(Point(0, 0), Point(1, 1)), + Line(Point(0, 0), Point(5, 0))).evalf(), pi.evalf() / 4) + assert Line(a, o).angle_between(Line(b, o)) == pi / 2 + z = Point3D(0, 0, 0) + assert Line3D.angle_between(Line3D(z, Point3D(1, 1, 1)), + Line3D(z, Point3D(5, 0, 0))) == acos(sqrt(3) / 3) + # direction of points is used to determine angle + assert Line3D.angle_between(Line3D(z, Point3D(1, 1, 1)), + Line3D(Point3D(5, 0, 0), z)) == acos(-sqrt(3) / 3) + + +def test_closing_angle(): + a = Ray((0, 0), angle=0) + b = Ray((1, 2), angle=pi/2) + assert a.closing_angle(b) == -pi/2 + assert b.closing_angle(a) == pi/2 + assert a.closing_angle(a) == 0 + + +def test_smallest_angle(): + a = Line(Point(1, 1), Point(1, 2)) + b = Line(Point(1, 1),Point(2, 3)) + assert a.smallest_angle_between(b) == acos(2*sqrt(5)/5) + + +def test_svg(): + a = Line(Point(1, 1),Point(1, 2)) + assert a._svg() == '' + a = Segment(Point(1, 0),Point(1, 1)) + assert a._svg() == '' + a = Ray(Point(2, 3), Point(3, 5)) + assert a._svg() == '' + + +def test_arbitrary_point(): + l1 = Line3D(Point3D(0, 0, 0), Point3D(1, 1, 1)) + l2 = Line(Point(x1, x1), Point(y1, y1)) + assert l2.arbitrary_point() in l2 + assert Ray((1, 1), angle=pi / 4).arbitrary_point() == \ + Point(t + 1, t + 1) + assert Segment((1, 1), (2, 3)).arbitrary_point() == Point(1 + t, 1 + 2 * t) + assert l1.perpendicular_segment(l1.arbitrary_point()) == l1.arbitrary_point() + assert Ray3D((1, 1, 1), direction_ratio=[1, 2, 3]).arbitrary_point() == \ + Point3D(t + 1, 2 * t + 1, 3 * t + 1) + assert Segment3D(Point3D(0, 0, 0), Point3D(1, 1, 1)).midpoint == \ + Point3D(S.Half, S.Half, S.Half) + assert Segment3D(Point3D(x1, x1, x1), Point3D(y1, y1, y1)).length == sqrt(3) * sqrt((x1 - y1) ** 2) + assert Segment3D((1, 1, 1), (2, 3, 4)).arbitrary_point() == \ + Point3D(t + 1, 2 * t + 1, 3 * t + 1) + raises(ValueError, (lambda: Line((x, 1), (2, 3)).arbitrary_point(x))) + + +def test_are_concurrent_2d(): + l1 = Line(Point(0, 0), Point(1, 1)) + l2 = Line(Point(x1, x1), Point(x1, 1 + x1)) + assert Line.are_concurrent(l1) is False + assert Line.are_concurrent(l1, l2) + assert Line.are_concurrent(l1, l1, l1, l2) + assert Line.are_concurrent(l1, l2, Line(Point(5, x1), Point(Rational(-3, 5), x1))) + assert Line.are_concurrent(l1, Line(Point(0, 0), Point(-x1, x1)), l2) is False + + +def test_are_concurrent_3d(): + p1 = Point3D(0, 0, 0) + l1 = Line(p1, Point3D(1, 1, 1)) + parallel_1 = Line3D(Point3D(0, 0, 0), Point3D(1, 0, 0)) + parallel_2 = Line3D(Point3D(0, 1, 0), Point3D(1, 1, 0)) + assert Line3D.are_concurrent(l1) is False + assert Line3D.are_concurrent(l1, Line(Point3D(x1, x1, x1), Point3D(y1, y1, y1))) is False + assert Line3D.are_concurrent(l1, Line3D(p1, Point3D(x1, x1, x1)), + Line(Point3D(x1, x1, x1), Point3D(x1, 1 + x1, 1))) is True + assert Line3D.are_concurrent(parallel_1, parallel_2) is False + + +def test_arguments(): + """Functions accepting `Point` objects in `geometry` + should also accept tuples, lists, and generators and + automatically convert them to points.""" + from sympy.utilities.iterables import subsets + + singles2d = ((1, 2), [1, 3], Point(1, 5)) + doubles2d = subsets(singles2d, 2) + l2d = Line(Point2D(1, 2), Point2D(2, 3)) + singles3d = ((1, 2, 3), [1, 2, 4], Point(1, 2, 6)) + doubles3d = subsets(singles3d, 2) + l3d = Line(Point3D(1, 2, 3), Point3D(1, 1, 2)) + singles4d = ((1, 2, 3, 4), [1, 2, 3, 5], Point(1, 2, 3, 7)) + doubles4d = subsets(singles4d, 2) + l4d = Line(Point(1, 2, 3, 4), Point(2, 2, 2, 2)) + # test 2D + test_single = ['contains', 'distance', 'equals', 'parallel_line', 'perpendicular_line', 'perpendicular_segment', + 'projection', 'intersection'] + for p in doubles2d: + Line2D(*p) + for func in test_single: + for p in singles2d: + getattr(l2d, func)(p) + # test 3D + for p in doubles3d: + Line3D(*p) + for func in test_single: + for p in singles3d: + getattr(l3d, func)(p) + # test 4D + for p in doubles4d: + Line(*p) + for func in test_single: + for p in singles4d: + getattr(l4d, func)(p) + + +def test_basic_properties_2d(): + p1 = Point(0, 0) + p2 = Point(1, 1) + p10 = Point(2000, 2000) + p_r3 = Ray(p1, p2).random_point() + p_r4 = Ray(p2, p1).random_point() + + l1 = Line(p1, p2) + l3 = Line(Point(x1, x1), Point(x1, 1 + x1)) + l4 = Line(p1, Point(1, 0)) + + r1 = Ray(p1, Point(0, 1)) + r2 = Ray(Point(0, 1), p1) + + s1 = Segment(p1, p10) + p_s1 = s1.random_point() + + assert Line((1, 1), slope=1) == Line((1, 1), (2, 2)) + assert Line((1, 1), slope=oo) == Line((1, 1), (1, 2)) + assert Line((1, 1), slope=oo).bounds == (1, 1, 1, 2) + assert Line((1, 1), slope=-oo) == Line((1, 1), (1, 2)) + assert Line(p1, p2).scale(2, 1) == Line(p1, Point(2, 1)) + assert Line(p1, p2) == Line(p1, p2) + assert Line(p1, p2) != Line(p2, p1) + assert l1 != Line(Point(x1, x1), Point(y1, y1)) + assert l1 != l3 + assert Line(p1, p10) != Line(p10, p1) + assert Line(p1, p10) != p1 + assert p1 in l1 # is p1 on the line l1? + assert p1 not in l3 + assert s1 in Line(p1, p10) + assert Ray(Point(0, 0), Point(0, 1)) in Ray(Point(0, 0), Point(0, 2)) + assert Ray(Point(0, 0), Point(0, 2)) in Ray(Point(0, 0), Point(0, 1)) + assert Ray(Point(0, 0), Point(0, 2)).xdirection == S.Zero + assert Ray(Point(0, 0), Point(1, 2)).xdirection == S.Infinity + assert Ray(Point(0, 0), Point(-1, 2)).xdirection == S.NegativeInfinity + assert Ray(Point(0, 0), Point(2, 0)).ydirection == S.Zero + assert Ray(Point(0, 0), Point(2, 2)).ydirection == S.Infinity + assert Ray(Point(0, 0), Point(2, -2)).ydirection == S.NegativeInfinity + assert (r1 in s1) is False + assert Segment(p1, p2) in s1 + assert Ray(Point(x1, x1), Point(x1, 1 + x1)) != Ray(p1, Point(-1, 5)) + assert Segment(p1, p2).midpoint == Point(S.Half, S.Half) + assert Segment(p1, Point(-x1, x1)).length == sqrt(2 * (x1 ** 2)) + + assert l1.slope == 1 + assert l3.slope is oo + assert l4.slope == 0 + assert Line(p1, Point(0, 1)).slope is oo + assert Line(r1.source, r1.random_point()).slope == r1.slope + assert Line(r2.source, r2.random_point()).slope == r2.slope + assert Segment(Point(0, -1), Segment(p1, Point(0, 1)).random_point()).slope == Segment(p1, Point(0, 1)).slope + + assert l4.coefficients == (0, 1, 0) + assert Line((-x, x), (-x + 1, x - 1)).coefficients == (1, 1, 0) + assert Line(p1, Point(0, 1)).coefficients == (1, 0, 0) + # issue 7963 + r = Ray((0, 0), angle=x) + assert r.subs(x, 3 * pi / 4) == Ray((0, 0), (-1, 1)) + assert r.subs(x, 5 * pi / 4) == Ray((0, 0), (-1, -1)) + assert r.subs(x, -pi / 4) == Ray((0, 0), (1, -1)) + assert r.subs(x, pi / 2) == Ray((0, 0), (0, 1)) + assert r.subs(x, -pi / 2) == Ray((0, 0), (0, -1)) + + for ind in range(0, 5): + assert l3.random_point() in l3 + + assert p_r3.x >= p1.x and p_r3.y >= p1.y + assert p_r4.x <= p2.x and p_r4.y <= p2.y + assert p1.x <= p_s1.x <= p10.x and p1.y <= p_s1.y <= p10.y + assert hash(s1) != hash(Segment(p10, p1)) + + assert s1.plot_interval() == [t, 0, 1] + assert Line(p1, p10).plot_interval() == [t, -5, 5] + assert Ray((0, 0), angle=pi / 4).plot_interval() == [t, 0, 10] + + +def test_basic_properties_3d(): + p1 = Point3D(0, 0, 0) + p2 = Point3D(1, 1, 1) + p3 = Point3D(x1, x1, x1) + p5 = Point3D(x1, 1 + x1, 1) + + l1 = Line3D(p1, p2) + l3 = Line3D(p3, p5) + + r1 = Ray3D(p1, Point3D(-1, 5, 0)) + r3 = Ray3D(p1, p2) + + s1 = Segment3D(p1, p2) + + assert Line3D((1, 1, 1), direction_ratio=[2, 3, 4]) == Line3D(Point3D(1, 1, 1), Point3D(3, 4, 5)) + assert Line3D((1, 1, 1), direction_ratio=[1, 5, 7]) == Line3D(Point3D(1, 1, 1), Point3D(2, 6, 8)) + assert Line3D((1, 1, 1), direction_ratio=[1, 2, 3]) == Line3D(Point3D(1, 1, 1), Point3D(2, 3, 4)) + assert Line3D(Point3D(0, 0, 0), Point3D(1, 0, 0)).direction_cosine == [1, 0, 0] + assert Line3D(Line3D(p1, Point3D(0, 1, 0))) == Line3D(p1, Point3D(0, 1, 0)) + assert Ray3D(Line3D(Point3D(0, 0, 0), Point3D(1, 0, 0))) == Ray3D(p1, Point3D(1, 0, 0)) + assert Line3D(p1, p2) != Line3D(p2, p1) + assert l1 != l3 + assert l1 != Line3D(p3, Point3D(y1, y1, y1)) + assert r3 != r1 + assert Ray3D(Point3D(0, 0, 0), Point3D(1, 1, 1)) in Ray3D(Point3D(0, 0, 0), Point3D(2, 2, 2)) + assert Ray3D(Point3D(0, 0, 0), Point3D(2, 2, 2)) in Ray3D(Point3D(0, 0, 0), Point3D(1, 1, 1)) + assert Ray3D(Point3D(0, 0, 0), Point3D(2, 2, 2)).xdirection == S.Infinity + assert Ray3D(Point3D(0, 0, 0), Point3D(2, 2, 2)).ydirection == S.Infinity + assert Ray3D(Point3D(0, 0, 0), Point3D(2, 2, 2)).zdirection == S.Infinity + assert Ray3D(Point3D(0, 0, 0), Point3D(-2, 2, 2)).xdirection == S.NegativeInfinity + assert Ray3D(Point3D(0, 0, 0), Point3D(2, -2, 2)).ydirection == S.NegativeInfinity + assert Ray3D(Point3D(0, 0, 0), Point3D(2, 2, -2)).zdirection == S.NegativeInfinity + assert Ray3D(Point3D(0, 0, 0), Point3D(0, 2, 2)).xdirection == S.Zero + assert Ray3D(Point3D(0, 0, 0), Point3D(2, 0, 2)).ydirection == S.Zero + assert Ray3D(Point3D(0, 0, 0), Point3D(2, 2, 0)).zdirection == S.Zero + assert p1 in l1 + assert p1 not in l3 + + assert l1.direction_ratio == [1, 1, 1] + + assert s1.midpoint == Point3D(S.Half, S.Half, S.Half) + # Test zdirection + assert Ray3D(p1, Point3D(0, 0, -1)).zdirection is S.NegativeInfinity + + +def test_contains(): + p1 = Point(0, 0) + + r = Ray(p1, Point(4, 4)) + r1 = Ray3D(p1, Point3D(0, 0, -1)) + r2 = Ray3D(p1, Point3D(0, 1, 0)) + r3 = Ray3D(p1, Point3D(0, 0, 1)) + + l = Line(Point(0, 1), Point(3, 4)) + # Segment contains + assert Point(0, (a + b) / 2) in Segment((0, a), (0, b)) + assert Point((a + b) / 2, 0) in Segment((a, 0), (b, 0)) + assert Point3D(0, 1, 0) in Segment3D((0, 1, 0), (0, 1, 0)) + assert Point3D(1, 0, 0) in Segment3D((1, 0, 0), (1, 0, 0)) + assert Segment3D(Point3D(0, 0, 0), Point3D(1, 0, 0)).contains([]) is True + assert Segment3D(Point3D(0, 0, 0), Point3D(1, 0, 0)).contains( + Segment3D(Point3D(2, 2, 2), Point3D(3, 2, 2))) is False + # Line contains + assert l.contains(Point(0, 1)) is True + assert l.contains((0, 1)) is True + assert l.contains((0, 0)) is False + # Ray contains + assert r.contains(p1) is True + assert r.contains((1, 1)) is True + assert r.contains((1, 3)) is False + assert r.contains(Segment((1, 1), (2, 2))) is True + assert r.contains(Segment((1, 2), (2, 5))) is False + assert r.contains(Ray((2, 2), (3, 3))) is True + assert r.contains(Ray((2, 2), (3, 5))) is False + assert r1.contains(Segment3D(p1, Point3D(0, 0, -10))) is True + assert r1.contains(Segment3D(Point3D(1, 1, 1), Point3D(2, 2, 2))) is False + assert r2.contains(Point3D(0, 0, 0)) is True + assert r3.contains(Point3D(0, 0, 0)) is True + assert Ray3D(Point3D(1, 1, 1), Point3D(1, 0, 0)).contains([]) is False + assert Line3D((0, 0, 0), (x, y, z)).contains((2 * x, 2 * y, 2 * z)) + with warns(UserWarning, test_stacklevel=False): + assert Line3D(p1, Point3D(0, 1, 0)).contains(Point(1.0, 1.0)) is False + + with warns(UserWarning, test_stacklevel=False): + assert r3.contains(Point(1.0, 1.0)) is False + + +def test_contains_nonreal_symbols(): + u, v, w, z = symbols('u, v, w, z') + l = Segment(Point(u, w), Point(v, z)) + p = Point(u*Rational(2, 3) + v/3, w*Rational(2, 3) + z/3) + assert l.contains(p) + + +def test_distance_2d(): + p1 = Point(0, 0) + p2 = Point(1, 1) + half = S.Half + + s1 = Segment(Point(0, 0), Point(1, 1)) + s2 = Segment(Point(half, half), Point(1, 0)) + + r = Ray(p1, p2) + + assert s1.distance(Point(0, 0)) == 0 + assert s1.distance((0, 0)) == 0 + assert s2.distance(Point(0, 0)) == 2 ** half / 2 + assert s2.distance(Point(Rational(3) / 2, Rational(3) / 2)) == 2 ** half + assert Line(p1, p2).distance(Point(-1, 1)) == sqrt(2) + assert Line(p1, p2).distance(Point(1, -1)) == sqrt(2) + assert Line(p1, p2).distance(Point(2, 2)) == 0 + assert Line(p1, p2).distance((-1, 1)) == sqrt(2) + assert Line((0, 0), (0, 1)).distance(p1) == 0 + assert Line((0, 0), (0, 1)).distance(p2) == 1 + assert Line((0, 0), (1, 0)).distance(p1) == 0 + assert Line((0, 0), (1, 0)).distance(p2) == 1 + assert r.distance(Point(-1, -1)) == sqrt(2) + assert r.distance(Point(1, 1)) == 0 + assert r.distance(Point(-1, 1)) == sqrt(2) + assert Ray((1, 1), (2, 2)).distance(Point(1.5, 3)) == 3 * sqrt(2) / 4 + assert r.distance((1, 1)) == 0 + + +def test_dimension_normalization(): + with warns(UserWarning, test_stacklevel=False): + assert Ray((1, 1), (2, 1, 2)) == Ray((1, 1, 0), (2, 1, 2)) + + +def test_distance_3d(): + p1, p2 = Point3D(0, 0, 0), Point3D(1, 1, 1) + p3 = Point3D(Rational(3) / 2, Rational(3) / 2, Rational(3) / 2) + + s1 = Segment3D(Point3D(0, 0, 0), Point3D(1, 1, 1)) + s2 = Segment3D(Point3D(S.Half, S.Half, S.Half), Point3D(1, 0, 1)) + + r = Ray3D(p1, p2) + + assert s1.distance(p1) == 0 + assert s2.distance(p1) == sqrt(3) / 2 + assert s2.distance(p3) == 2 * sqrt(6) / 3 + assert s1.distance((0, 0, 0)) == 0 + assert s2.distance((0, 0, 0)) == sqrt(3) / 2 + assert s1.distance(p1) == 0 + assert s2.distance(p1) == sqrt(3) / 2 + assert s2.distance(p3) == 2 * sqrt(6) / 3 + assert s1.distance((0, 0, 0)) == 0 + assert s2.distance((0, 0, 0)) == sqrt(3) / 2 + # Line to point + assert Line3D(p1, p2).distance(Point3D(-1, 1, 1)) == 2 * sqrt(6) / 3 + assert Line3D(p1, p2).distance(Point3D(1, -1, 1)) == 2 * sqrt(6) / 3 + assert Line3D(p1, p2).distance(Point3D(2, 2, 2)) == 0 + assert Line3D(p1, p2).distance((2, 2, 2)) == 0 + assert Line3D(p1, p2).distance((1, -1, 1)) == 2 * sqrt(6) / 3 + assert Line3D((0, 0, 0), (0, 1, 0)).distance(p1) == 0 + assert Line3D((0, 0, 0), (0, 1, 0)).distance(p2) == sqrt(2) + assert Line3D((0, 0, 0), (1, 0, 0)).distance(p1) == 0 + assert Line3D((0, 0, 0), (1, 0, 0)).distance(p2) == sqrt(2) + # Line to line + assert Line3D((0, 0, 0), (1, 0, 0)).distance(Line3D((0, 0, 0), (0, 1, 2))) == 0 + assert Line3D((0, 0, 0), (1, 0, 0)).distance(Line3D((0, 0, 0), (1, 0, 0))) == 0 + assert Line3D((0, 0, 0), (1, 0, 0)).distance(Line3D((10, 0, 0), (10, 1, 2))) == 0 + assert Line3D((0, 0, 0), (1, 0, 0)).distance(Line3D((0, 1, 0), (0, 1, 1))) == 1 + # Line to plane + assert Line3D((0, 0, 0), (1, 0, 0)).distance(Plane((2, 0, 0), (0, 0, 1))) == 0 + assert Line3D((0, 0, 0), (1, 0, 0)).distance(Plane((0, 1, 0), (0, 1, 0))) == 1 + assert Line3D((0, 0, 0), (1, 0, 0)).distance(Plane((1, 1, 3), (1, 0, 0))) == 0 + # Ray to point + assert r.distance(Point3D(-1, -1, -1)) == sqrt(3) + assert r.distance(Point3D(1, 1, 1)) == 0 + assert r.distance((-1, -1, -1)) == sqrt(3) + assert r.distance((1, 1, 1)) == 0 + assert Ray3D((0, 0, 0), (1, 1, 2)).distance((-1, -1, 2)) == 4 * sqrt(3) / 3 + assert Ray3D((1, 1, 1), (2, 2, 2)).distance(Point3D(1.5, -3, -1)) == Rational(9) / 2 + assert Ray3D((1, 1, 1), (2, 2, 2)).distance(Point3D(1.5, 3, 1)) == sqrt(78) / 6 + + +def test_equals(): + p1 = Point(0, 0) + p2 = Point(1, 1) + + l1 = Line(p1, p2) + l2 = Line((0, 5), slope=m) + l3 = Line(Point(x1, x1), Point(x1, 1 + x1)) + + assert l1.perpendicular_line(p1.args).equals(Line(Point(0, 0), Point(1, -1))) + assert l1.perpendicular_line(p1).equals(Line(Point(0, 0), Point(1, -1))) + assert Line(Point(x1, x1), Point(y1, y1)).parallel_line(Point(-x1, x1)). \ + equals(Line(Point(-x1, x1), Point(-y1, 2 * x1 - y1))) + assert l3.parallel_line(p1.args).equals(Line(Point(0, 0), Point(0, -1))) + assert l3.parallel_line(p1).equals(Line(Point(0, 0), Point(0, -1))) + assert (l2.distance(Point(2, 3)) - 2 * abs(m + 1) / sqrt(m ** 2 + 1)).equals(0) + assert Line3D(p1, Point3D(0, 1, 0)).equals(Point(1.0, 1.0)) is False + assert Line3D(Point3D(0, 0, 0), Point3D(1, 0, 0)).equals(Line3D(Point3D(-5, 0, 0), Point3D(-1, 0, 0))) is True + assert Line3D(Point3D(0, 0, 0), Point3D(1, 0, 0)).equals(Line3D(p1, Point3D(0, 1, 0))) is False + assert Ray3D(p1, Point3D(0, 0, -1)).equals(Point(1.0, 1.0)) is False + assert Ray3D(p1, Point3D(0, 0, -1)).equals(Ray3D(p1, Point3D(0, 0, -1))) is True + assert Line3D((0, 0), (t, t)).perpendicular_line(Point(0, 1, 0)).equals( + Line3D(Point3D(0, 1, 0), Point3D(S.Half, S.Half, 0))) + assert Line3D((0, 0), (t, t)).perpendicular_segment(Point(0, 1, 0)).equals(Segment3D((0, 1), (S.Half, S.Half))) + assert Line3D(p1, Point3D(0, 1, 0)).equals(Point(1.0, 1.0)) is False + + +def test_equation(): + p1 = Point(0, 0) + p2 = Point(1, 1) + l1 = Line(p1, p2) + l3 = Line(Point(x1, x1), Point(x1, 1 + x1)) + + assert simplify(l1.equation()) in (x - y, y - x) + assert simplify(l3.equation()) in (x - x1, x1 - x) + assert simplify(l1.equation()) in (x - y, y - x) + assert simplify(l3.equation()) in (x - x1, x1 - x) + + assert Line(p1, Point(1, 0)).equation(x=x, y=y) == y + assert Line(p1, Point(0, 1)).equation() == x + assert Line(Point(2, 0), Point(2, 1)).equation() == x - 2 + assert Line(p2, Point(2, 1)).equation() == y - 1 + + assert Line3D(Point(x1, x1, x1), Point(y1, y1, y1) + ).equation() == (-x + y, -x + z) + assert Line3D(Point(1, 2, 3), Point(2, 3, 4) + ).equation() == (-x + y - 1, -x + z - 2) + assert Line3D(Point(1, 2, 3), Point(1, 3, 4) + ).equation() == (x - 1, -y + z - 1) + assert Line3D(Point(1, 2, 3), Point(2, 2, 4) + ).equation() == (y - 2, -x + z - 2) + assert Line3D(Point(1, 2, 3), Point(2, 3, 3) + ).equation() == (-x + y - 1, z - 3) + assert Line3D(Point(1, 2, 3), Point(1, 2, 4) + ).equation() == (x - 1, y - 2) + assert Line3D(Point(1, 2, 3), Point(1, 3, 3) + ).equation() == (x - 1, z - 3) + assert Line3D(Point(1, 2, 3), Point(2, 2, 3) + ).equation() == (y - 2, z - 3) + + +def test_intersection_2d(): + p1 = Point(0, 0) + p2 = Point(1, 1) + p3 = Point(x1, x1) + p4 = Point(y1, y1) + + l1 = Line(p1, p2) + l3 = Line(Point(0, 0), Point(3, 4)) + + r1 = Ray(Point(1, 1), Point(2, 2)) + r2 = Ray(Point(0, 0), Point(3, 4)) + r4 = Ray(p1, p2) + r6 = Ray(Point(0, 1), Point(1, 2)) + r7 = Ray(Point(0.5, 0.5), Point(1, 1)) + + s1 = Segment(p1, p2) + s2 = Segment(Point(0.25, 0.25), Point(0.5, 0.5)) + s3 = Segment(Point(0, 0), Point(3, 4)) + + assert intersection(l1, p1) == [p1] + assert intersection(l1, Point(x1, 1 + x1)) == [] + assert intersection(l1, Line(p3, p4)) in [[l1], [Line(p3, p4)]] + assert intersection(l1, l1.parallel_line(Point(x1, 1 + x1))) == [] + assert intersection(l3, l3) == [l3] + assert intersection(l3, r2) == [r2] + assert intersection(l3, s3) == [s3] + assert intersection(s3, l3) == [s3] + assert intersection(Segment(Point(-10, 10), Point(10, 10)), Segment(Point(-5, -5), Point(-5, 5))) == [] + assert intersection(r2, l3) == [r2] + assert intersection(r1, Ray(Point(2, 2), Point(0, 0))) == [Segment(Point(1, 1), Point(2, 2))] + assert intersection(r1, Ray(Point(1, 1), Point(-1, -1))) == [Point(1, 1)] + assert intersection(r1, Segment(Point(0, 0), Point(2, 2))) == [Segment(Point(1, 1), Point(2, 2))] + + assert r4.intersection(s2) == [s2] + assert r4.intersection(Segment(Point(2, 3), Point(3, 4))) == [] + assert r4.intersection(Segment(Point(-1, -1), Point(0.5, 0.5))) == [Segment(p1, Point(0.5, 0.5))] + assert r4.intersection(Ray(p2, p1)) == [s1] + assert Ray(p2, p1).intersection(r6) == [] + assert r4.intersection(r7) == r7.intersection(r4) == [r7] + assert Ray3D((0, 0), (3, 0)).intersection(Ray3D((1, 0), (3, 0))) == [Ray3D((1, 0), (3, 0))] + assert Ray3D((1, 0), (3, 0)).intersection(Ray3D((0, 0), (3, 0))) == [Ray3D((1, 0), (3, 0))] + assert Ray(Point(0, 0), Point(0, 4)).intersection(Ray(Point(0, 1), Point(0, -1))) == \ + [Segment(Point(0, 0), Point(0, 1))] + + assert Segment3D((0, 0), (3, 0)).intersection( + Segment3D((1, 0), (2, 0))) == [Segment3D((1, 0), (2, 0))] + assert Segment3D((1, 0), (2, 0)).intersection( + Segment3D((0, 0), (3, 0))) == [Segment3D((1, 0), (2, 0))] + assert Segment3D((0, 0), (3, 0)).intersection( + Segment3D((3, 0), (4, 0))) == [Point3D((3, 0))] + assert Segment3D((0, 0), (3, 0)).intersection( + Segment3D((2, 0), (5, 0))) == [Segment3D((2, 0), (3, 0))] + assert Segment3D((0, 0), (3, 0)).intersection( + Segment3D((-2, 0), (1, 0))) == [Segment3D((0, 0), (1, 0))] + assert Segment3D((0, 0), (3, 0)).intersection( + Segment3D((-2, 0), (0, 0))) == [Point3D(0, 0)] + assert s1.intersection(Segment(Point(1, 1), Point(2, 2))) == [Point(1, 1)] + assert s1.intersection(Segment(Point(0.5, 0.5), Point(1.5, 1.5))) == [Segment(Point(0.5, 0.5), p2)] + assert s1.intersection(Segment(Point(4, 4), Point(5, 5))) == [] + assert s1.intersection(Segment(Point(-1, -1), p1)) == [p1] + assert s1.intersection(Segment(Point(-1, -1), Point(0.5, 0.5))) == [Segment(p1, Point(0.5, 0.5))] + assert s1.intersection(Line(Point(1, 0), Point(2, 1))) == [] + assert s1.intersection(s2) == [s2] + assert s2.intersection(s1) == [s2] + + assert asa(120, 8, 52) == \ + Triangle( + Point(0, 0), + Point(8, 0), + Point(-4 * cos(19 * pi / 90) / sin(2 * pi / 45), + 4 * sqrt(3) * cos(19 * pi / 90) / sin(2 * pi / 45))) + assert Line((0, 0), (1, 1)).intersection(Ray((1, 0), (1, 2))) == [Point(1, 1)] + assert Line((0, 0), (1, 1)).intersection(Segment((1, 0), (1, 2))) == [Point(1, 1)] + assert Ray((0, 0), (1, 1)).intersection(Ray((1, 0), (1, 2))) == [Point(1, 1)] + assert Ray((0, 0), (1, 1)).intersection(Segment((1, 0), (1, 2))) == [Point(1, 1)] + assert Ray((0, 0), (10, 10)).contains(Segment((1, 1), (2, 2))) is True + assert Segment((1, 1), (2, 2)) in Line((0, 0), (10, 10)) + assert s1.intersection(Ray((1, 1), (4, 4))) == [Point(1, 1)] + + # This test is disabled because it hangs after rref changes which simplify + # intermediate results and return a different representation from when the + # test was written. + # # 16628 - this should be fast + # p0 = Point2D(Rational(249, 5), Rational(497999, 10000)) + # p1 = Point2D((-58977084786*sqrt(405639795226) + 2030690077184193 + + # 20112207807*sqrt(630547164901) + 99600*sqrt(255775022850776494562626)) + # /(2000*sqrt(255775022850776494562626) + 1991998000*sqrt(405639795226) + # + 1991998000*sqrt(630547164901) + 1622561172902000), + # (-498000*sqrt(255775022850776494562626) - 995999*sqrt(630547164901) + + # 90004251917891999 + + # 496005510002*sqrt(405639795226))/(10000*sqrt(255775022850776494562626) + # + 9959990000*sqrt(405639795226) + 9959990000*sqrt(630547164901) + + # 8112805864510000)) + # p2 = Point2D(Rational(497, 10), Rational(-497, 10)) + # p3 = Point2D(Rational(-497, 10), Rational(-497, 10)) + # l = Line(p0, p1) + # s = Segment(p2, p3) + # n = (-52673223862*sqrt(405639795226) - 15764156209307469 - + # 9803028531*sqrt(630547164901) + + # 33200*sqrt(255775022850776494562626)) + # d = sqrt(405639795226) + 315274080450 + 498000*sqrt( + # 630547164901) + sqrt(255775022850776494562626) + # assert intersection(l, s) == [ + # Point2D(n/d*Rational(3, 2000), Rational(-497, 10))] + + +def test_line_intersection(): + # see also test_issue_11238 in test_matrices.py + x0 = tan(pi*Rational(13, 45)) + x1 = sqrt(3) + x2 = x0**2 + x, y = [8*x0/(x0 + x1), (24*x0 - 8*x1*x2)/(x2 - 3)] + assert Line(Point(0, 0), Point(1, -sqrt(3))).contains(Point(x, y)) is True + + +def test_intersection_3d(): + p1 = Point3D(0, 0, 0) + p2 = Point3D(1, 1, 1) + + l1 = Line3D(p1, p2) + l2 = Line3D(Point3D(0, 0, 0), Point3D(3, 4, 0)) + + r1 = Ray3D(Point3D(1, 1, 1), Point3D(2, 2, 2)) + r2 = Ray3D(Point3D(0, 0, 0), Point3D(3, 4, 0)) + + s1 = Segment3D(Point3D(0, 0, 0), Point3D(3, 4, 0)) + + assert intersection(l1, p1) == [p1] + assert intersection(l1, Point3D(x1, 1 + x1, 1)) == [] + assert intersection(l1, l1.parallel_line(p1)) == [Line3D(Point3D(0, 0, 0), Point3D(1, 1, 1))] + assert intersection(l2, r2) == [r2] + assert intersection(l2, s1) == [s1] + assert intersection(r2, l2) == [r2] + assert intersection(r1, Ray3D(Point3D(1, 1, 1), Point3D(-1, -1, -1))) == [Point3D(1, 1, 1)] + assert intersection(r1, Segment3D(Point3D(0, 0, 0), Point3D(2, 2, 2))) == [ + Segment3D(Point3D(1, 1, 1), Point3D(2, 2, 2))] + assert intersection(Ray3D(Point3D(1, 0, 0), Point3D(-1, 0, 0)), Ray3D(Point3D(0, 1, 0), Point3D(0, -1, 0))) \ + == [Point3D(0, 0, 0)] + assert intersection(r1, Ray3D(Point3D(2, 2, 2), Point3D(0, 0, 0))) == \ + [Segment3D(Point3D(1, 1, 1), Point3D(2, 2, 2))] + assert intersection(s1, r2) == [s1] + + assert Line3D(Point3D(4, 0, 1), Point3D(0, 4, 1)).intersection(Line3D(Point3D(0, 0, 1), Point3D(4, 4, 1))) == \ + [Point3D(2, 2, 1)] + assert Line3D((0, 1, 2), (0, 2, 3)).intersection(Line3D((0, 1, 2), (0, 1, 1))) == [Point3D(0, 1, 2)] + assert Line3D((0, 0), (t, t)).intersection(Line3D((0, 1), (t, t))) == \ + [Point3D(t, t)] + + assert Ray3D(Point3D(0, 0, 0), Point3D(0, 4, 0)).intersection(Ray3D(Point3D(0, 1, 1), Point3D(0, -1, 1))) == [] + + +def test_is_parallel(): + p1 = Point3D(0, 0, 0) + p2 = Point3D(1, 1, 1) + p3 = Point3D(x1, x1, x1) + + l2 = Line(Point(x1, x1), Point(y1, y1)) + l2_1 = Line(Point(x1, x1), Point(x1, 1 + x1)) + + assert Line.is_parallel(Line(Point(0, 0), Point(1, 1)), l2) + assert Line.is_parallel(l2, Line(Point(x1, x1), Point(x1, 1 + x1))) is False + assert Line.is_parallel(l2, l2.parallel_line(Point(-x1, x1))) + assert Line.is_parallel(l2_1, l2_1.parallel_line(Point(0, 0))) + assert Line3D(p1, p2).is_parallel(Line3D(p1, p2)) # same as in 2D + assert Line3D(Point3D(4, 0, 1), Point3D(0, 4, 1)).is_parallel(Line3D(Point3D(0, 0, 1), Point3D(4, 4, 1))) is False + assert Line3D(p1, p2).parallel_line(p3) == Line3D(Point3D(x1, x1, x1), + Point3D(x1 + 1, x1 + 1, x1 + 1)) + assert Line3D(p1, p2).parallel_line(p3.args) == \ + Line3D(Point3D(x1, x1, x1), Point3D(x1 + 1, x1 + 1, x1 + 1)) + assert Line3D(Point3D(4, 0, 1), Point3D(0, 4, 1)).is_parallel(Line3D(Point3D(0, 0, 1), Point3D(4, 4, 1))) is False + + +def test_is_perpendicular(): + p1 = Point(0, 0) + p2 = Point(1, 1) + + l1 = Line(p1, p2) + l2 = Line(Point(x1, x1), Point(y1, y1)) + l1_1 = Line(p1, Point(-x1, x1)) + # 2D + assert Line.is_perpendicular(l1, l1_1) + assert Line.is_perpendicular(l1, l2) is False + p = l1.random_point() + assert l1.perpendicular_segment(p) == p + # 3D + assert Line3D.is_perpendicular(Line3D(Point3D(0, 0, 0), Point3D(1, 0, 0)), + Line3D(Point3D(0, 0, 0), Point3D(0, 1, 0))) is True + assert Line3D.is_perpendicular(Line3D(Point3D(0, 0, 0), Point3D(1, 0, 0)), + Line3D(Point3D(0, 1, 0), Point3D(1, 1, 0))) is False + assert Line3D.is_perpendicular(Line3D(Point3D(0, 0, 0), Point3D(1, 1, 1)), + Line3D(Point3D(x1, x1, x1), Point3D(y1, y1, y1))) is False + + +def test_is_similar(): + p1 = Point(2000, 2000) + p2 = p1.scale(2, 2) + + r1 = Ray3D(Point3D(1, 1, 1), Point3D(1, 0, 0)) + r2 = Ray(Point(0, 0), Point(0, 1)) + + s1 = Segment(Point(0, 0), p1) + + assert s1.is_similar(Segment(p1, p2)) + assert s1.is_similar(r2) is False + assert r1.is_similar(Line3D(Point3D(1, 1, 1), Point3D(1, 0, 0))) is True + assert r1.is_similar(Line3D(Point3D(0, 0, 0), Point3D(0, 1, 0))) is False + + +def test_length(): + s2 = Segment3D(Point3D(x1, x1, x1), Point3D(y1, y1, y1)) + assert Line(Point(0, 0), Point(1, 1)).length is oo + assert s2.length == sqrt(3) * sqrt((x1 - y1) ** 2) + assert Line3D(Point3D(0, 0, 0), Point3D(1, 1, 1)).length is oo + + +def test_projection(): + p1 = Point(0, 0) + p2 = Point3D(0, 0, 0) + p3 = Point(-x1, x1) + + l1 = Line(p1, Point(1, 1)) + l2 = Line3D(Point3D(0, 0, 0), Point3D(1, 0, 0)) + l3 = Line3D(p2, Point3D(1, 1, 1)) + + r1 = Ray(Point(1, 1), Point(2, 2)) + + s1 = Segment(Point2D(0, 0), Point2D(0, 1)) + s2 = Segment(Point2D(1, 0), Point2D(2, 1/2)) + + assert Line(Point(x1, x1), Point(y1, y1)).projection(Point(y1, y1)) == Point(y1, y1) + assert Line(Point(x1, x1), Point(x1, 1 + x1)).projection(Point(1, 1)) == Point(x1, 1) + assert Segment(Point(-2, 2), Point(0, 4)).projection(r1) == Segment(Point(-1, 3), Point(0, 4)) + assert Segment(Point(0, 4), Point(-2, 2)).projection(r1) == Segment(Point(0, 4), Point(-1, 3)) + assert s2.projection(s1) == EmptySet + assert l1.projection(p3) == p1 + assert l1.projection(Ray(p1, Point(-1, 5))) == Ray(Point(0, 0), Point(2, 2)) + assert l1.projection(Ray(p1, Point(-1, 1))) == p1 + assert r1.projection(Ray(Point(1, 1), Point(-1, -1))) == Point(1, 1) + assert r1.projection(Ray(Point(0, 4), Point(-1, -5))) == Segment(Point(1, 1), Point(2, 2)) + assert r1.projection(Segment(Point(-1, 5), Point(-5, -10))) == Segment(Point(1, 1), Point(2, 2)) + assert r1.projection(Ray(Point(1, 1), Point(-1, -1))) == Point(1, 1) + assert r1.projection(Ray(Point(0, 4), Point(-1, -5))) == Segment(Point(1, 1), Point(2, 2)) + assert r1.projection(Segment(Point(-1, 5), Point(-5, -10))) == Segment(Point(1, 1), Point(2, 2)) + + assert l3.projection(Ray3D(p2, Point3D(-1, 5, 0))) == Ray3D(Point3D(0, 0, 0), Point3D(Rational(4, 3), Rational(4, 3), Rational(4, 3))) + assert l3.projection(Ray3D(p2, Point3D(-1, 1, 1))) == Ray3D(Point3D(0, 0, 0), Point3D(Rational(1, 3), Rational(1, 3), Rational(1, 3))) + assert l2.projection(Point3D(5, 5, 0)) == Point3D(5, 0) + assert l2.projection(Line3D(Point3D(0, 1, 0), Point3D(1, 1, 0))).equals(l2) + + +def test_perpendicular_line(): + # 3d - requires a particular orthogonal to be selected + p1, p2, p3 = Point(0, 0, 0), Point(2, 3, 4), Point(-2, 2, 0) + l = Line(p1, p2) + p = l.perpendicular_line(p3) + assert p.p1 == p3 + assert p.p2 in l + # 2d - does not require special selection + p1, p2, p3 = Point(0, 0), Point(2, 3), Point(-2, 2) + l = Line(p1, p2) + p = l.perpendicular_line(p3) + assert p.p1 == p3 + # p is directed from l to p3 + assert p.direction.unit == (p3 - l.projection(p3)).unit + + +def test_perpendicular_bisector(): + s1 = Segment(Point(0, 0), Point(1, 1)) + aline = Line(Point(S.Half, S.Half), Point(Rational(3, 2), Rational(-1, 2))) + on_line = Segment(Point(S.Half, S.Half), Point(Rational(3, 2), Rational(-1, 2))).midpoint + + assert s1.perpendicular_bisector().equals(aline) + assert s1.perpendicular_bisector(on_line).equals(Segment(s1.midpoint, on_line)) + assert s1.perpendicular_bisector(on_line + (1, 0)).equals(aline) + + +def test_raises(): + d, e = symbols('a,b', real=True) + s = Segment((d, 0), (e, 0)) + + raises(TypeError, lambda: Line((1, 1), 1)) + raises(ValueError, lambda: Line(Point(0, 0), Point(0, 0))) + raises(Undecidable, lambda: Point(2 * d, 0) in s) + raises(ValueError, lambda: Ray3D(Point(1.0, 1.0))) + raises(ValueError, lambda: Line3D(Point3D(0, 0, 0), Point3D(0, 0, 0))) + raises(TypeError, lambda: Line3D((1, 1), 1)) + raises(ValueError, lambda: Line3D(Point3D(0, 0, 0))) + raises(TypeError, lambda: Ray((1, 1), 1)) + raises(GeometryError, lambda: Line(Point(0, 0), Point(1, 0)) + .projection(Circle(Point(0, 0), 1))) + + +def test_ray_generation(): + assert Ray((1, 1), angle=pi / 4) == Ray((1, 1), (2, 2)) + assert Ray((1, 1), angle=pi / 2) == Ray((1, 1), (1, 2)) + assert Ray((1, 1), angle=-pi / 2) == Ray((1, 1), (1, 0)) + assert Ray((1, 1), angle=-3 * pi / 2) == Ray((1, 1), (1, 2)) + assert Ray((1, 1), angle=5 * pi / 2) == Ray((1, 1), (1, 2)) + assert Ray((1, 1), angle=5.0 * pi / 2) == Ray((1, 1), (1, 2)) + assert Ray((1, 1), angle=pi) == Ray((1, 1), (0, 1)) + assert Ray((1, 1), angle=3.0 * pi) == Ray((1, 1), (0, 1)) + assert Ray((1, 1), angle=4.0 * pi) == Ray((1, 1), (2, 1)) + assert Ray((1, 1), angle=0) == Ray((1, 1), (2, 1)) + assert Ray((1, 1), angle=4.05 * pi) == Ray(Point(1, 1), + Point(2, -sqrt(5) * sqrt(2 * sqrt(5) + 10) / 4 - sqrt( + 2 * sqrt(5) + 10) / 4 + 2 + sqrt(5))) + assert Ray((1, 1), angle=4.02 * pi) == Ray(Point(1, 1), + Point(2, 1 + tan(4.02 * pi))) + assert Ray((1, 1), angle=5) == Ray((1, 1), (2, 1 + tan(5))) + + assert Ray3D((1, 1, 1), direction_ratio=[4, 4, 4]) == Ray3D(Point3D(1, 1, 1), Point3D(5, 5, 5)) + assert Ray3D((1, 1, 1), direction_ratio=[1, 2, 3]) == Ray3D(Point3D(1, 1, 1), Point3D(2, 3, 4)) + assert Ray3D((1, 1, 1), direction_ratio=[1, 1, 1]) == Ray3D(Point3D(1, 1, 1), Point3D(2, 2, 2)) + + +def test_issue_7814(): + circle = Circle(Point(x, 0), y) + line = Line(Point(k, z), slope=0) + _s = sqrt((y - z)*(y + z)) + assert line.intersection(circle) == [Point2D(x + _s, z), Point2D(x - _s, z)] + + +def test_issue_2941(): + def _check(): + for f, g in cartes(*[(Line, Ray, Segment)] * 2): + l1 = f(a, b) + l2 = g(c, d) + assert l1.intersection(l2) == l2.intersection(l1) + # intersect at end point + c, d = (-2, -2), (-2, 0) + a, b = (0, 0), (1, 1) + _check() + # midline intersection + c, d = (-2, -3), (-2, 0) + _check() + + +def test_parameter_value(): + t = Symbol('t') + p1, p2 = Point(0, 1), Point(5, 6) + l = Line(p1, p2) + assert l.parameter_value((5, 6), t) == {t: 1} + raises(ValueError, lambda: l.parameter_value((0, 0), t)) + + +def test_bisectors(): + r1 = Line3D(Point3D(0, 0, 0), Point3D(1, 0, 0)) + r2 = Line3D(Point3D(0, 0, 0), Point3D(0, 1, 0)) + bisections = r1.bisectors(r2) + assert bisections == [Line3D(Point3D(0, 0, 0), Point3D(1, 1, 0)), + Line3D(Point3D(0, 0, 0), Point3D(1, -1, 0))] + ans = [Line3D(Point3D(0, 0, 0), Point3D(1, 0, 1)), + Line3D(Point3D(0, 0, 0), Point3D(-1, 0, 1))] + l1 = (0, 0, 0), (0, 0, 1) + l2 = (0, 0), (1, 0) + for a, b in cartes((Line, Segment, Ray), repeat=2): + assert a(*l1).bisectors(b(*l2)) == ans + + +def test_issue_8615(): + a = Line3D(Point3D(6, 5, 0), Point3D(6, -6, 0)) + b = Line3D(Point3D(6, -1, 19/10), Point3D(6, -1, 0)) + assert a.intersection(b) == [Point3D(6, -1, 0)] + + +def test_issue_12598(): + r1 = Ray(Point(0, 1), Point(0.98, 0.79).n(2)) + r2 = Ray(Point(0, 0), Point(0.71, 0.71).n(2)) + assert str(r1.intersection(r2)[0]) == 'Point2D(0.82, 0.82)' + l1 = Line((0, 0), (1, 1)) + l2 = Segment((-1, 1), (0, -1)).n(2) + assert str(l1.intersection(l2)[0]) == 'Point2D(-0.33, -0.33)' + l2 = Segment((-1, 1), (-1/2, 1/2)).n(2) + assert not l1.intersection(l2) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_parabola.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_parabola.py new file mode 100644 index 0000000000000000000000000000000000000000..2a683f26619952d93475aca9ebd3d47cfb3657a6 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_parabola.py @@ -0,0 +1,143 @@ +from sympy.core.numbers import (Rational, oo) +from sympy.core.singleton import S +from sympy.core.symbol import symbols +from sympy.functions.elementary.complexes import sign +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.geometry.ellipse import (Circle, Ellipse) +from sympy.geometry.line import (Line, Ray2D, Segment2D) +from sympy.geometry.parabola import Parabola +from sympy.geometry.point import (Point, Point2D) +from sympy.testing.pytest import raises + +from sympy.abc import x, y + +def test_parabola_geom(): + a, b = symbols('a b') + p1 = Point(0, 0) + p2 = Point(3, 7) + p3 = Point(0, 4) + p4 = Point(6, 0) + p5 = Point(a, a) + d1 = Line(Point(4, 0), Point(4, 9)) + d2 = Line(Point(7, 6), Point(3, 6)) + d3 = Line(Point(4, 0), slope=oo) + d4 = Line(Point(7, 6), slope=0) + d5 = Line(Point(b, a), slope=oo) + d6 = Line(Point(a, b), slope=0) + + half = S.Half + + pa1 = Parabola(None, d2) + pa2 = Parabola(directrix=d1) + pa3 = Parabola(p1, d1) + pa4 = Parabola(p2, d2) + pa5 = Parabola(p2, d4) + pa6 = Parabola(p3, d2) + pa7 = Parabola(p2, d1) + pa8 = Parabola(p4, d1) + pa9 = Parabola(p4, d3) + pa10 = Parabola(p5, d5) + pa11 = Parabola(p5, d6) + d = Line(Point(3, 7), Point(2, 9)) + pa12 = Parabola(Point(7, 8), d) + pa12r = Parabola(Point(7, 8).reflect(d), d) + + raises(ValueError, lambda: + Parabola(Point(7, 8, 9), Line(Point(6, 7), Point(7, 7)))) + raises(ValueError, lambda: + Parabola(Point(0, 2), Line(Point(7, 2), Point(6, 2)))) + raises(ValueError, lambda: Parabola(Point(7, 8), Point(3, 8))) + + # Basic Stuff + assert pa1.focus == Point(0, 0) + assert pa1.ambient_dimension == S(2) + assert pa2 == pa3 + assert pa4 != pa7 + assert pa6 != pa7 + assert pa6.focus == Point2D(0, 4) + assert pa6.focal_length == 1 + assert pa6.p_parameter == -1 + assert pa6.vertex == Point2D(0, 5) + assert pa6.eccentricity == 1 + assert pa7.focus == Point2D(3, 7) + assert pa7.focal_length == half + assert pa7.p_parameter == -half + assert pa7.vertex == Point2D(7*half, 7) + assert pa4.focal_length == half + assert pa4.p_parameter == half + assert pa4.vertex == Point2D(3, 13*half) + assert pa8.focal_length == 1 + assert pa8.p_parameter == 1 + assert pa8.vertex == Point2D(5, 0) + assert pa4.focal_length == pa5.focal_length + assert pa4.p_parameter == pa5.p_parameter + assert pa4.vertex == pa5.vertex + assert pa4.equation() == pa5.equation() + assert pa8.focal_length == pa9.focal_length + assert pa8.p_parameter == pa9.p_parameter + assert pa8.vertex == pa9.vertex + assert pa8.equation() == pa9.equation() + assert pa10.focal_length == pa11.focal_length == sqrt((a - b) ** 2) / 2 # if a, b real == abs(a - b)/2 + assert pa11.vertex == Point(*pa10.vertex[::-1]) == Point(a, + a - sqrt((a - b)**2)*sign(a - b)/2) # change axis x->y, y->x on pa10 + aos = pa12.axis_of_symmetry + assert aos == Line(Point(7, 8), Point(5, 7)) + assert pa12.directrix == Line(Point(3, 7), Point(2, 9)) + assert pa12.directrix.angle_between(aos) == S.Pi/2 + assert pa12.eccentricity == 1 + assert pa12.equation(x, y) == (x - 7)**2 + (y - 8)**2 - (-2*x - y + 13)**2/5 + assert pa12.focal_length == 9*sqrt(5)/10 + assert pa12.focus == Point(7, 8) + assert pa12.p_parameter == 9*sqrt(5)/10 + assert pa12.vertex == Point2D(S(26)/5, S(71)/10) + assert pa12r.focal_length == 9*sqrt(5)/10 + assert pa12r.focus == Point(-S(1)/5, S(22)/5) + assert pa12r.p_parameter == -9*sqrt(5)/10 + assert pa12r.vertex == Point(S(8)/5, S(53)/10) + + +def test_parabola_intersection(): + l1 = Line(Point(1, -2), Point(-1,-2)) + l2 = Line(Point(1, 2), Point(-1,2)) + l3 = Line(Point(1, 0), Point(-1,0)) + + p1 = Point(0,0) + p2 = Point(0, -2) + p3 = Point(120, -12) + parabola1 = Parabola(p1, l1) + + # parabola with parabola + assert parabola1.intersection(parabola1) == [parabola1] + assert parabola1.intersection(Parabola(p1, l2)) == [Point2D(-2, 0), Point2D(2, 0)] + assert parabola1.intersection(Parabola(p2, l3)) == [Point2D(0, -1)] + assert parabola1.intersection(Parabola(Point(16, 0), l1)) == [Point2D(8, 15)] + assert parabola1.intersection(Parabola(Point(0, 16), l1)) == [Point2D(-6, 8), Point2D(6, 8)] + assert parabola1.intersection(Parabola(p3, l3)) == [] + # parabola with point + assert parabola1.intersection(p1) == [] + assert parabola1.intersection(Point2D(0, -1)) == [Point2D(0, -1)] + assert parabola1.intersection(Point2D(4, 3)) == [Point2D(4, 3)] + # parabola with line + assert parabola1.intersection(Line(Point2D(-7, 3), Point(12, 3))) == [Point2D(-4, 3), Point2D(4, 3)] + assert parabola1.intersection(Line(Point(-4, -1), Point(4, -1))) == [Point(0, -1)] + assert parabola1.intersection(Line(Point(2, 0), Point(0, -2))) == [Point2D(2, 0)] + raises(TypeError, lambda: parabola1.intersection(Line(Point(0, 0, 0), Point(1, 1, 1)))) + # parabola with segment + assert parabola1.intersection(Segment2D((-4, -5), (4, 3))) == [Point2D(0, -1), Point2D(4, 3)] + assert parabola1.intersection(Segment2D((0, -5), (0, 6))) == [Point2D(0, -1)] + assert parabola1.intersection(Segment2D((-12, -65), (14, -68))) == [] + # parabola with ray + assert parabola1.intersection(Ray2D((-4, -5), (4, 3))) == [Point2D(0, -1), Point2D(4, 3)] + assert parabola1.intersection(Ray2D((0, 7), (1, 14))) == [Point2D(14 + 2*sqrt(57), 105 + 14*sqrt(57))] + assert parabola1.intersection(Ray2D((0, 7), (0, 14))) == [] + # parabola with ellipse/circle + assert parabola1.intersection(Circle(p1, 2)) == [Point2D(-2, 0), Point2D(2, 0)] + assert parabola1.intersection(Circle(p2, 1)) == [Point2D(0, -1)] + assert parabola1.intersection(Ellipse(p2, 2, 1)) == [Point2D(0, -1)] + assert parabola1.intersection(Ellipse(Point(0, 19), 5, 7)) == [] + assert parabola1.intersection(Ellipse((0, 3), 12, 4)) == [ + Point2D(0, -1), + Point2D(-4*sqrt(17)/3, Rational(59, 9)), + Point2D(4*sqrt(17)/3, Rational(59, 9))] + # parabola with unsupported type + raises(TypeError, lambda: parabola1.intersection(2)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_plane.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_plane.py new file mode 100644 index 0000000000000000000000000000000000000000..1010fce5c3bc68348eacee13f29c1d7588f17e39 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_plane.py @@ -0,0 +1,268 @@ +from sympy.core.numbers import (Rational, pi) +from sympy.core.singleton import S +from sympy.core.symbol import (Dummy, symbols) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (asin, cos, sin) +from sympy.geometry import Line, Point, Ray, Segment, Point3D, Line3D, Ray3D, Segment3D, Plane, Circle +from sympy.geometry.util import are_coplanar +from sympy.testing.pytest import raises + + +def test_plane(): + x, y, z, u, v = symbols('x y z u v', real=True) + p1 = Point3D(0, 0, 0) + p2 = Point3D(1, 1, 1) + p3 = Point3D(1, 2, 3) + pl3 = Plane(p1, p2, p3) + pl4 = Plane(p1, normal_vector=(1, 1, 1)) + pl4b = Plane(p1, p2) + pl5 = Plane(p3, normal_vector=(1, 2, 3)) + pl6 = Plane(Point3D(2, 3, 7), normal_vector=(2, 2, 2)) + pl7 = Plane(Point3D(1, -5, -6), normal_vector=(1, -2, 1)) + pl8 = Plane(p1, normal_vector=(0, 0, 1)) + pl9 = Plane(p1, normal_vector=(0, 12, 0)) + pl10 = Plane(p1, normal_vector=(-2, 0, 0)) + pl11 = Plane(p2, normal_vector=(0, 0, 1)) + l1 = Line3D(Point3D(5, 0, 0), Point3D(1, -1, 1)) + l2 = Line3D(Point3D(0, -2, 0), Point3D(3, 1, 1)) + l3 = Line3D(Point3D(0, -1, 0), Point3D(5, -1, 9)) + + raises(ValueError, lambda: Plane(p1, p1, p1)) + + assert Plane(p1, p2, p3) != Plane(p1, p3, p2) + assert Plane(p1, p2, p3).is_coplanar(Plane(p1, p3, p2)) + assert Plane(p1, p2, p3).is_coplanar(p1) + assert Plane(p1, p2, p3).is_coplanar(Circle(p1, 1)) is False + assert Plane(p1, normal_vector=(0, 0, 1)).is_coplanar(Circle(p1, 1)) + + assert pl3 == Plane(Point3D(0, 0, 0), normal_vector=(1, -2, 1)) + assert pl3 != pl4 + assert pl4 == pl4b + assert pl5 == Plane(Point3D(1, 2, 3), normal_vector=(1, 2, 3)) + + assert pl5.equation(x, y, z) == x + 2*y + 3*z - 14 + assert pl3.equation(x, y, z) == x - 2*y + z + + assert pl3.p1 == p1 + assert pl4.p1 == p1 + assert pl5.p1 == p3 + + assert pl4.normal_vector == (1, 1, 1) + assert pl5.normal_vector == (1, 2, 3) + + assert p1 in pl3 + assert p1 in pl4 + assert p3 in pl5 + + assert pl3.projection(Point(0, 0)) == p1 + p = pl3.projection(Point3D(1, 1, 0)) + assert p == Point3D(Rational(7, 6), Rational(2, 3), Rational(1, 6)) + assert p in pl3 + + l = pl3.projection_line(Line(Point(0, 0), Point(1, 1))) + assert l == Line3D(Point3D(0, 0, 0), Point3D(Rational(7, 6), Rational(2, 3), Rational(1, 6))) + assert l in pl3 + # get a segment that does not intersect the plane which is also + # parallel to pl3's normal veector + t = Dummy() + r = pl3.random_point() + a = pl3.perpendicular_line(r).arbitrary_point(t) + s = Segment3D(a.subs(t, 1), a.subs(t, 2)) + assert s.p1 not in pl3 and s.p2 not in pl3 + assert pl3.projection_line(s).equals(r) + assert pl3.projection_line(Segment(Point(1, 0), Point(1, 1))) == \ + Segment3D(Point3D(Rational(5, 6), Rational(1, 3), Rational(-1, 6)), Point3D(Rational(7, 6), Rational(2, 3), Rational(1, 6))) + assert pl6.projection_line(Ray(Point(1, 0), Point(1, 1))) == \ + Ray3D(Point3D(Rational(14, 3), Rational(11, 3), Rational(11, 3)), Point3D(Rational(13, 3), Rational(13, 3), Rational(10, 3))) + assert pl3.perpendicular_line(r.args) == pl3.perpendicular_line(r) + + assert pl3.is_parallel(pl6) is False + assert pl4.is_parallel(pl6) + assert pl3.is_parallel(Line(p1, p2)) + assert pl6.is_parallel(l1) is False + + assert pl3.is_perpendicular(pl6) + assert pl4.is_perpendicular(pl7) + assert pl6.is_perpendicular(pl7) + assert pl6.is_perpendicular(pl4) is False + assert pl6.is_perpendicular(l1) is False + assert pl6.is_perpendicular(Line((0, 0, 0), (1, 1, 1))) + assert pl6.is_perpendicular((1, 1)) is False + + assert pl6.distance(pl6.arbitrary_point(u, v)) == 0 + assert pl7.distance(pl7.arbitrary_point(u, v)) == 0 + assert pl6.distance(pl6.arbitrary_point(t)) == 0 + assert pl7.distance(pl7.arbitrary_point(t)) == 0 + assert pl6.p1.distance(pl6.arbitrary_point(t)).simplify() == 1 + assert pl7.p1.distance(pl7.arbitrary_point(t)).simplify() == 1 + assert pl3.arbitrary_point(t) == Point3D(-sqrt(30)*sin(t)/30 + \ + 2*sqrt(5)*cos(t)/5, sqrt(30)*sin(t)/15 + sqrt(5)*cos(t)/5, sqrt(30)*sin(t)/6) + assert pl3.arbitrary_point(u, v) == Point3D(2*u - v, u + 2*v, 5*v) + + assert pl7.distance(Point3D(1, 3, 5)) == 5*sqrt(6)/6 + assert pl6.distance(Point3D(0, 0, 0)) == 4*sqrt(3) + assert pl6.distance(pl6.p1) == 0 + assert pl7.distance(pl6) == 0 + assert pl7.distance(l1) == 0 + assert pl6.distance(Segment3D(Point3D(2, 3, 1), Point3D(1, 3, 4))) == \ + pl6.distance(Point3D(1, 3, 4)) == 4*sqrt(3)/3 + assert pl6.distance(Segment3D(Point3D(1, 3, 4), Point3D(0, 3, 7))) == \ + pl6.distance(Point3D(0, 3, 7)) == 2*sqrt(3)/3 + assert pl6.distance(Segment3D(Point3D(0, 3, 7), Point3D(-1, 3, 10))) == 0 + assert pl6.distance(Segment3D(Point3D(-1, 3, 10), Point3D(-2, 3, 13))) == 0 + assert pl6.distance(Segment3D(Point3D(-2, 3, 13), Point3D(-3, 3, 16))) == \ + pl6.distance(Point3D(-2, 3, 13)) == 2*sqrt(3)/3 + assert pl6.distance(Plane(Point3D(5, 5, 5), normal_vector=(8, 8, 8))) == sqrt(3) + assert pl6.distance(Ray3D(Point3D(1, 3, 4), direction_ratio=[1, 0, -3])) == 4*sqrt(3)/3 + assert pl6.distance(Ray3D(Point3D(2, 3, 1), direction_ratio=[-1, 0, 3])) == 0 + + + assert pl6.angle_between(pl3) == pi/2 + assert pl6.angle_between(pl6) == 0 + assert pl6.angle_between(pl4) == 0 + assert pl7.angle_between(Line3D(Point3D(2, 3, 5), Point3D(2, 4, 6))) == \ + -asin(sqrt(3)/6) + assert pl6.angle_between(Ray3D(Point3D(2, 4, 1), Point3D(6, 5, 3))) == \ + asin(sqrt(7)/3) + assert pl7.angle_between(Segment3D(Point3D(5, 6, 1), Point3D(1, 2, 4))) == \ + asin(7*sqrt(246)/246) + + assert are_coplanar(l1, l2, l3) is False + assert are_coplanar(l1) is False + assert are_coplanar(Point3D(2, 7, 2), Point3D(0, 0, 2), + Point3D(1, 1, 2), Point3D(1, 2, 2)) + assert are_coplanar(Plane(p1, p2, p3), Plane(p1, p3, p2)) + assert Plane.are_concurrent(pl3, pl4, pl5) is False + assert Plane.are_concurrent(pl6) is False + raises(ValueError, lambda: Plane.are_concurrent(Point3D(0, 0, 0))) + raises(ValueError, lambda: Plane((1, 2, 3), normal_vector=(0, 0, 0))) + + assert pl3.parallel_plane(Point3D(1, 2, 5)) == Plane(Point3D(1, 2, 5), \ + normal_vector=(1, -2, 1)) + + # perpendicular_plane + p = Plane((0, 0, 0), (1, 0, 0)) + # default + assert p.perpendicular_plane() == Plane(Point3D(0, 0, 0), (0, 1, 0)) + # 1 pt + assert p.perpendicular_plane(Point3D(1, 0, 1)) == \ + Plane(Point3D(1, 0, 1), (0, 1, 0)) + # pts as tuples + assert p.perpendicular_plane((1, 0, 1), (1, 1, 1)) == \ + Plane(Point3D(1, 0, 1), (0, 0, -1)) + # more than two planes + raises(ValueError, lambda: p.perpendicular_plane((1, 0, 1), (1, 1, 1), (1, 1, 0))) + + a, b = Point3D(0, 0, 0), Point3D(0, 1, 0) + Z = (0, 0, 1) + p = Plane(a, normal_vector=Z) + # case 4 + assert p.perpendicular_plane(a, b) == Plane(a, (1, 0, 0)) + n = Point3D(*Z) + # case 1 + assert p.perpendicular_plane(a, n) == Plane(a, (-1, 0, 0)) + # case 2 + assert Plane(a, normal_vector=b.args).perpendicular_plane(a, a + b) == \ + Plane(Point3D(0, 0, 0), (1, 0, 0)) + # case 1&3 + assert Plane(b, normal_vector=Z).perpendicular_plane(b, b + n) == \ + Plane(Point3D(0, 1, 0), (-1, 0, 0)) + # case 2&3 + assert Plane(b, normal_vector=b.args).perpendicular_plane(n, n + b) == \ + Plane(Point3D(0, 0, 1), (1, 0, 0)) + + p = Plane(a, normal_vector=(0, 0, 1)) + assert p.perpendicular_plane() == Plane(a, normal_vector=(1, 0, 0)) + + assert pl6.intersection(pl6) == [pl6] + assert pl4.intersection(pl4.p1) == [pl4.p1] + assert pl3.intersection(pl6) == [ + Line3D(Point3D(8, 4, 0), Point3D(2, 4, 6))] + assert pl3.intersection(Line3D(Point3D(1,2,4), Point3D(4,4,2))) == [ + Point3D(2, Rational(8, 3), Rational(10, 3))] + assert pl3.intersection(Plane(Point3D(6, 0, 0), normal_vector=(2, -5, 3)) + ) == [Line3D(Point3D(-24, -12, 0), Point3D(-25, -13, -1))] + assert pl6.intersection(Ray3D(Point3D(2, 3, 1), Point3D(1, 3, 4))) == [ + Point3D(-1, 3, 10)] + assert pl6.intersection(Segment3D(Point3D(2, 3, 1), Point3D(1, 3, 4))) == [] + assert pl7.intersection(Line(Point(2, 3), Point(4, 2))) == [ + Point3D(Rational(13, 2), Rational(3, 4), 0)] + r = Ray(Point(2, 3), Point(4, 2)) + assert Plane((1,2,0), normal_vector=(0,0,1)).intersection(r) == [ + Ray3D(Point(2, 3), Point(4, 2))] + assert pl9.intersection(pl8) == [Line3D(Point3D(0, 0, 0), Point3D(12, 0, 0))] + assert pl10.intersection(pl11) == [Line3D(Point3D(0, 0, 1), Point3D(0, 2, 1))] + assert pl4.intersection(pl8) == [Line3D(Point3D(0, 0, 0), Point3D(1, -1, 0))] + assert pl11.intersection(pl8) == [] + assert pl9.intersection(pl11) == [Line3D(Point3D(0, 0, 1), Point3D(12, 0, 1))] + assert pl9.intersection(pl4) == [Line3D(Point3D(0, 0, 0), Point3D(12, 0, -12))] + assert pl3.random_point() in pl3 + assert pl3.random_point(seed=1) in pl3 + + # test geometrical entity using equals + assert pl4.intersection(pl4.p1)[0].equals(pl4.p1) + assert pl3.intersection(pl6)[0].equals(Line3D(Point3D(8, 4, 0), Point3D(2, 4, 6))) + pl8 = Plane((1, 2, 0), normal_vector=(0, 0, 1)) + assert pl8.intersection(Line3D(p1, (1, 12, 0)))[0].equals(Line((0, 0, 0), (0.1, 1.2, 0))) + assert pl8.intersection(Ray3D(p1, (1, 12, 0)))[0].equals(Ray((0, 0, 0), (1, 12, 0))) + assert pl8.intersection(Segment3D(p1, (21, 1, 0)))[0].equals(Segment3D(p1, (21, 1, 0))) + assert pl8.intersection(Plane(p1, normal_vector=(0, 0, 112)))[0].equals(pl8) + assert pl8.intersection(Plane(p1, normal_vector=(0, 12, 0)))[0].equals( + Line3D(p1, direction_ratio=(112 * pi, 0, 0))) + assert pl8.intersection(Plane(p1, normal_vector=(11, 0, 1)))[0].equals( + Line3D(p1, direction_ratio=(0, -11, 0))) + assert pl8.intersection(Plane(p1, normal_vector=(1, 0, 11)))[0].equals( + Line3D(p1, direction_ratio=(0, 11, 0))) + assert pl8.intersection(Plane(p1, normal_vector=(-1, -1, -11)))[0].equals( + Line3D(p1, direction_ratio=(1, -1, 0))) + assert pl3.random_point() in pl3 + assert len(pl8.intersection(Ray3D(Point3D(0, 2, 3), Point3D(1, 0, 3)))) == 0 + # check if two plane are equals + assert pl6.intersection(pl6)[0].equals(pl6) + assert pl8.equals(Plane(p1, normal_vector=(0, 12, 0))) is False + assert pl8.equals(pl8) + assert pl8.equals(Plane(p1, normal_vector=(0, 0, -12))) + assert pl8.equals(Plane(p1, normal_vector=(0, 0, -12*sqrt(3)))) + assert pl8.equals(p1) is False + + # issue 8570 + l2 = Line3D(Point3D(Rational(50000004459633, 5000000000000), + Rational(-891926590718643, 1000000000000000), + Rational(231800966893633, 100000000000000)), + Point3D(Rational(50000004459633, 50000000000000), + Rational(-222981647679771, 250000000000000), + Rational(231800966893633, 100000000000000))) + + p2 = Plane(Point3D(Rational(402775636372767, 100000000000000), + Rational(-97224357654973, 100000000000000), + Rational(216793600814789, 100000000000000)), + (-S('9.00000087501922'), -S('4.81170658872543e-13'), + S('0.0'))) + + assert str([i.n(2) for i in p2.intersection(l2)]) == \ + '[Point3D(4.0, -0.89, 2.3)]' + + +def test_dimension_normalization(): + A = Plane(Point3D(1, 1, 2), normal_vector=(1, 1, 1)) + b = Point(1, 1) + assert A.projection(b) == Point(Rational(5, 3), Rational(5, 3), Rational(2, 3)) + + a, b = Point(0, 0), Point3D(0, 1) + Z = (0, 0, 1) + p = Plane(a, normal_vector=Z) + assert p.perpendicular_plane(a, b) == Plane(Point3D(0, 0, 0), (1, 0, 0)) + assert Plane((1, 2, 1), (2, 1, 0), (3, 1, 2) + ).intersection((2, 1)) == [Point(2, 1, 0)] + + +def test_parameter_value(): + t, u, v = symbols("t, u v") + p1, p2, p3 = Point(0, 0, 0), Point(0, 0, 1), Point(0, 1, 0) + p = Plane(p1, p2, p3) + assert p.parameter_value((0, -3, 2), t) == {t: asin(2*sqrt(13)/13)} + assert p.parameter_value((0, -3, 2), u, v) == {u: 3, v: 2} + assert p.parameter_value(p1, t) == p1 + raises(ValueError, lambda: p.parameter_value((1, 0, 0), t)) + raises(ValueError, lambda: p.parameter_value(Line(Point(0, 0), Point(1, 1)), t)) + raises(ValueError, lambda: p.parameter_value((0, -3, 2), t, 1)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_point.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_point.py new file mode 100644 index 0000000000000000000000000000000000000000..1f2b2768eb3fba2009f702351de1aac3ed6e71d4 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_point.py @@ -0,0 +1,481 @@ +from sympy.core.basic import Basic +from sympy.core.numbers import (I, Rational, pi) +from sympy.core.parameters import evaluate +from sympy.core.singleton import S +from sympy.core.symbol import Symbol +from sympy.core.sympify import sympify +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.geometry import Line, Point, Point2D, Point3D, Line3D, Plane +from sympy.geometry.entity import rotate, scale, translate, GeometryEntity +from sympy.matrices import Matrix +from sympy.utilities.iterables import subsets, permutations, cartes +from sympy.utilities.misc import Undecidable +from sympy.testing.pytest import raises, warns + + +def test_point(): + x = Symbol('x', real=True) + y = Symbol('y', real=True) + x1 = Symbol('x1', real=True) + x2 = Symbol('x2', real=True) + y1 = Symbol('y1', real=True) + y2 = Symbol('y2', real=True) + half = S.Half + p1 = Point(x1, x2) + p2 = Point(y1, y2) + p3 = Point(0, 0) + p4 = Point(1, 1) + p5 = Point(0, 1) + line = Line(Point(1, 0), slope=1) + + assert p1 in p1 + assert p1 not in p2 + assert p2.y == y2 + assert (p3 + p4) == p4 + assert (p2 - p1) == Point(y1 - x1, y2 - x2) + assert -p2 == Point(-y1, -y2) + raises(TypeError, lambda: Point(1)) + raises(ValueError, lambda: Point([1])) + raises(ValueError, lambda: Point(3, I)) + raises(ValueError, lambda: Point(2*I, I)) + raises(ValueError, lambda: Point(3 + I, I)) + + assert Point(34.05, sqrt(3)) == Point(Rational(681, 20), sqrt(3)) + assert Point.midpoint(p3, p4) == Point(half, half) + assert Point.midpoint(p1, p4) == Point(half + half*x1, half + half*x2) + assert Point.midpoint(p2, p2) == p2 + assert p2.midpoint(p2) == p2 + assert p1.origin == Point(0, 0) + + assert Point.distance(p3, p4) == sqrt(2) + assert Point.distance(p1, p1) == 0 + assert Point.distance(p3, p2) == sqrt(p2.x**2 + p2.y**2) + raises(TypeError, lambda: Point.distance(p1, 0)) + raises(TypeError, lambda: Point.distance(p1, GeometryEntity())) + + # distance should be symmetric + assert p1.distance(line) == line.distance(p1) + assert p4.distance(line) == line.distance(p4) + + assert Point.taxicab_distance(p4, p3) == 2 + + assert Point.canberra_distance(p4, p5) == 1 + raises(ValueError, lambda: Point.canberra_distance(p3, p3)) + + p1_1 = Point(x1, x1) + p1_2 = Point(y2, y2) + p1_3 = Point(x1 + 1, x1) + assert Point.is_collinear(p3) + + with warns(UserWarning, test_stacklevel=False): + assert Point.is_collinear(p3, Point(p3, dim=4)) + assert p3.is_collinear() + assert Point.is_collinear(p3, p4) + assert Point.is_collinear(p3, p4, p1_1, p1_2) + assert Point.is_collinear(p3, p4, p1_1, p1_3) is False + assert Point.is_collinear(p3, p3, p4, p5) is False + + raises(TypeError, lambda: Point.is_collinear(line)) + raises(TypeError, lambda: p1_1.is_collinear(line)) + + assert p3.intersection(Point(0, 0)) == [p3] + assert p3.intersection(p4) == [] + assert p3.intersection(line) == [] + with warns(UserWarning, test_stacklevel=False): + assert Point.intersection(Point(0, 0, 0), Point(0, 0)) == [Point(0, 0, 0)] + + x_pos = Symbol('x', positive=True) + p2_1 = Point(x_pos, 0) + p2_2 = Point(0, x_pos) + p2_3 = Point(-x_pos, 0) + p2_4 = Point(0, -x_pos) + p2_5 = Point(x_pos, 5) + assert Point.is_concyclic(p2_1) + assert Point.is_concyclic(p2_1, p2_2) + assert Point.is_concyclic(p2_1, p2_2, p2_3, p2_4) + for pts in permutations((p2_1, p2_2, p2_3, p2_5)): + assert Point.is_concyclic(*pts) is False + assert Point.is_concyclic(p4, p4 * 2, p4 * 3) is False + assert Point(0, 0).is_concyclic((1, 1), (2, 2), (2, 1)) is False + assert Point.is_concyclic(Point(0, 0, 0, 0), Point(1, 0, 0, 0), Point(1, 1, 0, 0), Point(1, 1, 1, 0)) is False + + assert p1.is_scalar_multiple(p1) + assert p1.is_scalar_multiple(2*p1) + assert not p1.is_scalar_multiple(p2) + assert Point.is_scalar_multiple(Point(1, 1), (-1, -1)) + assert Point.is_scalar_multiple(Point(0, 0), (0, -1)) + # test when is_scalar_multiple can't be determined + raises(Undecidable, lambda: Point.is_scalar_multiple(Point(sympify("x1%y1"), sympify("x2%y2")), Point(0, 1))) + + assert Point(0, 1).orthogonal_direction == Point(1, 0) + assert Point(1, 0).orthogonal_direction == Point(0, 1) + + assert p1.is_zero is None + assert p3.is_zero + assert p4.is_zero is False + assert p1.is_nonzero is None + assert p3.is_nonzero is False + assert p4.is_nonzero + + assert p4.scale(2, 3) == Point(2, 3) + assert p3.scale(2, 3) == p3 + + assert p4.rotate(pi, Point(0.5, 0.5)) == p3 + assert p1.__radd__(p2) == p1.midpoint(p2).scale(2, 2) + assert (-p3).__rsub__(p4) == p3.midpoint(p4).scale(2, 2) + + assert p4 * 5 == Point(5, 5) + assert p4 / 5 == Point(0.2, 0.2) + assert 5 * p4 == Point(5, 5) + + raises(ValueError, lambda: Point(0, 0) + 10) + + # Point differences should be simplified + assert Point(x*(x - 1), y) - Point(x**2 - x, y + 1) == Point(0, -1) + + a, b = S.Half, Rational(1, 3) + assert Point(a, b).evalf(2) == \ + Point(a.n(2), b.n(2), evaluate=False) + raises(ValueError, lambda: Point(1, 2) + 1) + + # test project + assert Point.project((0, 1), (1, 0)) == Point(0, 0) + assert Point.project((1, 1), (1, 0)) == Point(1, 0) + raises(ValueError, lambda: Point.project(p1, Point(0, 0))) + + # test transformations + p = Point(1, 0) + assert p.rotate(pi/2) == Point(0, 1) + assert p.rotate(pi/2, p) == p + p = Point(1, 1) + assert p.scale(2, 3) == Point(2, 3) + assert p.translate(1, 2) == Point(2, 3) + assert p.translate(1) == Point(2, 1) + assert p.translate(y=1) == Point(1, 2) + assert p.translate(*p.args) == Point(2, 2) + + # Check invalid input for transform + raises(ValueError, lambda: p3.transform(p3)) + raises(ValueError, lambda: p.transform(Matrix([[1, 0], [0, 1]]))) + + # test __contains__ + assert 0 in Point(0, 0, 0, 0) + assert 1 not in Point(0, 0, 0, 0) + + # test affine_rank + assert Point.affine_rank() == -1 + + +def test_point3D(): + x = Symbol('x', real=True) + y = Symbol('y', real=True) + x1 = Symbol('x1', real=True) + x2 = Symbol('x2', real=True) + x3 = Symbol('x3', real=True) + y1 = Symbol('y1', real=True) + y2 = Symbol('y2', real=True) + y3 = Symbol('y3', real=True) + half = S.Half + p1 = Point3D(x1, x2, x3) + p2 = Point3D(y1, y2, y3) + p3 = Point3D(0, 0, 0) + p4 = Point3D(1, 1, 1) + p5 = Point3D(0, 1, 2) + + assert p1 in p1 + assert p1 not in p2 + assert p2.y == y2 + assert (p3 + p4) == p4 + assert (p2 - p1) == Point3D(y1 - x1, y2 - x2, y3 - x3) + assert -p2 == Point3D(-y1, -y2, -y3) + + assert Point(34.05, sqrt(3)) == Point(Rational(681, 20), sqrt(3)) + assert Point3D.midpoint(p3, p4) == Point3D(half, half, half) + assert Point3D.midpoint(p1, p4) == Point3D(half + half*x1, half + half*x2, + half + half*x3) + assert Point3D.midpoint(p2, p2) == p2 + assert p2.midpoint(p2) == p2 + + assert Point3D.distance(p3, p4) == sqrt(3) + assert Point3D.distance(p1, p1) == 0 + assert Point3D.distance(p3, p2) == sqrt(p2.x**2 + p2.y**2 + p2.z**2) + + p1_1 = Point3D(x1, x1, x1) + p1_2 = Point3D(y2, y2, y2) + p1_3 = Point3D(x1 + 1, x1, x1) + Point3D.are_collinear(p3) + assert Point3D.are_collinear(p3, p4) + assert Point3D.are_collinear(p3, p4, p1_1, p1_2) + assert Point3D.are_collinear(p3, p4, p1_1, p1_3) is False + assert Point3D.are_collinear(p3, p3, p4, p5) is False + + assert p3.intersection(Point3D(0, 0, 0)) == [p3] + assert p3.intersection(p4) == [] + + + assert p4 * 5 == Point3D(5, 5, 5) + assert p4 / 5 == Point3D(0.2, 0.2, 0.2) + assert 5 * p4 == Point3D(5, 5, 5) + + raises(ValueError, lambda: Point3D(0, 0, 0) + 10) + + # Test coordinate properties + assert p1.coordinates == (x1, x2, x3) + assert p2.coordinates == (y1, y2, y3) + assert p3.coordinates == (0, 0, 0) + assert p4.coordinates == (1, 1, 1) + assert p5.coordinates == (0, 1, 2) + assert p5.x == 0 + assert p5.y == 1 + assert p5.z == 2 + + # Point differences should be simplified + assert Point3D(x*(x - 1), y, 2) - Point3D(x**2 - x, y + 1, 1) == \ + Point3D(0, -1, 1) + + a, b, c = S.Half, Rational(1, 3), Rational(1, 4) + assert Point3D(a, b, c).evalf(2) == \ + Point(a.n(2), b.n(2), c.n(2), evaluate=False) + raises(ValueError, lambda: Point3D(1, 2, 3) + 1) + + # test transformations + p = Point3D(1, 1, 1) + assert p.scale(2, 3) == Point3D(2, 3, 1) + assert p.translate(1, 2) == Point3D(2, 3, 1) + assert p.translate(1) == Point3D(2, 1, 1) + assert p.translate(z=1) == Point3D(1, 1, 2) + assert p.translate(*p.args) == Point3D(2, 2, 2) + + # Test __new__ + assert Point3D(0.1, 0.2, evaluate=False, on_morph='ignore').args[0].is_Float + + # Test length property returns correctly + assert p.length == 0 + assert p1_1.length == 0 + assert p1_2.length == 0 + + # Test are_colinear type error + raises(TypeError, lambda: Point3D.are_collinear(p, x)) + + # Test are_coplanar + assert Point.are_coplanar() + assert Point.are_coplanar((1, 2, 0), (1, 2, 0), (1, 3, 0)) + assert Point.are_coplanar((1, 2, 0), (1, 2, 3)) + with warns(UserWarning, test_stacklevel=False): + raises(ValueError, lambda: Point2D.are_coplanar((1, 2), (1, 2, 3))) + assert Point3D.are_coplanar((1, 2, 0), (1, 2, 3)) + assert Point.are_coplanar((0, 0, 0), (1, 1, 0), (1, 1, 1), (1, 2, 1)) is False + planar2 = Point3D(1, -1, 1) + planar3 = Point3D(-1, 1, 1) + assert Point3D.are_coplanar(p, planar2, planar3) == True + assert Point3D.are_coplanar(p, planar2, planar3, p3) == False + assert Point.are_coplanar(p, planar2) + planar2 = Point3D(1, 1, 2) + planar3 = Point3D(1, 1, 3) + assert Point3D.are_coplanar(p, planar2, planar3) # line, not plane + plane = Plane((1, 2, 1), (2, 1, 0), (3, 1, 2)) + assert Point.are_coplanar(*[plane.projection(((-1)**i, i)) for i in range(4)]) + + # all 2D points are coplanar + assert Point.are_coplanar(Point(x, y), Point(x, x + y), Point(y, x + 2)) is True + + # Test Intersection + assert planar2.intersection(Line3D(p, planar3)) == [Point3D(1, 1, 2)] + + # Test Scale + assert planar2.scale(1, 1, 1) == planar2 + assert planar2.scale(2, 2, 2, planar3) == Point3D(1, 1, 1) + assert planar2.scale(1, 1, 1, p3) == planar2 + + # Test Transform + identity = Matrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) + assert p.transform(identity) == p + trans = Matrix([[1, 0, 0, 1], [0, 1, 0, 1], [0, 0, 1, 1], [0, 0, 0, 1]]) + assert p.transform(trans) == Point3D(2, 2, 2) + raises(ValueError, lambda: p.transform(p)) + raises(ValueError, lambda: p.transform(Matrix([[1, 0], [0, 1]]))) + + # Test Equals + assert p.equals(x1) == False + + # Test __sub__ + p_4d = Point(0, 0, 0, 1) + with warns(UserWarning, test_stacklevel=False): + assert p - p_4d == Point(1, 1, 1, -1) + p_4d3d = Point(0, 0, 1, 0) + with warns(UserWarning, test_stacklevel=False): + assert p - p_4d3d == Point(1, 1, 0, 0) + + +def test_Point2D(): + + # Test Distance + p1 = Point2D(1, 5) + p2 = Point2D(4, 2.5) + p3 = (6, 3) + assert p1.distance(p2) == sqrt(61)/2 + assert p2.distance(p3) == sqrt(17)/2 + + # Test coordinates + assert p1.x == 1 + assert p1.y == 5 + assert p2.x == 4 + assert p2.y == S(5)/2 + assert p1.coordinates == (1, 5) + assert p2.coordinates == (4, S(5)/2) + + # test bounds + assert p1.bounds == (1, 5, 1, 5) + +def test_issue_9214(): + p1 = Point3D(4, -2, 6) + p2 = Point3D(1, 2, 3) + p3 = Point3D(7, 2, 3) + + assert Point3D.are_collinear(p1, p2, p3) is False + + +def test_issue_11617(): + p1 = Point3D(1,0,2) + p2 = Point2D(2,0) + + with warns(UserWarning, test_stacklevel=False): + assert p1.distance(p2) == sqrt(5) + + +def test_transform(): + p = Point(1, 1) + assert p.transform(rotate(pi/2)) == Point(-1, 1) + assert p.transform(scale(3, 2)) == Point(3, 2) + assert p.transform(translate(1, 2)) == Point(2, 3) + assert Point(1, 1).scale(2, 3, (4, 5)) == \ + Point(-2, -7) + assert Point(1, 1).translate(4, 5) == \ + Point(5, 6) + + +def test_concyclic_doctest_bug(): + p1, p2 = Point(-1, 0), Point(1, 0) + p3, p4 = Point(0, 1), Point(-1, 2) + assert Point.is_concyclic(p1, p2, p3) + assert not Point.is_concyclic(p1, p2, p3, p4) + + +def test_arguments(): + """Functions accepting `Point` objects in `geometry` + should also accept tuples and lists and + automatically convert them to points.""" + + singles2d = ((1,2), [1,2], Point(1,2)) + singles2d2 = ((1,3), [1,3], Point(1,3)) + doubles2d = cartes(singles2d, singles2d2) + p2d = Point2D(1,2) + singles3d = ((1,2,3), [1,2,3], Point(1,2,3)) + doubles3d = subsets(singles3d, 2) + p3d = Point3D(1,2,3) + singles4d = ((1,2,3,4), [1,2,3,4], Point(1,2,3,4)) + doubles4d = subsets(singles4d, 2) + p4d = Point(1,2,3,4) + + # test 2D + test_single = ['distance', 'is_scalar_multiple', 'taxicab_distance', 'midpoint', 'intersection', 'dot', 'equals', '__add__', '__sub__'] + test_double = ['is_concyclic', 'is_collinear'] + for p in singles2d: + Point2D(p) + for func in test_single: + for p in singles2d: + getattr(p2d, func)(p) + for func in test_double: + for p in doubles2d: + getattr(p2d, func)(*p) + + # test 3D + test_double = ['is_collinear'] + for p in singles3d: + Point3D(p) + for func in test_single: + for p in singles3d: + getattr(p3d, func)(p) + for func in test_double: + for p in doubles3d: + getattr(p3d, func)(*p) + + # test 4D + test_double = ['is_collinear'] + for p in singles4d: + Point(p) + for func in test_single: + for p in singles4d: + getattr(p4d, func)(p) + for func in test_double: + for p in doubles4d: + getattr(p4d, func)(*p) + + # test evaluate=False for ops + x = Symbol('x') + a = Point(0, 1) + assert a + (0.1, x) == Point(0.1, 1 + x, evaluate=False) + a = Point(0, 1) + assert a/10.0 == Point(0, 0.1, evaluate=False) + a = Point(0, 1) + assert a*10.0 == Point(0, 10.0, evaluate=False) + + # test evaluate=False when changing dimensions + u = Point(.1, .2, evaluate=False) + u4 = Point(u, dim=4, on_morph='ignore') + assert u4.args == (.1, .2, 0, 0) + assert all(i.is_Float for i in u4.args[:2]) + # and even when *not* changing dimensions + assert all(i.is_Float for i in Point(u).args) + + # never raise error if creating an origin + assert Point(dim=3, on_morph='error') + + # raise error with unmatched dimension + raises(ValueError, lambda: Point(1, 1, dim=3, on_morph='error')) + # test unknown on_morph + raises(ValueError, lambda: Point(1, 1, dim=3, on_morph='unknown')) + # test invalid expressions + raises(TypeError, lambda: Point(Basic(), Basic())) + +def test_unit(): + assert Point(1, 1).unit == Point(sqrt(2)/2, sqrt(2)/2) + + +def test_dot(): + raises(TypeError, lambda: Point(1, 2).dot(Line((0, 0), (1, 1)))) + + +def test__normalize_dimension(): + assert Point._normalize_dimension(Point(1, 2), Point(3, 4)) == [ + Point(1, 2), Point(3, 4)] + assert Point._normalize_dimension( + Point(1, 2), Point(3, 4, 0), on_morph='ignore') == [ + Point(1, 2, 0), Point(3, 4, 0)] + + +def test_issue_22684(): + # Used to give an error + with evaluate(False): + Point(1, 2) + + +def test_direction_cosine(): + p1 = Point3D(0, 0, 0) + p2 = Point3D(1, 1, 1) + + assert p1.direction_cosine(Point3D(1, 0, 0)) == [1, 0, 0] + assert p1.direction_cosine(Point3D(0, 1, 0)) == [0, 1, 0] + assert p1.direction_cosine(Point3D(0, 0, pi)) == [0, 0, 1] + + assert p1.direction_cosine(Point3D(5, 0, 0)) == [1, 0, 0] + assert p1.direction_cosine(Point3D(0, sqrt(3), 0)) == [0, 1, 0] + assert p1.direction_cosine(Point3D(0, 0, 5)) == [0, 0, 1] + + assert p1.direction_cosine(Point3D(2.4, 2.4, 0)) == [sqrt(2)/2, sqrt(2)/2, 0] + assert p1.direction_cosine(Point3D(1, 1, 1)) == [sqrt(3) / 3, sqrt(3) / 3, sqrt(3) / 3] + assert p1.direction_cosine(Point3D(-12, 0 -15)) == [-4*sqrt(41)/41, -5*sqrt(41)/41, 0] + + assert p2.direction_cosine(Point3D(0, 0, 0)) == [-sqrt(3) / 3, -sqrt(3) / 3, -sqrt(3) / 3] + assert p2.direction_cosine(Point3D(1, 1, 12)) == [0, 0, 1] + assert p2.direction_cosine(Point3D(12, 1, 12)) == [sqrt(2) / 2, 0, sqrt(2) / 2] diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_polygon.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_polygon.py new file mode 100644 index 0000000000000000000000000000000000000000..520023349f363bdb12146465305c2a5650c80934 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_polygon.py @@ -0,0 +1,676 @@ +from sympy.core.numbers import (Float, Rational, oo, pi) +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.elementary.complexes import Abs +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (acos, cos, sin) +from sympy.functions.elementary.trigonometric import tan +from sympy.geometry import (Circle, Ellipse, GeometryError, Point, Point2D, + Polygon, Ray, RegularPolygon, Segment, Triangle, + are_similar, convex_hull, intersection, Line, Ray2D) +from sympy.testing.pytest import raises, slow, warns +from sympy.core.random import verify_numerically +from sympy.geometry.polygon import rad, deg +from sympy.integrals.integrals import integrate +from sympy.utilities.iterables import rotate_left + + +def feq(a, b): + """Test if two floating point values are 'equal'.""" + t_float = Float("1.0E-10") + return -t_float < a - b < t_float + +@slow +def test_polygon(): + x = Symbol('x', real=True) + y = Symbol('y', real=True) + q = Symbol('q', real=True) + u = Symbol('u', real=True) + v = Symbol('v', real=True) + w = Symbol('w', real=True) + x1 = Symbol('x1', real=True) + half = S.Half + a, b, c = Point(0, 0), Point(2, 0), Point(3, 3) + t = Triangle(a, b, c) + assert Polygon(Point(0, 0)) == Point(0, 0) + assert Polygon(a, Point(1, 0), b, c) == t + assert Polygon(Point(1, 0), b, c, a) == t + assert Polygon(b, c, a, Point(1, 0)) == t + # 2 "remove folded" tests + assert Polygon(a, Point(3, 0), b, c) == t + assert Polygon(a, b, Point(3, -1), b, c) == t + # remove multiple collinear points + assert Polygon(Point(-4, 15), Point(-11, 15), Point(-15, 15), + Point(-15, 33/5), Point(-15, -87/10), Point(-15, -15), + Point(-42/5, -15), Point(-2, -15), Point(7, -15), Point(15, -15), + Point(15, -3), Point(15, 10), Point(15, 15)) == \ + Polygon(Point(-15, -15), Point(15, -15), Point(15, 15), Point(-15, 15)) + + p1 = Polygon( + Point(0, 0), Point(3, -1), + Point(6, 0), Point(4, 5), + Point(2, 3), Point(0, 3)) + p2 = Polygon( + Point(6, 0), Point(3, -1), + Point(0, 0), Point(0, 3), + Point(2, 3), Point(4, 5)) + p3 = Polygon( + Point(0, 0), Point(3, 0), + Point(5, 2), Point(4, 4)) + p4 = Polygon( + Point(0, 0), Point(4, 4), + Point(5, 2), Point(3, 0)) + p5 = Polygon( + Point(0, 0), Point(4, 4), + Point(0, 4)) + p6 = Polygon( + Point(-11, 1), Point(-9, 6.6), + Point(-4, -3), Point(-8.4, -8.7)) + p7 = Polygon( + Point(x, y), Point(q, u), + Point(v, w)) + p8 = Polygon( + Point(x, y), Point(v, w), + Point(q, u)) + p9 = Polygon( + Point(0, 0), Point(4, 4), + Point(3, 0), Point(5, 2)) + p10 = Polygon( + Point(0, 2), Point(2, 2), + Point(0, 0), Point(2, 0)) + p11 = Polygon(Point(0, 0), 1, n=3) + p12 = Polygon(Point(0, 0), 1, 0, n=3) + p13 = Polygon( + Point(0, 0),Point(8, 8), + Point(23, 20),Point(0, 20)) + p14 = Polygon(*rotate_left(p13.args, 1)) + + + r = Ray(Point(-9, 6.6), Point(-9, 5.5)) + # + # General polygon + # + assert p1 == p2 + assert len(p1.args) == 6 + assert len(p1.sides) == 6 + assert p1.perimeter == 5 + 2*sqrt(10) + sqrt(29) + sqrt(8) + assert p1.area == 22 + assert not p1.is_convex() + assert Polygon((-1, 1), (2, -1), (2, 1), (-1, -1), (3, 0) + ).is_convex() is False + # ensure convex for both CW and CCW point specification + assert p3.is_convex() + assert p4.is_convex() + dict5 = p5.angles + assert dict5[Point(0, 0)] == pi / 4 + assert dict5[Point(0, 4)] == pi / 2 + assert p5.encloses_point(Point(x, y)) is None + assert p5.encloses_point(Point(1, 3)) + assert p5.encloses_point(Point(0, 0)) is False + assert p5.encloses_point(Point(4, 0)) is False + assert p1.encloses(Circle(Point(2.5, 2.5), 5)) is False + assert p1.encloses(Ellipse(Point(2.5, 2), 5, 6)) is False + assert p5.plot_interval('x') == [x, 0, 1] + assert p5.distance( + Polygon(Point(10, 10), Point(14, 14), Point(10, 14))) == 6 * sqrt(2) + assert p5.distance( + Polygon(Point(1, 8), Point(5, 8), Point(8, 12), Point(1, 12))) == 4 + with warns(UserWarning, \ + match="Polygons may intersect producing erroneous output"): + Polygon(Point(0, 0), Point(1, 0), Point(1, 1)).distance( + Polygon(Point(0, 0), Point(0, 1), Point(1, 1))) + assert hash(p5) == hash(Polygon(Point(0, 0), Point(4, 4), Point(0, 4))) + assert hash(p1) == hash(p2) + assert hash(p7) == hash(p8) + assert hash(p3) != hash(p9) + assert p5 == Polygon(Point(4, 4), Point(0, 4), Point(0, 0)) + assert Polygon(Point(4, 4), Point(0, 4), Point(0, 0)) in p5 + assert p5 != Point(0, 4) + assert Point(0, 1) in p5 + assert p5.arbitrary_point('t').subs(Symbol('t', real=True), 0) == \ + Point(0, 0) + raises(ValueError, lambda: Polygon( + Point(x, 0), Point(0, y), Point(x, y)).arbitrary_point('x')) + assert p6.intersection(r) == [Point(-9, Rational(-84, 13)), Point(-9, Rational(33, 5))] + assert p10.area == 0 + assert p11 == RegularPolygon(Point(0, 0), 1, 3, 0) + assert p11 == p12 + assert p11.vertices[0] == Point(1, 0) + assert p11.args[0] == Point(0, 0) + p11.spin(pi/2) + assert p11.vertices[0] == Point(0, 1) + # + # Regular polygon + # + p1 = RegularPolygon(Point(0, 0), 10, 5) + p2 = RegularPolygon(Point(0, 0), 5, 5) + raises(GeometryError, lambda: RegularPolygon(Point(0, 0), Point(0, + 1), Point(1, 1))) + raises(GeometryError, lambda: RegularPolygon(Point(0, 0), 1, 2)) + raises(ValueError, lambda: RegularPolygon(Point(0, 0), 1, 2.5)) + + assert p1 != p2 + assert p1.interior_angle == pi*Rational(3, 5) + assert p1.exterior_angle == pi*Rational(2, 5) + assert p2.apothem == 5*cos(pi/5) + assert p2.circumcenter == p1.circumcenter == Point(0, 0) + assert p1.circumradius == p1.radius == 10 + assert p2.circumcircle == Circle(Point(0, 0), 5) + assert p2.incircle == Circle(Point(0, 0), p2.apothem) + assert p2.inradius == p2.apothem == (5 * (1 + sqrt(5)) / 4) + p2.spin(pi / 10) + dict1 = p2.angles + assert dict1[Point(0, 5)] == 3 * pi / 5 + assert p1.is_convex() + assert p1.rotation == 0 + assert p1.encloses_point(Point(0, 0)) + assert p1.encloses_point(Point(11, 0)) is False + assert p2.encloses_point(Point(0, 4.9)) + p1.spin(pi/3) + assert p1.rotation == pi/3 + assert p1.vertices[0] == Point(5, 5*sqrt(3)) + for var in p1.args: + if isinstance(var, Point): + assert var == Point(0, 0) + else: + assert var in (5, 10, pi / 3) + assert p1 != Point(0, 0) + assert p1 != p5 + + # while spin works in place (notice that rotation is 2pi/3 below) + # rotate returns a new object + p1_old = p1 + assert p1.rotate(pi/3) == RegularPolygon(Point(0, 0), 10, 5, pi*Rational(2, 3)) + assert p1 == p1_old + + assert p1.area == (-250*sqrt(5) + 1250)/(4*tan(pi/5)) + assert p1.length == 20*sqrt(-sqrt(5)/8 + Rational(5, 8)) + assert p1.scale(2, 2) == \ + RegularPolygon(p1.center, p1.radius*2, p1._n, p1.rotation) + assert RegularPolygon((0, 0), 1, 4).scale(2, 3) == \ + Polygon(Point(2, 0), Point(0, 3), Point(-2, 0), Point(0, -3)) + + assert repr(p1) == str(p1) + + # + # Angles + # + angles = p4.angles + assert feq(angles[Point(0, 0)].evalf(), Float("0.7853981633974483")) + assert feq(angles[Point(4, 4)].evalf(), Float("1.2490457723982544")) + assert feq(angles[Point(5, 2)].evalf(), Float("1.8925468811915388")) + assert feq(angles[Point(3, 0)].evalf(), Float("2.3561944901923449")) + + angles = p3.angles + assert feq(angles[Point(0, 0)].evalf(), Float("0.7853981633974483")) + assert feq(angles[Point(4, 4)].evalf(), Float("1.2490457723982544")) + assert feq(angles[Point(5, 2)].evalf(), Float("1.8925468811915388")) + assert feq(angles[Point(3, 0)].evalf(), Float("2.3561944901923449")) + + # https://github.com/sympy/sympy/issues/24885 + interior_angles_sum = sum(p13.angles.values()) + assert feq(interior_angles_sum, (len(p13.angles) - 2)*pi ) + interior_angles_sum = sum(p14.angles.values()) + assert feq(interior_angles_sum, (len(p14.angles) - 2)*pi ) + + # + # Triangle + # + p1 = Point(0, 0) + p2 = Point(5, 0) + p3 = Point(0, 5) + t1 = Triangle(p1, p2, p3) + t2 = Triangle(p1, p2, Point(Rational(5, 2), sqrt(Rational(75, 4)))) + t3 = Triangle(p1, Point(x1, 0), Point(0, x1)) + s1 = t1.sides + assert Triangle(p1, p2, p1) == Polygon(p1, p2, p1) == Segment(p1, p2) + raises(GeometryError, lambda: Triangle(Point(0, 0))) + + # Basic stuff + assert Triangle(p1, p1, p1) == p1 + assert Triangle(p2, p2*2, p2*3) == Segment(p2, p2*3) + assert t1.area == Rational(25, 2) + assert t1.is_right() + assert t2.is_right() is False + assert t3.is_right() + assert p1 in t1 + assert t1.sides[0] in t1 + assert Segment((0, 0), (1, 0)) in t1 + assert Point(5, 5) not in t2 + assert t1.is_convex() + assert feq(t1.angles[p1].evalf(), pi.evalf()/2) + + assert t1.is_equilateral() is False + assert t2.is_equilateral() + assert t3.is_equilateral() is False + assert are_similar(t1, t2) is False + assert are_similar(t1, t3) + assert are_similar(t2, t3) is False + assert t1.is_similar(Point(0, 0)) is False + assert t1.is_similar(t2) is False + + # Bisectors + bisectors = t1.bisectors() + assert bisectors[p1] == Segment( + p1, Point(Rational(5, 2), Rational(5, 2))) + assert t2.bisectors()[p2] == Segment( + Point(5, 0), Point(Rational(5, 4), 5*sqrt(3)/4)) + p4 = Point(0, x1) + assert t3.bisectors()[p4] == Segment(p4, Point(x1*(sqrt(2) - 1), 0)) + ic = (250 - 125*sqrt(2))/50 + assert t1.incenter == Point(ic, ic) + + # Inradius + assert t1.inradius == t1.incircle.radius == 5 - 5*sqrt(2)/2 + assert t2.inradius == t2.incircle.radius == 5*sqrt(3)/6 + assert t3.inradius == t3.incircle.radius == x1**2/((2 + sqrt(2))*Abs(x1)) + + # Exradius + assert t1.exradii[t1.sides[2]] == 5*sqrt(2)/2 + + # Excenters + assert t1.excenters[t1.sides[2]] == Point2D(25*sqrt(2), -5*sqrt(2)/2) + + # Circumcircle + assert t1.circumcircle.center == Point(2.5, 2.5) + + # Medians + Centroid + m = t1.medians + assert t1.centroid == Point(Rational(5, 3), Rational(5, 3)) + assert m[p1] == Segment(p1, Point(Rational(5, 2), Rational(5, 2))) + assert t3.medians[p1] == Segment(p1, Point(x1/2, x1/2)) + assert intersection(m[p1], m[p2], m[p3]) == [t1.centroid] + assert t1.medial == Triangle(Point(2.5, 0), Point(0, 2.5), Point(2.5, 2.5)) + + # Nine-point circle + assert t1.nine_point_circle == Circle(Point(2.5, 0), + Point(0, 2.5), Point(2.5, 2.5)) + assert t1.nine_point_circle == Circle(Point(0, 0), + Point(0, 2.5), Point(2.5, 2.5)) + + # Perpendicular + altitudes = t1.altitudes + assert altitudes[p1] == Segment(p1, Point(Rational(5, 2), Rational(5, 2))) + assert altitudes[p2].equals(s1[0]) + assert altitudes[p3] == s1[2] + assert t1.orthocenter == p1 + t = S('''Triangle( + Point(100080156402737/5000000000000, 79782624633431/500000000000), + Point(39223884078253/2000000000000, 156345163124289/1000000000000), + Point(31241359188437/1250000000000, 338338270939941/1000000000000000))''') + assert t.orthocenter == S('''Point(-780660869050599840216997''' + '''79471538701955848721853/80368430960602242240789074233100000000000000,''' + '''20151573611150265741278060334545897615974257/16073686192120448448157''' + '''8148466200000000000)''') + + # Ensure + assert len(intersection(*bisectors.values())) == 1 + assert len(intersection(*altitudes.values())) == 1 + assert len(intersection(*m.values())) == 1 + + # Distance + p1 = Polygon( + Point(0, 0), Point(1, 0), + Point(1, 1), Point(0, 1)) + p2 = Polygon( + Point(0, Rational(5)/4), Point(1, Rational(5)/4), + Point(1, Rational(9)/4), Point(0, Rational(9)/4)) + p3 = Polygon( + Point(1, 2), Point(2, 2), + Point(2, 1)) + p4 = Polygon( + Point(1, 1), Point(Rational(6)/5, 1), + Point(1, Rational(6)/5)) + pt1 = Point(half, half) + pt2 = Point(1, 1) + + '''Polygon to Point''' + assert p1.distance(pt1) == half + assert p1.distance(pt2) == 0 + assert p2.distance(pt1) == Rational(3)/4 + assert p3.distance(pt2) == sqrt(2)/2 + + '''Polygon to Polygon''' + # p1.distance(p2) emits a warning + with warns(UserWarning, \ + match="Polygons may intersect producing erroneous output"): + assert p1.distance(p2) == half/2 + + assert p1.distance(p3) == sqrt(2)/2 + + # p3.distance(p4) emits a warning + with warns(UserWarning, \ + match="Polygons may intersect producing erroneous output"): + assert p3.distance(p4) == (sqrt(2)/2 - sqrt(Rational(2)/25)/2) + + +def test_convex_hull(): + p = [Point(-5, -1), Point(-2, 1), Point(-2, -1), Point(-1, -3), \ + Point(0, 0), Point(1, 1), Point(2, 2), Point(2, -1), Point(3, 1), \ + Point(4, -1), Point(6, 2)] + ch = Polygon(p[0], p[3], p[9], p[10], p[6], p[1]) + #test handling of duplicate points + p.append(p[3]) + + #more than 3 collinear points + another_p = [Point(-45, -85), Point(-45, 85), Point(-45, 26), \ + Point(-45, -24)] + ch2 = Segment(another_p[0], another_p[1]) + + assert convex_hull(*another_p) == ch2 + assert convex_hull(*p) == ch + assert convex_hull(p[0]) == p[0] + assert convex_hull(p[0], p[1]) == Segment(p[0], p[1]) + + # no unique points + assert convex_hull(*[p[-1]]*3) == p[-1] + + # collection of items + assert convex_hull(*[Point(0, 0), \ + Segment(Point(1, 0), Point(1, 1)), \ + RegularPolygon(Point(2, 0), 2, 4)]) == \ + Polygon(Point(0, 0), Point(2, -2), Point(4, 0), Point(2, 2)) + + +def test_encloses(): + # square with a dimpled left side + s = Polygon(Point(0, 0), Point(1, 0), Point(1, 1), Point(0, 1), \ + Point(S.Half, S.Half)) + # the following is True if the polygon isn't treated as closing on itself + assert s.encloses(Point(0, S.Half)) is False + assert s.encloses(Point(S.Half, S.Half)) is False # it's a vertex + assert s.encloses(Point(Rational(3, 4), S.Half)) is True + + +def test_triangle_kwargs(): + assert Triangle(sss=(3, 4, 5)) == \ + Triangle(Point(0, 0), Point(3, 0), Point(3, 4)) + assert Triangle(asa=(30, 2, 30)) == \ + Triangle(Point(0, 0), Point(2, 0), Point(1, sqrt(3)/3)) + assert Triangle(sas=(1, 45, 2)) == \ + Triangle(Point(0, 0), Point(2, 0), Point(sqrt(2)/2, sqrt(2)/2)) + assert Triangle(sss=(1, 2, 5)) is None + assert deg(rad(180)) == 180 + + +def test_transform(): + pts = [Point(0, 0), Point(S.Half, Rational(1, 4)), Point(1, 1)] + pts_out = [Point(-4, -10), Point(-3, Rational(-37, 4)), Point(-2, -7)] + assert Triangle(*pts).scale(2, 3, (4, 5)) == Triangle(*pts_out) + assert RegularPolygon((0, 0), 1, 4).scale(2, 3, (4, 5)) == \ + Polygon(Point(-2, -10), Point(-4, -7), Point(-6, -10), Point(-4, -13)) + # Checks for symmetric scaling + assert RegularPolygon((0, 0), 1, 4).scale(2, 2) == \ + RegularPolygon(Point2D(0, 0), 2, 4, 0) + +def test_reflect(): + x = Symbol('x', real=True) + y = Symbol('y', real=True) + b = Symbol('b') + m = Symbol('m') + l = Line((0, b), slope=m) + p = Point(x, y) + r = p.reflect(l) + dp = l.perpendicular_segment(p).length + dr = l.perpendicular_segment(r).length + + assert verify_numerically(dp, dr) + + assert Polygon((1, 0), (2, 0), (2, 2)).reflect(Line((3, 0), slope=oo)) \ + == Triangle(Point(5, 0), Point(4, 0), Point(4, 2)) + assert Polygon((1, 0), (2, 0), (2, 2)).reflect(Line((0, 3), slope=oo)) \ + == Triangle(Point(-1, 0), Point(-2, 0), Point(-2, 2)) + assert Polygon((1, 0), (2, 0), (2, 2)).reflect(Line((0, 3), slope=0)) \ + == Triangle(Point(1, 6), Point(2, 6), Point(2, 4)) + assert Polygon((1, 0), (2, 0), (2, 2)).reflect(Line((3, 0), slope=0)) \ + == Triangle(Point(1, 0), Point(2, 0), Point(2, -2)) + +def test_bisectors(): + p1, p2, p3 = Point(0, 0), Point(1, 0), Point(0, 1) + p = Polygon(Point(0, 0), Point(2, 0), Point(1, 1), Point(0, 3)) + q = Polygon(Point(1, 0), Point(2, 0), Point(3, 3), Point(-1, 5)) + poly = Polygon(Point(3, 4), Point(0, 0), Point(8, 7), Point(-1, 1), Point(19, -19)) + t = Triangle(p1, p2, p3) + assert t.bisectors()[p2] == Segment(Point(1, 0), Point(0, sqrt(2) - 1)) + assert p.bisectors()[Point2D(0, 3)] == Ray2D(Point2D(0, 3), \ + Point2D(sin(acos(2*sqrt(5)/5)/2), 3 - cos(acos(2*sqrt(5)/5)/2))) + assert q.bisectors()[Point2D(-1, 5)] == \ + Ray2D(Point2D(-1, 5), Point2D(-1 + sqrt(29)*(5*sin(acos(9*sqrt(145)/145)/2) + \ + 2*cos(acos(9*sqrt(145)/145)/2))/29, sqrt(29)*(-5*cos(acos(9*sqrt(145)/145)/2) + \ + 2*sin(acos(9*sqrt(145)/145)/2))/29 + 5)) + assert poly.bisectors()[Point2D(-1, 1)] == Ray2D(Point2D(-1, 1), \ + Point2D(-1 + sin(acos(sqrt(26)/26)/2 + pi/4), 1 - sin(-acos(sqrt(26)/26)/2 + pi/4))) + +def test_incenter(): + assert Triangle(Point(0, 0), Point(1, 0), Point(0, 1)).incenter \ + == Point(1 - sqrt(2)/2, 1 - sqrt(2)/2) + +def test_inradius(): + assert Triangle(Point(0, 0), Point(4, 0), Point(0, 3)).inradius == 1 + +def test_incircle(): + assert Triangle(Point(0, 0), Point(2, 0), Point(0, 2)).incircle \ + == Circle(Point(2 - sqrt(2), 2 - sqrt(2)), 2 - sqrt(2)) + +def test_exradii(): + t = Triangle(Point(0, 0), Point(6, 0), Point(0, 2)) + assert t.exradii[t.sides[2]] == (-2 + sqrt(10)) + +def test_medians(): + t = Triangle(Point(0, 0), Point(1, 0), Point(0, 1)) + assert t.medians[Point(0, 0)] == Segment(Point(0, 0), Point(S.Half, S.Half)) + +def test_medial(): + assert Triangle(Point(0, 0), Point(1, 0), Point(0, 1)).medial \ + == Triangle(Point(S.Half, 0), Point(S.Half, S.Half), Point(0, S.Half)) + +def test_nine_point_circle(): + assert Triangle(Point(0, 0), Point(1, 0), Point(0, 1)).nine_point_circle \ + == Circle(Point2D(Rational(1, 4), Rational(1, 4)), sqrt(2)/4) + +def test_eulerline(): + assert Triangle(Point(0, 0), Point(1, 0), Point(0, 1)).eulerline \ + == Line(Point2D(0, 0), Point2D(S.Half, S.Half)) + assert Triangle(Point(0, 0), Point(10, 0), Point(5, 5*sqrt(3))).eulerline \ + == Point2D(5, 5*sqrt(3)/3) + assert Triangle(Point(4, -6), Point(4, -1), Point(-3, 3)).eulerline \ + == Line(Point2D(Rational(64, 7), 3), Point2D(Rational(-29, 14), Rational(-7, 2))) + +def test_intersection(): + poly1 = Triangle(Point(0, 0), Point(1, 0), Point(0, 1)) + poly2 = Polygon(Point(0, 1), Point(-5, 0), + Point(0, -4), Point(0, Rational(1, 5)), + Point(S.Half, -0.1), Point(1, 0), Point(0, 1)) + + assert poly1.intersection(poly2) == [Point2D(Rational(1, 3), 0), + Segment(Point(0, Rational(1, 5)), Point(0, 0)), + Segment(Point(1, 0), Point(0, 1))] + assert poly2.intersection(poly1) == [Point(Rational(1, 3), 0), + Segment(Point(0, 0), Point(0, Rational(1, 5))), + Segment(Point(1, 0), Point(0, 1))] + assert poly1.intersection(Point(0, 0)) == [Point(0, 0)] + assert poly1.intersection(Point(-12, -43)) == [] + assert poly2.intersection(Line((-12, 0), (12, 0))) == [Point(-5, 0), + Point(0, 0), Point(Rational(1, 3), 0), Point(1, 0)] + assert poly2.intersection(Line((-12, 12), (12, 12))) == [] + assert poly2.intersection(Ray((-3, 4), (1, 0))) == [Segment(Point(1, 0), + Point(0, 1))] + assert poly2.intersection(Circle((0, -1), 1)) == [Point(0, -2), + Point(0, 0)] + assert poly1.intersection(poly1) == [Segment(Point(0, 0), Point(1, 0)), + Segment(Point(0, 1), Point(0, 0)), Segment(Point(1, 0), Point(0, 1))] + assert poly2.intersection(poly2) == [Segment(Point(-5, 0), Point(0, -4)), + Segment(Point(0, -4), Point(0, Rational(1, 5))), + Segment(Point(0, Rational(1, 5)), Point(S.Half, Rational(-1, 10))), + Segment(Point(0, 1), Point(-5, 0)), + Segment(Point(S.Half, Rational(-1, 10)), Point(1, 0)), + Segment(Point(1, 0), Point(0, 1))] + assert poly2.intersection(Triangle(Point(0, 1), Point(1, 0), Point(-1, 1))) \ + == [Point(Rational(-5, 7), Rational(6, 7)), Segment(Point2D(0, 1), Point(1, 0))] + assert poly1.intersection(RegularPolygon((-12, -15), 3, 3)) == [] + + +def test_parameter_value(): + t = Symbol('t') + sq = Polygon((0, 0), (0, 1), (1, 1), (1, 0)) + assert sq.parameter_value((0.5, 1), t) == {t: Rational(3, 8)} + q = Polygon((0, 0), (2, 1), (2, 4), (4, 0)) + assert q.parameter_value((4, 0), t) == {t: -6 + 3*sqrt(5)} # ~= 0.708 + + raises(ValueError, lambda: sq.parameter_value((5, 6), t)) + raises(ValueError, lambda: sq.parameter_value(Circle(Point(0, 0), 1), t)) + + +def test_issue_12966(): + poly = Polygon(Point(0, 0), Point(0, 10), Point(5, 10), Point(5, 5), + Point(10, 5), Point(10, 0)) + t = Symbol('t') + pt = poly.arbitrary_point(t) + DELTA = 5/poly.perimeter + assert [pt.subs(t, DELTA*i) for i in range(int(1/DELTA))] == [ + Point(0, 0), Point(0, 5), Point(0, 10), Point(5, 10), + Point(5, 5), Point(10, 5), Point(10, 0), Point(5, 0)] + + +def test_second_moment_of_area(): + x, y = symbols('x, y') + # triangle + p1, p2, p3 = [(0, 0), (4, 0), (0, 2)] + p = (0, 0) + # equation of hypotenuse + eq_y = (1-x/4)*2 + I_yy = integrate((x**2) * (integrate(1, (y, 0, eq_y))), (x, 0, 4)) + I_xx = integrate(1 * (integrate(y**2, (y, 0, eq_y))), (x, 0, 4)) + I_xy = integrate(x * (integrate(y, (y, 0, eq_y))), (x, 0, 4)) + + triangle = Polygon(p1, p2, p3) + + assert (I_xx - triangle.second_moment_of_area(p)[0]) == 0 + assert (I_yy - triangle.second_moment_of_area(p)[1]) == 0 + assert (I_xy - triangle.second_moment_of_area(p)[2]) == 0 + + # rectangle + p1, p2, p3, p4=[(0, 0), (4, 0), (4, 2), (0, 2)] + I_yy = integrate((x**2) * integrate(1, (y, 0, 2)), (x, 0, 4)) + I_xx = integrate(1 * integrate(y**2, (y, 0, 2)), (x, 0, 4)) + I_xy = integrate(x * integrate(y, (y, 0, 2)), (x, 0, 4)) + + rectangle = Polygon(p1, p2, p3, p4) + + assert (I_xx - rectangle.second_moment_of_area(p)[0]) == 0 + assert (I_yy - rectangle.second_moment_of_area(p)[1]) == 0 + assert (I_xy - rectangle.second_moment_of_area(p)[2]) == 0 + + + r = RegularPolygon(Point(0, 0), 5, 3) + assert r.second_moment_of_area() == (1875*sqrt(3)/S(32), 1875*sqrt(3)/S(32), 0) + + +def test_first_moment(): + a, b = symbols('a, b', positive=True) + # rectangle + p1 = Polygon((0, 0), (a, 0), (a, b), (0, b)) + assert p1.first_moment_of_area() == (a*b**2/8, a**2*b/8) + assert p1.first_moment_of_area((a/3, b/4)) == (-3*a*b**2/32, -a**2*b/9) + + p1 = Polygon((0, 0), (40, 0), (40, 30), (0, 30)) + assert p1.first_moment_of_area() == (4500, 6000) + + # triangle + p2 = Polygon((0, 0), (a, 0), (a/2, b)) + assert p2.first_moment_of_area() == (4*a*b**2/81, a**2*b/24) + assert p2.first_moment_of_area((a/8, b/6)) == (-25*a*b**2/648, -5*a**2*b/768) + + p2 = Polygon((0, 0), (12, 0), (12, 30)) + assert p2.first_moment_of_area() == (S(1600)/3, -S(640)/3) + + +def test_section_modulus_and_polar_second_moment_of_area(): + a, b = symbols('a, b', positive=True) + x, y = symbols('x, y') + rectangle = Polygon((0, b), (0, 0), (a, 0), (a, b)) + assert rectangle.section_modulus(Point(x, y)) == (a*b**3/12/(-b/2 + y), a**3*b/12/(-a/2 + x)) + assert rectangle.polar_second_moment_of_area() == a**3*b/12 + a*b**3/12 + + convex = RegularPolygon((0, 0), 1, 6) + assert convex.section_modulus() == (Rational(5, 8), sqrt(3)*Rational(5, 16)) + assert convex.polar_second_moment_of_area() == 5*sqrt(3)/S(8) + + concave = Polygon((0, 0), (1, 8), (3, 4), (4, 6), (7, 1)) + assert concave.section_modulus() == (Rational(-6371, 429), Rational(-9778, 519)) + assert concave.polar_second_moment_of_area() == Rational(-38669, 252) + + +def test_cut_section(): + # concave polygon + p = Polygon((-1, -1), (1, Rational(5, 2)), (2, 1), (3, Rational(5, 2)), (4, 2), (5, 3), (-1, 3)) + l = Line((0, 0), (Rational(9, 2), 3)) + p1 = p.cut_section(l)[0] + p2 = p.cut_section(l)[1] + assert p1 == Polygon( + Point2D(Rational(-9, 13), Rational(-6, 13)), Point2D(1, Rational(5, 2)), Point2D(Rational(24, 13), Rational(16, 13)), + Point2D(Rational(12, 5), Rational(8, 5)), Point2D(3, Rational(5, 2)), Point2D(Rational(24, 7), Rational(16, 7)), + Point2D(Rational(9, 2), 3), Point2D(-1, 3), Point2D(-1, Rational(-2, 3))) + assert p2 == Polygon(Point2D(-1, -1), Point2D(Rational(-9, 13), Rational(-6, 13)), Point2D(Rational(24, 13), Rational(16, 13)), + Point2D(2, 1), Point2D(Rational(12, 5), Rational(8, 5)), Point2D(Rational(24, 7), Rational(16, 7)), Point2D(4, 2), Point2D(5, 3), + Point2D(Rational(9, 2), 3), Point2D(-1, Rational(-2, 3))) + + # convex polygon + p = RegularPolygon(Point2D(0, 0), 6, 6) + s = p.cut_section(Line((0, 0), slope=1)) + assert s[0] == Polygon(Point2D(-3*sqrt(3) + 9, -3*sqrt(3) + 9), Point2D(3, 3*sqrt(3)), + Point2D(-3, 3*sqrt(3)), Point2D(-6, 0), Point2D(-9 + 3*sqrt(3), -9 + 3*sqrt(3))) + assert s[1] == Polygon(Point2D(6, 0), Point2D(-3*sqrt(3) + 9, -3*sqrt(3) + 9), + Point2D(-9 + 3*sqrt(3), -9 + 3*sqrt(3)), Point2D(-3, -3*sqrt(3)), Point2D(3, -3*sqrt(3))) + + # case where line does not intersects but coincides with the edge of polygon + a, b = 20, 10 + t1, t2, t3, t4 = [(0, b), (0, 0), (a, 0), (a, b)] + p = Polygon(t1, t2, t3, t4) + p1, p2 = p.cut_section(Line((0, b), slope=0)) + assert p1 == None + assert p2 == Polygon(Point2D(0, 10), Point2D(0, 0), Point2D(20, 0), Point2D(20, 10)) + + p3, p4 = p.cut_section(Line((0, 0), slope=0)) + assert p3 == Polygon(Point2D(0, 10), Point2D(0, 0), Point2D(20, 0), Point2D(20, 10)) + assert p4 == None + + # case where the line does not intersect with a polygon at all + raises(ValueError, lambda: p.cut_section(Line((0, a), slope=0))) + +def test_type_of_triangle(): + # Isoceles triangle + p1 = Polygon(Point(0, 0), Point(5, 0), Point(2, 4)) + assert p1.is_isosceles() == True + assert p1.is_scalene() == False + assert p1.is_equilateral() == False + + # Scalene triangle + p2 = Polygon (Point(0, 0), Point(0, 2), Point(4, 0)) + assert p2.is_isosceles() == False + assert p2.is_scalene() == True + assert p2.is_equilateral() == False + + # Equilateral triangle + p3 = Polygon(Point(0, 0), Point(6, 0), Point(3, sqrt(27))) + assert p3.is_isosceles() == True + assert p3.is_scalene() == False + assert p3.is_equilateral() == True + +def test_do_poly_distance(): + # Non-intersecting polygons + square1 = Polygon (Point(0, 0), Point(0, 1), Point(1, 1), Point(1, 0)) + triangle1 = Polygon(Point(1, 2), Point(2, 2), Point(2, 1)) + assert square1._do_poly_distance(triangle1) == sqrt(2)/2 + + # Polygons which sides intersect + square2 = Polygon(Point(1, 0), Point(2, 0), Point(2, 1), Point(1, 1)) + with warns(UserWarning, \ + match="Polygons may intersect producing erroneous output", test_stacklevel=False): + assert square1._do_poly_distance(square2) == 0 + + # Polygons which bodies intersect + triangle2 = Polygon(Point(0, -1), Point(2, -1), Point(S.Half, S.Half)) + with warns(UserWarning, \ + match="Polygons may intersect producing erroneous output", test_stacklevel=False): + assert triangle2._do_poly_distance(square1) == 0 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_util.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_util.py new file mode 100644 index 0000000000000000000000000000000000000000..da52a795a9383c6438ca06303e8ae6506dccdc65 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/geometry/tests/test_util.py @@ -0,0 +1,170 @@ +import pytest +from sympy.core.numbers import Float +from sympy.core.function import (Derivative, Function) +from sympy.core.singleton import S +from sympy.core.symbol import Symbol +from sympy.functions import exp, cos, sin, tan, cosh, sinh +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.geometry import Point, Point2D, Line, Polygon, Segment, convex_hull,\ + intersection, centroid, Point3D, Line3D, Ray, Ellipse +from sympy.geometry.util import idiff, closest_points, farthest_points, _ordered_points, are_coplanar +from sympy.solvers.solvers import solve +from sympy.testing.pytest import raises + + +def test_idiff(): + x = Symbol('x', real=True) + y = Symbol('y', real=True) + t = Symbol('t', real=True) + f = Function('f') + g = Function('g') + # the use of idiff in ellipse also provides coverage + circ = x**2 + y**2 - 4 + ans = -3*x*(x**2/y**2 + 1)/y**3 + assert ans == idiff(circ, y, x, 3), idiff(circ, y, x, 3) + assert ans == idiff(circ, [y], x, 3) + assert idiff(circ, y, x, 3) == ans + explicit = 12*x/sqrt(-x**2 + 4)**5 + assert ans.subs(y, solve(circ, y)[0]).equals(explicit) + assert True in [sol.diff(x, 3).equals(explicit) for sol in solve(circ, y)] + assert idiff(x + t + y, [y, t], x) == -Derivative(t, x) - 1 + assert idiff(f(x) * exp(f(x)) - x * exp(x), f(x), x) == (x + 1)*exp(x)*exp(-f(x))/(f(x) + 1) + assert idiff(f(x) - y * exp(x), [f(x), y], x) == (y + Derivative(y, x))*exp(x) + assert idiff(f(x) - y * exp(x), [y, f(x)], x) == -y + Derivative(f(x), x)*exp(-x) + assert idiff(f(x) - g(x), [f(x), g(x)], x) == Derivative(g(x), x) + # this should be fast + fxy = y - (-10*(-sin(x) + 1/x)**2 + tan(x)**2 + 2*cosh(x/10)) + assert idiff(fxy, y, x) == -20*sin(x)*cos(x) + 2*tan(x)**3 + \ + 2*tan(x) + sinh(x/10)/5 + 20*cos(x)/x - 20*sin(x)/x**2 + 20/x**3 + + +def test_intersection(): + assert intersection(Point(0, 0)) == [] + raises(TypeError, lambda: intersection(Point(0, 0), 3)) + assert intersection( + Segment((0, 0), (2, 0)), + Segment((-1, 0), (1, 0)), + Line((0, 0), (0, 1)), pairwise=True) == [ + Point(0, 0), Segment((0, 0), (1, 0))] + assert intersection( + Line((0, 0), (0, 1)), + Segment((0, 0), (2, 0)), + Segment((-1, 0), (1, 0)), pairwise=True) == [ + Point(0, 0), Segment((0, 0), (1, 0))] + assert intersection( + Line((0, 0), (0, 1)), + Segment((0, 0), (2, 0)), + Segment((-1, 0), (1, 0)), + Line((0, 0), slope=1), pairwise=True) == [ + Point(0, 0), Segment((0, 0), (1, 0))] + R = 4.0 + c = intersection( + Ray(Point2D(0.001, -1), + Point2D(0.0008, -1.7)), + Ellipse(center=Point2D(0, 0), hradius=R, vradius=2.0), pairwise=True)[0].coordinates + assert c == pytest.approx( + Point2D(0.000714285723396502, -1.99999996811224, evaluate=False).coordinates) + # check this is responds to a lower precision parameter + R = Float(4, 5) + c2 = intersection( + Ray(Point2D(0.001, -1), + Point2D(0.0008, -1.7)), + Ellipse(center=Point2D(0, 0), hradius=R, vradius=2.0), pairwise=True)[0].coordinates + assert c2 == pytest.approx( + Point2D(0.000714285723396502, -1.99999996811224, evaluate=False).coordinates) + assert c[0]._prec == 53 + assert c2[0]._prec == 20 + + +def test_convex_hull(): + raises(TypeError, lambda: convex_hull(Point(0, 0), 3)) + points = [(1, -1), (1, -2), (3, -1), (-5, -2), (15, -4)] + assert convex_hull(*points, **{"polygon": False}) == ( + [Point2D(-5, -2), Point2D(1, -1), Point2D(3, -1), Point2D(15, -4)], + [Point2D(-5, -2), Point2D(15, -4)]) + + +def test_centroid(): + p = Polygon((0, 0), (10, 0), (10, 10)) + q = p.translate(0, 20) + assert centroid(p, q) == Point(20, 40)/3 + p = Segment((0, 0), (2, 0)) + q = Segment((0, 0), (2, 2)) + assert centroid(p, q) == Point(1, -sqrt(2) + 2) + assert centroid(Point(0, 0), Point(2, 0)) == Point(2, 0)/2 + assert centroid(Point(0, 0), Point(0, 0), Point(2, 0)) == Point(2, 0)/3 + + +def test_farthest_points_closest_points(): + from sympy.core.random import randint + from sympy.utilities.iterables import subsets + + for how in (min, max): + if how == min: + func = closest_points + else: + func = farthest_points + + raises(ValueError, lambda: func(Point2D(0, 0), Point2D(0, 0))) + + # 3rd pt dx is close and pt is closer to 1st pt + p1 = [Point2D(0, 0), Point2D(3, 0), Point2D(1, 1)] + # 3rd pt dx is close and pt is closer to 2nd pt + p2 = [Point2D(0, 0), Point2D(3, 0), Point2D(2, 1)] + # 3rd pt dx is close and but pt is not closer + p3 = [Point2D(0, 0), Point2D(3, 0), Point2D(1, 10)] + # 3rd pt dx is not closer and it's closer to 2nd pt + p4 = [Point2D(0, 0), Point2D(3, 0), Point2D(4, 0)] + # 3rd pt dx is not closer and it's closer to 1st pt + p5 = [Point2D(0, 0), Point2D(3, 0), Point2D(-1, 0)] + # duplicate point doesn't affect outcome + dup = [Point2D(0, 0), Point2D(3, 0), Point2D(3, 0), Point2D(-1, 0)] + # symbolic + x = Symbol('x', positive=True) + s = [Point2D(a) for a in ((x, 1), (x + 3, 2), (x + 2, 2))] + + for points in (p1, p2, p3, p4, p5, dup, s): + d = how(i.distance(j) for i, j in subsets(set(points), 2)) + ans = a, b = list(func(*points))[0] + assert a.distance(b) == d + assert ans == _ordered_points(ans) + + # if the following ever fails, the above tests were not sufficient + # and the logical error in the routine should be fixed + points = set() + while len(points) != 7: + points.add(Point2D(randint(1, 100), randint(1, 100))) + points = list(points) + d = how(i.distance(j) for i, j in subsets(points, 2)) + ans = a, b = list(func(*points))[0] + assert a.distance(b) == d + assert ans == _ordered_points(ans) + + # equidistant points + a, b, c = ( + Point2D(0, 0), Point2D(1, 0), Point2D(S.Half, sqrt(3)/2)) + ans = {_ordered_points((i, j)) + for i, j in subsets((a, b, c), 2)} + assert closest_points(b, c, a) == ans + assert farthest_points(b, c, a) == ans + + # unique to farthest + points = [(1, 1), (1, 2), (3, 1), (-5, 2), (15, 4)] + assert farthest_points(*points) == { + (Point2D(-5, 2), Point2D(15, 4))} + points = [(1, -1), (1, -2), (3, -1), (-5, -2), (15, -4)] + assert farthest_points(*points) == { + (Point2D(-5, -2), Point2D(15, -4))} + assert farthest_points((1, 1), (0, 0)) == { + (Point2D(0, 0), Point2D(1, 1))} + raises(ValueError, lambda: farthest_points((1, 1))) + + +def test_are_coplanar(): + a = Line3D(Point3D(5, 0, 0), Point3D(1, -1, 1)) + b = Line3D(Point3D(0, -2, 0), Point3D(3, 1, 1)) + c = Line3D(Point3D(0, -1, 0), Point3D(5, -1, 9)) + d = Line(Point2D(0, 3), Point2D(1, 5)) + + assert are_coplanar(a, b, c) == False + assert are_coplanar(a, d) == False diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b6549221dcfa4ab6889313e4a4688b10f8c5f45e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/__pycache__/holonomicerrors.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/__pycache__/holonomicerrors.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..09ff553d42166c50917007bf0903bbe0ef77ebe2 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/__pycache__/holonomicerrors.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/__pycache__/numerical.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/__pycache__/numerical.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cb5cbf10cc7f220ab57a596e80f9cc6b038bfa29 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/__pycache__/numerical.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/__pycache__/recurrence.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/__pycache__/recurrence.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a4076016427a7508f824d0fca890c1d65d4aed77 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/__pycache__/recurrence.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..08ec1ba176866d563c175c708e6dbfb7bac6a395 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/tests/__pycache__/test_holonomic.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/tests/__pycache__/test_holonomic.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..33a288f8982c48dd88134fb577df48f80f9d716e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/tests/__pycache__/test_holonomic.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/tests/__pycache__/test_recurrence.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/tests/__pycache__/test_recurrence.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0db8d9ab4a95f4c4a1ff63e41efe89f192a56474 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/tests/__pycache__/test_recurrence.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/tests/test_holonomic.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/tests/test_holonomic.py new file mode 100644 index 0000000000000000000000000000000000000000..49956419e917b3bc81a163d29862c539f33f6284 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/tests/test_holonomic.py @@ -0,0 +1,851 @@ +from sympy.holonomic import (DifferentialOperator, HolonomicFunction, + DifferentialOperators, from_hyper, + from_meijerg, expr_to_holonomic) +from sympy.holonomic.recurrence import RecurrenceOperators, HolonomicSequence +from sympy.core import EulerGamma +from sympy.core.numbers import (I, Rational, pi) +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.hyperbolic import (asinh, cosh) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.functions.special.bessel import besselj +from sympy.functions.special.beta_functions import beta +from sympy.functions.special.error_functions import (Ci, Si, erf, erfc) +from sympy.functions.special.gamma_functions import gamma +from sympy.functions.special.hyper import (hyper, meijerg) +from sympy.printing.str import sstr +from sympy.series.order import O +from sympy.simplify.hyperexpand import hyperexpand +from sympy.polys.domains.integerring import ZZ +from sympy.polys.domains.rationalfield import QQ +from sympy.polys.domains.realfield import RR + + +def test_DifferentialOperator(): + x = symbols('x') + R, Dx = DifferentialOperators(QQ.old_poly_ring(x), 'Dx') + assert Dx == R.derivative_operator + assert Dx == DifferentialOperator([R.base.zero, R.base.one], R) + assert x * Dx + x**2 * Dx**2 == DifferentialOperator([0, x, x**2], R) + assert (x**2 + 1) + Dx + x * \ + Dx**5 == DifferentialOperator([x**2 + 1, 1, 0, 0, 0, x], R) + assert (x * Dx + x**2 + 1 - Dx * (x**3 + x))**3 == (-48 * x**6) + \ + (-57 * x**7) * Dx + (-15 * x**8) * Dx**2 + (-x**9) * Dx**3 + p = (x * Dx**2 + (x**2 + 3) * Dx**5) * (Dx + x**2) + q = (2 * x) + (4 * x**2) * Dx + (x**3) * Dx**2 + \ + (20 * x**2 + x + 60) * Dx**3 + (10 * x**3 + 30 * x) * Dx**4 + \ + (x**4 + 3 * x**2) * Dx**5 + (x**2 + 3) * Dx**6 + assert p == q + + +def test_HolonomicFunction_addition(): + x = symbols('x') + R, Dx = DifferentialOperators(ZZ.old_poly_ring(x), 'Dx') + p = HolonomicFunction(Dx**2 * x, x) + q = HolonomicFunction((2) * Dx + (x) * Dx**2, x) + assert p == q + p = HolonomicFunction(x * Dx + 1, x) + q = HolonomicFunction(Dx + 1, x) + r = HolonomicFunction((x - 2) + (x**2 - 2) * Dx + (x**2 - x) * Dx**2, x) + assert p + q == r + p = HolonomicFunction(x * Dx + Dx**2 * (x**2 + 2), x) + q = HolonomicFunction(Dx - 3, x) + r = HolonomicFunction((-54 * x**2 - 126 * x - 150) + (-135 * x**3 - 252 * x**2 - 270 * x + 140) * Dx +\ + (-27 * x**4 - 24 * x**2 + 14 * x - 150) * Dx**2 + \ + (9 * x**4 + 15 * x**3 + 38 * x**2 + 30 * x +40) * Dx**3, x) + assert p + q == r + p = HolonomicFunction(Dx**5 - 1, x) + q = HolonomicFunction(x**3 + Dx, x) + r = HolonomicFunction((-x**18 + 45*x**14 - 525*x**10 + 1575*x**6 - x**3 - 630*x**2) + \ + (-x**15 + 30*x**11 - 195*x**7 + 210*x**3 - 1)*Dx + (x**18 - 45*x**14 + 525*x**10 - \ + 1575*x**6 + x**3 + 630*x**2)*Dx**5 + (x**15 - 30*x**11 + 195*x**7 - 210*x**3 + \ + 1)*Dx**6, x) + assert p+q == r + + p = x**2 + 3*x + 8 + q = x**3 - 7*x + 5 + p = p*Dx - p.diff() + q = q*Dx - q.diff() + r = HolonomicFunction(p, x) + HolonomicFunction(q, x) + s = HolonomicFunction((6*x**2 + 18*x + 14) + (-4*x**3 - 18*x**2 - 62*x + 10)*Dx +\ + (x**4 + 6*x**3 + 31*x**2 - 10*x - 71)*Dx**2, x) + assert r == s + + +def test_HolonomicFunction_multiplication(): + x = symbols('x') + R, Dx = DifferentialOperators(ZZ.old_poly_ring(x), 'Dx') + p = HolonomicFunction(Dx+x+x*Dx**2, x) + q = HolonomicFunction(x*Dx+Dx*x+Dx**2, x) + r = HolonomicFunction((8*x**6 + 4*x**4 + 6*x**2 + 3) + (24*x**5 - 4*x**3 + 24*x)*Dx + \ + (8*x**6 + 20*x**4 + 12*x**2 + 2)*Dx**2 + (8*x**5 + 4*x**3 + 4*x)*Dx**3 + \ + (2*x**4 + x**2)*Dx**4, x) + assert p*q == r + p = HolonomicFunction(Dx**2+1, x) + q = HolonomicFunction(Dx-1, x) + r = HolonomicFunction((2) + (-2)*Dx + (1)*Dx**2, x) + assert p*q == r + p = HolonomicFunction(Dx**2+1+x+Dx, x) + q = HolonomicFunction((Dx*x-1)**2, x) + r = HolonomicFunction((4*x**7 + 11*x**6 + 16*x**5 + 4*x**4 - 6*x**3 - 7*x**2 - 8*x - 2) + \ + (8*x**6 + 26*x**5 + 24*x**4 - 3*x**3 - 11*x**2 - 6*x - 2)*Dx + \ + (8*x**6 + 18*x**5 + 15*x**4 - 3*x**3 - 6*x**2 - 6*x - 2)*Dx**2 + (8*x**5 + \ + 10*x**4 + 6*x**3 - 2*x**2 - 4*x)*Dx**3 + (4*x**5 + 3*x**4 - x**2)*Dx**4, x) + assert p*q == r + p = HolonomicFunction(x*Dx**2-1, x) + q = HolonomicFunction(Dx*x-x, x) + r = HolonomicFunction((x - 3) + (-2*x + 2)*Dx + (x)*Dx**2, x) + assert p*q == r + + +def test_HolonomicFunction_power(): + x = symbols('x') + R, Dx = DifferentialOperators(ZZ.old_poly_ring(x), 'Dx') + p = HolonomicFunction(Dx+x+x*Dx**2, x) + a = HolonomicFunction(Dx, x) + for n in range(10): + assert a == p**n + a *= p + + +def test_addition_initial_condition(): + x = symbols('x') + R, Dx = DifferentialOperators(QQ.old_poly_ring(x), 'Dx') + p = HolonomicFunction(Dx-1, x, 0, [3]) + q = HolonomicFunction(Dx**2+1, x, 0, [1, 0]) + r = HolonomicFunction(-1 + Dx - Dx**2 + Dx**3, x, 0, [4, 3, 2]) + assert p + q == r + p = HolonomicFunction(Dx - x + Dx**2, x, 0, [1, 2]) + q = HolonomicFunction(Dx**2 + x, x, 0, [1, 0]) + r = HolonomicFunction((-x**4 - x**3/4 - x**2 + Rational(1, 4)) + (x**3 + x**2/4 + x*Rational(3, 4) + 1)*Dx + \ + (x*Rational(-3, 2) + Rational(7, 4))*Dx**2 + (x**2 - x*Rational(7, 4) + Rational(1, 4))*Dx**3 + (x**2 + x/4 + S.Half)*Dx**4, x, 0, [2, 2, -2, 2]) + assert p + q == r + p = HolonomicFunction(Dx**2 + 4*x*Dx + x**2, x, 0, [3, 4]) + q = HolonomicFunction(Dx**2 + 1, x, 0, [1, 1]) + r = HolonomicFunction((x**6 + 2*x**4 - 5*x**2 - 6) + (4*x**5 + 36*x**3 - 32*x)*Dx + \ + (x**6 + 3*x**4 + 5*x**2 - 9)*Dx**2 + (4*x**5 + 36*x**3 - 32*x)*Dx**3 + (x**4 + \ + 10*x**2 - 3)*Dx**4, x, 0, [4, 5, -1, -17]) + assert p + q == r + q = HolonomicFunction(Dx**3 + x, x, 2, [3, 0, 1]) + p = HolonomicFunction(Dx - 1, x, 2, [1]) + r = HolonomicFunction((-x**2 - x + 1) + (x**2 + x)*Dx + (-x - 2)*Dx**3 + \ + (x + 1)*Dx**4, x, 2, [4, 1, 2, -5 ]) + assert p + q == r + p = expr_to_holonomic(sin(x)) + q = expr_to_holonomic(1/x, x0=1) + r = HolonomicFunction((x**2 + 6) + (x**3 + 2*x)*Dx + (x**2 + 6)*Dx**2 + (x**3 + 2*x)*Dx**3, \ + x, 1, [sin(1) + 1, -1 + cos(1), -sin(1) + 2]) + assert p + q == r + C_1 = symbols('C_1') + p = expr_to_holonomic(sqrt(x)) + q = expr_to_holonomic(sqrt(x**2-x)) + r = (p + q).to_expr().subs(C_1, -I/2).expand() + assert r == I*sqrt(x)*sqrt(-x + 1) + sqrt(x) + + +def test_multiplication_initial_condition(): + x = symbols('x') + R, Dx = DifferentialOperators(QQ.old_poly_ring(x), 'Dx') + p = HolonomicFunction(Dx**2 + x*Dx - 1, x, 0, [3, 1]) + q = HolonomicFunction(Dx**2 + 1, x, 0, [1, 1]) + r = HolonomicFunction((x**4 + 14*x**2 + 60) + 4*x*Dx + (x**4 + 9*x**2 + 20)*Dx**2 + \ + (2*x**3 + 18*x)*Dx**3 + (x**2 + 10)*Dx**4, x, 0, [3, 4, 2, 3]) + assert p * q == r + p = HolonomicFunction(Dx**2 + x, x, 0, [1, 0]) + q = HolonomicFunction(Dx**3 - x**2, x, 0, [3, 3, 3]) + r = HolonomicFunction((x**8 - 37*x**7/27 - 10*x**6/27 - 164*x**5/9 - 184*x**4/9 + \ + 160*x**3/27 + 404*x**2/9 + 8*x + Rational(40, 3)) + (6*x**7 - 128*x**6/9 - 98*x**5/9 - 28*x**4/9 + \ + 8*x**3/9 + 28*x**2 + x*Rational(40, 9) - 40)*Dx + (3*x**6 - 82*x**5/9 + 76*x**4/9 + 4*x**3/3 + \ + 220*x**2/9 - x*Rational(80, 3))*Dx**2 + (-2*x**6 + 128*x**5/27 - 2*x**4/3 -80*x**2/9 + Rational(200, 9))*Dx**3 + \ + (3*x**5 - 64*x**4/9 - 28*x**3/9 + 6*x**2 - x*Rational(20, 9) - Rational(20, 3))*Dx**4 + (-4*x**3 + 64*x**2/9 + \ + x*Rational(8, 3))*Dx**5 + (x**4 - 64*x**3/27 - 4*x**2/3 + Rational(20, 9))*Dx**6, x, 0, [3, 3, 3, -3, -12, -24]) + assert p * q == r + p = HolonomicFunction(Dx - 1, x, 0, [2]) + q = HolonomicFunction(Dx**2 + 1, x, 0, [0, 1]) + r = HolonomicFunction(2 -2*Dx + Dx**2, x, 0, [0, 2]) + assert p * q == r + q = HolonomicFunction(x*Dx**2 + 1 + 2*Dx, x, 0,[0, 1]) + r = HolonomicFunction((x - 1) + (-2*x + 2)*Dx + x*Dx**2, x, 0, [0, 2]) + assert p * q == r + p = HolonomicFunction(Dx**2 - 1, x, 0, [1, 3]) + q = HolonomicFunction(Dx**3 + 1, x, 0, [1, 2, 1]) + r = HolonomicFunction(6*Dx + 3*Dx**2 + 2*Dx**3 - 3*Dx**4 + Dx**6, x, 0, [1, 5, 14, 17, 17, 2]) + assert p * q == r + p = expr_to_holonomic(sin(x)) + q = expr_to_holonomic(1/x, x0=1) + r = HolonomicFunction(x + 2*Dx + x*Dx**2, x, 1, [sin(1), -sin(1) + cos(1)]) + assert p * q == r + p = expr_to_holonomic(sqrt(x)) + q = expr_to_holonomic(sqrt(x**2-x)) + r = (p * q).to_expr() + assert r == I*x*sqrt(-x + 1) + + +def test_HolonomicFunction_composition(): + x = symbols('x') + R, Dx = DifferentialOperators(ZZ.old_poly_ring(x), 'Dx') + p = HolonomicFunction(Dx-1, x).composition(x**2+x) + r = HolonomicFunction((-2*x - 1) + Dx, x) + assert p == r + p = HolonomicFunction(Dx**2+1, x).composition(x**5+x**2+1) + r = HolonomicFunction((125*x**12 + 150*x**9 + 60*x**6 + 8*x**3) + (-20*x**3 - 2)*Dx + \ + (5*x**4 + 2*x)*Dx**2, x) + assert p == r + p = HolonomicFunction(Dx**2*x+x, x).composition(2*x**3+x**2+1) + r = HolonomicFunction((216*x**9 + 324*x**8 + 180*x**7 + 152*x**6 + 112*x**5 + \ + 36*x**4 + 4*x**3) + (24*x**4 + 16*x**3 + 3*x**2 - 6*x - 1)*Dx + (6*x**5 + 5*x**4 + \ + x**3 + 3*x**2 + x)*Dx**2, x) + assert p == r + p = HolonomicFunction(Dx**2+1, x).composition(1-x**2) + r = HolonomicFunction((4*x**3) - Dx + x*Dx**2, x) + assert p == r + p = HolonomicFunction(Dx**2+1, x).composition(x - 2/(x**2 + 1)) + r = HolonomicFunction((x**12 + 6*x**10 + 12*x**9 + 15*x**8 + 48*x**7 + 68*x**6 + \ + 72*x**5 + 111*x**4 + 112*x**3 + 54*x**2 + 12*x + 1) + (12*x**8 + 32*x**6 + \ + 24*x**4 - 4)*Dx + (x**12 + 6*x**10 + 4*x**9 + 15*x**8 + 16*x**7 + 20*x**6 + 24*x**5+ \ + 15*x**4 + 16*x**3 + 6*x**2 + 4*x + 1)*Dx**2, x) + assert p == r + + +def test_from_hyper(): + x = symbols('x') + R, Dx = DifferentialOperators(QQ.old_poly_ring(x), 'Dx') + p = hyper([1, 1], [Rational(3, 2)], x**2/4) + q = HolonomicFunction((4*x) + (5*x**2 - 8)*Dx + (x**3 - 4*x)*Dx**2, x, 1, [2*sqrt(3)*pi/9, -4*sqrt(3)*pi/27 + Rational(4, 3)]) + r = from_hyper(p) + assert r == q + p = from_hyper(hyper([1], [Rational(3, 2)], x**2/4)) + q = HolonomicFunction(-x + (-x**2/2 + 2)*Dx + x*Dx**2, x) + # x0 = 1 + y0 = '[sqrt(pi)*exp(1/4)*erf(1/2), -sqrt(pi)*exp(1/4)*erf(1/2)/2 + 1]' + assert sstr(p.y0) == y0 + assert q.annihilator == p.annihilator + + +def test_from_meijerg(): + x = symbols('x') + R, Dx = DifferentialOperators(QQ.old_poly_ring(x), 'Dx') + p = from_meijerg(meijerg(([], [Rational(3, 2)]), ([S.Half], [S.Half, 1]), x)) + q = HolonomicFunction(x/2 - Rational(1, 4) + (-x**2 + x/4)*Dx + x**2*Dx**2 + x**3*Dx**3, x, 1, \ + [1/sqrt(pi), 1/(2*sqrt(pi)), -1/(4*sqrt(pi))]) + assert p == q + p = from_meijerg(meijerg(([], []), ([0], []), x)) + q = HolonomicFunction(1 + Dx, x, 0, [1]) + assert p == q + p = from_meijerg(meijerg(([1], []), ([S.Half], [0]), x)) + q = HolonomicFunction((x + S.Half)*Dx + x*Dx**2, x, 1, [sqrt(pi)*erf(1), exp(-1)]) + assert p == q + p = from_meijerg(meijerg(([0], [1]), ([0], []), 2*x**2)) + q = HolonomicFunction((3*x**2 - 1)*Dx + x**3*Dx**2, x, 1, [-exp(Rational(-1, 2)) + 1, -exp(Rational(-1, 2))]) + assert p == q + + +def test_to_Sequence(): + x = symbols('x') + R, Dx = DifferentialOperators(ZZ.old_poly_ring(x), 'Dx') + n = symbols('n', integer=True) + _, Sn = RecurrenceOperators(ZZ.old_poly_ring(n), 'Sn') + p = HolonomicFunction(x**2*Dx**4 + x + Dx, x).to_sequence() + q = [(HolonomicSequence(1 + (n + 2)*Sn**2 + (n**4 + 6*n**3 + 11*n**2 + 6*n)*Sn**3), 0, 1)] + assert p == q + p = HolonomicFunction(x**2*Dx**4 + x**3 + Dx**2, x).to_sequence() + q = [(HolonomicSequence(1 + (n**4 + 14*n**3 + 72*n**2 + 163*n + 140)*Sn**5), 0, 0)] + assert p == q + p = HolonomicFunction(x**3*Dx**4 + 1 + Dx**2, x).to_sequence() + q = [(HolonomicSequence(1 + (n**4 - 2*n**3 - n**2 + 2*n)*Sn + (n**2 + 3*n + 2)*Sn**2), 0, 0)] + assert p == q + p = HolonomicFunction(3*x**3*Dx**4 + 2*x*Dx + x*Dx**3, x).to_sequence() + q = [(HolonomicSequence(2*n + (3*n**4 - 6*n**3 - 3*n**2 + 6*n)*Sn + (n**3 + 3*n**2 + 2*n)*Sn**2), 0, 1)] + assert p == q + + +def test_to_Sequence_Initial_Coniditons(): + x = symbols('x') + R, Dx = DifferentialOperators(QQ.old_poly_ring(x), 'Dx') + n = symbols('n', integer=True) + _, Sn = RecurrenceOperators(QQ.old_poly_ring(n), 'Sn') + p = HolonomicFunction(Dx - 1, x, 0, [1]).to_sequence() + q = [(HolonomicSequence(-1 + (n + 1)*Sn, 1), 0)] + assert p == q + p = HolonomicFunction(Dx**2 + 1, x, 0, [0, 1]).to_sequence() + q = [(HolonomicSequence(1 + (n**2 + 3*n + 2)*Sn**2, [0, 1]), 0)] + assert p == q + p = HolonomicFunction(Dx**2 + 1 + x**3*Dx, x, 0, [2, 3]).to_sequence() + q = [(HolonomicSequence(n + Sn**2 + (n**2 + 7*n + 12)*Sn**4, [2, 3, -1, Rational(-1, 2), Rational(1, 12)]), 1)] + assert p == q + p = HolonomicFunction(x**3*Dx**5 + 1 + Dx, x).to_sequence() + q = [(HolonomicSequence(1 + (n + 1)*Sn + (n**5 - 5*n**3 + 4*n)*Sn**2), 0, 3)] + assert p == q + C_0, C_1, C_2, C_3 = symbols('C_0, C_1, C_2, C_3') + p = expr_to_holonomic(log(1+x**2)) + q = [(HolonomicSequence(n**2 + (n**2 + 2*n)*Sn**2, [0, 0, C_2]), 0, 1)] + assert p.to_sequence() == q + p = p.diff() + q = [(HolonomicSequence((n + 2) + (n + 2)*Sn**2, [C_0, 0]), 1, 0)] + assert p.to_sequence() == q + p = expr_to_holonomic(erf(x) + x).to_sequence() + q = [(HolonomicSequence((2*n**2 - 2*n) + (n**3 + 2*n**2 - n - 2)*Sn**2, [0, 1 + 2/sqrt(pi), 0, C_3]), 0, 2)] + assert p == q + +def test_series(): + x = symbols('x') + R, Dx = DifferentialOperators(ZZ.old_poly_ring(x), 'Dx') + p = HolonomicFunction(Dx**2 + 2*x*Dx, x, 0, [0, 1]).series(n=10) + q = x - x**3/3 + x**5/10 - x**7/42 + x**9/216 + O(x**10) + assert p == q + p = HolonomicFunction(Dx - 1, x).composition(x**2, 0, [1]) # e^(x**2) + q = HolonomicFunction(Dx**2 + 1, x, 0, [1, 0]) # cos(x) + r = (p * q).series(n=10) # expansion of cos(x) * exp(x**2) + s = 1 + x**2/2 + x**4/24 - 31*x**6/720 - 179*x**8/8064 + O(x**10) + assert r == s + t = HolonomicFunction((1 + x)*Dx**2 + Dx, x, 0, [0, 1]) # log(1 + x) + r = (p * t + q).series(n=10) + s = 1 + x - x**2 + 4*x**3/3 - 17*x**4/24 + 31*x**5/30 - 481*x**6/720 +\ + 71*x**7/105 - 20159*x**8/40320 + 379*x**9/840 + O(x**10) + assert r == s + p = HolonomicFunction((6+6*x-3*x**2) - (10*x-3*x**2-3*x**3)*Dx + \ + (4-6*x**3+2*x**4)*Dx**2, x, 0, [0, 1]).series(n=7) + q = x + x**3/6 - 3*x**4/16 + x**5/20 - 23*x**6/960 + O(x**7) + assert p == q + p = HolonomicFunction((6+6*x-3*x**2) - (10*x-3*x**2-3*x**3)*Dx + \ + (4-6*x**3+2*x**4)*Dx**2, x, 0, [1, 0]).series(n=7) + q = 1 - 3*x**2/4 - x**3/4 - 5*x**4/32 - 3*x**5/40 - 17*x**6/384 + O(x**7) + assert p == q + p = expr_to_holonomic(erf(x) + x).series(n=10) + C_3 = symbols('C_3') + q = (erf(x) + x).series(n=10) + assert p.subs(C_3, -2/(3*sqrt(pi))) == q + assert expr_to_holonomic(sqrt(x**3 + x)).series(n=10) == sqrt(x**3 + x).series(n=10) + assert expr_to_holonomic((2*x - 3*x**2)**Rational(1, 3)).series() == ((2*x - 3*x**2)**Rational(1, 3)).series() + assert expr_to_holonomic(sqrt(x**2-x)).series() == (sqrt(x**2-x)).series() + assert expr_to_holonomic(cos(x)**2/x**2, y0={-2: [1, 0, -1]}).series(n=10) == (cos(x)**2/x**2).series(n=10) + assert expr_to_holonomic(cos(x)**2/x**2, x0=1).series(n=10).together() == (cos(x)**2/x**2).series(n=10, x0=1).together() + assert expr_to_holonomic(cos(x-1)**2/(x-1)**2, x0=1, y0={-2: [1, 0, -1]}).series(n=10) \ + == (cos(x-1)**2/(x-1)**2).series(x0=1, n=10) + +def test_evalf_euler(): + x = symbols('x') + R, Dx = DifferentialOperators(QQ.old_poly_ring(x), 'Dx') + + # log(1+x) + p = HolonomicFunction((1 + x)*Dx**2 + Dx, x, 0, [0, 1]) + + # path taken is a straight line from 0 to 1, on the real axis + r = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1] + s = '0.699525841805253' # approx. equal to log(2) i.e. 0.693147180559945 + assert sstr(p.evalf(r, method='Euler')[-1]) == s + + # path taken is a triangle 0-->1+i-->2 + r = [0.1 + 0.1*I] + for i in range(9): + r.append(r[-1]+0.1+0.1*I) + for i in range(10): + r.append(r[-1]+0.1-0.1*I) + + # close to the exact solution 1.09861228866811 + # imaginary part also close to zero + s = '1.07530466271334 - 0.0251200594793912*I' + assert sstr(p.evalf(r, method='Euler')[-1]) == s + + # sin(x) + p = HolonomicFunction(Dx**2 + 1, x, 0, [0, 1]) + s = '0.905546532085401 - 6.93889390390723e-18*I' + assert sstr(p.evalf(r, method='Euler')[-1]) == s + + # computing sin(pi/2) using this method + # using a linear path from 0 to pi/2 + r = [0.1] + for i in range(14): + r.append(r[-1] + 0.1) + r.append(pi/2) + s = '1.08016557252834' # close to 1.0 (exact solution) + assert sstr(p.evalf(r, method='Euler')[-1]) == s + + # trying different path, a rectangle (0-->i-->pi/2 + i-->pi/2) + # computing the same value sin(pi/2) using different path + r = [0.1*I] + for i in range(9): + r.append(r[-1]+0.1*I) + for i in range(15): + r.append(r[-1]+0.1) + r.append(pi/2+I) + for i in range(10): + r.append(r[-1]-0.1*I) + + # close to 1.0 + s = '0.976882381836257 - 1.65557671738537e-16*I' + assert sstr(p.evalf(r, method='Euler')[-1]) == s + + # cos(x) + p = HolonomicFunction(Dx**2 + 1, x, 0, [1, 0]) + # compute cos(pi) along 0-->pi + r = [0.05] + for i in range(61): + r.append(r[-1]+0.05) + r.append(pi) + # close to -1 (exact answer) + s = '-1.08140824719196' + assert sstr(p.evalf(r, method='Euler')[-1]) == s + + # a rectangular path (0 -> i -> 2+i -> 2) + r = [0.1*I] + for i in range(9): + r.append(r[-1]+0.1*I) + for i in range(20): + r.append(r[-1]+0.1) + for i in range(10): + r.append(r[-1]-0.1*I) + + p = HolonomicFunction(Dx**2 + 1, x, 0, [1,1]).evalf(r, method='Euler') + s = '0.501421652861245 - 3.88578058618805e-16*I' + assert sstr(p[-1]) == s + +def test_evalf_rk4(): + x = symbols('x') + R, Dx = DifferentialOperators(QQ.old_poly_ring(x), 'Dx') + + # log(1+x) + p = HolonomicFunction((1 + x)*Dx**2 + Dx, x, 0, [0, 1]) + + # path taken is a straight line from 0 to 1, on the real axis + r = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1] + s = '0.693146363174626' # approx. equal to log(2) i.e. 0.693147180559945 + assert sstr(p.evalf(r)[-1]) == s + + # path taken is a triangle 0-->1+i-->2 + r = [0.1 + 0.1*I] + for i in range(9): + r.append(r[-1]+0.1+0.1*I) + for i in range(10): + r.append(r[-1]+0.1-0.1*I) + + # close to the exact solution 1.09861228866811 + # imaginary part also close to zero + s = '1.098616 + 1.36083e-7*I' + assert sstr(p.evalf(r)[-1].n(7)) == s + + # sin(x) + p = HolonomicFunction(Dx**2 + 1, x, 0, [0, 1]) + s = '0.90929463522785 + 1.52655665885959e-16*I' + assert sstr(p.evalf(r)[-1]) == s + + # computing sin(pi/2) using this method + # using a linear path from 0 to pi/2 + r = [0.1] + for i in range(14): + r.append(r[-1] + 0.1) + r.append(pi/2) + s = '0.999999895088917' # close to 1.0 (exact solution) + assert sstr(p.evalf(r)[-1]) == s + + # trying different path, a rectangle (0-->i-->pi/2 + i-->pi/2) + # computing the same value sin(pi/2) using different path + r = [0.1*I] + for i in range(9): + r.append(r[-1]+0.1*I) + for i in range(15): + r.append(r[-1]+0.1) + r.append(pi/2+I) + for i in range(10): + r.append(r[-1]-0.1*I) + + # close to 1.0 + s = '1.00000003415141 + 6.11940487991086e-16*I' + assert sstr(p.evalf(r)[-1]) == s + + # cos(x) + p = HolonomicFunction(Dx**2 + 1, x, 0, [1, 0]) + # compute cos(pi) along 0-->pi + r = [0.05] + for i in range(61): + r.append(r[-1]+0.05) + r.append(pi) + # close to -1 (exact answer) + s = '-0.999999993238714' + assert sstr(p.evalf(r)[-1]) == s + + # a rectangular path (0 -> i -> 2+i -> 2) + r = [0.1*I] + for i in range(9): + r.append(r[-1]+0.1*I) + for i in range(20): + r.append(r[-1]+0.1) + for i in range(10): + r.append(r[-1]-0.1*I) + + p = HolonomicFunction(Dx**2 + 1, x, 0, [1,1]).evalf(r) + s = '0.493152791638442 - 1.41553435639707e-15*I' + assert sstr(p[-1]) == s + + +def test_expr_to_holonomic(): + x = symbols('x') + R, Dx = DifferentialOperators(QQ.old_poly_ring(x), 'Dx') + p = expr_to_holonomic((sin(x)/x)**2) + q = HolonomicFunction(8*x + (4*x**2 + 6)*Dx + 6*x*Dx**2 + x**2*Dx**3, x, 0, \ + [1, 0, Rational(-2, 3)]) + assert p == q + p = expr_to_holonomic(1/(1+x**2)**2) + q = HolonomicFunction(4*x + (x**2 + 1)*Dx, x, 0, [1]) + assert p == q + p = expr_to_holonomic(exp(x)*sin(x)+x*log(1+x)) + q = HolonomicFunction((2*x**3 + 10*x**2 + 20*x + 18) + (-2*x**4 - 10*x**3 - 20*x**2 \ + - 18*x)*Dx + (2*x**5 + 6*x**4 + 7*x**3 + 8*x**2 + 10*x - 4)*Dx**2 + \ + (-2*x**5 - 5*x**4 - 2*x**3 + 2*x**2 - x + 4)*Dx**3 + (x**5 + 2*x**4 - x**3 - \ + 7*x**2/2 + x + Rational(5, 2))*Dx**4, x, 0, [0, 1, 4, -1]) + assert p == q + p = expr_to_holonomic(x*exp(x)+cos(x)+1) + q = HolonomicFunction((-x - 3)*Dx + (x + 2)*Dx**2 + (-x - 3)*Dx**3 + (x + 2)*Dx**4, x, \ + 0, [2, 1, 1, 3]) + assert p == q + assert (x*exp(x)+cos(x)+1).series(n=10) == p.series(n=10) + p = expr_to_holonomic(log(1 + x)**2 + 1) + q = HolonomicFunction(Dx + (3*x + 3)*Dx**2 + (x**2 + 2*x + 1)*Dx**3, x, 0, [1, 0, 2]) + assert p == q + p = expr_to_holonomic(erf(x)**2 + x) + q = HolonomicFunction((8*x**4 - 2*x**2 + 2)*Dx**2 + (6*x**3 - x/2)*Dx**3 + \ + (x**2+ Rational(1, 4))*Dx**4, x, 0, [0, 1, 8/pi, 0]) + assert p == q + p = expr_to_holonomic(cosh(x)*x) + q = HolonomicFunction((-x**2 + 2) -2*x*Dx + x**2*Dx**2, x, 0, [0, 1]) + assert p == q + p = expr_to_holonomic(besselj(2, x)) + q = HolonomicFunction((x**2 - 4) + x*Dx + x**2*Dx**2, x, 0, [0, 0]) + assert p == q + p = expr_to_holonomic(besselj(0, x) + exp(x)) + q = HolonomicFunction((-x**2 - x/2 + S.Half) + (x**2 - x/2 - Rational(3, 2))*Dx + (-x**2 + x/2 + 1)*Dx**2 +\ + (x**2 + x/2)*Dx**3, x, 0, [2, 1, S.Half]) + assert p == q + p = expr_to_holonomic(sin(x)**2/x) + q = HolonomicFunction(4 + 4*x*Dx + 3*Dx**2 + x*Dx**3, x, 0, [0, 1, 0]) + assert p == q + p = expr_to_holonomic(sin(x)**2/x, x0=2) + q = HolonomicFunction((4) + (4*x)*Dx + (3)*Dx**2 + (x)*Dx**3, x, 2, [sin(2)**2/2, + sin(2)*cos(2) - sin(2)**2/4, -3*sin(2)**2/4 + cos(2)**2 - sin(2)*cos(2)]) + assert p == q + p = expr_to_holonomic(log(x)/2 - Ci(2*x)/2 + Ci(2)/2) + q = HolonomicFunction(4*Dx + 4*x*Dx**2 + 3*Dx**3 + x*Dx**4, x, 0, \ + [-log(2)/2 - EulerGamma/2 + Ci(2)/2, 0, 1, 0]) + assert p == q + p = p.to_expr() + q = log(x)/2 - Ci(2*x)/2 + Ci(2)/2 + assert p == q + p = expr_to_holonomic(x**S.Half, x0=1) + q = HolonomicFunction(x*Dx - S.Half, x, 1, [1]) + assert p == q + p = expr_to_holonomic(sqrt(1 + x**2)) + q = HolonomicFunction((-x) + (x**2 + 1)*Dx, x, 0, [1]) + assert p == q + assert (expr_to_holonomic(sqrt(x) + sqrt(2*x)).to_expr()-\ + (sqrt(x) + sqrt(2*x))).simplify() == 0 + assert expr_to_holonomic(3*x+2*sqrt(x)).to_expr() == 3*x+2*sqrt(x) + p = expr_to_holonomic((x**4+x**3+5*x**2+3*x+2)/x**2, lenics=3) + q = HolonomicFunction((-2*x**4 - x**3 + 3*x + 4) + (x**5 + x**4 + 5*x**3 + 3*x**2 + \ + 2*x)*Dx, x, 0, {-2: [2, 3, 5]}) + assert p == q + p = expr_to_holonomic(1/(x-1)**2, lenics=3, x0=1) + q = HolonomicFunction((2) + (x - 1)*Dx, x, 1, {-2: [1, 0, 0]}) + assert p == q + a = symbols("a") + p = expr_to_holonomic(sqrt(a*x), x=x) + assert p.to_expr() == sqrt(a)*sqrt(x) + +def test_to_hyper(): + x = symbols('x') + R, Dx = DifferentialOperators(QQ.old_poly_ring(x), 'Dx') + p = HolonomicFunction(Dx - 2, x, 0, [3]).to_hyper() + q = 3 * hyper([], [], 2*x) + assert p == q + p = hyperexpand(HolonomicFunction((1 + x) * Dx - 3, x, 0, [2]).to_hyper()).expand() + q = 2*x**3 + 6*x**2 + 6*x + 2 + assert p == q + p = HolonomicFunction((1 + x)*Dx**2 + Dx, x, 0, [0, 1]).to_hyper() + q = -x**2*hyper((2, 2, 1), (3, 2), -x)/2 + x + assert p == q + p = HolonomicFunction(2*x*Dx + Dx**2, x, 0, [0, 2/sqrt(pi)]).to_hyper() + q = 2*x*hyper((S.Half,), (Rational(3, 2),), -x**2)/sqrt(pi) + assert p == q + p = hyperexpand(HolonomicFunction(2*x*Dx + Dx**2, x, 0, [1, -2/sqrt(pi)]).to_hyper()) + q = erfc(x) + assert p.rewrite(erfc) == q + p = hyperexpand(HolonomicFunction((x**2 - 1) + x*Dx + x**2*Dx**2, + x, 0, [0, S.Half]).to_hyper()) + q = besselj(1, x) + assert p == q + p = hyperexpand(HolonomicFunction(x*Dx**2 + Dx + x, x, 0, [1, 0]).to_hyper()) + q = besselj(0, x) + assert p == q + +def test_to_expr(): + x = symbols('x') + R, Dx = DifferentialOperators(ZZ.old_poly_ring(x), 'Dx') + p = HolonomicFunction(Dx - 1, x, 0, [1]).to_expr() + q = exp(x) + assert p == q + p = HolonomicFunction(Dx**2 + 1, x, 0, [1, 0]).to_expr() + q = cos(x) + assert p == q + p = HolonomicFunction(Dx**2 - 1, x, 0, [1, 0]).to_expr() + q = cosh(x) + assert p == q + p = HolonomicFunction(2 + (4*x - 1)*Dx + \ + (x**2 - x)*Dx**2, x, 0, [1, 2]).to_expr().expand() + q = 1/(x**2 - 2*x + 1) + assert p == q + p = expr_to_holonomic(sin(x)**2/x).integrate((x, 0, x)).to_expr() + q = (sin(x)**2/x).integrate((x, 0, x)) + assert p == q + C_0, C_1, C_2, C_3 = symbols('C_0, C_1, C_2, C_3') + p = expr_to_holonomic(log(1+x**2)).to_expr() + q = C_2*log(x**2 + 1) + assert p == q + p = expr_to_holonomic(log(1+x**2)).diff().to_expr() + q = C_0*x/(x**2 + 1) + assert p == q + p = expr_to_holonomic(erf(x) + x).to_expr() + q = 3*C_3*x - 3*sqrt(pi)*C_3*erf(x)/2 + x + 2*x/sqrt(pi) + assert p == q + p = expr_to_holonomic(sqrt(x), x0=1).to_expr() + assert p == sqrt(x) + assert expr_to_holonomic(sqrt(x)).to_expr() == sqrt(x) + p = expr_to_holonomic(sqrt(1 + x**2)).to_expr() + assert p == sqrt(1+x**2) + p = expr_to_holonomic((2*x**2 + 1)**Rational(2, 3)).to_expr() + assert p == (2*x**2 + 1)**Rational(2, 3) + p = expr_to_holonomic(sqrt(-x**2+2*x)).to_expr() + assert p == sqrt(x)*sqrt(-x + 2) + p = expr_to_holonomic((-2*x**3+7*x)**Rational(2, 3)).to_expr() + q = x**Rational(2, 3)*(-2*x**2 + 7)**Rational(2, 3) + assert p == q + p = from_hyper(hyper((-2, -3), (S.Half, ), x)) + s = hyperexpand(hyper((-2, -3), (S.Half, ), x)) + D_0 = Symbol('D_0') + C_0 = Symbol('C_0') + assert (p.to_expr().subs({C_0:1, D_0:0}) - s).simplify() == 0 + p.y0 = {0: [1], S.Half: [0]} + assert p.to_expr() == s + assert expr_to_holonomic(x**5).to_expr() == x**5 + assert expr_to_holonomic(2*x**3-3*x**2).to_expr().expand() == \ + 2*x**3-3*x**2 + a = symbols("a") + p = (expr_to_holonomic(1.4*x)*expr_to_holonomic(a*x, x)).to_expr() + q = 1.4*a*x**2 + assert p == q + p = (expr_to_holonomic(1.4*x)+expr_to_holonomic(a*x, x)).to_expr() + q = x*(a + 1.4) + assert p == q + p = (expr_to_holonomic(1.4*x)+expr_to_holonomic(x)).to_expr() + assert p == 2.4*x + + +def test_integrate(): + x = symbols('x') + R, Dx = DifferentialOperators(ZZ.old_poly_ring(x), 'Dx') + p = expr_to_holonomic(sin(x)**2/x, x0=1).integrate((x, 2, 3)) + q = '0.166270406994788' + assert sstr(p) == q + p = expr_to_holonomic(sin(x)).integrate((x, 0, x)).to_expr() + q = 1 - cos(x) + assert p == q + p = expr_to_holonomic(sin(x)).integrate((x, 0, 3)) + q = 1 - cos(3) + assert p == q + p = expr_to_holonomic(sin(x)/x, x0=1).integrate((x, 1, 2)) + q = '0.659329913368450' + assert sstr(p) == q + p = expr_to_holonomic(sin(x)**2/x, x0=1).integrate((x, 1, 0)) + q = '-0.423690480850035' + assert sstr(p) == q + p = expr_to_holonomic(sin(x)/x) + assert p.integrate(x).to_expr() == Si(x) + assert p.integrate((x, 0, 2)) == Si(2) + p = expr_to_holonomic(sin(x)**2/x) + q = p.to_expr() + assert p.integrate(x).to_expr() == q.integrate((x, 0, x)) + assert p.integrate((x, 0, 1)) == q.integrate((x, 0, 1)) + assert expr_to_holonomic(1/x, x0=1).integrate(x).to_expr() == log(x) + p = expr_to_holonomic((x + 1)**3*exp(-x), x0=-1).integrate(x).to_expr() + q = (-x**3 - 6*x**2 - 15*x + 6*exp(x + 1) - 16)*exp(-x) + assert p == q + p = expr_to_holonomic(cos(x)**2/x**2, y0={-2: [1, 0, -1]}).integrate(x).to_expr() + q = -Si(2*x) - cos(x)**2/x + assert p == q + p = expr_to_holonomic(sqrt(x**2+x)).integrate(x).to_expr() + q = (x**Rational(3, 2)*(2*x**2 + 3*x + 1) - x*sqrt(x + 1)*asinh(sqrt(x)))/(4*x*sqrt(x + 1)) + assert p == q + p = expr_to_holonomic(sqrt(x**2+1)).integrate(x).to_expr() + q = (sqrt(x**2+1)).integrate(x) + assert (p-q).simplify() == 0 + p = expr_to_holonomic(1/x**2, y0={-2:[1, 0, 0]}) + r = expr_to_holonomic(1/x**2, lenics=3) + assert p == r + q = expr_to_holonomic(cos(x)**2) + assert (r*q).integrate(x).to_expr() == -Si(2*x) - cos(x)**2/x + + +def test_diff(): + x, y = symbols('x, y') + R, Dx = DifferentialOperators(ZZ.old_poly_ring(x), 'Dx') + p = HolonomicFunction(x*Dx**2 + 1, x, 0, [0, 1]) + assert p.diff().to_expr() == p.to_expr().diff().simplify() + p = HolonomicFunction(Dx**2 - 1, x, 0, [1, 0]) + assert p.diff(x, 2).to_expr() == p.to_expr() + p = expr_to_holonomic(Si(x)) + assert p.diff().to_expr() == sin(x)/x + assert p.diff(y) == 0 + C_0, C_1, C_2, C_3 = symbols('C_0, C_1, C_2, C_3') + q = Si(x) + assert p.diff(x).to_expr() == q.diff() + assert p.diff(x, 2).to_expr().subs(C_0, Rational(-1, 3)).cancel() == q.diff(x, 2).cancel() + assert p.diff(x, 3).series().subs({C_3: Rational(-1, 3), C_0: 0}) == q.diff(x, 3).series() + + +def test_extended_domain_in_expr_to_holonomic(): + x = symbols('x') + p = expr_to_holonomic(1.2*cos(3.1*x)) + assert p.to_expr() == 1.2*cos(3.1*x) + assert sstr(p.integrate(x).to_expr()) == '0.387096774193548*sin(3.1*x)' + _, Dx = DifferentialOperators(RR.old_poly_ring(x), 'Dx') + p = expr_to_holonomic(1.1329138213*x) + q = HolonomicFunction((-1.1329138213) + (1.1329138213*x)*Dx, x, 0, {1: [1.1329138213]}) + assert p == q + assert p.to_expr() == 1.1329138213*x + assert sstr(p.integrate((x, 1, 2))) == sstr((1.1329138213*x).integrate((x, 1, 2))) + y, z = symbols('y, z') + p = expr_to_holonomic(sin(x*y*z), x=x) + assert p.to_expr() == sin(x*y*z) + assert p.integrate(x).to_expr() == (-cos(x*y*z) + 1)/(y*z) + p = expr_to_holonomic(sin(x*y + z), x=x).integrate(x).to_expr() + q = (cos(z) - cos(x*y + z))/y + assert p == q + a = symbols('a') + p = expr_to_holonomic(a*x, x) + assert p.to_expr() == a*x + assert p.integrate(x).to_expr() == a*x**2/2 + D_2, C_1 = symbols("D_2, C_1") + p = expr_to_holonomic(x) + expr_to_holonomic(1.2*cos(x)) + p = p.to_expr().subs(D_2, 0) + assert p - x - 1.2*cos(1.0*x) == 0 + p = expr_to_holonomic(x) * expr_to_holonomic(1.2*cos(x)) + p = p.to_expr().subs(C_1, 0) + assert p - 1.2*x*cos(1.0*x) == 0 + + +def test_to_meijerg(): + x = symbols('x') + assert hyperexpand(expr_to_holonomic(sin(x)).to_meijerg()) == sin(x) + assert hyperexpand(expr_to_holonomic(cos(x)).to_meijerg()) == cos(x) + assert hyperexpand(expr_to_holonomic(exp(x)).to_meijerg()) == exp(x) + assert hyperexpand(expr_to_holonomic(log(x)).to_meijerg()).simplify() == log(x) + assert expr_to_holonomic(4*x**2/3 + 7).to_meijerg() == 4*x**2/3 + 7 + assert hyperexpand(expr_to_holonomic(besselj(2, x), lenics=3).to_meijerg()) == besselj(2, x) + p = hyper((Rational(-1, 2), -3), (), x) + assert from_hyper(p).to_meijerg() == hyperexpand(p) + p = hyper((S.One, S(3)), (S(2), ), x) + assert (hyperexpand(from_hyper(p).to_meijerg()) - hyperexpand(p)).expand() == 0 + p = from_hyper(hyper((-2, -3), (S.Half, ), x)) + s = hyperexpand(hyper((-2, -3), (S.Half, ), x)) + C_0 = Symbol('C_0') + C_1 = Symbol('C_1') + D_0 = Symbol('D_0') + assert (hyperexpand(p.to_meijerg()).subs({C_0:1, D_0:0}) - s).simplify() == 0 + p.y0 = {0: [1], S.Half: [0]} + assert (hyperexpand(p.to_meijerg()) - s).simplify() == 0 + p = expr_to_holonomic(besselj(S.Half, x), initcond=False) + assert (p.to_expr() - (D_0*sin(x) + C_0*cos(x) + C_1*sin(x))/sqrt(x)).simplify() == 0 + p = expr_to_holonomic(besselj(S.Half, x), y0={Rational(-1, 2): [sqrt(2)/sqrt(pi), sqrt(2)/sqrt(pi)]}) + assert (p.to_expr() - besselj(S.Half, x) - besselj(Rational(-1, 2), x)).simplify() == 0 + + +def test_gaussian(): + mu, x = symbols("mu x") + sd = symbols("sd", positive=True) + Q = QQ[mu, sd].get_field() + e = sqrt(2)*exp(-(-mu + x)**2/(2*sd**2))/(2*sqrt(pi)*sd) + h1 = expr_to_holonomic(e, x, domain=Q) + + _, Dx = DifferentialOperators(Q.old_poly_ring(x), 'Dx') + h2 = HolonomicFunction((-mu/sd**2 + x/sd**2) + (1)*Dx, x) + + assert h1 == h2 + + +def test_beta(): + a, b, x = symbols("a b x", positive=True) + e = x**(a - 1)*(-x + 1)**(b - 1)/beta(a, b) + Q = QQ[a, b].get_field() + h1 = expr_to_holonomic(e, x, domain=Q) + + _, Dx = DifferentialOperators(Q.old_poly_ring(x), 'Dx') + h2 = HolonomicFunction((a + x*(-a - b + 2) - 1) + (x**2 - x)*Dx, x) + + assert h1 == h2 + + +def test_gamma(): + a, b, x = symbols("a b x", positive=True) + e = b**(-a)*x**(a - 1)*exp(-x/b)/gamma(a) + Q = QQ[a, b].get_field() + h1 = expr_to_holonomic(e, x, domain=Q) + + _, Dx = DifferentialOperators(Q.old_poly_ring(x), 'Dx') + h2 = HolonomicFunction((-a + 1 + x/b) + (x)*Dx, x) + + assert h1 == h2 + + +def test_symbolic_power(): + x, n = symbols("x n") + Q = QQ[n].get_field() + _, Dx = DifferentialOperators(Q.old_poly_ring(x), 'Dx') + h1 = HolonomicFunction((-1) + (x)*Dx, x) ** -n + h2 = HolonomicFunction((n) + (x)*Dx, x) + + assert h1 == h2 + + +def test_negative_power(): + x = symbols("x") + _, Dx = DifferentialOperators(QQ.old_poly_ring(x), 'Dx') + h1 = HolonomicFunction((-1) + (x)*Dx, x) ** -2 + h2 = HolonomicFunction((2) + (x)*Dx, x) + + assert h1 == h2 + + +def test_expr_in_power(): + x, n = symbols("x n") + Q = QQ[n].get_field() + _, Dx = DifferentialOperators(Q.old_poly_ring(x), 'Dx') + h1 = HolonomicFunction((-1) + (x)*Dx, x) ** (n - 3) + h2 = HolonomicFunction((-n + 3) + (x)*Dx, x) + + assert h1 == h2 + + +def test_DifferentialOperatorEqPoly(): + x = symbols('x', integer=True) + R, Dx = DifferentialOperators(QQ.old_poly_ring(x), 'Dx') + do = DifferentialOperator([x**2, R.base.zero, R.base.zero], R) + do2 = DifferentialOperator([x**2, 1, x], R) + assert not do == do2 + + # polynomial comparison issue, see https://github.com/sympy/sympy/pull/15799 + # should work once that is solved + # p = do.listofpoly[0] + # assert do == p + + p2 = do2.listofpoly[0] + assert not do2 == p2 + + +def test_DifferentialOperatorPow(): + x = symbols('x', integer=True) + R, _ = DifferentialOperators(QQ.old_poly_ring(x), 'Dx') + do = DifferentialOperator([x**2, R.base.zero, R.base.zero], R) + a = DifferentialOperator([R.base.one], R) + for n in range(10): + assert a == do**n + a *= do diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/tests/test_recurrence.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/tests/test_recurrence.py new file mode 100644 index 0000000000000000000000000000000000000000..526595e91c5fc507877275e3e53e78c6f3716095 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/holonomic/tests/test_recurrence.py @@ -0,0 +1,41 @@ +from sympy.holonomic.recurrence import RecurrenceOperators, RecurrenceOperator +from sympy.core.symbol import symbols +from sympy.polys.domains.rationalfield import QQ + + +def test_RecurrenceOperator(): + n = symbols('n', integer=True) + R, Sn = RecurrenceOperators(QQ.old_poly_ring(n), 'Sn') + assert Sn*n == (n + 1)*Sn + assert Sn*n**2 == (n**2+1+2*n)*Sn + assert Sn**2*n**2 == (n**2 + 4*n + 4)*Sn**2 + p = (Sn**3*n**2 + Sn*n)**2 + q = (n**2 + 3*n + 2)*Sn**2 + (2*n**3 + 19*n**2 + 57*n + 52)*Sn**4 + (n**4 + 18*n**3 + \ + 117*n**2 + 324*n + 324)*Sn**6 + assert p == q + + +def test_RecurrenceOperatorEqPoly(): + n = symbols('n', integer=True) + R, Sn = RecurrenceOperators(QQ.old_poly_ring(n), 'Sn') + rr = RecurrenceOperator([n**2, 0, 0], R) + rr2 = RecurrenceOperator([n**2, 1, n], R) + assert not rr == rr2 + + # polynomial comparison issue, see https://github.com/sympy/sympy/pull/15799 + # should work once that is solved + # d = rr.listofpoly[0] + # assert rr == d + + d2 = rr2.listofpoly[0] + assert not rr2 == d2 + + +def test_RecurrenceOperatorPow(): + n = symbols('n', integer=True) + R, _ = RecurrenceOperators(QQ.old_poly_ring(n), 'Sn') + rr = RecurrenceOperator([n**2, 0, 0], R) + a = RecurrenceOperator([R.base.one], R) + for m in range(10): + assert a == rr**m + a *= rr diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ef5b062d3ce81eed02b065facf5eee7a03291241 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/__pycache__/printing.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/__pycache__/printing.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0175766d2f77663f62c0873fa794a66865ad50c6 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/__pycache__/printing.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/__pycache__/session.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/__pycache__/session.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ed663b2ce1f412caec0681752c7c5152f641a0bb Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/__pycache__/session.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/__pycache__/traversal.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/__pycache__/traversal.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e39409ae8bd5ed4396fff267fa051a7d54e47ca5 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/__pycache__/traversal.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d07950f947c46f582598e0605a26ce55e3990814 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/tests/__pycache__/test_interactive.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/tests/__pycache__/test_interactive.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7376bf91482da5ccd7f05f4f1b7235ce829349c7 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/tests/__pycache__/test_interactive.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/tests/__pycache__/test_ipython.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/tests/__pycache__/test_ipython.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..740e88141e14ac0ea7bce49cb8805b068b7d8d47 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/tests/__pycache__/test_ipython.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/tests/test_interactive.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/tests/test_interactive.py new file mode 100644 index 0000000000000000000000000000000000000000..3e088c42fd872c13849e593b04734158f5d1e5bc --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/tests/test_interactive.py @@ -0,0 +1,10 @@ +from sympy.interactive.session import int_to_Integer + + +def test_int_to_Integer(): + assert int_to_Integer("1 + 2.2 + 0x3 + 40") == \ + 'Integer (1 )+2.2 +Integer (0x3 )+Integer (40 )' + assert int_to_Integer("0b101") == 'Integer (0b101 )' + assert int_to_Integer("ab1 + 1 + '1 + 2'") == "ab1 +Integer (1 )+'1 + 2'" + assert int_to_Integer("(2 + \n3)") == '(Integer (2 )+\nInteger (3 ))' + assert int_to_Integer("2 + 2.0 + 2j + 2e-10") == 'Integer (2 )+2.0 +2j +2e-10 ' diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/tests/test_ipython.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/tests/test_ipython.py new file mode 100644 index 0000000000000000000000000000000000000000..ac4734406d2f1197732a9dcbdd94b2b34e9fe170 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/interactive/tests/test_ipython.py @@ -0,0 +1,278 @@ +"""Tests of tools for setting up interactive IPython sessions. """ + +from sympy.interactive.session import (init_ipython_session, + enable_automatic_symbols, enable_automatic_int_sympification) + +from sympy.core import Symbol, Rational, Integer +from sympy.external import import_module +from sympy.testing.pytest import raises + +# TODO: The code below could be made more granular with something like: +# +# @requires('IPython', version=">=1.0") +# def test_automatic_symbols(ipython): + +ipython = import_module("IPython", min_module_version="1.0") + +if not ipython: + #bin/test will not execute any tests now + disabled = True + +# WARNING: These tests will modify the existing IPython environment. IPython +# uses a single instance for its interpreter, so there is no way to isolate +# the test from another IPython session. It also means that if this test is +# run twice in the same Python session it will fail. This isn't usually a +# problem because the test suite is run in a subprocess by default, but if the +# tests are run with subprocess=False it can pollute the current IPython +# session. See the discussion in issue #15149. + +def test_automatic_symbols(): + # NOTE: Because of the way the hook works, you have to use run_cell(code, + # True). This means that the code must have no Out, or it will be printed + # during the tests. + app = init_ipython_session() + app.run_cell("from sympy import *") + + enable_automatic_symbols(app) + + symbol = "verylongsymbolname" + assert symbol not in app.user_ns + app.run_cell("a = %s" % symbol, True) + assert symbol not in app.user_ns + app.run_cell("a = type(%s)" % symbol, True) + assert app.user_ns['a'] == Symbol + app.run_cell("%s = Symbol('%s')" % (symbol, symbol), True) + assert symbol in app.user_ns + + # Check that built-in names aren't overridden + app.run_cell("a = all == __builtin__.all", True) + assert "all" not in app.user_ns + assert app.user_ns['a'] is True + + # Check that SymPy names aren't overridden + app.run_cell("import sympy") + app.run_cell("a = factorial == sympy.factorial", True) + assert app.user_ns['a'] is True + + +def test_int_to_Integer(): + # XXX: Warning, don't test with == here. 0.5 == Rational(1, 2) is True! + app = init_ipython_session() + app.run_cell("from sympy import Integer") + app.run_cell("a = 1") + assert isinstance(app.user_ns['a'], int) + + enable_automatic_int_sympification(app) + app.run_cell("a = 1/2") + assert isinstance(app.user_ns['a'], Rational) + app.run_cell("a = 1") + assert isinstance(app.user_ns['a'], Integer) + app.run_cell("a = int(1)") + assert isinstance(app.user_ns['a'], int) + app.run_cell("a = (1/\n2)") + assert app.user_ns['a'] == Rational(1, 2) + # TODO: How can we test that the output of a SyntaxError is the original + # input, not the transformed input? + + +def test_ipythonprinting(): + # Initialize and setup IPython session + app = init_ipython_session() + app.run_cell("ip = get_ipython()") + app.run_cell("inst = ip.instance()") + app.run_cell("format = inst.display_formatter.format") + app.run_cell("from sympy import Symbol") + + # Printing without printing extension + app.run_cell("a = format(Symbol('pi'))") + app.run_cell("a2 = format(Symbol('pi')**2)") + # Deal with API change starting at IPython 1.0 + if int(ipython.__version__.split(".")[0]) < 1: + assert app.user_ns['a']['text/plain'] == "pi" + assert app.user_ns['a2']['text/plain'] == "pi**2" + else: + assert app.user_ns['a'][0]['text/plain'] == "pi" + assert app.user_ns['a2'][0]['text/plain'] == "pi**2" + + # Load printing extension + app.run_cell("from sympy import init_printing") + app.run_cell("init_printing()") + # Printing with printing extension + app.run_cell("a = format(Symbol('pi'))") + app.run_cell("a2 = format(Symbol('pi')**2)") + # Deal with API change starting at IPython 1.0 + if int(ipython.__version__.split(".")[0]) < 1: + assert app.user_ns['a']['text/plain'] in ('\N{GREEK SMALL LETTER PI}', 'pi') + assert app.user_ns['a2']['text/plain'] in (' 2\n\N{GREEK SMALL LETTER PI} ', ' 2\npi ') + else: + assert app.user_ns['a'][0]['text/plain'] in ('\N{GREEK SMALL LETTER PI}', 'pi') + assert app.user_ns['a2'][0]['text/plain'] in (' 2\n\N{GREEK SMALL LETTER PI} ', ' 2\npi ') + + +def test_print_builtin_option(): + # Initialize and setup IPython session + app = init_ipython_session() + app.run_cell("ip = get_ipython()") + app.run_cell("inst = ip.instance()") + app.run_cell("format = inst.display_formatter.format") + app.run_cell("from sympy import Symbol") + app.run_cell("from sympy import init_printing") + + app.run_cell("a = format({Symbol('pi'): 3.14, Symbol('n_i'): 3})") + # Deal with API change starting at IPython 1.0 + if int(ipython.__version__.split(".")[0]) < 1: + text = app.user_ns['a']['text/plain'] + raises(KeyError, lambda: app.user_ns['a']['text/latex']) + else: + text = app.user_ns['a'][0]['text/plain'] + raises(KeyError, lambda: app.user_ns['a'][0]['text/latex']) + # XXX: How can we make this ignore the terminal width? This test fails if + # the terminal is too narrow. + assert text in ("{pi: 3.14, n_i: 3}", + '{n\N{LATIN SUBSCRIPT SMALL LETTER I}: 3, \N{GREEK SMALL LETTER PI}: 3.14}', + "{n_i: 3, pi: 3.14}", + '{\N{GREEK SMALL LETTER PI}: 3.14, n\N{LATIN SUBSCRIPT SMALL LETTER I}: 3}') + + # If we enable the default printing, then the dictionary's should render + # as a LaTeX version of the whole dict: ${\pi: 3.14, n_i: 3}$ + app.run_cell("inst.display_formatter.formatters['text/latex'].enabled = True") + app.run_cell("init_printing(use_latex=True)") + app.run_cell("a = format({Symbol('pi'): 3.14, Symbol('n_i'): 3})") + # Deal with API change starting at IPython 1.0 + if int(ipython.__version__.split(".")[0]) < 1: + text = app.user_ns['a']['text/plain'] + latex = app.user_ns['a']['text/latex'] + else: + text = app.user_ns['a'][0]['text/plain'] + latex = app.user_ns['a'][0]['text/latex'] + assert text in ("{pi: 3.14, n_i: 3}", + '{n\N{LATIN SUBSCRIPT SMALL LETTER I}: 3, \N{GREEK SMALL LETTER PI}: 3.14}', + "{n_i: 3, pi: 3.14}", + '{\N{GREEK SMALL LETTER PI}: 3.14, n\N{LATIN SUBSCRIPT SMALL LETTER I}: 3}') + assert latex == r'$\displaystyle \left\{ n_{i} : 3, \ \pi : 3.14\right\}$' + + # Objects with an _latex overload should also be handled by our tuple + # printer. + app.run_cell("""\ + class WithOverload: + def _latex(self, printer): + return r"\\LaTeX" + """) + app.run_cell("a = format((WithOverload(),))") + # Deal with API change starting at IPython 1.0 + if int(ipython.__version__.split(".")[0]) < 1: + latex = app.user_ns['a']['text/latex'] + else: + latex = app.user_ns['a'][0]['text/latex'] + assert latex == r'$\displaystyle \left( \LaTeX,\right)$' + + app.run_cell("inst.display_formatter.formatters['text/latex'].enabled = True") + app.run_cell("init_printing(use_latex=True, print_builtin=False)") + app.run_cell("a = format({Symbol('pi'): 3.14, Symbol('n_i'): 3})") + # Deal with API change starting at IPython 1.0 + if int(ipython.__version__.split(".")[0]) < 1: + text = app.user_ns['a']['text/plain'] + raises(KeyError, lambda: app.user_ns['a']['text/latex']) + else: + text = app.user_ns['a'][0]['text/plain'] + raises(KeyError, lambda: app.user_ns['a'][0]['text/latex']) + # Note : In Python 3 we have one text type: str which holds Unicode data + # and two byte types bytes and bytearray. + # Python 3.3.3 + IPython 0.13.2 gives: '{n_i: 3, pi: 3.14}' + # Python 3.3.3 + IPython 1.1.0 gives: '{n_i: 3, pi: 3.14}' + assert text in ("{pi: 3.14, n_i: 3}", "{n_i: 3, pi: 3.14}") + + +def test_builtin_containers(): + # Initialize and setup IPython session + app = init_ipython_session() + app.run_cell("ip = get_ipython()") + app.run_cell("inst = ip.instance()") + app.run_cell("format = inst.display_formatter.format") + app.run_cell("inst.display_formatter.formatters['text/latex'].enabled = True") + app.run_cell("from sympy import init_printing, Matrix") + app.run_cell('init_printing(use_latex=True, use_unicode=False)') + + # Make sure containers that shouldn't pretty print don't. + app.run_cell('a = format((True, False))') + app.run_cell('import sys') + app.run_cell('b = format(sys.flags)') + app.run_cell('c = format((Matrix([1, 2]),))') + # Deal with API change starting at IPython 1.0 + if int(ipython.__version__.split(".")[0]) < 1: + assert app.user_ns['a']['text/plain'] == '(True, False)' + assert 'text/latex' not in app.user_ns['a'] + assert app.user_ns['b']['text/plain'][:10] == 'sys.flags(' + assert 'text/latex' not in app.user_ns['b'] + assert app.user_ns['c']['text/plain'] == \ +"""\ + [1] \n\ +([ ],) + [2] \ +""" + assert app.user_ns['c']['text/latex'] == '$\\displaystyle \\left( \\left[\\begin{matrix}1\\\\2\\end{matrix}\\right],\\right)$' + else: + assert app.user_ns['a'][0]['text/plain'] == '(True, False)' + assert 'text/latex' not in app.user_ns['a'][0] + assert app.user_ns['b'][0]['text/plain'][:10] == 'sys.flags(' + assert 'text/latex' not in app.user_ns['b'][0] + assert app.user_ns['c'][0]['text/plain'] == \ +"""\ + [1] \n\ +([ ],) + [2] \ +""" + assert app.user_ns['c'][0]['text/latex'] == '$\\displaystyle \\left( \\left[\\begin{matrix}1\\\\2\\end{matrix}\\right],\\right)$' + +def test_matplotlib_bad_latex(): + # Initialize and setup IPython session + app = init_ipython_session() + app.run_cell("import IPython") + app.run_cell("ip = get_ipython()") + app.run_cell("inst = ip.instance()") + app.run_cell("format = inst.display_formatter.format") + app.run_cell("from sympy import init_printing, Matrix") + app.run_cell("init_printing(use_latex='matplotlib')") + + # The png formatter is not enabled by default in this context + app.run_cell("inst.display_formatter.formatters['image/png'].enabled = True") + + # Make sure no warnings are raised by IPython + app.run_cell("import warnings") + # IPython.core.formatters.FormatterWarning was introduced in IPython 2.0 + if int(ipython.__version__.split(".")[0]) < 2: + app.run_cell("warnings.simplefilter('error')") + else: + app.run_cell("warnings.simplefilter('error', IPython.core.formatters.FormatterWarning)") + + # This should not raise an exception + app.run_cell("a = format(Matrix([1, 2, 3]))") + + # issue 9799 + app.run_cell("from sympy import Piecewise, Symbol, Eq") + app.run_cell("x = Symbol('x'); pw = format(Piecewise((1, Eq(x, 0)), (0, True)))") + + +def test_override_repr_latex(): + # Initialize and setup IPython session + app = init_ipython_session() + app.run_cell("import IPython") + app.run_cell("ip = get_ipython()") + app.run_cell("inst = ip.instance()") + app.run_cell("format = inst.display_formatter.format") + app.run_cell("inst.display_formatter.formatters['text/latex'].enabled = True") + app.run_cell("from sympy import init_printing") + app.run_cell("from sympy import Symbol") + app.run_cell("init_printing(use_latex=True)") + app.run_cell("""\ + class SymbolWithOverload(Symbol): + def _repr_latex_(self): + return r"Hello " + super()._repr_latex_() + " world" + """) + app.run_cell("a = format(SymbolWithOverload('s'))") + + if int(ipython.__version__.split(".")[0]) < 1: + latex = app.user_ns['a']['text/latex'] + else: + latex = app.user_ns['a'][0]['text/latex'] + assert latex == r'Hello $\displaystyle s$ world' diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..911083e0db86a6d3a288bf4a038bbfc1d161b9f1 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/decompositions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/decompositions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4fc0970ebb53a230fdf33f9ba21706ce4e93dc5b Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/decompositions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/dense.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/dense.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ba4346aac4de73aa449a4fa6fbe1918213be570a Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/dense.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/determinant.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/determinant.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..203c26530ed4d5222979ea9a70f91101bda100b9 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/determinant.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/eigen.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/eigen.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fdfd8b6b80247233d5d06ac5cc4bf4c2f3ef5934 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/eigen.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/exceptions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/exceptions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..90f3b0db285579399be521e2d7ccbc5603a5a066 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/exceptions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/graph.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/graph.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..988264ae8d0b4b06be35624b521421430dfa385c Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/graph.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/immutable.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/immutable.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..84b5c91f47fe3178066d8cb552adc38ec44838bf Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/immutable.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/inverse.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/inverse.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..379a58f75165d5d51f828680b7fe328ab44e3b31 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/inverse.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/kind.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/kind.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c466130c4fcc5377f594b1e1a1937f0a65712c1a Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/kind.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/matrices.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/matrices.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c48fc0bbc9133f442e2dfa6bc8801b6c64e9ecce Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/matrices.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/normalforms.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/normalforms.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f84150dfede1f939b321ace5fcdcb9684e3df972 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/normalforms.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/reductions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/reductions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..017eae15c227bd9659011276edb3f556f25898ff Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/reductions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/repmatrix.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/repmatrix.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..df2ad3968a7984b064957d7d401fc2b73277d21f Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/repmatrix.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/solvers.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/solvers.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a044c2765156e5f08d0af12ba24925862a659456 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/solvers.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/sparse.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/sparse.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3384345307cb85a0057ca57ab558d784bd89a106 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/sparse.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/sparsetools.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/sparsetools.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8a0f6770820878a7888959f0aa7537ee937a5c04 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/sparsetools.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/subspaces.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/subspaces.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..90941c769822f4202d47bc6af2a1f39bb381ff42 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/subspaces.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/utilities.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/utilities.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a81cd1f0e48ec8a771f8ab057bfb44d0b5f22fef Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/__pycache__/utilities.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/benchmarks/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/benchmarks/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/benchmarks/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/benchmarks/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f3f2c6476ef5695495a434a8b8f46cd71bd7c7ff Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/benchmarks/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/benchmarks/__pycache__/bench_matrix.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/benchmarks/__pycache__/bench_matrix.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1805b4d26ab8a3a07d7b130234390794841f5b24 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/benchmarks/__pycache__/bench_matrix.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/benchmarks/bench_matrix.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/benchmarks/bench_matrix.py new file mode 100644 index 0000000000000000000000000000000000000000..4fb845600533c4c6fef196fe5a45b98890f4ad78 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/benchmarks/bench_matrix.py @@ -0,0 +1,21 @@ +from sympy.core.numbers import Integer +from sympy.matrices.dense import (eye, zeros) + +i3 = Integer(3) +M = eye(100) + + +def timeit_Matrix__getitem_ii(): + M[3, 3] + + +def timeit_Matrix__getitem_II(): + M[i3, i3] + + +def timeit_Matrix__getslice(): + M[:, :] + + +def timeit_Matrix_zeronm(): + zeros(100, 100) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..5f4ab203ab74165d1003cdedd83945ea3fcf8f47 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__init__.py @@ -0,0 +1,62 @@ +""" A module which handles Matrix Expressions """ + +from .slice import MatrixSlice +from .blockmatrix import BlockMatrix, BlockDiagMatrix, block_collapse, blockcut +from .companion import CompanionMatrix +from .funcmatrix import FunctionMatrix +from .inverse import Inverse +from .matadd import MatAdd +from .matexpr import MatrixExpr, MatrixSymbol, matrix_symbols +from .matmul import MatMul +from .matpow import MatPow +from .trace import Trace, trace +from .determinant import Determinant, det, Permanent, per +from .transpose import Transpose +from .adjoint import Adjoint +from .hadamard import hadamard_product, HadamardProduct, hadamard_power, HadamardPower +from .diagonal import DiagonalMatrix, DiagonalOf, DiagMatrix, diagonalize_vector +from .dotproduct import DotProduct +from .kronecker import kronecker_product, KroneckerProduct, combine_kronecker +from .permutation import PermutationMatrix, MatrixPermute +from .sets import MatrixSet +from .special import ZeroMatrix, Identity, OneMatrix + +__all__ = [ + 'MatrixSlice', + + 'BlockMatrix', 'BlockDiagMatrix', 'block_collapse', 'blockcut', + 'FunctionMatrix', + + 'CompanionMatrix', + + 'Inverse', + + 'MatAdd', + + 'Identity', 'MatrixExpr', 'MatrixSymbol', 'ZeroMatrix', 'OneMatrix', + 'matrix_symbols', 'MatrixSet', + + 'MatMul', + + 'MatPow', + + 'Trace', 'trace', + + 'Determinant', 'det', + + 'Transpose', + + 'Adjoint', + + 'hadamard_product', 'HadamardProduct', 'hadamard_power', 'HadamardPower', + + 'DiagonalMatrix', 'DiagonalOf', 'DiagMatrix', 'diagonalize_vector', + + 'DotProduct', + + 'kronecker_product', 'KroneckerProduct', 'combine_kronecker', + + 'PermutationMatrix', 'MatrixPermute', + + 'Permanent', 'per' +] diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..59a1d297352c20a11d8f0a17f67458993c8a9067 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/_shape.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/_shape.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c2fb2876e02ab4dbb9c91bac9a8e3ac995258b41 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/_shape.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/adjoint.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/adjoint.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c40e7f42bf132d5f3b3014ea18af811b0e237945 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/adjoint.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/applyfunc.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/applyfunc.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..183a6cdb365397f403ae5e4b72dca134fd7c84a1 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/applyfunc.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/blockmatrix.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/blockmatrix.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a6d644e3e2258933470866275a28fe8c0191b71d Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/blockmatrix.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/companion.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/companion.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8ca3817bcd3b83bcf46fe6946769b2e9273fcc6d Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/companion.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/determinant.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/determinant.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3fc753e9cd0e2a0dc8659c73422fcb9976ec3986 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/determinant.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/diagonal.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/diagonal.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..561d942af0618a05ca81ea72b4f5aaabb1ce165a Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/diagonal.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/dotproduct.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/dotproduct.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3050c119da5288e0c409ff01bc5b577e3a2e87a4 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/dotproduct.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/factorizations.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/factorizations.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b3a13eae9d24e27066dc56c5aaef052569936d0d Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/factorizations.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/fourier.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/fourier.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ad44aa4858b7392b378c178cc8e9ca70ffa5349b Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/fourier.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/funcmatrix.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/funcmatrix.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4c9f02e2323ad351c456841388078256ec7324a6 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/funcmatrix.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/hadamard.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/hadamard.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..956910a5f77542e54765c1b2a5325178555f1be3 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/hadamard.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/inverse.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/inverse.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7968d748fa3313020e8d0c6c5839665989ce7312 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/inverse.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/kronecker.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/kronecker.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9dff866a1cb3d4b6f667f1006b6b517b98792adc Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/kronecker.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/matadd.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/matadd.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3c252058a05b4443897880494bdf9c6f1dcdbc44 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/matadd.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/matexpr.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/matexpr.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..897ac4b8b976ab9c446faae61366599cb441563f Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/matexpr.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/matmul.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/matmul.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1c68e3395ea522198983f3333efd54929cb2152b Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/matmul.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/matpow.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/matpow.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5902db01be9fbbf005260ff792777fb08a4f71d6 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/matpow.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/permutation.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/permutation.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d9ea1e29810469ee4505575bad83e7a3cd8c0523 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/permutation.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/sets.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/sets.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..71efadba4a868038b8f2306c273493d77ed86d86 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/sets.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/slice.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/slice.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..457ed66d32947bb03110aa8cf2c8b9cab58b802a Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/slice.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/special.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/special.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3c6660e006208f7c52e60ec9abda269d42aa5275 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/special.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/trace.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/trace.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e8544d921bd582fb82e0b245a2f262007348b9dd Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/trace.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/transpose.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/transpose.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..067817648bd30c25142a5e4aab36f6591f1bab85 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/__pycache__/transpose.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/_shape.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/_shape.py new file mode 100644 index 0000000000000000000000000000000000000000..a95d481bf8e1edf4c62992044cd50563b335caac --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/_shape.py @@ -0,0 +1,102 @@ +from sympy.core.relational import Eq +from sympy.core.expr import Expr +from sympy.core.numbers import Integer +from sympy.logic.boolalg import Boolean, And +from sympy.matrices.expressions.matexpr import MatrixExpr +from sympy.matrices.exceptions import ShapeError +from typing import Union + + +def is_matadd_valid(*args: MatrixExpr) -> Boolean: + """Return the symbolic condition how ``MatAdd``, ``HadamardProduct`` + makes sense. + + Parameters + ========== + + args + The list of arguments of matrices to be tested for. + + Examples + ======== + + >>> from sympy import MatrixSymbol, symbols + >>> from sympy.matrices.expressions._shape import is_matadd_valid + + >>> m, n, p, q = symbols('m n p q') + >>> A = MatrixSymbol('A', m, n) + >>> B = MatrixSymbol('B', p, q) + >>> is_matadd_valid(A, B) + Eq(m, p) & Eq(n, q) + """ + rows, cols = zip(*(arg.shape for arg in args)) + return And( + *(Eq(i, j) for i, j in zip(rows[:-1], rows[1:])), + *(Eq(i, j) for i, j in zip(cols[:-1], cols[1:])), + ) + + +def is_matmul_valid(*args: Union[MatrixExpr, Expr]) -> Boolean: + """Return the symbolic condition how ``MatMul`` makes sense + + Parameters + ========== + + args + The list of arguments of matrices and scalar expressions to be tested + for. + + Examples + ======== + + >>> from sympy import MatrixSymbol, symbols + >>> from sympy.matrices.expressions._shape import is_matmul_valid + + >>> m, n, p, q = symbols('m n p q') + >>> A = MatrixSymbol('A', m, n) + >>> B = MatrixSymbol('B', p, q) + >>> is_matmul_valid(A, B) + Eq(n, p) + """ + rows, cols = zip(*(arg.shape for arg in args if isinstance(arg, MatrixExpr))) + return And(*(Eq(i, j) for i, j in zip(cols[:-1], rows[1:]))) + + +def is_square(arg: MatrixExpr, /) -> Boolean: + """Return the symbolic condition how the matrix is assumed to be square + + Parameters + ========== + + arg + The matrix to be tested for. + + Examples + ======== + + >>> from sympy import MatrixSymbol, symbols + >>> from sympy.matrices.expressions._shape import is_square + + >>> m, n = symbols('m n') + >>> A = MatrixSymbol('A', m, n) + >>> is_square(A) + Eq(m, n) + """ + return Eq(arg.rows, arg.cols) + + +def validate_matadd_integer(*args: MatrixExpr) -> None: + """Validate matrix shape for addition only for integer values""" + rows, cols = zip(*(x.shape for x in args)) + if len(set(filter(lambda x: isinstance(x, (int, Integer)), rows))) > 1: + raise ShapeError(f"Matrices have mismatching shape: {rows}") + if len(set(filter(lambda x: isinstance(x, (int, Integer)), cols))) > 1: + raise ShapeError(f"Matrices have mismatching shape: {cols}") + + +def validate_matmul_integer(*args: MatrixExpr) -> None: + """Validate matrix shape for multiplication only for integer values""" + for A, B in zip(args[:-1], args[1:]): + i, j = A.cols, B.rows + if isinstance(i, (int, Integer)) and isinstance(j, (int, Integer)) and i != j: + raise ShapeError("Matrices are not aligned", i, j) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/adjoint.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/adjoint.py new file mode 100644 index 0000000000000000000000000000000000000000..2039a7b2eb8eeacb02435979121c4133a11d8e02 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/adjoint.py @@ -0,0 +1,60 @@ +from sympy.core import Basic +from sympy.functions import adjoint, conjugate +from sympy.matrices.expressions.matexpr import MatrixExpr + + +class Adjoint(MatrixExpr): + """ + The Hermitian adjoint of a matrix expression. + + This is a symbolic object that simply stores its argument without + evaluating it. To actually compute the adjoint, use the ``adjoint()`` + function. + + Examples + ======== + + >>> from sympy import MatrixSymbol, Adjoint, adjoint + >>> A = MatrixSymbol('A', 3, 5) + >>> B = MatrixSymbol('B', 5, 3) + >>> Adjoint(A*B) + Adjoint(A*B) + >>> adjoint(A*B) + Adjoint(B)*Adjoint(A) + >>> adjoint(A*B) == Adjoint(A*B) + False + >>> adjoint(A*B) == Adjoint(A*B).doit() + True + """ + is_Adjoint = True + + def doit(self, **hints): + arg = self.arg + if hints.get('deep', True) and isinstance(arg, Basic): + return adjoint(arg.doit(**hints)) + else: + return adjoint(self.arg) + + @property + def arg(self): + return self.args[0] + + @property + def shape(self): + return self.arg.shape[::-1] + + def _entry(self, i, j, **kwargs): + return conjugate(self.arg._entry(j, i, **kwargs)) + + def _eval_adjoint(self): + return self.arg + + def _eval_transpose(self): + return self.arg.conjugate() + + def _eval_conjugate(self): + return self.arg.transpose() + + def _eval_trace(self): + from sympy.matrices.expressions.trace import Trace + return conjugate(Trace(self.arg)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/applyfunc.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/applyfunc.py new file mode 100644 index 0000000000000000000000000000000000000000..c0363658447a8dc37a152b30e45533bac582b10c --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/applyfunc.py @@ -0,0 +1,204 @@ +from sympy.core.expr import ExprBuilder +from sympy.core.function import (Function, FunctionClass, Lambda) +from sympy.core.symbol import Dummy +from sympy.core.sympify import sympify, _sympify +from sympy.matrices.expressions import MatrixExpr +from sympy.matrices.matrixbase import MatrixBase + + +class ElementwiseApplyFunction(MatrixExpr): + r""" + Apply function to a matrix elementwise without evaluating. + + Examples + ======== + + It can be created by calling ``.applyfunc()`` on a matrix + expression: + + >>> from sympy import MatrixSymbol + >>> from sympy.matrices.expressions.applyfunc import ElementwiseApplyFunction + >>> from sympy import exp + >>> X = MatrixSymbol("X", 3, 3) + >>> X.applyfunc(exp) + Lambda(_d, exp(_d)).(X) + + Otherwise using the class constructor: + + >>> from sympy import eye + >>> expr = ElementwiseApplyFunction(exp, eye(3)) + >>> expr + Lambda(_d, exp(_d)).(Matrix([ + [1, 0, 0], + [0, 1, 0], + [0, 0, 1]])) + >>> expr.doit() + Matrix([ + [E, 1, 1], + [1, E, 1], + [1, 1, E]]) + + Notice the difference with the real mathematical functions: + + >>> exp(eye(3)) + Matrix([ + [E, 0, 0], + [0, E, 0], + [0, 0, E]]) + """ + + def __new__(cls, function, expr): + expr = _sympify(expr) + if not expr.is_Matrix: + raise ValueError("{} must be a matrix instance.".format(expr)) + + if expr.shape == (1, 1): + # Check if the function returns a matrix, in that case, just apply + # the function instead of creating an ElementwiseApplyFunc object: + ret = function(expr) + if isinstance(ret, MatrixExpr): + return ret + + if not isinstance(function, (FunctionClass, Lambda)): + d = Dummy('d') + function = Lambda(d, function(d)) + + function = sympify(function) + if not isinstance(function, (FunctionClass, Lambda)): + raise ValueError( + "{} should be compatible with SymPy function classes." + .format(function)) + + if 1 not in function.nargs: + raise ValueError( + '{} should be able to accept 1 arguments.'.format(function)) + + if not isinstance(function, Lambda): + d = Dummy('d') + function = Lambda(d, function(d)) + + obj = MatrixExpr.__new__(cls, function, expr) + return obj + + @property + def function(self): + return self.args[0] + + @property + def expr(self): + return self.args[1] + + @property + def shape(self): + return self.expr.shape + + def doit(self, **hints): + deep = hints.get("deep", True) + expr = self.expr + if deep: + expr = expr.doit(**hints) + function = self.function + if isinstance(function, Lambda) and function.is_identity: + # This is a Lambda containing the identity function. + return expr + if isinstance(expr, MatrixBase): + return expr.applyfunc(self.function) + elif isinstance(expr, ElementwiseApplyFunction): + return ElementwiseApplyFunction( + lambda x: self.function(expr.function(x)), + expr.expr + ).doit(**hints) + else: + return self + + def _entry(self, i, j, **kwargs): + return self.function(self.expr._entry(i, j, **kwargs)) + + def _get_function_fdiff(self): + d = Dummy("d") + function = self.function(d) + fdiff = function.diff(d) + if isinstance(fdiff, Function): + fdiff = type(fdiff) + else: + fdiff = Lambda(d, fdiff) + return fdiff + + def _eval_derivative(self, x): + from sympy.matrices.expressions.hadamard import hadamard_product + dexpr = self.expr.diff(x) + fdiff = self._get_function_fdiff() + return hadamard_product( + dexpr, + ElementwiseApplyFunction(fdiff, self.expr) + ) + + def _eval_derivative_matrix_lines(self, x): + from sympy.matrices.expressions.special import Identity + from sympy.tensor.array.expressions.array_expressions import ArrayContraction + from sympy.tensor.array.expressions.array_expressions import ArrayDiagonal + from sympy.tensor.array.expressions.array_expressions import ArrayTensorProduct + + fdiff = self._get_function_fdiff() + lr = self.expr._eval_derivative_matrix_lines(x) + ewdiff = ElementwiseApplyFunction(fdiff, self.expr) + if 1 in x.shape: + # Vector: + iscolumn = self.shape[1] == 1 + for i in lr: + if iscolumn: + ptr1 = i.first_pointer + ptr2 = Identity(self.shape[1]) + else: + ptr1 = Identity(self.shape[0]) + ptr2 = i.second_pointer + + subexpr = ExprBuilder( + ArrayDiagonal, + [ + ExprBuilder( + ArrayTensorProduct, + [ + ewdiff, + ptr1, + ptr2, + ] + ), + (0, 2) if iscolumn else (1, 4) + ], + validator=ArrayDiagonal._validate + ) + i._lines = [subexpr] + i._first_pointer_parent = subexpr.args[0].args + i._first_pointer_index = 1 + i._second_pointer_parent = subexpr.args[0].args + i._second_pointer_index = 2 + else: + # Matrix case: + for i in lr: + ptr1 = i.first_pointer + ptr2 = i.second_pointer + newptr1 = Identity(ptr1.shape[1]) + newptr2 = Identity(ptr2.shape[1]) + subexpr = ExprBuilder( + ArrayContraction, + [ + ExprBuilder( + ArrayTensorProduct, + [ptr1, newptr1, ewdiff, ptr2, newptr2] + ), + (1, 2, 4), + (5, 7, 8), + ], + validator=ArrayContraction._validate + ) + i._first_pointer_parent = subexpr.args[0].args + i._first_pointer_index = 1 + i._second_pointer_parent = subexpr.args[0].args + i._second_pointer_index = 4 + i._lines = [subexpr] + return lr + + def _eval_transpose(self): + from sympy.matrices.expressions.transpose import Transpose + return self.func(self.function, Transpose(self.expr).doit()) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/blockmatrix.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/blockmatrix.py new file mode 100644 index 0000000000000000000000000000000000000000..0125d6233ba7cf8c0b590fbb655d9c7c447e0bd4 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/blockmatrix.py @@ -0,0 +1,975 @@ +from sympy.assumptions.ask import (Q, ask) +from sympy.core import Basic, Add, Mul, S +from sympy.core.sympify import _sympify +from sympy.functions.elementary.complexes import re, im +from sympy.strategies import typed, exhaust, condition, do_one, unpack +from sympy.strategies.traverse import bottom_up +from sympy.utilities.iterables import is_sequence, sift +from sympy.utilities.misc import filldedent + +from sympy.matrices import Matrix, ShapeError +from sympy.matrices.exceptions import NonInvertibleMatrixError +from sympy.matrices.expressions.determinant import det, Determinant +from sympy.matrices.expressions.inverse import Inverse +from sympy.matrices.expressions.matadd import MatAdd +from sympy.matrices.expressions.matexpr import MatrixExpr, MatrixElement +from sympy.matrices.expressions.matmul import MatMul +from sympy.matrices.expressions.matpow import MatPow +from sympy.matrices.expressions.slice import MatrixSlice +from sympy.matrices.expressions.special import ZeroMatrix, Identity +from sympy.matrices.expressions.trace import trace +from sympy.matrices.expressions.transpose import Transpose, transpose + + +class BlockMatrix(MatrixExpr): + """A BlockMatrix is a Matrix comprised of other matrices. + + The submatrices are stored in a SymPy Matrix object but accessed as part of + a Matrix Expression + + >>> from sympy import (MatrixSymbol, BlockMatrix, symbols, + ... Identity, ZeroMatrix, block_collapse) + >>> n,m,l = symbols('n m l') + >>> X = MatrixSymbol('X', n, n) + >>> Y = MatrixSymbol('Y', m, m) + >>> Z = MatrixSymbol('Z', n, m) + >>> B = BlockMatrix([[X, Z], [ZeroMatrix(m,n), Y]]) + >>> print(B) + Matrix([ + [X, Z], + [0, Y]]) + + >>> C = BlockMatrix([[Identity(n), Z]]) + >>> print(C) + Matrix([[I, Z]]) + + >>> print(block_collapse(C*B)) + Matrix([[X, Z + Z*Y]]) + + Some matrices might be comprised of rows of blocks with + the matrices in each row having the same height and the + rows all having the same total number of columns but + not having the same number of columns for each matrix + in each row. In this case, the matrix is not a block + matrix and should be instantiated by Matrix. + + >>> from sympy import ones, Matrix + >>> dat = [ + ... [ones(3,2), ones(3,3)*2], + ... [ones(2,3)*3, ones(2,2)*4]] + ... + >>> BlockMatrix(dat) + Traceback (most recent call last): + ... + ValueError: + Although this matrix is comprised of blocks, the blocks do not fill + the matrix in a size-symmetric fashion. To create a full matrix from + these arguments, pass them directly to Matrix. + >>> Matrix(dat) + Matrix([ + [1, 1, 2, 2, 2], + [1, 1, 2, 2, 2], + [1, 1, 2, 2, 2], + [3, 3, 3, 4, 4], + [3, 3, 3, 4, 4]]) + + See Also + ======== + sympy.matrices.matrixbase.MatrixBase.irregular + """ + def __new__(cls, *args, **kwargs): + from sympy.matrices.immutable import ImmutableDenseMatrix + isMat = lambda i: getattr(i, 'is_Matrix', False) + if len(args) != 1 or \ + not is_sequence(args[0]) or \ + len({isMat(r) for r in args[0]}) != 1: + raise ValueError(filldedent(''' + expecting a sequence of 1 or more rows + containing Matrices.''')) + rows = args[0] if args else [] + if not isMat(rows): + if rows and isMat(rows[0]): + rows = [rows] # rows is not list of lists or [] + # regularity check + # same number of matrices in each row + blocky = ok = len({len(r) for r in rows}) == 1 + if ok: + # same number of rows for each matrix in a row + for r in rows: + ok = len({i.rows for i in r}) == 1 + if not ok: + break + blocky = ok + if ok: + # same number of cols for each matrix in each col + for c in range(len(rows[0])): + ok = len({rows[i][c].cols + for i in range(len(rows))}) == 1 + if not ok: + break + if not ok: + # same total cols in each row + ok = len({ + sum(i.cols for i in r) for r in rows}) == 1 + if blocky and ok: + raise ValueError(filldedent(''' + Although this matrix is comprised of blocks, + the blocks do not fill the matrix in a + size-symmetric fashion. To create a full matrix + from these arguments, pass them directly to + Matrix.''')) + raise ValueError(filldedent(''' + When there are not the same number of rows in each + row's matrices or there are not the same number of + total columns in each row, the matrix is not a + block matrix. If this matrix is known to consist of + blocks fully filling a 2-D space then see + Matrix.irregular.''')) + mat = ImmutableDenseMatrix(rows, evaluate=False) + obj = Basic.__new__(cls, mat) + return obj + + @property + def shape(self): + numrows = numcols = 0 + M = self.blocks + for i in range(M.shape[0]): + numrows += M[i, 0].shape[0] + for i in range(M.shape[1]): + numcols += M[0, i].shape[1] + return (numrows, numcols) + + @property + def blockshape(self): + return self.blocks.shape + + @property + def blocks(self): + return self.args[0] + + @property + def rowblocksizes(self): + return [self.blocks[i, 0].rows for i in range(self.blockshape[0])] + + @property + def colblocksizes(self): + return [self.blocks[0, i].cols for i in range(self.blockshape[1])] + + def structurally_equal(self, other): + return (isinstance(other, BlockMatrix) + and self.shape == other.shape + and self.blockshape == other.blockshape + and self.rowblocksizes == other.rowblocksizes + and self.colblocksizes == other.colblocksizes) + + def _blockmul(self, other): + if (isinstance(other, BlockMatrix) and + self.colblocksizes == other.rowblocksizes): + return BlockMatrix(self.blocks*other.blocks) + + return self * other + + def _blockadd(self, other): + if (isinstance(other, BlockMatrix) + and self.structurally_equal(other)): + return BlockMatrix(self.blocks + other.blocks) + + return self + other + + def _eval_transpose(self): + # Flip all the individual matrices + matrices = [transpose(matrix) for matrix in self.blocks] + # Make a copy + M = Matrix(self.blockshape[0], self.blockshape[1], matrices) + # Transpose the block structure + M = M.transpose() + return BlockMatrix(M) + + def _eval_adjoint(self): + return BlockMatrix( + Matrix(self.blockshape[0], self.blockshape[1], self.blocks).adjoint() + ) + + def _eval_trace(self): + if self.rowblocksizes == self.colblocksizes: + blocks = [self.blocks[i, i] for i in range(self.blockshape[0])] + return Add(*[trace(block) for block in blocks]) + + def _eval_determinant(self): + if self.blockshape == (1, 1): + return det(self.blocks[0, 0]) + if self.blockshape == (2, 2): + [[A, B], + [C, D]] = self.blocks.tolist() + if ask(Q.invertible(A)): + return det(A)*det(D - C*A.I*B) + elif ask(Q.invertible(D)): + return det(D)*det(A - B*D.I*C) + return Determinant(self) + + def _eval_as_real_imag(self): + real_matrices = [re(matrix) for matrix in self.blocks] + real_matrices = Matrix(self.blockshape[0], self.blockshape[1], real_matrices) + + im_matrices = [im(matrix) for matrix in self.blocks] + im_matrices = Matrix(self.blockshape[0], self.blockshape[1], im_matrices) + + return (BlockMatrix(real_matrices), BlockMatrix(im_matrices)) + + def _eval_derivative(self, x): + return BlockMatrix(self.blocks.diff(x)) + + def transpose(self): + """Return transpose of matrix. + + Examples + ======== + + >>> from sympy import MatrixSymbol, BlockMatrix, ZeroMatrix + >>> from sympy.abc import m, n + >>> X = MatrixSymbol('X', n, n) + >>> Y = MatrixSymbol('Y', m, m) + >>> Z = MatrixSymbol('Z', n, m) + >>> B = BlockMatrix([[X, Z], [ZeroMatrix(m,n), Y]]) + >>> B.transpose() + Matrix([ + [X.T, 0], + [Z.T, Y.T]]) + >>> _.transpose() + Matrix([ + [X, Z], + [0, Y]]) + """ + return self._eval_transpose() + + def schur(self, mat = 'A', generalized = False): + """Return the Schur Complement of the 2x2 BlockMatrix + + Parameters + ========== + + mat : String, optional + The matrix with respect to which the + Schur Complement is calculated. 'A' is + used by default + + generalized : bool, optional + If True, returns the generalized Schur + Component which uses Moore-Penrose Inverse + + Examples + ======== + + >>> from sympy import symbols, MatrixSymbol, BlockMatrix + >>> m, n = symbols('m n') + >>> A = MatrixSymbol('A', n, n) + >>> B = MatrixSymbol('B', n, m) + >>> C = MatrixSymbol('C', m, n) + >>> D = MatrixSymbol('D', m, m) + >>> X = BlockMatrix([[A, B], [C, D]]) + + The default Schur Complement is evaluated with "A" + + >>> X.schur() + -C*A**(-1)*B + D + >>> X.schur('D') + A - B*D**(-1)*C + + Schur complement with non-invertible matrices is not + defined. Instead, the generalized Schur complement can + be calculated which uses the Moore-Penrose Inverse. To + achieve this, `generalized` must be set to `True` + + >>> X.schur('B', generalized=True) + C - D*(B.T*B)**(-1)*B.T*A + >>> X.schur('C', generalized=True) + -A*(C.T*C)**(-1)*C.T*D + B + + Returns + ======= + + M : Matrix + The Schur Complement Matrix + + Raises + ====== + + ShapeError + If the block matrix is not a 2x2 matrix + + NonInvertibleMatrixError + If given matrix is non-invertible + + References + ========== + + .. [1] Wikipedia Article on Schur Component : https://en.wikipedia.org/wiki/Schur_complement + + See Also + ======== + + sympy.matrices.matrixbase.MatrixBase.pinv + """ + + if self.blockshape == (2, 2): + [[A, B], + [C, D]] = self.blocks.tolist() + d={'A' : A, 'B' : B, 'C' : C, 'D' : D} + try: + inv = (d[mat].T*d[mat]).inv()*d[mat].T if generalized else d[mat].inv() + if mat == 'A': + return D - C * inv * B + elif mat == 'B': + return C - D * inv * A + elif mat == 'C': + return B - A * inv * D + elif mat == 'D': + return A - B * inv * C + #For matrices where no sub-matrix is square + return self + except NonInvertibleMatrixError: + raise NonInvertibleMatrixError('The given matrix is not invertible. Please set generalized=True \ + to compute the generalized Schur Complement which uses Moore-Penrose Inverse') + else: + raise ShapeError('Schur Complement can only be calculated for 2x2 block matrices') + + def LDUdecomposition(self): + """Returns the Block LDU decomposition of + a 2x2 Block Matrix + + Returns + ======= + + (L, D, U) : Matrices + L : Lower Diagonal Matrix + D : Diagonal Matrix + U : Upper Diagonal Matrix + + Examples + ======== + + >>> from sympy import symbols, MatrixSymbol, BlockMatrix, block_collapse + >>> m, n = symbols('m n') + >>> A = MatrixSymbol('A', n, n) + >>> B = MatrixSymbol('B', n, m) + >>> C = MatrixSymbol('C', m, n) + >>> D = MatrixSymbol('D', m, m) + >>> X = BlockMatrix([[A, B], [C, D]]) + >>> L, D, U = X.LDUdecomposition() + >>> block_collapse(L*D*U) + Matrix([ + [A, B], + [C, D]]) + + Raises + ====== + + ShapeError + If the block matrix is not a 2x2 matrix + + NonInvertibleMatrixError + If the matrix "A" is non-invertible + + See Also + ======== + sympy.matrices.expressions.blockmatrix.BlockMatrix.UDLdecomposition + sympy.matrices.expressions.blockmatrix.BlockMatrix.LUdecomposition + """ + if self.blockshape == (2,2): + [[A, B], + [C, D]] = self.blocks.tolist() + try: + AI = A.I + except NonInvertibleMatrixError: + raise NonInvertibleMatrixError('Block LDU decomposition cannot be calculated when\ + "A" is singular') + Ip = Identity(B.shape[0]) + Iq = Identity(B.shape[1]) + Z = ZeroMatrix(*B.shape) + L = BlockMatrix([[Ip, Z], [C*AI, Iq]]) + D = BlockDiagMatrix(A, self.schur()) + U = BlockMatrix([[Ip, AI*B],[Z.T, Iq]]) + return L, D, U + else: + raise ShapeError("Block LDU decomposition is supported only for 2x2 block matrices") + + def UDLdecomposition(self): + """Returns the Block UDL decomposition of + a 2x2 Block Matrix + + Returns + ======= + + (U, D, L) : Matrices + U : Upper Diagonal Matrix + D : Diagonal Matrix + L : Lower Diagonal Matrix + + Examples + ======== + + >>> from sympy import symbols, MatrixSymbol, BlockMatrix, block_collapse + >>> m, n = symbols('m n') + >>> A = MatrixSymbol('A', n, n) + >>> B = MatrixSymbol('B', n, m) + >>> C = MatrixSymbol('C', m, n) + >>> D = MatrixSymbol('D', m, m) + >>> X = BlockMatrix([[A, B], [C, D]]) + >>> U, D, L = X.UDLdecomposition() + >>> block_collapse(U*D*L) + Matrix([ + [A, B], + [C, D]]) + + Raises + ====== + + ShapeError + If the block matrix is not a 2x2 matrix + + NonInvertibleMatrixError + If the matrix "D" is non-invertible + + See Also + ======== + sympy.matrices.expressions.blockmatrix.BlockMatrix.LDUdecomposition + sympy.matrices.expressions.blockmatrix.BlockMatrix.LUdecomposition + """ + if self.blockshape == (2,2): + [[A, B], + [C, D]] = self.blocks.tolist() + try: + DI = D.I + except NonInvertibleMatrixError: + raise NonInvertibleMatrixError('Block UDL decomposition cannot be calculated when\ + "D" is singular') + Ip = Identity(A.shape[0]) + Iq = Identity(B.shape[1]) + Z = ZeroMatrix(*B.shape) + U = BlockMatrix([[Ip, B*DI], [Z.T, Iq]]) + D = BlockDiagMatrix(self.schur('D'), D) + L = BlockMatrix([[Ip, Z],[DI*C, Iq]]) + return U, D, L + else: + raise ShapeError("Block UDL decomposition is supported only for 2x2 block matrices") + + def LUdecomposition(self): + """Returns the Block LU decomposition of + a 2x2 Block Matrix + + Returns + ======= + + (L, U) : Matrices + L : Lower Diagonal Matrix + U : Upper Diagonal Matrix + + Examples + ======== + + >>> from sympy import symbols, MatrixSymbol, BlockMatrix, block_collapse + >>> m, n = symbols('m n') + >>> A = MatrixSymbol('A', n, n) + >>> B = MatrixSymbol('B', n, m) + >>> C = MatrixSymbol('C', m, n) + >>> D = MatrixSymbol('D', m, m) + >>> X = BlockMatrix([[A, B], [C, D]]) + >>> L, U = X.LUdecomposition() + >>> block_collapse(L*U) + Matrix([ + [A, B], + [C, D]]) + + Raises + ====== + + ShapeError + If the block matrix is not a 2x2 matrix + + NonInvertibleMatrixError + If the matrix "A" is non-invertible + + See Also + ======== + sympy.matrices.expressions.blockmatrix.BlockMatrix.UDLdecomposition + sympy.matrices.expressions.blockmatrix.BlockMatrix.LDUdecomposition + """ + if self.blockshape == (2,2): + [[A, B], + [C, D]] = self.blocks.tolist() + try: + A = A**S.Half + AI = A.I + except NonInvertibleMatrixError: + raise NonInvertibleMatrixError('Block LU decomposition cannot be calculated when\ + "A" is singular') + Z = ZeroMatrix(*B.shape) + Q = self.schur()**S.Half + L = BlockMatrix([[A, Z], [C*AI, Q]]) + U = BlockMatrix([[A, AI*B],[Z.T, Q]]) + return L, U + else: + raise ShapeError("Block LU decomposition is supported only for 2x2 block matrices") + + def _entry(self, i, j, **kwargs): + # Find row entry + orig_i, orig_j = i, j + for row_block, numrows in enumerate(self.rowblocksizes): + cmp = i < numrows + if cmp == True: + break + elif cmp == False: + i -= numrows + elif row_block < self.blockshape[0] - 1: + # Can't tell which block and it's not the last one, return unevaluated + return MatrixElement(self, orig_i, orig_j) + for col_block, numcols in enumerate(self.colblocksizes): + cmp = j < numcols + if cmp == True: + break + elif cmp == False: + j -= numcols + elif col_block < self.blockshape[1] - 1: + return MatrixElement(self, orig_i, orig_j) + return self.blocks[row_block, col_block][i, j] + + @property + def is_Identity(self): + if self.blockshape[0] != self.blockshape[1]: + return False + for i in range(self.blockshape[0]): + for j in range(self.blockshape[1]): + if i==j and not self.blocks[i, j].is_Identity: + return False + if i!=j and not self.blocks[i, j].is_ZeroMatrix: + return False + return True + + @property + def is_structurally_symmetric(self): + return self.rowblocksizes == self.colblocksizes + + def equals(self, other): + if self == other: + return True + if (isinstance(other, BlockMatrix) and self.blocks == other.blocks): + return True + return super().equals(other) + + +class BlockDiagMatrix(BlockMatrix): + """A sparse matrix with block matrices along its diagonals + + Examples + ======== + + >>> from sympy import MatrixSymbol, BlockDiagMatrix, symbols + >>> n, m, l = symbols('n m l') + >>> X = MatrixSymbol('X', n, n) + >>> Y = MatrixSymbol('Y', m, m) + >>> BlockDiagMatrix(X, Y) + Matrix([ + [X, 0], + [0, Y]]) + + Notes + ===== + + If you want to get the individual diagonal blocks, use + :meth:`get_diag_blocks`. + + See Also + ======== + + sympy.matrices.dense.diag + """ + def __new__(cls, *mats): + return Basic.__new__(BlockDiagMatrix, *[_sympify(m) for m in mats]) + + @property + def diag(self): + return self.args + + @property + def blocks(self): + from sympy.matrices.immutable import ImmutableDenseMatrix + mats = self.args + data = [[mats[i] if i == j else ZeroMatrix(mats[i].rows, mats[j].cols) + for j in range(len(mats))] + for i in range(len(mats))] + return ImmutableDenseMatrix(data, evaluate=False) + + @property + def shape(self): + return (sum(block.rows for block in self.args), + sum(block.cols for block in self.args)) + + @property + def blockshape(self): + n = len(self.args) + return (n, n) + + @property + def rowblocksizes(self): + return [block.rows for block in self.args] + + @property + def colblocksizes(self): + return [block.cols for block in self.args] + + def _all_square_blocks(self): + """Returns true if all blocks are square""" + return all(mat.is_square for mat in self.args) + + def _eval_determinant(self): + if self._all_square_blocks(): + return Mul(*[det(mat) for mat in self.args]) + # At least one block is non-square. Since the entire matrix must be square we know there must + # be at least two blocks in this matrix, in which case the entire matrix is necessarily rank-deficient + return S.Zero + + def _eval_inverse(self, expand='ignored'): + if self._all_square_blocks(): + return BlockDiagMatrix(*[mat.inverse() for mat in self.args]) + # See comment in _eval_determinant() + raise NonInvertibleMatrixError('Matrix det == 0; not invertible.') + + def _eval_transpose(self): + return BlockDiagMatrix(*[mat.transpose() for mat in self.args]) + + def _blockmul(self, other): + if (isinstance(other, BlockDiagMatrix) and + self.colblocksizes == other.rowblocksizes): + return BlockDiagMatrix(*[a*b for a, b in zip(self.args, other.args)]) + else: + return BlockMatrix._blockmul(self, other) + + def _blockadd(self, other): + if (isinstance(other, BlockDiagMatrix) and + self.blockshape == other.blockshape and + self.rowblocksizes == other.rowblocksizes and + self.colblocksizes == other.colblocksizes): + return BlockDiagMatrix(*[a + b for a, b in zip(self.args, other.args)]) + else: + return BlockMatrix._blockadd(self, other) + + def get_diag_blocks(self): + """Return the list of diagonal blocks of the matrix. + + Examples + ======== + + >>> from sympy import BlockDiagMatrix, Matrix + + >>> A = Matrix([[1, 2], [3, 4]]) + >>> B = Matrix([[5, 6], [7, 8]]) + >>> M = BlockDiagMatrix(A, B) + + How to get diagonal blocks from the block diagonal matrix: + + >>> diag_blocks = M.get_diag_blocks() + >>> diag_blocks[0] + Matrix([ + [1, 2], + [3, 4]]) + >>> diag_blocks[1] + Matrix([ + [5, 6], + [7, 8]]) + """ + return self.args + + +def block_collapse(expr): + """Evaluates a block matrix expression + + >>> from sympy import MatrixSymbol, BlockMatrix, symbols, Identity, ZeroMatrix, block_collapse + >>> n,m,l = symbols('n m l') + >>> X = MatrixSymbol('X', n, n) + >>> Y = MatrixSymbol('Y', m, m) + >>> Z = MatrixSymbol('Z', n, m) + >>> B = BlockMatrix([[X, Z], [ZeroMatrix(m, n), Y]]) + >>> print(B) + Matrix([ + [X, Z], + [0, Y]]) + + >>> C = BlockMatrix([[Identity(n), Z]]) + >>> print(C) + Matrix([[I, Z]]) + + >>> print(block_collapse(C*B)) + Matrix([[X, Z + Z*Y]]) + """ + from sympy.strategies.util import expr_fns + + hasbm = lambda expr: isinstance(expr, MatrixExpr) and expr.has(BlockMatrix) + + conditioned_rl = condition( + hasbm, + typed( + {MatAdd: do_one(bc_matadd, bc_block_plus_ident), + MatMul: do_one(bc_matmul, bc_dist), + MatPow: bc_matmul, + Transpose: bc_transpose, + Inverse: bc_inverse, + BlockMatrix: do_one(bc_unpack, deblock)} + ) + ) + + rule = exhaust( + bottom_up( + exhaust(conditioned_rl), + fns=expr_fns + ) + ) + + result = rule(expr) + doit = getattr(result, 'doit', None) + if doit is not None: + return doit() + else: + return result + +def bc_unpack(expr): + if expr.blockshape == (1, 1): + return expr.blocks[0, 0] + return expr + +def bc_matadd(expr): + args = sift(expr.args, lambda M: isinstance(M, BlockMatrix)) + blocks = args[True] + if not blocks: + return expr + + nonblocks = args[False] + block = blocks[0] + for b in blocks[1:]: + block = block._blockadd(b) + if nonblocks: + return MatAdd(*nonblocks) + block + else: + return block + +def bc_block_plus_ident(expr): + idents = [arg for arg in expr.args if arg.is_Identity] + if not idents: + return expr + + blocks = [arg for arg in expr.args if isinstance(arg, BlockMatrix)] + if (blocks and all(b.structurally_equal(blocks[0]) for b in blocks) + and blocks[0].is_structurally_symmetric): + block_id = BlockDiagMatrix(*[Identity(k) + for k in blocks[0].rowblocksizes]) + rest = [arg for arg in expr.args if not arg.is_Identity and not isinstance(arg, BlockMatrix)] + return MatAdd(block_id * len(idents), *blocks, *rest).doit() + + return expr + +def bc_dist(expr): + """ Turn a*[X, Y] into [a*X, a*Y] """ + factor, mat = expr.as_coeff_mmul() + if factor == 1: + return expr + + unpacked = unpack(mat) + + if isinstance(unpacked, BlockDiagMatrix): + B = unpacked.diag + new_B = [factor * mat for mat in B] + return BlockDiagMatrix(*new_B) + elif isinstance(unpacked, BlockMatrix): + B = unpacked.blocks + new_B = [ + [factor * B[i, j] for j in range(B.cols)] for i in range(B.rows)] + return BlockMatrix(new_B) + return expr + + +def bc_matmul(expr): + if isinstance(expr, MatPow): + if expr.args[1].is_Integer and expr.args[1] > 0: + factor, matrices = 1, [expr.args[0]]*expr.args[1] + else: + return expr + else: + factor, matrices = expr.as_coeff_matrices() + + i = 0 + while (i+1 < len(matrices)): + A, B = matrices[i:i+2] + if isinstance(A, BlockMatrix) and isinstance(B, BlockMatrix): + matrices[i] = A._blockmul(B) + matrices.pop(i+1) + elif isinstance(A, BlockMatrix): + matrices[i] = A._blockmul(BlockMatrix([[B]])) + matrices.pop(i+1) + elif isinstance(B, BlockMatrix): + matrices[i] = BlockMatrix([[A]])._blockmul(B) + matrices.pop(i+1) + else: + i+=1 + return MatMul(factor, *matrices).doit() + +def bc_transpose(expr): + collapse = block_collapse(expr.arg) + return collapse._eval_transpose() + + +def bc_inverse(expr): + if isinstance(expr.arg, BlockDiagMatrix): + return expr.inverse() + + expr2 = blockinverse_1x1(expr) + if expr != expr2: + return expr2 + return blockinverse_2x2(Inverse(reblock_2x2(expr.arg))) + +def blockinverse_1x1(expr): + if isinstance(expr.arg, BlockMatrix) and expr.arg.blockshape == (1, 1): + mat = Matrix([[expr.arg.blocks[0].inverse()]]) + return BlockMatrix(mat) + return expr + + +def blockinverse_2x2(expr): + if isinstance(expr.arg, BlockMatrix) and expr.arg.blockshape == (2, 2): + # See: Inverses of 2x2 Block Matrices, Tzon-Tzer Lu and Sheng-Hua Shiou + [[A, B], + [C, D]] = expr.arg.blocks.tolist() + + formula = _choose_2x2_inversion_formula(A, B, C, D) + if formula != None: + MI = expr.arg.schur(formula).I + if formula == 'A': + AI = A.I + return BlockMatrix([[AI + AI * B * MI * C * AI, -AI * B * MI], [-MI * C * AI, MI]]) + if formula == 'B': + BI = B.I + return BlockMatrix([[-MI * D * BI, MI], [BI + BI * A * MI * D * BI, -BI * A * MI]]) + if formula == 'C': + CI = C.I + return BlockMatrix([[-CI * D * MI, CI + CI * D * MI * A * CI], [MI, -MI * A * CI]]) + if formula == 'D': + DI = D.I + return BlockMatrix([[MI, -MI * B * DI], [-DI * C * MI, DI + DI * C * MI * B * DI]]) + + return expr + + +def _choose_2x2_inversion_formula(A, B, C, D): + """ + Assuming [[A, B], [C, D]] would form a valid square block matrix, find + which of the classical 2x2 block matrix inversion formulas would be + best suited. + + Returns 'A', 'B', 'C', 'D' to represent the algorithm involving inversion + of the given argument or None if the matrix cannot be inverted using + any of those formulas. + """ + # Try to find a known invertible matrix. Note that the Schur complement + # is currently not being considered for this + A_inv = ask(Q.invertible(A)) + if A_inv == True: + return 'A' + B_inv = ask(Q.invertible(B)) + if B_inv == True: + return 'B' + C_inv = ask(Q.invertible(C)) + if C_inv == True: + return 'C' + D_inv = ask(Q.invertible(D)) + if D_inv == True: + return 'D' + # Otherwise try to find a matrix that isn't known to be non-invertible + if A_inv != False: + return 'A' + if B_inv != False: + return 'B' + if C_inv != False: + return 'C' + if D_inv != False: + return 'D' + return None + + +def deblock(B): + """ Flatten a BlockMatrix of BlockMatrices """ + if not isinstance(B, BlockMatrix) or not B.blocks.has(BlockMatrix): + return B + wrap = lambda x: x if isinstance(x, BlockMatrix) else BlockMatrix([[x]]) + bb = B.blocks.applyfunc(wrap) # everything is a block + + try: + MM = Matrix(0, sum(bb[0, i].blocks.shape[1] for i in range(bb.shape[1])), []) + for row in range(0, bb.shape[0]): + M = Matrix(bb[row, 0].blocks) + for col in range(1, bb.shape[1]): + M = M.row_join(bb[row, col].blocks) + MM = MM.col_join(M) + + return BlockMatrix(MM) + except ShapeError: + return B + + +def reblock_2x2(expr): + """ + Reblock a BlockMatrix so that it has 2x2 blocks of block matrices. If + possible in such a way that the matrix continues to be invertible using the + classical 2x2 block inversion formulas. + """ + if not isinstance(expr, BlockMatrix) or not all(d > 2 for d in expr.blockshape): + return expr + + BM = BlockMatrix # for brevity's sake + rowblocks, colblocks = expr.blockshape + blocks = expr.blocks + for i in range(1, rowblocks): + for j in range(1, colblocks): + # try to split rows at i and cols at j + A = bc_unpack(BM(blocks[:i, :j])) + B = bc_unpack(BM(blocks[:i, j:])) + C = bc_unpack(BM(blocks[i:, :j])) + D = bc_unpack(BM(blocks[i:, j:])) + + formula = _choose_2x2_inversion_formula(A, B, C, D) + if formula is not None: + return BlockMatrix([[A, B], [C, D]]) + + # else: nothing worked, just split upper left corner + return BM([[blocks[0, 0], BM(blocks[0, 1:])], + [BM(blocks[1:, 0]), BM(blocks[1:, 1:])]]) + + +def bounds(sizes): + """ Convert sequence of numbers into pairs of low-high pairs + + >>> from sympy.matrices.expressions.blockmatrix import bounds + >>> bounds((1, 10, 50)) + [(0, 1), (1, 11), (11, 61)] + """ + low = 0 + rv = [] + for size in sizes: + rv.append((low, low + size)) + low += size + return rv + +def blockcut(expr, rowsizes, colsizes): + """ Cut a matrix expression into Blocks + + >>> from sympy import ImmutableMatrix, blockcut + >>> M = ImmutableMatrix(4, 4, range(16)) + >>> B = blockcut(M, (1, 3), (1, 3)) + >>> type(B).__name__ + 'BlockMatrix' + >>> ImmutableMatrix(B.blocks[0, 1]) + Matrix([[1, 2, 3]]) + """ + + rowbounds = bounds(rowsizes) + colbounds = bounds(colsizes) + return BlockMatrix([[MatrixSlice(expr, rowbound, colbound) + for colbound in colbounds] + for rowbound in rowbounds]) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/companion.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/companion.py new file mode 100644 index 0000000000000000000000000000000000000000..6969c917f63806cb1f5417804e01ecc1350d1406 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/companion.py @@ -0,0 +1,56 @@ +from sympy.core.singleton import S +from sympy.core.sympify import _sympify +from sympy.polys.polytools import Poly + +from .matexpr import MatrixExpr + + +class CompanionMatrix(MatrixExpr): + """A symbolic companion matrix of a polynomial. + + Examples + ======== + + >>> from sympy import Poly, Symbol, symbols + >>> from sympy.matrices.expressions import CompanionMatrix + >>> x = Symbol('x') + >>> c0, c1, c2, c3, c4 = symbols('c0:5') + >>> p = Poly(c0 + c1*x + c2*x**2 + c3*x**3 + c4*x**4 + x**5, x) + >>> CompanionMatrix(p) + CompanionMatrix(Poly(x**5 + c4*x**4 + c3*x**3 + c2*x**2 + c1*x + c0, + x, domain='ZZ[c0,c1,c2,c3,c4]')) + """ + def __new__(cls, poly): + poly = _sympify(poly) + if not isinstance(poly, Poly): + raise ValueError("{} must be a Poly instance.".format(poly)) + if not poly.is_monic: + raise ValueError("{} must be a monic polynomial.".format(poly)) + if not poly.is_univariate: + raise ValueError( + "{} must be a univariate polynomial.".format(poly)) + if not poly.degree() >= 1: + raise ValueError( + "{} must have degree not less than 1.".format(poly)) + + return super().__new__(cls, poly) + + + @property + def shape(self): + poly = self.args[0] + size = poly.degree() + return size, size + + + def _entry(self, i, j): + if j == self.cols - 1: + return -self.args[0].all_coeffs()[-1 - i] + elif i == j + 1: + return S.One + return S.Zero + + + def as_explicit(self): + from sympy.matrices.immutable import ImmutableDenseMatrix + return ImmutableDenseMatrix.companion(self.args[0]) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/determinant.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/determinant.py new file mode 100644 index 0000000000000000000000000000000000000000..b323b3f93a5a0404bf2205f39d25b931d173b6d9 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/determinant.py @@ -0,0 +1,148 @@ +from sympy.core.basic import Basic +from sympy.core.expr import Expr +from sympy.core.singleton import S +from sympy.core.sympify import sympify +from sympy.matrices.exceptions import NonSquareMatrixError +from sympy.matrices.matrixbase import MatrixBase + + +class Determinant(Expr): + """Matrix Determinant + + Represents the determinant of a matrix expression. + + Examples + ======== + + >>> from sympy import MatrixSymbol, Determinant, eye + >>> A = MatrixSymbol('A', 3, 3) + >>> Determinant(A) + Determinant(A) + >>> Determinant(eye(3)).doit() + 1 + """ + is_commutative = True + + def __new__(cls, mat): + mat = sympify(mat) + if not mat.is_Matrix: + raise TypeError("Input to Determinant, %s, not a matrix" % str(mat)) + + if mat.is_square is False: + raise NonSquareMatrixError("Det of a non-square matrix") + + return Basic.__new__(cls, mat) + + @property + def arg(self): + return self.args[0] + + @property + def kind(self): + return self.arg.kind.element_kind + + def doit(self, **hints): + arg = self.arg + if hints.get('deep', True): + arg = arg.doit(**hints) + + result = arg._eval_determinant() + if result is not None: + return result + + return self + + +def det(matexpr): + """ Matrix Determinant + + Examples + ======== + + >>> from sympy import MatrixSymbol, det, eye + >>> A = MatrixSymbol('A', 3, 3) + >>> det(A) + Determinant(A) + >>> det(eye(3)) + 1 + """ + + return Determinant(matexpr).doit() + +class Permanent(Expr): + """Matrix Permanent + + Represents the permanent of a matrix expression. + + Examples + ======== + + >>> from sympy import MatrixSymbol, Permanent, ones + >>> A = MatrixSymbol('A', 3, 3) + >>> Permanent(A) + Permanent(A) + >>> Permanent(ones(3, 3)).doit() + 6 + """ + + def __new__(cls, mat): + mat = sympify(mat) + if not mat.is_Matrix: + raise TypeError("Input to Permanent, %s, not a matrix" % str(mat)) + + return Basic.__new__(cls, mat) + + @property + def arg(self): + return self.args[0] + + def doit(self, expand=False, **hints): + if isinstance(self.arg, MatrixBase): + return self.arg.per() + else: + return self + +def per(matexpr): + """ Matrix Permanent + + Examples + ======== + + >>> from sympy import MatrixSymbol, Matrix, per, ones + >>> A = MatrixSymbol('A', 3, 3) + >>> per(A) + Permanent(A) + >>> per(ones(5, 5)) + 120 + >>> M = Matrix([1, 2, 5]) + >>> per(M) + 8 + """ + + return Permanent(matexpr).doit() + +from sympy.assumptions.ask import ask, Q +from sympy.assumptions.refine import handlers_dict + + +def refine_Determinant(expr, assumptions): + """ + >>> from sympy import MatrixSymbol, Q, assuming, refine, det + >>> X = MatrixSymbol('X', 2, 2) + >>> det(X) + Determinant(X) + >>> with assuming(Q.orthogonal(X)): + ... print(refine(det(X))) + 1 + """ + if ask(Q.orthogonal(expr.arg), assumptions): + return S.One + elif ask(Q.singular(expr.arg), assumptions): + return S.Zero + elif ask(Q.unit_triangular(expr.arg), assumptions): + return S.One + + return expr + + +handlers_dict['Determinant'] = refine_Determinant diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/diagonal.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/diagonal.py new file mode 100644 index 0000000000000000000000000000000000000000..ba8a0216588143e3e251dab84c25f038fad550a4 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/diagonal.py @@ -0,0 +1,220 @@ +from sympy.core.sympify import _sympify + +from sympy.matrices.expressions import MatrixExpr +from sympy.core import S, Eq, Ge +from sympy.core.mul import Mul +from sympy.functions.special.tensor_functions import KroneckerDelta + + +class DiagonalMatrix(MatrixExpr): + """DiagonalMatrix(M) will create a matrix expression that + behaves as though all off-diagonal elements, + `M[i, j]` where `i != j`, are zero. + + Examples + ======== + + >>> from sympy import MatrixSymbol, DiagonalMatrix, Symbol + >>> n = Symbol('n', integer=True) + >>> m = Symbol('m', integer=True) + >>> D = DiagonalMatrix(MatrixSymbol('x', 2, 3)) + >>> D[1, 2] + 0 + >>> D[1, 1] + x[1, 1] + + The length of the diagonal -- the lesser of the two dimensions of `M` -- + is accessed through the `diagonal_length` property: + + >>> D.diagonal_length + 2 + >>> DiagonalMatrix(MatrixSymbol('x', n + 1, n)).diagonal_length + n + + When one of the dimensions is symbolic the other will be treated as + though it is smaller: + + >>> tall = DiagonalMatrix(MatrixSymbol('x', n, 3)) + >>> tall.diagonal_length + 3 + >>> tall[10, 1] + 0 + + When the size of the diagonal is not known, a value of None will + be returned: + + >>> DiagonalMatrix(MatrixSymbol('x', n, m)).diagonal_length is None + True + + """ + arg = property(lambda self: self.args[0]) + + shape = property(lambda self: self.arg.shape) # type:ignore + + @property + def diagonal_length(self): + r, c = self.shape + if r.is_Integer and c.is_Integer: + m = min(r, c) + elif r.is_Integer and not c.is_Integer: + m = r + elif c.is_Integer and not r.is_Integer: + m = c + elif r == c: + m = r + else: + try: + m = min(r, c) + except TypeError: + m = None + return m + + def _entry(self, i, j, **kwargs): + if self.diagonal_length is not None: + if Ge(i, self.diagonal_length) is S.true: + return S.Zero + elif Ge(j, self.diagonal_length) is S.true: + return S.Zero + eq = Eq(i, j) + if eq is S.true: + return self.arg[i, i] + elif eq is S.false: + return S.Zero + return self.arg[i, j]*KroneckerDelta(i, j) + + +class DiagonalOf(MatrixExpr): + """DiagonalOf(M) will create a matrix expression that + is equivalent to the diagonal of `M`, represented as + a single column matrix. + + Examples + ======== + + >>> from sympy import MatrixSymbol, DiagonalOf, Symbol + >>> n = Symbol('n', integer=True) + >>> m = Symbol('m', integer=True) + >>> x = MatrixSymbol('x', 2, 3) + >>> diag = DiagonalOf(x) + >>> diag.shape + (2, 1) + + The diagonal can be addressed like a matrix or vector and will + return the corresponding element of the original matrix: + + >>> diag[1, 0] == diag[1] == x[1, 1] + True + + The length of the diagonal -- the lesser of the two dimensions of `M` -- + is accessed through the `diagonal_length` property: + + >>> diag.diagonal_length + 2 + >>> DiagonalOf(MatrixSymbol('x', n + 1, n)).diagonal_length + n + + When only one of the dimensions is symbolic the other will be + treated as though it is smaller: + + >>> dtall = DiagonalOf(MatrixSymbol('x', n, 3)) + >>> dtall.diagonal_length + 3 + + When the size of the diagonal is not known, a value of None will + be returned: + + >>> DiagonalOf(MatrixSymbol('x', n, m)).diagonal_length is None + True + + """ + arg = property(lambda self: self.args[0]) + @property + def shape(self): + r, c = self.arg.shape + if r.is_Integer and c.is_Integer: + m = min(r, c) + elif r.is_Integer and not c.is_Integer: + m = r + elif c.is_Integer and not r.is_Integer: + m = c + elif r == c: + m = r + else: + try: + m = min(r, c) + except TypeError: + m = None + return m, S.One + + @property + def diagonal_length(self): + return self.shape[0] + + def _entry(self, i, j, **kwargs): + return self.arg._entry(i, i, **kwargs) + + +class DiagMatrix(MatrixExpr): + """ + Turn a vector into a diagonal matrix. + """ + def __new__(cls, vector): + vector = _sympify(vector) + obj = MatrixExpr.__new__(cls, vector) + shape = vector.shape + dim = shape[1] if shape[0] == 1 else shape[0] + if vector.shape[0] != 1: + obj._iscolumn = True + else: + obj._iscolumn = False + obj._shape = (dim, dim) + obj._vector = vector + return obj + + @property + def shape(self): + return self._shape + + def _entry(self, i, j, **kwargs): + if self._iscolumn: + result = self._vector._entry(i, 0, **kwargs) + else: + result = self._vector._entry(0, j, **kwargs) + if i != j: + result *= KroneckerDelta(i, j) + return result + + def _eval_transpose(self): + return self + + def as_explicit(self): + from sympy.matrices.dense import diag + return diag(*list(self._vector.as_explicit())) + + def doit(self, **hints): + from sympy.assumptions import ask, Q + from sympy.matrices.expressions.matmul import MatMul + from sympy.matrices.expressions.transpose import Transpose + from sympy.matrices.dense import eye + from sympy.matrices.matrixbase import MatrixBase + vector = self._vector + # This accounts for shape (1, 1) and identity matrices, among others: + if ask(Q.diagonal(vector)): + return vector + if isinstance(vector, MatrixBase): + ret = eye(max(vector.shape)) + for i in range(ret.shape[0]): + ret[i, i] = vector[i] + return type(vector)(ret) + if vector.is_MatMul: + matrices = [arg for arg in vector.args if arg.is_Matrix] + scalars = [arg for arg in vector.args if arg not in matrices] + if scalars: + return Mul.fromiter(scalars)*DiagMatrix(MatMul.fromiter(matrices).doit()).doit() + if isinstance(vector, Transpose): + vector = vector.arg + return DiagMatrix(vector) + + +def diagonalize_vector(vector): + return DiagMatrix(vector).doit() diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/dotproduct.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/dotproduct.py new file mode 100644 index 0000000000000000000000000000000000000000..3a413f8c79a221505f0c082d7f19f78597a2befc --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/dotproduct.py @@ -0,0 +1,55 @@ +from sympy.core import Basic, Expr +from sympy.core.sympify import _sympify +from sympy.matrices.expressions.transpose import transpose + + +class DotProduct(Expr): + """ + Dot product of vector matrices + + The input should be two 1 x n or n x 1 matrices. The output represents the + scalar dotproduct. + + This is similar to using MatrixElement and MatMul, except DotProduct does + not require that one vector to be a row vector and the other vector to be + a column vector. + + >>> from sympy import MatrixSymbol, DotProduct + >>> A = MatrixSymbol('A', 1, 3) + >>> B = MatrixSymbol('B', 1, 3) + >>> DotProduct(A, B) + DotProduct(A, B) + >>> DotProduct(A, B).doit() + A[0, 0]*B[0, 0] + A[0, 1]*B[0, 1] + A[0, 2]*B[0, 2] + """ + + def __new__(cls, arg1, arg2): + arg1, arg2 = _sympify((arg1, arg2)) + + if not arg1.is_Matrix: + raise TypeError("Argument 1 of DotProduct is not a matrix") + if not arg2.is_Matrix: + raise TypeError("Argument 2 of DotProduct is not a matrix") + if not (1 in arg1.shape): + raise TypeError("Argument 1 of DotProduct is not a vector") + if not (1 in arg2.shape): + raise TypeError("Argument 2 of DotProduct is not a vector") + + if set(arg1.shape) != set(arg2.shape): + raise TypeError("DotProduct arguments are not the same length") + + return Basic.__new__(cls, arg1, arg2) + + def doit(self, expand=False, **hints): + if self.args[0].shape == self.args[1].shape: + if self.args[0].shape[0] == 1: + mul = self.args[0]*transpose(self.args[1]) + else: + mul = transpose(self.args[0])*self.args[1] + else: + if self.args[0].shape[0] == 1: + mul = self.args[0]*self.args[1] + else: + mul = transpose(self.args[0])*transpose(self.args[1]) + + return mul[0] diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/factorizations.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/factorizations.py new file mode 100644 index 0000000000000000000000000000000000000000..aff2bb81ecff99d8e733f282ac2dd187d76ce895 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/factorizations.py @@ -0,0 +1,62 @@ +from sympy.matrices.expressions import MatrixExpr +from sympy.assumptions.ask import Q + +class Factorization(MatrixExpr): + arg = property(lambda self: self.args[0]) + shape = property(lambda self: self.arg.shape) # type: ignore + +class LofLU(Factorization): + @property + def predicates(self): + return (Q.lower_triangular,) +class UofLU(Factorization): + @property + def predicates(self): + return (Q.upper_triangular,) + +class LofCholesky(LofLU): pass +class UofCholesky(UofLU): pass + +class QofQR(Factorization): + @property + def predicates(self): + return (Q.orthogonal,) +class RofQR(Factorization): + @property + def predicates(self): + return (Q.upper_triangular,) + +class EigenVectors(Factorization): + @property + def predicates(self): + return (Q.orthogonal,) +class EigenValues(Factorization): + @property + def predicates(self): + return (Q.diagonal,) + +class UofSVD(Factorization): + @property + def predicates(self): + return (Q.orthogonal,) +class SofSVD(Factorization): + @property + def predicates(self): + return (Q.diagonal,) +class VofSVD(Factorization): + @property + def predicates(self): + return (Q.orthogonal,) + + +def lu(expr): + return LofLU(expr), UofLU(expr) + +def qr(expr): + return QofQR(expr), RofQR(expr) + +def eig(expr): + return EigenValues(expr), EigenVectors(expr) + +def svd(expr): + return UofSVD(expr), SofSVD(expr), VofSVD(expr) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/fourier.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/fourier.py new file mode 100644 index 0000000000000000000000000000000000000000..5fa9222c2a9b218f42636267235d5dd44c25f8bb --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/fourier.py @@ -0,0 +1,91 @@ +from sympy.core.sympify import _sympify +from sympy.matrices.expressions import MatrixExpr +from sympy.core.numbers import I +from sympy.core.singleton import S +from sympy.functions.elementary.exponential import exp +from sympy.functions.elementary.miscellaneous import sqrt + + +class DFT(MatrixExpr): + r""" + Returns a discrete Fourier transform matrix. The matrix is scaled + with :math:`\frac{1}{\sqrt{n}}` so that it is unitary. + + Parameters + ========== + + n : integer or Symbol + Size of the transform. + + Examples + ======== + + >>> from sympy.abc import n + >>> from sympy.matrices.expressions.fourier import DFT + >>> DFT(3) + DFT(3) + >>> DFT(3).as_explicit() + Matrix([ + [sqrt(3)/3, sqrt(3)/3, sqrt(3)/3], + [sqrt(3)/3, sqrt(3)*exp(-2*I*pi/3)/3, sqrt(3)*exp(2*I*pi/3)/3], + [sqrt(3)/3, sqrt(3)*exp(2*I*pi/3)/3, sqrt(3)*exp(-2*I*pi/3)/3]]) + >>> DFT(n).shape + (n, n) + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/DFT_matrix + + """ + + def __new__(cls, n): + n = _sympify(n) + cls._check_dim(n) + + obj = super().__new__(cls, n) + return obj + + n = property(lambda self: self.args[0]) # type: ignore + shape = property(lambda self: (self.n, self.n)) # type: ignore + + def _entry(self, i, j, **kwargs): + w = exp(-2*S.Pi*I/self.n) + return w**(i*j) / sqrt(self.n) + + def _eval_inverse(self): + return IDFT(self.n) + + +class IDFT(DFT): + r""" + Returns an inverse discrete Fourier transform matrix. The matrix is scaled + with :math:`\frac{1}{\sqrt{n}}` so that it is unitary. + + Parameters + ========== + + n : integer or Symbol + Size of the transform + + Examples + ======== + + >>> from sympy.matrices.expressions.fourier import DFT, IDFT + >>> IDFT(3) + IDFT(3) + >>> IDFT(4)*DFT(4) + I + + See Also + ======== + + DFT + + """ + def _entry(self, i, j, **kwargs): + w = exp(-2*S.Pi*I/self.n) + return w**(-i*j) / sqrt(self.n) + + def _eval_inverse(self): + return DFT(self.n) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/funcmatrix.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/funcmatrix.py new file mode 100644 index 0000000000000000000000000000000000000000..91106edb489b73ac9dd6cb94adc508c0db75d3a5 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/funcmatrix.py @@ -0,0 +1,118 @@ +from .matexpr import MatrixExpr +from sympy.core.function import FunctionClass, Lambda +from sympy.core.symbol import Dummy +from sympy.core.sympify import _sympify, sympify +from sympy.matrices import Matrix +from sympy.functions.elementary.complexes import re, im + + +class FunctionMatrix(MatrixExpr): + """Represents a matrix using a function (``Lambda``) which gives + outputs according to the coordinates of each matrix entries. + + Parameters + ========== + + rows : nonnegative integer. Can be symbolic. + + cols : nonnegative integer. Can be symbolic. + + lamda : Function, Lambda or str + If it is a SymPy ``Function`` or ``Lambda`` instance, + it should be able to accept two arguments which represents the + matrix coordinates. + + If it is a pure string containing Python ``lambda`` semantics, + it is interpreted by the SymPy parser and casted into a SymPy + ``Lambda`` instance. + + Examples + ======== + + Creating a ``FunctionMatrix`` from ``Lambda``: + + >>> from sympy import FunctionMatrix, symbols, Lambda, MatPow + >>> i, j, n, m = symbols('i,j,n,m') + >>> FunctionMatrix(n, m, Lambda((i, j), i + j)) + FunctionMatrix(n, m, Lambda((i, j), i + j)) + + Creating a ``FunctionMatrix`` from a SymPy function: + + >>> from sympy import KroneckerDelta + >>> X = FunctionMatrix(3, 3, KroneckerDelta) + >>> X.as_explicit() + Matrix([ + [1, 0, 0], + [0, 1, 0], + [0, 0, 1]]) + + Creating a ``FunctionMatrix`` from a SymPy undefined function: + + >>> from sympy import Function + >>> f = Function('f') + >>> X = FunctionMatrix(3, 3, f) + >>> X.as_explicit() + Matrix([ + [f(0, 0), f(0, 1), f(0, 2)], + [f(1, 0), f(1, 1), f(1, 2)], + [f(2, 0), f(2, 1), f(2, 2)]]) + + Creating a ``FunctionMatrix`` from Python ``lambda``: + + >>> FunctionMatrix(n, m, 'lambda i, j: i + j') + FunctionMatrix(n, m, Lambda((i, j), i + j)) + + Example of lazy evaluation of matrix product: + + >>> Y = FunctionMatrix(1000, 1000, Lambda((i, j), i + j)) + >>> isinstance(Y*Y, MatPow) # this is an expression object + True + >>> (Y**2)[10,10] # So this is evaluated lazily + 342923500 + + Notes + ===== + + This class provides an alternative way to represent an extremely + dense matrix with entries in some form of a sequence, in a most + sparse way. + """ + def __new__(cls, rows, cols, lamda): + rows, cols = _sympify(rows), _sympify(cols) + cls._check_dim(rows) + cls._check_dim(cols) + + lamda = sympify(lamda) + if not isinstance(lamda, (FunctionClass, Lambda)): + raise ValueError( + "{} should be compatible with SymPy function classes." + .format(lamda)) + + if 2 not in lamda.nargs: + raise ValueError( + '{} should be able to accept 2 arguments.'.format(lamda)) + + if not isinstance(lamda, Lambda): + i, j = Dummy('i'), Dummy('j') + lamda = Lambda((i, j), lamda(i, j)) + + return super().__new__(cls, rows, cols, lamda) + + @property + def shape(self): + return self.args[0:2] + + @property + def lamda(self): + return self.args[2] + + def _entry(self, i, j, **kwargs): + return self.lamda(i, j) + + def _eval_trace(self): + from sympy.matrices.expressions.trace import Trace + from sympy.concrete.summations import Sum + return Trace(self).rewrite(Sum).doit() + + def _eval_as_real_imag(self): + return (re(Matrix(self)), im(Matrix(self))) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/hadamard.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/hadamard.py new file mode 100644 index 0000000000000000000000000000000000000000..38c9033ebea3a7bfc569223978dc6ef3890206cf --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/hadamard.py @@ -0,0 +1,464 @@ +from collections import Counter + +from sympy.core import Mul, sympify +from sympy.core.add import Add +from sympy.core.expr import ExprBuilder +from sympy.core.sorting import default_sort_key +from sympy.functions.elementary.exponential import log +from sympy.matrices.expressions.matexpr import MatrixExpr +from sympy.matrices.expressions._shape import validate_matadd_integer as validate +from sympy.matrices.expressions.special import ZeroMatrix, OneMatrix +from sympy.strategies import ( + unpack, flatten, condition, exhaust, rm_id, sort +) +from sympy.utilities.exceptions import sympy_deprecation_warning + + +def hadamard_product(*matrices): + """ + Return the elementwise (aka Hadamard) product of matrices. + + Examples + ======== + + >>> from sympy import hadamard_product, MatrixSymbol + >>> A = MatrixSymbol('A', 2, 3) + >>> B = MatrixSymbol('B', 2, 3) + >>> hadamard_product(A) + A + >>> hadamard_product(A, B) + HadamardProduct(A, B) + >>> hadamard_product(A, B)[0, 1] + A[0, 1]*B[0, 1] + """ + if not matrices: + raise TypeError("Empty Hadamard product is undefined") + if len(matrices) == 1: + return matrices[0] + return HadamardProduct(*matrices).doit() + + +class HadamardProduct(MatrixExpr): + """ + Elementwise product of matrix expressions + + Examples + ======== + + Hadamard product for matrix symbols: + + >>> from sympy import hadamard_product, HadamardProduct, MatrixSymbol + >>> A = MatrixSymbol('A', 5, 5) + >>> B = MatrixSymbol('B', 5, 5) + >>> isinstance(hadamard_product(A, B), HadamardProduct) + True + + Notes + ===== + + This is a symbolic object that simply stores its argument without + evaluating it. To actually compute the product, use the function + ``hadamard_product()`` or ``HadamardProduct.doit`` + """ + is_HadamardProduct = True + + def __new__(cls, *args, evaluate=False, check=None): + args = list(map(sympify, args)) + if len(args) == 0: + # We currently don't have a way to support one-matrices of generic dimensions: + raise ValueError("HadamardProduct needs at least one argument") + + if not all(isinstance(arg, MatrixExpr) for arg in args): + raise TypeError("Mix of Matrix and Scalar symbols") + + if check is not None: + sympy_deprecation_warning( + "Passing check to HadamardProduct is deprecated and the check argument will be removed in a future version.", + deprecated_since_version="1.11", + active_deprecations_target='remove-check-argument-from-matrix-operations') + + if check is not False: + validate(*args) + + obj = super().__new__(cls, *args) + if evaluate: + obj = obj.doit(deep=False) + return obj + + @property + def shape(self): + return self.args[0].shape + + def _entry(self, i, j, **kwargs): + return Mul(*[arg._entry(i, j, **kwargs) for arg in self.args]) + + def _eval_transpose(self): + from sympy.matrices.expressions.transpose import transpose + return HadamardProduct(*list(map(transpose, self.args))) + + def doit(self, **hints): + expr = self.func(*(i.doit(**hints) for i in self.args)) + # Check for explicit matrices: + from sympy.matrices.matrixbase import MatrixBase + from sympy.matrices.immutable import ImmutableMatrix + + explicit = [i for i in expr.args if isinstance(i, MatrixBase)] + if explicit: + remainder = [i for i in expr.args if i not in explicit] + expl_mat = ImmutableMatrix([ + Mul.fromiter(i) for i in zip(*explicit) + ]).reshape(*self.shape) + expr = HadamardProduct(*([expl_mat] + remainder)) + + return canonicalize(expr) + + def _eval_derivative(self, x): + terms = [] + args = list(self.args) + for i in range(len(args)): + factors = args[:i] + [args[i].diff(x)] + args[i+1:] + terms.append(hadamard_product(*factors)) + return Add.fromiter(terms) + + def _eval_derivative_matrix_lines(self, x): + from sympy.tensor.array.expressions.array_expressions import ArrayDiagonal + from sympy.tensor.array.expressions.array_expressions import ArrayTensorProduct + from sympy.matrices.expressions.matexpr import _make_matrix + + with_x_ind = [i for i, arg in enumerate(self.args) if arg.has(x)] + lines = [] + for ind in with_x_ind: + left_args = self.args[:ind] + right_args = self.args[ind+1:] + + d = self.args[ind]._eval_derivative_matrix_lines(x) + hadam = hadamard_product(*(right_args + left_args)) + diagonal = [(0, 2), (3, 4)] + diagonal = [e for j, e in enumerate(diagonal) if self.shape[j] != 1] + for i in d: + l1 = i._lines[i._first_line_index] + l2 = i._lines[i._second_line_index] + subexpr = ExprBuilder( + ArrayDiagonal, + [ + ExprBuilder( + ArrayTensorProduct, + [ + ExprBuilder(_make_matrix, [l1]), + hadam, + ExprBuilder(_make_matrix, [l2]), + ] + ), + *diagonal], + + ) + i._first_pointer_parent = subexpr.args[0].args[0].args + i._first_pointer_index = 0 + i._second_pointer_parent = subexpr.args[0].args[2].args + i._second_pointer_index = 0 + i._lines = [subexpr] + lines.append(i) + + return lines + + +# TODO Implement algorithm for rewriting Hadamard product as diagonal matrix +# if matmul identy matrix is multiplied. +def canonicalize(x): + """Canonicalize the Hadamard product ``x`` with mathematical properties. + + Examples + ======== + + >>> from sympy import MatrixSymbol, HadamardProduct + >>> from sympy import OneMatrix, ZeroMatrix + >>> from sympy.matrices.expressions.hadamard import canonicalize + >>> from sympy import init_printing + >>> init_printing(use_unicode=False) + + >>> A = MatrixSymbol('A', 2, 2) + >>> B = MatrixSymbol('B', 2, 2) + >>> C = MatrixSymbol('C', 2, 2) + + Hadamard product associativity: + + >>> X = HadamardProduct(A, HadamardProduct(B, C)) + >>> X + A.*(B.*C) + >>> canonicalize(X) + A.*B.*C + + Hadamard product commutativity: + + >>> X = HadamardProduct(A, B) + >>> Y = HadamardProduct(B, A) + >>> X + A.*B + >>> Y + B.*A + >>> canonicalize(X) + A.*B + >>> canonicalize(Y) + A.*B + + Hadamard product identity: + + >>> X = HadamardProduct(A, OneMatrix(2, 2)) + >>> X + A.*1 + >>> canonicalize(X) + A + + Absorbing element of Hadamard product: + + >>> X = HadamardProduct(A, ZeroMatrix(2, 2)) + >>> X + A.*0 + >>> canonicalize(X) + 0 + + Rewriting to Hadamard Power + + >>> X = HadamardProduct(A, A, A) + >>> X + A.*A.*A + >>> canonicalize(X) + .3 + A + + Notes + ===== + + As the Hadamard product is associative, nested products can be flattened. + + The Hadamard product is commutative so that factors can be sorted for + canonical form. + + A matrix of only ones is an identity for Hadamard product, + so every matrices of only ones can be removed. + + Any zero matrix will make the whole product a zero matrix. + + Duplicate elements can be collected and rewritten as HadamardPower + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Hadamard_product_(matrices) + """ + # Associativity + rule = condition( + lambda x: isinstance(x, HadamardProduct), + flatten + ) + fun = exhaust(rule) + x = fun(x) + + # Identity + fun = condition( + lambda x: isinstance(x, HadamardProduct), + rm_id(lambda x: isinstance(x, OneMatrix)) + ) + x = fun(x) + + # Absorbing by Zero Matrix + def absorb(x): + if any(isinstance(c, ZeroMatrix) for c in x.args): + return ZeroMatrix(*x.shape) + else: + return x + fun = condition( + lambda x: isinstance(x, HadamardProduct), + absorb + ) + x = fun(x) + + # Rewriting with HadamardPower + if isinstance(x, HadamardProduct): + tally = Counter(x.args) + + new_arg = [] + for base, exp in tally.items(): + if exp == 1: + new_arg.append(base) + else: + new_arg.append(HadamardPower(base, exp)) + + x = HadamardProduct(*new_arg) + + # Commutativity + fun = condition( + lambda x: isinstance(x, HadamardProduct), + sort(default_sort_key) + ) + x = fun(x) + + # Unpacking + x = unpack(x) + return x + + +def hadamard_power(base, exp): + base = sympify(base) + exp = sympify(exp) + if exp == 1: + return base + if not base.is_Matrix: + return base**exp + if exp.is_Matrix: + raise ValueError("cannot raise expression to a matrix") + return HadamardPower(base, exp) + + +class HadamardPower(MatrixExpr): + r""" + Elementwise power of matrix expressions + + Parameters + ========== + + base : scalar or matrix + + exp : scalar or matrix + + Notes + ===== + + There are four definitions for the hadamard power which can be used. + Let's consider `A, B` as `(m, n)` matrices, and `a, b` as scalars. + + Matrix raised to a scalar exponent: + + .. math:: + A^{\circ b} = \begin{bmatrix} + A_{0, 0}^b & A_{0, 1}^b & \cdots & A_{0, n-1}^b \\ + A_{1, 0}^b & A_{1, 1}^b & \cdots & A_{1, n-1}^b \\ + \vdots & \vdots & \ddots & \vdots \\ + A_{m-1, 0}^b & A_{m-1, 1}^b & \cdots & A_{m-1, n-1}^b + \end{bmatrix} + + Scalar raised to a matrix exponent: + + .. math:: + a^{\circ B} = \begin{bmatrix} + a^{B_{0, 0}} & a^{B_{0, 1}} & \cdots & a^{B_{0, n-1}} \\ + a^{B_{1, 0}} & a^{B_{1, 1}} & \cdots & a^{B_{1, n-1}} \\ + \vdots & \vdots & \ddots & \vdots \\ + a^{B_{m-1, 0}} & a^{B_{m-1, 1}} & \cdots & a^{B_{m-1, n-1}} + \end{bmatrix} + + Matrix raised to a matrix exponent: + + .. math:: + A^{\circ B} = \begin{bmatrix} + A_{0, 0}^{B_{0, 0}} & A_{0, 1}^{B_{0, 1}} & + \cdots & A_{0, n-1}^{B_{0, n-1}} \\ + A_{1, 0}^{B_{1, 0}} & A_{1, 1}^{B_{1, 1}} & + \cdots & A_{1, n-1}^{B_{1, n-1}} \\ + \vdots & \vdots & + \ddots & \vdots \\ + A_{m-1, 0}^{B_{m-1, 0}} & A_{m-1, 1}^{B_{m-1, 1}} & + \cdots & A_{m-1, n-1}^{B_{m-1, n-1}} + \end{bmatrix} + + Scalar raised to a scalar exponent: + + .. math:: + a^{\circ b} = a^b + """ + + def __new__(cls, base, exp): + base = sympify(base) + exp = sympify(exp) + + if base.is_scalar and exp.is_scalar: + return base ** exp + + if isinstance(base, MatrixExpr) and isinstance(exp, MatrixExpr): + validate(base, exp) + + obj = super().__new__(cls, base, exp) + return obj + + @property + def base(self): + return self._args[0] + + @property + def exp(self): + return self._args[1] + + @property + def shape(self): + if self.base.is_Matrix: + return self.base.shape + return self.exp.shape + + def _entry(self, i, j, **kwargs): + base = self.base + exp = self.exp + + if base.is_Matrix: + a = base._entry(i, j, **kwargs) + elif base.is_scalar: + a = base + else: + raise ValueError( + 'The base {} must be a scalar or a matrix.'.format(base)) + + if exp.is_Matrix: + b = exp._entry(i, j, **kwargs) + elif exp.is_scalar: + b = exp + else: + raise ValueError( + 'The exponent {} must be a scalar or a matrix.'.format(exp)) + + return a ** b + + def _eval_transpose(self): + from sympy.matrices.expressions.transpose import transpose + return HadamardPower(transpose(self.base), self.exp) + + def _eval_derivative(self, x): + dexp = self.exp.diff(x) + logbase = self.base.applyfunc(log) + dlbase = logbase.diff(x) + return hadamard_product( + dexp*logbase + self.exp*dlbase, + self + ) + + def _eval_derivative_matrix_lines(self, x): + from sympy.tensor.array.expressions.array_expressions import ArrayTensorProduct + from sympy.tensor.array.expressions.array_expressions import ArrayDiagonal + from sympy.matrices.expressions.matexpr import _make_matrix + + lr = self.base._eval_derivative_matrix_lines(x) + for i in lr: + diagonal = [(1, 2), (3, 4)] + diagonal = [e for j, e in enumerate(diagonal) if self.base.shape[j] != 1] + l1 = i._lines[i._first_line_index] + l2 = i._lines[i._second_line_index] + subexpr = ExprBuilder( + ArrayDiagonal, + [ + ExprBuilder( + ArrayTensorProduct, + [ + ExprBuilder(_make_matrix, [l1]), + self.exp*hadamard_power(self.base, self.exp-1), + ExprBuilder(_make_matrix, [l2]), + ] + ), + *diagonal], + validator=ArrayDiagonal._validate + ) + i._first_pointer_parent = subexpr.args[0].args[0].args + i._first_pointer_index = 0 + i._first_line_index = 0 + i._second_pointer_parent = subexpr.args[0].args[2].args + i._second_pointer_index = 0 + i._second_line_index = 0 + i._lines = [subexpr] + return lr diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/inverse.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/inverse.py new file mode 100644 index 0000000000000000000000000000000000000000..cfc3feccd7126a761f18f23599eed9413c86a9e5 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/inverse.py @@ -0,0 +1,112 @@ +from sympy.core.sympify import _sympify +from sympy.core import S, Basic + +from sympy.matrices.exceptions import NonSquareMatrixError +from sympy.matrices.expressions.matpow import MatPow + + +class Inverse(MatPow): + """ + The multiplicative inverse of a matrix expression + + This is a symbolic object that simply stores its argument without + evaluating it. To actually compute the inverse, use the ``.inverse()`` + method of matrices. + + Examples + ======== + + >>> from sympy import MatrixSymbol, Inverse + >>> A = MatrixSymbol('A', 3, 3) + >>> B = MatrixSymbol('B', 3, 3) + >>> Inverse(A) + A**(-1) + >>> A.inverse() == Inverse(A) + True + >>> (A*B).inverse() + B**(-1)*A**(-1) + >>> Inverse(A*B) + (A*B)**(-1) + + """ + is_Inverse = True + exp = S.NegativeOne + + def __new__(cls, mat, exp=S.NegativeOne): + # exp is there to make it consistent with + # inverse.func(*inverse.args) == inverse + mat = _sympify(mat) + exp = _sympify(exp) + if not mat.is_Matrix: + raise TypeError("mat should be a matrix") + if mat.is_square is False: + raise NonSquareMatrixError("Inverse of non-square matrix %s" % mat) + return Basic.__new__(cls, mat, exp) + + @property + def arg(self): + return self.args[0] + + @property + def shape(self): + return self.arg.shape + + def _eval_inverse(self): + return self.arg + + def _eval_transpose(self): + return Inverse(self.arg.transpose()) + + def _eval_adjoint(self): + return Inverse(self.arg.adjoint()) + + def _eval_conjugate(self): + return Inverse(self.arg.conjugate()) + + def _eval_determinant(self): + from sympy.matrices.expressions.determinant import det + return 1/det(self.arg) + + def doit(self, **hints): + if 'inv_expand' in hints and hints['inv_expand'] == False: + return self + + arg = self.arg + if hints.get('deep', True): + arg = arg.doit(**hints) + + return arg.inverse() + + def _eval_derivative_matrix_lines(self, x): + arg = self.args[0] + lines = arg._eval_derivative_matrix_lines(x) + for line in lines: + line.first_pointer *= -self.T + line.second_pointer *= self + return lines + + +from sympy.assumptions.ask import ask, Q +from sympy.assumptions.refine import handlers_dict + + +def refine_Inverse(expr, assumptions): + """ + >>> from sympy import MatrixSymbol, Q, assuming, refine + >>> X = MatrixSymbol('X', 2, 2) + >>> X.I + X**(-1) + >>> with assuming(Q.orthogonal(X)): + ... print(refine(X.I)) + X.T + """ + if ask(Q.orthogonal(expr), assumptions): + return expr.arg.T + elif ask(Q.unitary(expr), assumptions): + return expr.arg.conjugate() + elif ask(Q.singular(expr), assumptions): + raise ValueError("Inverse of singular matrix %s" % expr.arg) + + return expr + +handlers_dict['Inverse'] = refine_Inverse diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/kronecker.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/kronecker.py new file mode 100644 index 0000000000000000000000000000000000000000..1dd175cb0d500af3e786e2d0dbf6b010947840b4 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/kronecker.py @@ -0,0 +1,434 @@ +"""Implementation of the Kronecker product""" +from functools import reduce +from math import prod + +from sympy.core import Mul, sympify +from sympy.functions import adjoint +from sympy.matrices.exceptions import ShapeError +from sympy.matrices.expressions.matexpr import MatrixExpr +from sympy.matrices.expressions.transpose import transpose +from sympy.matrices.expressions.special import Identity +from sympy.matrices.matrixbase import MatrixBase +from sympy.strategies import ( + canon, condition, distribute, do_one, exhaust, flatten, typed, unpack) +from sympy.strategies.traverse import bottom_up +from sympy.utilities import sift + +from .matadd import MatAdd +from .matmul import MatMul +from .matpow import MatPow + + +def kronecker_product(*matrices): + """ + The Kronecker product of two or more arguments. + + This computes the explicit Kronecker product for subclasses of + ``MatrixBase`` i.e. explicit matrices. Otherwise, a symbolic + ``KroneckerProduct`` object is returned. + + + Examples + ======== + + For ``MatrixSymbol`` arguments a ``KroneckerProduct`` object is returned. + Elements of this matrix can be obtained by indexing, or for MatrixSymbols + with known dimension the explicit matrix can be obtained with + ``.as_explicit()`` + + >>> from sympy import kronecker_product, MatrixSymbol + >>> A = MatrixSymbol('A', 2, 2) + >>> B = MatrixSymbol('B', 2, 2) + >>> kronecker_product(A) + A + >>> kronecker_product(A, B) + KroneckerProduct(A, B) + >>> kronecker_product(A, B)[0, 1] + A[0, 0]*B[0, 1] + >>> kronecker_product(A, B).as_explicit() + Matrix([ + [A[0, 0]*B[0, 0], A[0, 0]*B[0, 1], A[0, 1]*B[0, 0], A[0, 1]*B[0, 1]], + [A[0, 0]*B[1, 0], A[0, 0]*B[1, 1], A[0, 1]*B[1, 0], A[0, 1]*B[1, 1]], + [A[1, 0]*B[0, 0], A[1, 0]*B[0, 1], A[1, 1]*B[0, 0], A[1, 1]*B[0, 1]], + [A[1, 0]*B[1, 0], A[1, 0]*B[1, 1], A[1, 1]*B[1, 0], A[1, 1]*B[1, 1]]]) + + For explicit matrices the Kronecker product is returned as a Matrix + + >>> from sympy import Matrix, kronecker_product + >>> sigma_x = Matrix([ + ... [0, 1], + ... [1, 0]]) + ... + >>> Isigma_y = Matrix([ + ... [0, 1], + ... [-1, 0]]) + ... + >>> kronecker_product(sigma_x, Isigma_y) + Matrix([ + [ 0, 0, 0, 1], + [ 0, 0, -1, 0], + [ 0, 1, 0, 0], + [-1, 0, 0, 0]]) + + See Also + ======== + KroneckerProduct + + """ + if not matrices: + raise TypeError("Empty Kronecker product is undefined") + if len(matrices) == 1: + return matrices[0] + else: + return KroneckerProduct(*matrices).doit() + + +class KroneckerProduct(MatrixExpr): + """ + The Kronecker product of two or more arguments. + + The Kronecker product is a non-commutative product of matrices. + Given two matrices of dimension (m, n) and (s, t) it produces a matrix + of dimension (m s, n t). + + This is a symbolic object that simply stores its argument without + evaluating it. To actually compute the product, use the function + ``kronecker_product()`` or call the ``.doit()`` or ``.as_explicit()`` + methods. + + >>> from sympy import KroneckerProduct, MatrixSymbol + >>> A = MatrixSymbol('A', 5, 5) + >>> B = MatrixSymbol('B', 5, 5) + >>> isinstance(KroneckerProduct(A, B), KroneckerProduct) + True + """ + is_KroneckerProduct = True + + def __new__(cls, *args, check=True): + args = list(map(sympify, args)) + if all(a.is_Identity for a in args): + ret = Identity(prod(a.rows for a in args)) + if all(isinstance(a, MatrixBase) for a in args): + return ret.as_explicit() + else: + return ret + + if check: + validate(*args) + return super().__new__(cls, *args) + + @property + def shape(self): + rows, cols = self.args[0].shape + for mat in self.args[1:]: + rows *= mat.rows + cols *= mat.cols + return (rows, cols) + + def _entry(self, i, j, **kwargs): + result = 1 + for mat in reversed(self.args): + i, m = divmod(i, mat.rows) + j, n = divmod(j, mat.cols) + result *= mat[m, n] + return result + + def _eval_adjoint(self): + return KroneckerProduct(*list(map(adjoint, self.args))).doit() + + def _eval_conjugate(self): + return KroneckerProduct(*[a.conjugate() for a in self.args]).doit() + + def _eval_transpose(self): + return KroneckerProduct(*list(map(transpose, self.args))).doit() + + def _eval_trace(self): + from .trace import trace + return Mul(*[trace(a) for a in self.args]) + + def _eval_determinant(self): + from .determinant import det, Determinant + if not all(a.is_square for a in self.args): + return Determinant(self) + + m = self.rows + return Mul(*[det(a)**(m/a.rows) for a in self.args]) + + def _eval_inverse(self): + try: + return KroneckerProduct(*[a.inverse() for a in self.args]) + except ShapeError: + from sympy.matrices.expressions.inverse import Inverse + return Inverse(self) + + def structurally_equal(self, other): + '''Determine whether two matrices have the same Kronecker product structure + + Examples + ======== + + >>> from sympy import KroneckerProduct, MatrixSymbol, symbols + >>> m, n = symbols(r'm, n', integer=True) + >>> A = MatrixSymbol('A', m, m) + >>> B = MatrixSymbol('B', n, n) + >>> C = MatrixSymbol('C', m, m) + >>> D = MatrixSymbol('D', n, n) + >>> KroneckerProduct(A, B).structurally_equal(KroneckerProduct(C, D)) + True + >>> KroneckerProduct(A, B).structurally_equal(KroneckerProduct(D, C)) + False + >>> KroneckerProduct(A, B).structurally_equal(C) + False + ''' + # Inspired by BlockMatrix + return (isinstance(other, KroneckerProduct) + and self.shape == other.shape + and len(self.args) == len(other.args) + and all(a.shape == b.shape for (a, b) in zip(self.args, other.args))) + + def has_matching_shape(self, other): + '''Determine whether two matrices have the appropriate structure to bring matrix + multiplication inside the KroneckerProdut + + Examples + ======== + >>> from sympy import KroneckerProduct, MatrixSymbol, symbols + >>> m, n = symbols(r'm, n', integer=True) + >>> A = MatrixSymbol('A', m, n) + >>> B = MatrixSymbol('B', n, m) + >>> KroneckerProduct(A, B).has_matching_shape(KroneckerProduct(B, A)) + True + >>> KroneckerProduct(A, B).has_matching_shape(KroneckerProduct(A, B)) + False + >>> KroneckerProduct(A, B).has_matching_shape(A) + False + ''' + return (isinstance(other, KroneckerProduct) + and self.cols == other.rows + and len(self.args) == len(other.args) + and all(a.cols == b.rows for (a, b) in zip(self.args, other.args))) + + def _eval_expand_kroneckerproduct(self, **hints): + return flatten(canon(typed({KroneckerProduct: distribute(KroneckerProduct, MatAdd)}))(self)) + + def _kronecker_add(self, other): + if self.structurally_equal(other): + return self.__class__(*[a + b for (a, b) in zip(self.args, other.args)]) + else: + return self + other + + def _kronecker_mul(self, other): + if self.has_matching_shape(other): + return self.__class__(*[a*b for (a, b) in zip(self.args, other.args)]) + else: + return self * other + + def doit(self, **hints): + deep = hints.get('deep', True) + if deep: + args = [arg.doit(**hints) for arg in self.args] + else: + args = self.args + return canonicalize(KroneckerProduct(*args)) + + +def validate(*args): + if not all(arg.is_Matrix for arg in args): + raise TypeError("Mix of Matrix and Scalar symbols") + + +# rules + +def extract_commutative(kron): + c_part = [] + nc_part = [] + for arg in kron.args: + c, nc = arg.args_cnc() + c_part.extend(c) + nc_part.append(Mul._from_args(nc)) + + c_part = Mul(*c_part) + if c_part != 1: + return c_part*KroneckerProduct(*nc_part) + return kron + + +def matrix_kronecker_product(*matrices): + """Compute the Kronecker product of a sequence of SymPy Matrices. + + This is the standard Kronecker product of matrices [1]. + + Parameters + ========== + + matrices : tuple of MatrixBase instances + The matrices to take the Kronecker product of. + + Returns + ======= + + matrix : MatrixBase + The Kronecker product matrix. + + Examples + ======== + + >>> from sympy import Matrix + >>> from sympy.matrices.expressions.kronecker import ( + ... matrix_kronecker_product) + + >>> m1 = Matrix([[1,2],[3,4]]) + >>> m2 = Matrix([[1,0],[0,1]]) + >>> matrix_kronecker_product(m1, m2) + Matrix([ + [1, 0, 2, 0], + [0, 1, 0, 2], + [3, 0, 4, 0], + [0, 3, 0, 4]]) + >>> matrix_kronecker_product(m2, m1) + Matrix([ + [1, 2, 0, 0], + [3, 4, 0, 0], + [0, 0, 1, 2], + [0, 0, 3, 4]]) + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Kronecker_product + """ + # Make sure we have a sequence of Matrices + if not all(isinstance(m, MatrixBase) for m in matrices): + raise TypeError( + 'Sequence of Matrices expected, got: %s' % repr(matrices) + ) + + # Pull out the first element in the product. + matrix_expansion = matrices[-1] + # Do the kronecker product working from right to left. + for mat in reversed(matrices[:-1]): + rows = mat.rows + cols = mat.cols + # Go through each row appending kronecker product to. + # running matrix_expansion. + for i in range(rows): + start = matrix_expansion*mat[i*cols] + # Go through each column joining each item + for j in range(cols - 1): + start = start.row_join( + matrix_expansion*mat[i*cols + j + 1] + ) + # If this is the first element, make it the start of the + # new row. + if i == 0: + next = start + else: + next = next.col_join(start) + matrix_expansion = next + + MatrixClass = max(matrices, key=lambda M: M._class_priority).__class__ + if isinstance(matrix_expansion, MatrixClass): + return matrix_expansion + else: + return MatrixClass(matrix_expansion) + + +def explicit_kronecker_product(kron): + # Make sure we have a sequence of Matrices + if not all(isinstance(m, MatrixBase) for m in kron.args): + return kron + + return matrix_kronecker_product(*kron.args) + + +rules = (unpack, + explicit_kronecker_product, + flatten, + extract_commutative) + +canonicalize = exhaust(condition(lambda x: isinstance(x, KroneckerProduct), + do_one(*rules))) + + +def _kronecker_dims_key(expr): + if isinstance(expr, KroneckerProduct): + return tuple(a.shape for a in expr.args) + else: + return (0,) + + +def kronecker_mat_add(expr): + args = sift(expr.args, _kronecker_dims_key) + nonkrons = args.pop((0,), None) + if not args: + return expr + + krons = [reduce(lambda x, y: x._kronecker_add(y), group) + for group in args.values()] + + if not nonkrons: + return MatAdd(*krons) + else: + return MatAdd(*krons) + nonkrons + + +def kronecker_mat_mul(expr): + # modified from block matrix code + factor, matrices = expr.as_coeff_matrices() + + i = 0 + while i < len(matrices) - 1: + A, B = matrices[i:i+2] + if isinstance(A, KroneckerProduct) and isinstance(B, KroneckerProduct): + matrices[i] = A._kronecker_mul(B) + matrices.pop(i+1) + else: + i += 1 + + return factor*MatMul(*matrices) + + +def kronecker_mat_pow(expr): + if isinstance(expr.base, KroneckerProduct) and all(a.is_square for a in expr.base.args): + return KroneckerProduct(*[MatPow(a, expr.exp) for a in expr.base.args]) + else: + return expr + + +def combine_kronecker(expr): + """Combine KronekeckerProduct with expression. + + If possible write operations on KroneckerProducts of compatible shapes + as a single KroneckerProduct. + + Examples + ======== + + >>> from sympy.matrices.expressions import combine_kronecker + >>> from sympy import MatrixSymbol, KroneckerProduct, symbols + >>> m, n = symbols(r'm, n', integer=True) + >>> A = MatrixSymbol('A', m, n) + >>> B = MatrixSymbol('B', n, m) + >>> combine_kronecker(KroneckerProduct(A, B)*KroneckerProduct(B, A)) + KroneckerProduct(A*B, B*A) + >>> combine_kronecker(KroneckerProduct(A, B)+KroneckerProduct(B.T, A.T)) + KroneckerProduct(A + B.T, B + A.T) + >>> C = MatrixSymbol('C', n, n) + >>> D = MatrixSymbol('D', m, m) + >>> combine_kronecker(KroneckerProduct(C, D)**m) + KroneckerProduct(C**m, D**m) + """ + def haskron(expr): + return isinstance(expr, MatrixExpr) and expr.has(KroneckerProduct) + + rule = exhaust( + bottom_up(exhaust(condition(haskron, typed( + {MatAdd: kronecker_mat_add, + MatMul: kronecker_mat_mul, + MatPow: kronecker_mat_pow}))))) + result = rule(expr) + doit = getattr(result, 'doit', None) + if doit is not None: + return doit() + else: + return result diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/matadd.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/matadd.py new file mode 100644 index 0000000000000000000000000000000000000000..cfae1e5010e4077c7210c85c4315ed2404f245d7 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/matadd.py @@ -0,0 +1,155 @@ +from functools import reduce +import operator + +from sympy.core import Basic, sympify +from sympy.core.add import add, Add, _could_extract_minus_sign +from sympy.core.sorting import default_sort_key +from sympy.functions import adjoint +from sympy.matrices.matrixbase import MatrixBase +from sympy.matrices.expressions.transpose import transpose +from sympy.strategies import (rm_id, unpack, flatten, sort, condition, + exhaust, do_one, glom) +from sympy.matrices.expressions.matexpr import MatrixExpr +from sympy.matrices.expressions.special import ZeroMatrix, GenericZeroMatrix +from sympy.matrices.expressions._shape import validate_matadd_integer as validate +from sympy.utilities.iterables import sift +from sympy.utilities.exceptions import sympy_deprecation_warning + +# XXX: MatAdd should perhaps not subclass directly from Add +class MatAdd(MatrixExpr, Add): + """A Sum of Matrix Expressions + + MatAdd inherits from and operates like SymPy Add + + Examples + ======== + + >>> from sympy import MatAdd, MatrixSymbol + >>> A = MatrixSymbol('A', 5, 5) + >>> B = MatrixSymbol('B', 5, 5) + >>> C = MatrixSymbol('C', 5, 5) + >>> MatAdd(A, B, C) + A + B + C + """ + is_MatAdd = True + + identity = GenericZeroMatrix() + + def __new__(cls, *args, evaluate=False, check=None, _sympify=True): + if not args: + return cls.identity + + # This must be removed aggressively in the constructor to avoid + # TypeErrors from GenericZeroMatrix().shape + args = list(filter(lambda i: cls.identity != i, args)) + if _sympify: + args = list(map(sympify, args)) + + if not all(isinstance(arg, MatrixExpr) for arg in args): + raise TypeError("Mix of Matrix and Scalar symbols") + + obj = Basic.__new__(cls, *args) + + if check is not None: + sympy_deprecation_warning( + "Passing check to MatAdd is deprecated and the check argument will be removed in a future version.", + deprecated_since_version="1.11", + active_deprecations_target='remove-check-argument-from-matrix-operations') + + if check is not False: + validate(*args) + + if evaluate: + obj = cls._evaluate(obj) + + return obj + + @classmethod + def _evaluate(cls, expr): + return canonicalize(expr) + + @property + def shape(self): + return self.args[0].shape + + def could_extract_minus_sign(self): + return _could_extract_minus_sign(self) + + def expand(self, **kwargs): + expanded = super(MatAdd, self).expand(**kwargs) + return self._evaluate(expanded) + + def _entry(self, i, j, **kwargs): + return Add(*[arg._entry(i, j, **kwargs) for arg in self.args]) + + def _eval_transpose(self): + return MatAdd(*[transpose(arg) for arg in self.args]).doit() + + def _eval_adjoint(self): + return MatAdd(*[adjoint(arg) for arg in self.args]).doit() + + def _eval_trace(self): + from .trace import trace + return Add(*[trace(arg) for arg in self.args]).doit() + + def doit(self, **hints): + deep = hints.get('deep', True) + if deep: + args = [arg.doit(**hints) for arg in self.args] + else: + args = self.args + return canonicalize(MatAdd(*args)) + + def _eval_derivative_matrix_lines(self, x): + add_lines = [arg._eval_derivative_matrix_lines(x) for arg in self.args] + return [j for i in add_lines for j in i] + +add.register_handlerclass((Add, MatAdd), MatAdd) + + +factor_of = lambda arg: arg.as_coeff_mmul()[0] +matrix_of = lambda arg: unpack(arg.as_coeff_mmul()[1]) +def combine(cnt, mat): + if cnt == 1: + return mat + else: + return cnt * mat + + +def merge_explicit(matadd): + """ Merge explicit MatrixBase arguments + + Examples + ======== + + >>> from sympy import MatrixSymbol, eye, Matrix, MatAdd, pprint + >>> from sympy.matrices.expressions.matadd import merge_explicit + >>> A = MatrixSymbol('A', 2, 2) + >>> B = eye(2) + >>> C = Matrix([[1, 2], [3, 4]]) + >>> X = MatAdd(A, B, C) + >>> pprint(X) + [1 0] [1 2] + A + [ ] + [ ] + [0 1] [3 4] + >>> pprint(merge_explicit(X)) + [2 2] + A + [ ] + [3 5] + """ + groups = sift(matadd.args, lambda arg: isinstance(arg, MatrixBase)) + if len(groups[True]) > 1: + return MatAdd(*(groups[False] + [reduce(operator.add, groups[True])])) + else: + return matadd + + +rules = (rm_id(lambda x: x == 0 or isinstance(x, ZeroMatrix)), + unpack, + flatten, + glom(matrix_of, factor_of, combine), + merge_explicit, + sort(default_sort_key)) + +canonicalize = exhaust(condition(lambda x: isinstance(x, MatAdd), + do_one(*rules))) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/matexpr.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/matexpr.py new file mode 100644 index 0000000000000000000000000000000000000000..a4e99296ccfcbdac5e09a86ecee020adf9831c73 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/matexpr.py @@ -0,0 +1,888 @@ +from __future__ import annotations +from functools import wraps + +from sympy.core import S, Integer, Basic, Mul, Add +from sympy.core.assumptions import check_assumptions +from sympy.core.decorators import call_highest_priority +from sympy.core.expr import Expr, ExprBuilder +from sympy.core.logic import FuzzyBool +from sympy.core.symbol import Str, Dummy, symbols, Symbol +from sympy.core.sympify import SympifyError, _sympify +from sympy.external.gmpy import SYMPY_INTS +from sympy.functions import conjugate, adjoint +from sympy.functions.special.tensor_functions import KroneckerDelta +from sympy.matrices.exceptions import NonSquareMatrixError +from sympy.matrices.kind import MatrixKind +from sympy.matrices.matrixbase import MatrixBase +from sympy.multipledispatch import dispatch +from sympy.utilities.misc import filldedent + + +def _sympifyit(arg, retval=None): + # This version of _sympifyit sympifies MutableMatrix objects + def deco(func): + @wraps(func) + def __sympifyit_wrapper(a, b): + try: + b = _sympify(b) + return func(a, b) + except SympifyError: + return retval + + return __sympifyit_wrapper + + return deco + + +class MatrixExpr(Expr): + """Superclass for Matrix Expressions + + MatrixExprs represent abstract matrices, linear transformations represented + within a particular basis. + + Examples + ======== + + >>> from sympy import MatrixSymbol + >>> A = MatrixSymbol('A', 3, 3) + >>> y = MatrixSymbol('y', 3, 1) + >>> x = (A.T*A).I * A * y + + See Also + ======== + + MatrixSymbol, MatAdd, MatMul, Transpose, Inverse + """ + __slots__: tuple[str, ...] = () + + # Should not be considered iterable by the + # sympy.utilities.iterables.iterable function. Subclass that actually are + # iterable (i.e., explicit matrices) should set this to True. + _iterable = False + + _op_priority = 11.0 + + is_Matrix: bool = True + is_MatrixExpr: bool = True + is_Identity: FuzzyBool = None + is_Inverse = False + is_Transpose = False + is_ZeroMatrix = False + is_MatAdd = False + is_MatMul = False + + is_commutative = False + is_number = False + is_symbol = False + is_scalar = False + + kind: MatrixKind = MatrixKind() + + def __new__(cls, *args, **kwargs): + args = map(_sympify, args) + return Basic.__new__(cls, *args, **kwargs) + + # The following is adapted from the core Expr object + + @property + def shape(self) -> tuple[Expr, Expr]: + raise NotImplementedError + + @property + def _add_handler(self): + return MatAdd + + @property + def _mul_handler(self): + return MatMul + + def __neg__(self): + return MatMul(S.NegativeOne, self).doit() + + def __abs__(self): + raise NotImplementedError + + @_sympifyit('other', NotImplemented) + @call_highest_priority('__radd__') + def __add__(self, other): + return MatAdd(self, other).doit() + + @_sympifyit('other', NotImplemented) + @call_highest_priority('__add__') + def __radd__(self, other): + return MatAdd(other, self).doit() + + @_sympifyit('other', NotImplemented) + @call_highest_priority('__rsub__') + def __sub__(self, other): + return MatAdd(self, -other).doit() + + @_sympifyit('other', NotImplemented) + @call_highest_priority('__sub__') + def __rsub__(self, other): + return MatAdd(other, -self).doit() + + @_sympifyit('other', NotImplemented) + @call_highest_priority('__rmul__') + def __mul__(self, other): + return MatMul(self, other).doit() + + @_sympifyit('other', NotImplemented) + @call_highest_priority('__rmul__') + def __matmul__(self, other): + return MatMul(self, other).doit() + + @_sympifyit('other', NotImplemented) + @call_highest_priority('__mul__') + def __rmul__(self, other): + return MatMul(other, self).doit() + + @_sympifyit('other', NotImplemented) + @call_highest_priority('__mul__') + def __rmatmul__(self, other): + return MatMul(other, self).doit() + + @_sympifyit('other', NotImplemented) + @call_highest_priority('__rpow__') + def __pow__(self, other): + return MatPow(self, other).doit() + + @_sympifyit('other', NotImplemented) + @call_highest_priority('__pow__') + def __rpow__(self, other): + raise NotImplementedError("Matrix Power not defined") + + @_sympifyit('other', NotImplemented) + @call_highest_priority('__rtruediv__') + def __truediv__(self, other): + return self * other**S.NegativeOne + + @_sympifyit('other', NotImplemented) + @call_highest_priority('__truediv__') + def __rtruediv__(self, other): + raise NotImplementedError() + #return MatMul(other, Pow(self, S.NegativeOne)) + + @property + def rows(self): + return self.shape[0] + + @property + def cols(self): + return self.shape[1] + + @property + def is_square(self) -> bool | None: + rows, cols = self.shape + if isinstance(rows, Integer) and isinstance(cols, Integer): + return rows == cols + if rows == cols: + return True + return None + + def _eval_conjugate(self): + from sympy.matrices.expressions.adjoint import Adjoint + return Adjoint(Transpose(self)) + + def as_real_imag(self, deep=True, **hints): + return self._eval_as_real_imag() + + def _eval_as_real_imag(self): + real = S.Half * (self + self._eval_conjugate()) + im = (self - self._eval_conjugate())/(2*S.ImaginaryUnit) + return (real, im) + + def _eval_inverse(self): + return Inverse(self) + + def _eval_determinant(self): + return Determinant(self) + + def _eval_transpose(self): + return Transpose(self) + + def _eval_trace(self): + return None + + def _eval_power(self, exp): + """ + Override this in sub-classes to implement simplification of powers. The cases where the exponent + is -1, 0, 1 are already covered in MatPow.doit(), so implementations can exclude these cases. + """ + return MatPow(self, exp) + + def _eval_simplify(self, **kwargs): + if self.is_Atom: + return self + else: + from sympy.simplify import simplify + return self.func(*[simplify(x, **kwargs) for x in self.args]) + + def _eval_adjoint(self): + from sympy.matrices.expressions.adjoint import Adjoint + return Adjoint(self) + + def _eval_derivative_n_times(self, x, n): + return Basic._eval_derivative_n_times(self, x, n) + + def _eval_derivative(self, x): + # `x` is a scalar: + if self.has(x): + # See if there are other methods using it: + return super()._eval_derivative(x) + else: + return ZeroMatrix(*self.shape) + + @classmethod + def _check_dim(cls, dim): + """Helper function to check invalid matrix dimensions""" + ok = not dim.is_Float and check_assumptions( + dim, integer=True, nonnegative=True) + if ok is False: + raise ValueError( + "The dimension specification {} should be " + "a nonnegative integer.".format(dim)) + + + def _entry(self, i, j, **kwargs): + raise NotImplementedError( + "Indexing not implemented for %s" % self.__class__.__name__) + + def adjoint(self): + return adjoint(self) + + def as_coeff_Mul(self, rational=False): + """Efficiently extract the coefficient of a product.""" + return S.One, self + + def conjugate(self): + return conjugate(self) + + def transpose(self): + from sympy.matrices.expressions.transpose import transpose + return transpose(self) + + @property + def T(self): + '''Matrix transposition''' + return self.transpose() + + def inverse(self): + if self.is_square is False: + raise NonSquareMatrixError('Inverse of non-square matrix') + return self._eval_inverse() + + def inv(self): + return self.inverse() + + def det(self): + from sympy.matrices.expressions.determinant import det + return det(self) + + @property + def I(self): + return self.inverse() + + def valid_index(self, i, j): + def is_valid(idx): + return isinstance(idx, (int, Integer, Symbol, Expr)) + return (is_valid(i) and is_valid(j) and + (self.rows is None or + (i >= -self.rows) != False and (i < self.rows) != False) and + (j >= -self.cols) != False and (j < self.cols) != False) + + def __getitem__(self, key): + if not isinstance(key, tuple) and isinstance(key, slice): + from sympy.matrices.expressions.slice import MatrixSlice + return MatrixSlice(self, key, (0, None, 1)) + if isinstance(key, tuple) and len(key) == 2: + i, j = key + if isinstance(i, slice) or isinstance(j, slice): + from sympy.matrices.expressions.slice import MatrixSlice + return MatrixSlice(self, i, j) + i, j = _sympify(i), _sympify(j) + if self.valid_index(i, j) != False: + return self._entry(i, j) + else: + raise IndexError("Invalid indices (%s, %s)" % (i, j)) + elif isinstance(key, (SYMPY_INTS, Integer)): + # row-wise decomposition of matrix + rows, cols = self.shape + # allow single indexing if number of columns is known + if not isinstance(cols, Integer): + raise IndexError(filldedent(''' + Single indexing is only supported when the number + of columns is known.''')) + key = _sympify(key) + i = key // cols + j = key % cols + if self.valid_index(i, j) != False: + return self._entry(i, j) + else: + raise IndexError("Invalid index %s" % key) + elif isinstance(key, (Symbol, Expr)): + raise IndexError(filldedent(''' + Only integers may be used when addressing the matrix + with a single index.''')) + raise IndexError("Invalid index, wanted %s[i,j]" % self) + + def _is_shape_symbolic(self) -> bool: + return (not isinstance(self.rows, (SYMPY_INTS, Integer)) + or not isinstance(self.cols, (SYMPY_INTS, Integer))) + + def as_explicit(self): + """ + Returns a dense Matrix with elements represented explicitly + + Returns an object of type ImmutableDenseMatrix. + + Examples + ======== + + >>> from sympy import Identity + >>> I = Identity(3) + >>> I + I + >>> I.as_explicit() + Matrix([ + [1, 0, 0], + [0, 1, 0], + [0, 0, 1]]) + + See Also + ======== + as_mutable: returns mutable Matrix type + + """ + if self._is_shape_symbolic(): + raise ValueError( + 'Matrix with symbolic shape ' + 'cannot be represented explicitly.') + from sympy.matrices.immutable import ImmutableDenseMatrix + return ImmutableDenseMatrix([[self[i, j] + for j in range(self.cols)] + for i in range(self.rows)]) + + def as_mutable(self): + """ + Returns a dense, mutable matrix with elements represented explicitly + + Examples + ======== + + >>> from sympy import Identity + >>> I = Identity(3) + >>> I + I + >>> I.shape + (3, 3) + >>> I.as_mutable() + Matrix([ + [1, 0, 0], + [0, 1, 0], + [0, 0, 1]]) + + See Also + ======== + as_explicit: returns ImmutableDenseMatrix + """ + return self.as_explicit().as_mutable() + + def __array__(self, dtype=object, copy=None): + if copy is not None and not copy: + raise TypeError("Cannot implement copy=False when converting Matrix to ndarray") + from numpy import empty + a = empty(self.shape, dtype=object) + for i in range(self.rows): + for j in range(self.cols): + a[i, j] = self[i, j] + return a + + def equals(self, other): + """ + Test elementwise equality between matrices, potentially of different + types + + >>> from sympy import Identity, eye + >>> Identity(3).equals(eye(3)) + True + """ + return self.as_explicit().equals(other) + + def canonicalize(self): + return self + + def as_coeff_mmul(self): + return S.One, MatMul(self) + + @staticmethod + def from_index_summation(expr, first_index=None, last_index=None, dimensions=None): + r""" + Parse expression of matrices with explicitly summed indices into a + matrix expression without indices, if possible. + + This transformation expressed in mathematical notation: + + `\sum_{j=0}^{N-1} A_{i,j} B_{j,k} \Longrightarrow \mathbf{A}\cdot \mathbf{B}` + + Optional parameter ``first_index``: specify which free index to use as + the index starting the expression. + + Examples + ======== + + >>> from sympy import MatrixSymbol, MatrixExpr, Sum + >>> from sympy.abc import i, j, k, l, N + >>> A = MatrixSymbol("A", N, N) + >>> B = MatrixSymbol("B", N, N) + >>> expr = Sum(A[i, j]*B[j, k], (j, 0, N-1)) + >>> MatrixExpr.from_index_summation(expr) + A*B + + Transposition is detected: + + >>> expr = Sum(A[j, i]*B[j, k], (j, 0, N-1)) + >>> MatrixExpr.from_index_summation(expr) + A.T*B + + Detect the trace: + + >>> expr = Sum(A[i, i], (i, 0, N-1)) + >>> MatrixExpr.from_index_summation(expr) + Trace(A) + + More complicated expressions: + + >>> expr = Sum(A[i, j]*B[k, j]*A[l, k], (j, 0, N-1), (k, 0, N-1)) + >>> MatrixExpr.from_index_summation(expr) + A*B.T*A.T + """ + from sympy.tensor.array.expressions.from_indexed_to_array import convert_indexed_to_array + from sympy.tensor.array.expressions.from_array_to_matrix import convert_array_to_matrix + first_indices = [] + if first_index is not None: + first_indices.append(first_index) + if last_index is not None: + first_indices.append(last_index) + arr = convert_indexed_to_array(expr, first_indices=first_indices) + return convert_array_to_matrix(arr) + + def applyfunc(self, func): + from .applyfunc import ElementwiseApplyFunction + return ElementwiseApplyFunction(func, self) + + +@dispatch(MatrixExpr, Expr) +def _eval_is_eq(lhs, rhs): # noqa:F811 + return False + +@dispatch(MatrixExpr, MatrixExpr) # type: ignore +def _eval_is_eq(lhs, rhs): # noqa:F811 + if lhs.shape != rhs.shape: + return False + if (lhs - rhs).is_ZeroMatrix: + return True + +def get_postprocessor(cls): + def _postprocessor(expr): + # To avoid circular imports, we can't have MatMul/MatAdd on the top level + mat_class = {Mul: MatMul, Add: MatAdd}[cls] + nonmatrices = [] + matrices = [] + for term in expr.args: + if isinstance(term, MatrixExpr): + matrices.append(term) + else: + nonmatrices.append(term) + + if not matrices: + return cls._from_args(nonmatrices) + + if nonmatrices: + if cls == Mul: + for i in range(len(matrices)): + if not matrices[i].is_MatrixExpr: + # If one of the matrices explicit, absorb the scalar into it + # (doit will combine all explicit matrices into one, so it + # doesn't matter which) + matrices[i] = matrices[i].__mul__(cls._from_args(nonmatrices)) + nonmatrices = [] + break + + else: + # Maintain the ability to create Add(scalar, matrix) without + # raising an exception. That way different algorithms can + # replace matrix expressions with non-commutative symbols to + # manipulate them like non-commutative scalars. + return cls._from_args(nonmatrices + [mat_class(*matrices).doit(deep=False)]) + + if mat_class == MatAdd: + return mat_class(*matrices).doit(deep=False) + return mat_class(cls._from_args(nonmatrices), *matrices).doit(deep=False) + return _postprocessor + + +Basic._constructor_postprocessor_mapping[MatrixExpr] = { + "Mul": [get_postprocessor(Mul)], + "Add": [get_postprocessor(Add)], +} + + +def _matrix_derivative(expr, x, old_algorithm=False): + + if isinstance(expr, MatrixBase) or isinstance(x, MatrixBase): + # Do not use array expressions for explicit matrices: + old_algorithm = True + + if old_algorithm: + return _matrix_derivative_old_algorithm(expr, x) + + from sympy.tensor.array.expressions.from_matrix_to_array import convert_matrix_to_array + from sympy.tensor.array.expressions.arrayexpr_derivatives import array_derive + from sympy.tensor.array.expressions.from_array_to_matrix import convert_array_to_matrix + + array_expr = convert_matrix_to_array(expr) + diff_array_expr = array_derive(array_expr, x) + diff_matrix_expr = convert_array_to_matrix(diff_array_expr) + return diff_matrix_expr + + +def _matrix_derivative_old_algorithm(expr, x): + from sympy.tensor.array.array_derivatives import ArrayDerivative + lines = expr._eval_derivative_matrix_lines(x) + + parts = [i.build() for i in lines] + + from sympy.tensor.array.expressions.from_array_to_matrix import convert_array_to_matrix + + parts = [[convert_array_to_matrix(j) for j in i] for i in parts] + + def _get_shape(elem): + if isinstance(elem, MatrixExpr): + return elem.shape + return 1, 1 + + def get_rank(parts): + return sum(j not in (1, None) for i in parts for j in _get_shape(i)) + + ranks = [get_rank(i) for i in parts] + rank = ranks[0] + + def contract_one_dims(parts): + if len(parts) == 1: + return parts[0] + else: + p1, p2 = parts[:2] + if p2.is_Matrix: + p2 = p2.T + if p1 == Identity(1): + pbase = p2 + elif p2 == Identity(1): + pbase = p1 + else: + pbase = p1*p2 + if len(parts) == 2: + return pbase + else: # len(parts) > 2 + if pbase.is_Matrix: + raise ValueError("") + return pbase*Mul.fromiter(parts[2:]) + + if rank <= 2: + return Add.fromiter([contract_one_dims(i) for i in parts]) + + return ArrayDerivative(expr, x) + + +class MatrixElement(Expr): + parent = property(lambda self: self.args[0]) + i = property(lambda self: self.args[1]) + j = property(lambda self: self.args[2]) + _diff_wrt = True + is_symbol = True + is_commutative = True + + def __new__(cls, name, n, m): + n, m = map(_sympify, (n, m)) + if isinstance(name, str): + name = Symbol(name) + else: + if isinstance(name, MatrixBase): + if n.is_Integer and m.is_Integer: + return name[n, m] + name = _sympify(name) # change mutable into immutable + else: + name = _sympify(name) + if not isinstance(name.kind, MatrixKind): + raise TypeError("First argument of MatrixElement should be a matrix") + if not getattr(name, 'valid_index', lambda n, m: True)(n, m): + raise IndexError('indices out of range') + obj = Expr.__new__(cls, name, n, m) + return obj + + @property + def symbol(self): + return self.args[0] + + def doit(self, **hints): + deep = hints.get('deep', True) + if deep: + args = [arg.doit(**hints) for arg in self.args] + else: + args = self.args + return args[0][args[1], args[2]] + + @property + def indices(self): + return self.args[1:] + + def _eval_derivative(self, v): + + if not isinstance(v, MatrixElement): + return self.parent.diff(v)[self.i, self.j] + + M = self.args[0] + + m, n = self.parent.shape + + if M == v.args[0]: + return KroneckerDelta(self.args[1], v.args[1], (0, m-1)) * \ + KroneckerDelta(self.args[2], v.args[2], (0, n-1)) + + if isinstance(M, Inverse): + from sympy.concrete.summations import Sum + i, j = self.args[1:] + i1, i2 = symbols("z1, z2", cls=Dummy) + Y = M.args[0] + r1, r2 = Y.shape + return -Sum(M[i, i1]*Y[i1, i2].diff(v)*M[i2, j], (i1, 0, r1-1), (i2, 0, r2-1)) + + if self.has(v.args[0]): + return None + + return S.Zero + + +class MatrixSymbol(MatrixExpr): + """Symbolic representation of a Matrix object + + Creates a SymPy Symbol to represent a Matrix. This matrix has a shape and + can be included in Matrix Expressions + + Examples + ======== + + >>> from sympy import MatrixSymbol, Identity + >>> A = MatrixSymbol('A', 3, 4) # A 3 by 4 Matrix + >>> B = MatrixSymbol('B', 4, 3) # A 4 by 3 Matrix + >>> A.shape + (3, 4) + >>> 2*A*B + Identity(3) + I + 2*A*B + """ + is_commutative = False + is_symbol = True + _diff_wrt = True + + def __new__(cls, name, n, m): + n, m = _sympify(n), _sympify(m) + + cls._check_dim(m) + cls._check_dim(n) + + if isinstance(name, str): + name = Str(name) + obj = Basic.__new__(cls, name, n, m) + return obj + + @property + def shape(self): + return self.args[1], self.args[2] + + @property + def name(self): + return self.args[0].name + + def _entry(self, i, j, **kwargs): + return MatrixElement(self, i, j) + + @property + def free_symbols(self): + return {self} + + def _eval_simplify(self, **kwargs): + return self + + def _eval_derivative(self, x): + # x is a scalar: + return ZeroMatrix(self.shape[0], self.shape[1]) + + def _eval_derivative_matrix_lines(self, x): + if self != x: + first = ZeroMatrix(x.shape[0], self.shape[0]) if self.shape[0] != 1 else S.Zero + second = ZeroMatrix(x.shape[1], self.shape[1]) if self.shape[1] != 1 else S.Zero + return [_LeftRightArgs( + [first, second], + )] + else: + first = Identity(self.shape[0]) if self.shape[0] != 1 else S.One + second = Identity(self.shape[1]) if self.shape[1] != 1 else S.One + return [_LeftRightArgs( + [first, second], + )] + + +def matrix_symbols(expr): + return [sym for sym in expr.free_symbols if sym.is_Matrix] + + +class _LeftRightArgs: + r""" + Helper class to compute matrix derivatives. + + The logic: when an expression is derived by a matrix `X_{mn}`, two lines of + matrix multiplications are created: the one contracted to `m` (first line), + and the one contracted to `n` (second line). + + Transposition flips the side by which new matrices are connected to the + lines. + + The trace connects the end of the two lines. + """ + + def __init__(self, lines, higher=S.One): + self._lines = list(lines) + self._first_pointer_parent = self._lines + self._first_pointer_index = 0 + self._first_line_index = 0 + self._second_pointer_parent = self._lines + self._second_pointer_index = 1 + self._second_line_index = 1 + self.higher = higher + + @property + def first_pointer(self): + return self._first_pointer_parent[self._first_pointer_index] + + @first_pointer.setter + def first_pointer(self, value): + self._first_pointer_parent[self._first_pointer_index] = value + + @property + def second_pointer(self): + return self._second_pointer_parent[self._second_pointer_index] + + @second_pointer.setter + def second_pointer(self, value): + self._second_pointer_parent[self._second_pointer_index] = value + + def __repr__(self): + built = [self._build(i) for i in self._lines] + return "_LeftRightArgs(lines=%s, higher=%s)" % ( + built, + self.higher, + ) + + def transpose(self): + self._first_pointer_parent, self._second_pointer_parent = self._second_pointer_parent, self._first_pointer_parent + self._first_pointer_index, self._second_pointer_index = self._second_pointer_index, self._first_pointer_index + self._first_line_index, self._second_line_index = self._second_line_index, self._first_line_index + return self + + @staticmethod + def _build(expr): + if isinstance(expr, ExprBuilder): + return expr.build() + if isinstance(expr, list): + if len(expr) == 1: + return expr[0] + else: + return expr[0](*[_LeftRightArgs._build(i) for i in expr[1]]) + else: + return expr + + def build(self): + data = [self._build(i) for i in self._lines] + if self.higher != 1: + data += [self._build(self.higher)] + data = list(data) + return data + + def matrix_form(self): + if self.first != 1 and self.higher != 1: + raise ValueError("higher dimensional array cannot be represented") + + def _get_shape(elem): + if isinstance(elem, MatrixExpr): + return elem.shape + return (None, None) + + if _get_shape(self.first)[1] != _get_shape(self.second)[1]: + # Remove one-dimensional identity matrices: + # (this is needed by `a.diff(a)` where `a` is a vector) + if _get_shape(self.second) == (1, 1): + return self.first*self.second[0, 0] + if _get_shape(self.first) == (1, 1): + return self.first[1, 1]*self.second.T + raise ValueError("incompatible shapes") + if self.first != 1: + return self.first*self.second.T + else: + return self.higher + + def rank(self): + """ + Number of dimensions different from trivial (warning: not related to + matrix rank). + """ + rank = 0 + if self.first != 1: + rank += sum(i != 1 for i in self.first.shape) + if self.second != 1: + rank += sum(i != 1 for i in self.second.shape) + if self.higher != 1: + rank += 2 + return rank + + def _multiply_pointer(self, pointer, other): + from ...tensor.array.expressions.array_expressions import ArrayTensorProduct + from ...tensor.array.expressions.array_expressions import ArrayContraction + + subexpr = ExprBuilder( + ArrayContraction, + [ + ExprBuilder( + ArrayTensorProduct, + [ + pointer, + other + ] + ), + (1, 2) + ], + validator=ArrayContraction._validate + ) + + return subexpr + + def append_first(self, other): + self.first_pointer *= other + + def append_second(self, other): + self.second_pointer *= other + + +def _make_matrix(x): + from sympy.matrices.immutable import ImmutableDenseMatrix + if isinstance(x, MatrixExpr): + return x + return ImmutableDenseMatrix([[x]]) + + +from .matmul import MatMul +from .matadd import MatAdd +from .matpow import MatPow +from .transpose import Transpose +from .inverse import Inverse +from .special import ZeroMatrix, Identity +from .determinant import Determinant diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/matmul.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/matmul.py new file mode 100644 index 0000000000000000000000000000000000000000..1c46f7ff5251d89793423f92ea02d7243601de3f --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/matmul.py @@ -0,0 +1,496 @@ +from sympy.assumptions.ask import ask, Q +from sympy.assumptions.refine import handlers_dict +from sympy.core import Basic, sympify, S +from sympy.core.mul import mul, Mul +from sympy.core.numbers import Number, Integer +from sympy.core.symbol import Dummy +from sympy.functions import adjoint +from sympy.strategies import (rm_id, unpack, typed, flatten, exhaust, + do_one, new) +from sympy.matrices.exceptions import NonInvertibleMatrixError +from sympy.matrices.matrixbase import MatrixBase +from sympy.utilities.exceptions import sympy_deprecation_warning +from sympy.matrices.expressions._shape import validate_matmul_integer as validate + +from .inverse import Inverse +from .matexpr import MatrixExpr +from .matpow import MatPow +from .transpose import transpose +from .permutation import PermutationMatrix +from .special import ZeroMatrix, Identity, GenericIdentity, OneMatrix + + +# XXX: MatMul should perhaps not subclass directly from Mul +class MatMul(MatrixExpr, Mul): + """ + A product of matrix expressions + + Examples + ======== + + >>> from sympy import MatMul, MatrixSymbol + >>> A = MatrixSymbol('A', 5, 4) + >>> B = MatrixSymbol('B', 4, 3) + >>> C = MatrixSymbol('C', 3, 6) + >>> MatMul(A, B, C) + A*B*C + """ + is_MatMul = True + + identity = GenericIdentity() + + def __new__(cls, *args, evaluate=False, check=None, _sympify=True): + if not args: + return cls.identity + + # This must be removed aggressively in the constructor to avoid + # TypeErrors from GenericIdentity().shape + args = list(filter(lambda i: cls.identity != i, args)) + if _sympify: + args = list(map(sympify, args)) + obj = Basic.__new__(cls, *args) + factor, matrices = obj.as_coeff_matrices() + + if check is not None: + sympy_deprecation_warning( + "Passing check to MatMul is deprecated and the check argument will be removed in a future version.", + deprecated_since_version="1.11", + active_deprecations_target='remove-check-argument-from-matrix-operations') + + if check is not False: + validate(*matrices) + + if not matrices: + # Should it be + # + # return Basic.__neq__(cls, factor, GenericIdentity()) ? + return factor + + if evaluate: + return cls._evaluate(obj) + + return obj + + @classmethod + def _evaluate(cls, expr): + return canonicalize(expr) + + @property + def shape(self): + matrices = [arg for arg in self.args if arg.is_Matrix] + return (matrices[0].rows, matrices[-1].cols) + + def _entry(self, i, j, expand=True, **kwargs): + # Avoid cyclic imports + from sympy.concrete.summations import Sum + from sympy.matrices.immutable import ImmutableMatrix + + coeff, matrices = self.as_coeff_matrices() + + if len(matrices) == 1: # situation like 2*X, matmul is just X + return coeff * matrices[0][i, j] + + indices = [None]*(len(matrices) + 1) + ind_ranges = [None]*(len(matrices) - 1) + indices[0] = i + indices[-1] = j + + def f(): + counter = 1 + while True: + yield Dummy("i_%i" % counter) + counter += 1 + + dummy_generator = kwargs.get("dummy_generator", f()) + + for i in range(1, len(matrices)): + indices[i] = next(dummy_generator) + + for i, arg in enumerate(matrices[:-1]): + ind_ranges[i] = arg.shape[1] - 1 + matrices = [arg._entry(indices[i], indices[i+1], dummy_generator=dummy_generator) for i, arg in enumerate(matrices)] + expr_in_sum = Mul.fromiter(matrices) + if any(v.has(ImmutableMatrix) for v in matrices): + expand = True + result = coeff*Sum( + expr_in_sum, + *zip(indices[1:-1], [0]*len(ind_ranges), ind_ranges) + ) + + # Don't waste time in result.doit() if the sum bounds are symbolic + if not any(isinstance(v, (Integer, int)) for v in ind_ranges): + expand = False + return result.doit() if expand else result + + def as_coeff_matrices(self): + scalars = [x for x in self.args if not x.is_Matrix] + matrices = [x for x in self.args if x.is_Matrix] + coeff = Mul(*scalars) + if coeff.is_commutative is False: + raise NotImplementedError("noncommutative scalars in MatMul are not supported.") + + return coeff, matrices + + def as_coeff_mmul(self): + coeff, matrices = self.as_coeff_matrices() + return coeff, MatMul(*matrices) + + def expand(self, **kwargs): + expanded = super(MatMul, self).expand(**kwargs) + return self._evaluate(expanded) + + def _eval_transpose(self): + """Transposition of matrix multiplication. + + Notes + ===== + + The following rules are applied. + + Transposition for matrix multiplied with another matrix: + `\\left(A B\\right)^{T} = B^{T} A^{T}` + + Transposition for matrix multiplied with scalar: + `\\left(c A\\right)^{T} = c A^{T}` + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Transpose + """ + coeff, matrices = self.as_coeff_matrices() + return MatMul( + coeff, *[transpose(arg) for arg in matrices[::-1]]).doit() + + def _eval_adjoint(self): + return MatMul(*[adjoint(arg) for arg in self.args[::-1]]).doit() + + def _eval_trace(self): + factor, mmul = self.as_coeff_mmul() + if factor != 1: + from .trace import trace + return factor * trace(mmul.doit()) + + def _eval_determinant(self): + from sympy.matrices.expressions.determinant import Determinant + factor, matrices = self.as_coeff_matrices() + square_matrices = only_squares(*matrices) + return factor**self.rows * Mul(*list(map(Determinant, square_matrices))) + + def _eval_inverse(self): + if all(arg.is_square for arg in self.args if isinstance(arg, MatrixExpr)): + return MatMul(*( + arg.inverse() if isinstance(arg, MatrixExpr) else arg**-1 + for arg in self.args[::-1] + ) + ).doit() + return Inverse(self) + + def doit(self, **hints): + deep = hints.get('deep', True) + if deep: + args = tuple(arg.doit(**hints) for arg in self.args) + else: + args = self.args + + # treat scalar*MatrixSymbol or scalar*MatPow separately + expr = canonicalize(MatMul(*args)) + return expr + + # Needed for partial compatibility with Mul + def args_cnc(self, cset=False, warn=True, **kwargs): + coeff_c = [x for x in self.args if x.is_commutative] + coeff_nc = [x for x in self.args if not x.is_commutative] + if cset: + clen = len(coeff_c) + coeff_c = set(coeff_c) + if clen and warn and len(coeff_c) != clen: + raise ValueError('repeated commutative arguments: %s' % + [ci for ci in coeff_c if list(self.args).count(ci) > 1]) + return [coeff_c, coeff_nc] + + def _eval_derivative_matrix_lines(self, x): + from .transpose import Transpose + with_x_ind = [i for i, arg in enumerate(self.args) if arg.has(x)] + lines = [] + for ind in with_x_ind: + left_args = self.args[:ind] + right_args = self.args[ind+1:] + + if right_args: + right_mat = MatMul.fromiter(right_args) + else: + right_mat = Identity(self.shape[1]) + if left_args: + left_rev = MatMul.fromiter([Transpose(i).doit() if i.is_Matrix else i for i in reversed(left_args)]) + else: + left_rev = Identity(self.shape[0]) + + d = self.args[ind]._eval_derivative_matrix_lines(x) + for i in d: + i.append_first(left_rev) + i.append_second(right_mat) + lines.append(i) + + return lines + +mul.register_handlerclass((Mul, MatMul), MatMul) + + +# Rules +def newmul(*args): + if args[0] == 1: + args = args[1:] + return new(MatMul, *args) + +def any_zeros(mul): + if any(arg.is_zero or (arg.is_Matrix and arg.is_ZeroMatrix) + for arg in mul.args): + matrices = [arg for arg in mul.args if arg.is_Matrix] + return ZeroMatrix(matrices[0].rows, matrices[-1].cols) + return mul + +def merge_explicit(matmul): + """ Merge explicit MatrixBase arguments + + >>> from sympy import MatrixSymbol, Matrix, MatMul, pprint + >>> from sympy.matrices.expressions.matmul import merge_explicit + >>> A = MatrixSymbol('A', 2, 2) + >>> B = Matrix([[1, 1], [1, 1]]) + >>> C = Matrix([[1, 2], [3, 4]]) + >>> X = MatMul(A, B, C) + >>> pprint(X) + [1 1] [1 2] + A*[ ]*[ ] + [1 1] [3 4] + >>> pprint(merge_explicit(X)) + [4 6] + A*[ ] + [4 6] + + >>> X = MatMul(B, A, C) + >>> pprint(X) + [1 1] [1 2] + [ ]*A*[ ] + [1 1] [3 4] + >>> pprint(merge_explicit(X)) + [1 1] [1 2] + [ ]*A*[ ] + [1 1] [3 4] + """ + if not any(isinstance(arg, MatrixBase) for arg in matmul.args): + return matmul + newargs = [] + last = matmul.args[0] + for arg in matmul.args[1:]: + if isinstance(arg, (MatrixBase, Number)) and isinstance(last, (MatrixBase, Number)): + last = last * arg + else: + newargs.append(last) + last = arg + newargs.append(last) + + return MatMul(*newargs) + +def remove_ids(mul): + """ Remove Identities from a MatMul + + This is a modified version of sympy.strategies.rm_id. + This is necessary because MatMul may contain both MatrixExprs and Exprs + as args. + + See Also + ======== + + sympy.strategies.rm_id + """ + # Separate Exprs from MatrixExprs in args + factor, mmul = mul.as_coeff_mmul() + # Apply standard rm_id for MatMuls + result = rm_id(lambda x: x.is_Identity is True)(mmul) + if result != mmul: + return newmul(factor, *result.args) # Recombine and return + else: + return mul + +def factor_in_front(mul): + factor, matrices = mul.as_coeff_matrices() + if factor != 1: + return newmul(factor, *matrices) + return mul + +def combine_powers(mul): + r"""Combine consecutive powers with the same base into one, e.g. + $$A \times A^2 \Rightarrow A^3$$ + + This also cancels out the possible matrix inverses using the + knowledgebase of :class:`~.Inverse`, e.g., + $$ Y \times X \times X^{-1} \Rightarrow Y $$ + """ + factor, args = mul.as_coeff_matrices() + new_args = [args[0]] + + for i in range(1, len(args)): + A = new_args[-1] + B = args[i] + + if isinstance(B, Inverse) and isinstance(B.arg, MatMul): + Bargs = B.arg.args + l = len(Bargs) + if list(Bargs) == new_args[-l:]: + new_args = new_args[:-l] + [Identity(B.shape[0])] + continue + + if isinstance(A, Inverse) and isinstance(A.arg, MatMul): + Aargs = A.arg.args + l = len(Aargs) + if list(Aargs) == args[i:i+l]: + identity = Identity(A.shape[0]) + new_args[-1] = identity + for j in range(i, i+l): + args[j] = identity + continue + + if A.is_square == False or B.is_square == False: + new_args.append(B) + continue + + if isinstance(A, MatPow): + A_base, A_exp = A.args + else: + A_base, A_exp = A, S.One + + if isinstance(B, MatPow): + B_base, B_exp = B.args + else: + B_base, B_exp = B, S.One + + if A_base == B_base: + new_exp = A_exp + B_exp + new_args[-1] = MatPow(A_base, new_exp).doit(deep=False) + continue + elif not isinstance(B_base, MatrixBase): + try: + B_base_inv = B_base.inverse() + except NonInvertibleMatrixError: + B_base_inv = None + if B_base_inv is not None and A_base == B_base_inv: + new_exp = A_exp - B_exp + new_args[-1] = MatPow(A_base, new_exp).doit(deep=False) + continue + new_args.append(B) + + return newmul(factor, *new_args) + +def combine_permutations(mul): + """Refine products of permutation matrices as the products of cycles. + """ + args = mul.args + l = len(args) + if l < 2: + return mul + + result = [args[0]] + for i in range(1, l): + A = result[-1] + B = args[i] + if isinstance(A, PermutationMatrix) and \ + isinstance(B, PermutationMatrix): + cycle_1 = A.args[0] + cycle_2 = B.args[0] + result[-1] = PermutationMatrix(cycle_1 * cycle_2) + else: + result.append(B) + + return MatMul(*result) + +def combine_one_matrices(mul): + """ + Combine products of OneMatrix + + e.g. OneMatrix(2, 3) * OneMatrix(3, 4) -> 3 * OneMatrix(2, 4) + """ + factor, args = mul.as_coeff_matrices() + new_args = [args[0]] + + for B in args[1:]: + A = new_args[-1] + if not isinstance(A, OneMatrix) or not isinstance(B, OneMatrix): + new_args.append(B) + continue + new_args.pop() + new_args.append(OneMatrix(A.shape[0], B.shape[1])) + factor *= A.shape[1] + + return newmul(factor, *new_args) + +def distribute_monom(mul): + """ + Simplify MatMul expressions but distributing + rational term to MatMul. + + e.g. 2*(A+B) -> 2*A + 2*B + """ + args = mul.args + if len(args) == 2: + from .matadd import MatAdd + if args[0].is_MatAdd and args[1].is_Rational: + return MatAdd(*[MatMul(mat, args[1]).doit() for mat in args[0].args]) + if args[1].is_MatAdd and args[0].is_Rational: + return MatAdd(*[MatMul(args[0], mat).doit() for mat in args[1].args]) + return mul + +rules = ( + distribute_monom, any_zeros, remove_ids, combine_one_matrices, combine_powers, unpack, rm_id(lambda x: x == 1), + merge_explicit, factor_in_front, flatten, combine_permutations) + +canonicalize = exhaust(typed({MatMul: do_one(*rules)})) + +def only_squares(*matrices): + """factor matrices only if they are square""" + if matrices[0].rows != matrices[-1].cols: + raise RuntimeError("Invalid matrices being multiplied") + out = [] + start = 0 + for i, M in enumerate(matrices): + if M.cols == matrices[start].rows: + out.append(MatMul(*matrices[start:i+1]).doit()) + start = i+1 + return out + + +def refine_MatMul(expr, assumptions): + """ + >>> from sympy import MatrixSymbol, Q, assuming, refine + >>> X = MatrixSymbol('X', 2, 2) + >>> expr = X * X.T + >>> print(expr) + X*X.T + >>> with assuming(Q.orthogonal(X)): + ... print(refine(expr)) + I + """ + newargs = [] + exprargs = [] + + for args in expr.args: + if args.is_Matrix: + exprargs.append(args) + else: + newargs.append(args) + + last = exprargs[0] + for arg in exprargs[1:]: + if arg == last.T and ask(Q.orthogonal(arg), assumptions): + last = Identity(arg.shape[0]) + elif arg == last.conjugate() and ask(Q.unitary(arg), assumptions): + last = Identity(arg.shape[0]) + else: + newargs.append(last) + last = arg + newargs.append(last) + + return MatMul(*newargs) + + +handlers_dict['MatMul'] = refine_MatMul diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/matpow.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/matpow.py new file mode 100644 index 0000000000000000000000000000000000000000..b6472995e134e9e5ebfd28a901480665d1531275 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/matpow.py @@ -0,0 +1,150 @@ +from .matexpr import MatrixExpr +from .special import Identity +from sympy.core import S +from sympy.core.expr import ExprBuilder +from sympy.core.cache import cacheit +from sympy.core.power import Pow +from sympy.core.sympify import _sympify +from sympy.matrices import MatrixBase +from sympy.matrices.exceptions import NonSquareMatrixError + + +class MatPow(MatrixExpr): + def __new__(cls, base, exp, evaluate=False, **options): + base = _sympify(base) + if not base.is_Matrix: + raise TypeError("MatPow base should be a matrix") + + if base.is_square is False: + raise NonSquareMatrixError("Power of non-square matrix %s" % base) + + exp = _sympify(exp) + obj = super().__new__(cls, base, exp) + + if evaluate: + obj = obj.doit(deep=False) + + return obj + + @property + def base(self): + return self.args[0] + + @property + def exp(self): + return self.args[1] + + @property + def shape(self): + return self.base.shape + + @cacheit + def _get_explicit_matrix(self): + return self.base.as_explicit()**self.exp + + def _entry(self, i, j, **kwargs): + from sympy.matrices.expressions import MatMul + A = self.doit() + if isinstance(A, MatPow): + # We still have a MatPow, make an explicit MatMul out of it. + if A.exp.is_Integer and A.exp.is_positive: + A = MatMul(*[A.base for k in range(A.exp)]) + elif not self._is_shape_symbolic(): + return A._get_explicit_matrix()[i, j] + else: + # Leave the expression unevaluated: + from sympy.matrices.expressions.matexpr import MatrixElement + return MatrixElement(self, i, j) + return A[i, j] + + def doit(self, **hints): + if hints.get('deep', True): + base, exp = (arg.doit(**hints) for arg in self.args) + else: + base, exp = self.args + + # combine all powers, e.g. (A ** 2) ** 3 -> A ** 6 + while isinstance(base, MatPow): + exp *= base.args[1] + base = base.args[0] + + if isinstance(base, MatrixBase): + # Delegate + return base ** exp + + # Handle simple cases so that _eval_power() in MatrixExpr sub-classes can ignore them + if exp == S.One: + return base + if exp == S.Zero: + return Identity(base.rows) + if exp == S.NegativeOne: + from sympy.matrices.expressions import Inverse + return Inverse(base).doit(**hints) + + eval_power = getattr(base, '_eval_power', None) + if eval_power is not None: + return eval_power(exp) + + return MatPow(base, exp) + + def _eval_transpose(self): + base, exp = self.args + return MatPow(base.transpose(), exp) + + def _eval_adjoint(self): + base, exp = self.args + return MatPow(base.adjoint(), exp) + + def _eval_conjugate(self): + base, exp = self.args + return MatPow(base.conjugate(), exp) + + def _eval_derivative(self, x): + return Pow._eval_derivative(self, x) + + def _eval_derivative_matrix_lines(self, x): + from sympy.tensor.array.expressions.array_expressions import ArrayContraction + from ...tensor.array.expressions.array_expressions import ArrayTensorProduct + from .matmul import MatMul + from .inverse import Inverse + exp = self.exp + if self.base.shape == (1, 1) and not exp.has(x): + lr = self.base._eval_derivative_matrix_lines(x) + for i in lr: + subexpr = ExprBuilder( + ArrayContraction, + [ + ExprBuilder( + ArrayTensorProduct, + [ + Identity(1), + i._lines[0], + exp*self.base**(exp-1), + i._lines[1], + Identity(1), + ] + ), + (0, 3, 4), (5, 7, 8) + ], + validator=ArrayContraction._validate + ) + i._first_pointer_parent = subexpr.args[0].args + i._first_pointer_index = 0 + i._second_pointer_parent = subexpr.args[0].args + i._second_pointer_index = 4 + i._lines = [subexpr] + return lr + if (exp > 0) == True: + newexpr = MatMul.fromiter([self.base for i in range(exp)]) + elif (exp == -1) == True: + return Inverse(self.base)._eval_derivative_matrix_lines(x) + elif (exp < 0) == True: + newexpr = MatMul.fromiter([Inverse(self.base) for i in range(-exp)]) + elif (exp == 0) == True: + return self.doit()._eval_derivative_matrix_lines(x) + else: + raise NotImplementedError("cannot evaluate %s derived by %s" % (self, x)) + return newexpr._eval_derivative_matrix_lines(x) + + def _eval_inverse(self): + return MatPow(self.base, -self.exp) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/permutation.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/permutation.py new file mode 100644 index 0000000000000000000000000000000000000000..5634fa941a53d8890583fe61bb29bc34f4e6000d --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/permutation.py @@ -0,0 +1,303 @@ +from sympy.core import S +from sympy.core.sympify import _sympify +from sympy.functions import KroneckerDelta + +from .matexpr import MatrixExpr +from .special import ZeroMatrix, Identity, OneMatrix + + +class PermutationMatrix(MatrixExpr): + """A Permutation Matrix + + Parameters + ========== + + perm : Permutation + The permutation the matrix uses. + + The size of the permutation determines the matrix size. + + See the documentation of + :class:`sympy.combinatorics.permutations.Permutation` for + the further information of how to create a permutation object. + + Examples + ======== + + >>> from sympy import Matrix, PermutationMatrix + >>> from sympy.combinatorics import Permutation + + Creating a permutation matrix: + + >>> p = Permutation(1, 2, 0) + >>> P = PermutationMatrix(p) + >>> P = P.as_explicit() + >>> P + Matrix([ + [0, 1, 0], + [0, 0, 1], + [1, 0, 0]]) + + Permuting a matrix row and column: + + >>> M = Matrix([0, 1, 2]) + >>> Matrix(P*M) + Matrix([ + [1], + [2], + [0]]) + + >>> Matrix(M.T*P) + Matrix([[2, 0, 1]]) + + See Also + ======== + + sympy.combinatorics.permutations.Permutation + """ + + def __new__(cls, perm): + from sympy.combinatorics.permutations import Permutation + + perm = _sympify(perm) + if not isinstance(perm, Permutation): + raise ValueError( + "{} must be a SymPy Permutation instance.".format(perm)) + + return super().__new__(cls, perm) + + @property + def shape(self): + size = self.args[0].size + return (size, size) + + @property + def is_Identity(self): + return self.args[0].is_Identity + + def doit(self, **hints): + if self.is_Identity: + return Identity(self.rows) + return self + + def _entry(self, i, j, **kwargs): + perm = self.args[0] + return KroneckerDelta(perm.apply(i), j) + + def _eval_power(self, exp): + return PermutationMatrix(self.args[0] ** exp).doit() + + def _eval_inverse(self): + return PermutationMatrix(self.args[0] ** -1) + + _eval_transpose = _eval_adjoint = _eval_inverse + + def _eval_determinant(self): + sign = self.args[0].signature() + if sign == 1: + return S.One + elif sign == -1: + return S.NegativeOne + raise NotImplementedError + + def _eval_rewrite_as_BlockDiagMatrix(self, *args, **kwargs): + from sympy.combinatorics.permutations import Permutation + from .blockmatrix import BlockDiagMatrix + + perm = self.args[0] + full_cyclic_form = perm.full_cyclic_form + + cycles_picks = [] + + # Stage 1. Decompose the cycles into the blockable form. + a, b, c = 0, 0, 0 + flag = False + for cycle in full_cyclic_form: + l = len(cycle) + m = max(cycle) + + if not flag: + if m + 1 > a + l: + flag = True + temp = [cycle] + b = m + c = l + else: + cycles_picks.append([cycle]) + a += l + + else: + if m > b: + if m + 1 == a + c + l: + temp.append(cycle) + cycles_picks.append(temp) + flag = False + a = m+1 + else: + b = m + temp.append(cycle) + c += l + else: + if b + 1 == a + c + l: + temp.append(cycle) + cycles_picks.append(temp) + flag = False + a = b+1 + else: + temp.append(cycle) + c += l + + # Stage 2. Normalize each decomposed cycles and build matrix. + p = 0 + args = [] + for pick in cycles_picks: + new_cycles = [] + l = 0 + for cycle in pick: + new_cycle = [i - p for i in cycle] + new_cycles.append(new_cycle) + l += len(cycle) + p += l + perm = Permutation(new_cycles) + mat = PermutationMatrix(perm) + args.append(mat) + + return BlockDiagMatrix(*args) + + +class MatrixPermute(MatrixExpr): + r"""Symbolic representation for permuting matrix rows or columns. + + Parameters + ========== + + perm : Permutation, PermutationMatrix + The permutation to use for permuting the matrix. + The permutation can be resized to the suitable one, + + axis : 0 or 1 + The axis to permute alongside. + If `0`, it will permute the matrix rows. + If `1`, it will permute the matrix columns. + + Notes + ===== + + This follows the same notation used in + :meth:`sympy.matrices.matrixbase.MatrixBase.permute`. + + Examples + ======== + + >>> from sympy import Matrix, MatrixPermute + >>> from sympy.combinatorics import Permutation + + Permuting the matrix rows: + + >>> p = Permutation(1, 2, 0) + >>> A = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + >>> B = MatrixPermute(A, p, axis=0) + >>> B.as_explicit() + Matrix([ + [4, 5, 6], + [7, 8, 9], + [1, 2, 3]]) + + Permuting the matrix columns: + + >>> B = MatrixPermute(A, p, axis=1) + >>> B.as_explicit() + Matrix([ + [2, 3, 1], + [5, 6, 4], + [8, 9, 7]]) + + See Also + ======== + + sympy.matrices.matrixbase.MatrixBase.permute + """ + def __new__(cls, mat, perm, axis=S.Zero): + from sympy.combinatorics.permutations import Permutation + + mat = _sympify(mat) + if not mat.is_Matrix: + raise ValueError( + "{} must be a SymPy matrix instance.".format(perm)) + + perm = _sympify(perm) + if isinstance(perm, PermutationMatrix): + perm = perm.args[0] + + if not isinstance(perm, Permutation): + raise ValueError( + "{} must be a SymPy Permutation or a PermutationMatrix " \ + "instance".format(perm)) + + axis = _sympify(axis) + if axis not in (0, 1): + raise ValueError("The axis must be 0 or 1.") + + mat_size = mat.shape[axis] + if mat_size != perm.size: + try: + perm = perm.resize(mat_size) + except ValueError: + raise ValueError( + "Size does not match between the permutation {} " + "and the matrix {} threaded over the axis {} " + "and cannot be converted." + .format(perm, mat, axis)) + + return super().__new__(cls, mat, perm, axis) + + def doit(self, deep=True, **hints): + mat, perm, axis = self.args + + if deep: + mat = mat.doit(deep=deep, **hints) + perm = perm.doit(deep=deep, **hints) + + if perm.is_Identity: + return mat + + if mat.is_Identity: + if axis is S.Zero: + return PermutationMatrix(perm) + elif axis is S.One: + return PermutationMatrix(perm**-1) + + if isinstance(mat, (ZeroMatrix, OneMatrix)): + return mat + + if isinstance(mat, MatrixPermute) and mat.args[2] == axis: + return MatrixPermute(mat.args[0], perm * mat.args[1], axis) + + return self + + @property + def shape(self): + return self.args[0].shape + + def _entry(self, i, j, **kwargs): + mat, perm, axis = self.args + + if axis == 0: + return mat[perm.apply(i), j] + elif axis == 1: + return mat[i, perm.apply(j)] + + def _eval_rewrite_as_MatMul(self, *args, **kwargs): + from .matmul import MatMul + + mat, perm, axis = self.args + + deep = kwargs.get("deep", True) + + if deep: + mat = mat.rewrite(MatMul) + + if axis == 0: + return MatMul(PermutationMatrix(perm), mat) + elif axis == 1: + return MatMul(mat, PermutationMatrix(perm**-1)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/sets.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/sets.py new file mode 100644 index 0000000000000000000000000000000000000000..ab4930ea8f1b058977a8dd1abdc62f1f5e2195c1 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/sets.py @@ -0,0 +1,68 @@ +from sympy.core.assumptions import check_assumptions +from sympy.core.logic import fuzzy_and +from sympy.core.sympify import _sympify +from sympy.matrices.kind import MatrixKind +from sympy.sets.sets import Set, SetKind +from sympy.core.kind import NumberKind +from .matexpr import MatrixExpr + + +class MatrixSet(Set): + """ + MatrixSet represents the set of matrices with ``shape = (n, m)`` over the + given set. + + Examples + ======== + + >>> from sympy.matrices import MatrixSet + >>> from sympy import S, I, Matrix + >>> M = MatrixSet(2, 2, set=S.Reals) + >>> X = Matrix([[1, 2], [3, 4]]) + >>> X in M + True + >>> X = Matrix([[1, 2], [I, 4]]) + >>> X in M + False + + """ + is_empty = False + + def __new__(cls, n, m, set): + n, m, set = _sympify(n), _sympify(m), _sympify(set) + cls._check_dim(n) + cls._check_dim(m) + if not isinstance(set, Set): + raise TypeError("{} should be an instance of Set.".format(set)) + return Set.__new__(cls, n, m, set) + + @property + def shape(self): + return self.args[:2] + + @property + def set(self): + return self.args[2] + + def _contains(self, other): + if not isinstance(other, MatrixExpr): + raise TypeError("{} should be an instance of MatrixExpr.".format(other)) + if other.shape != self.shape: + are_symbolic = any(_sympify(x).is_Symbol for x in other.shape + self.shape) + if are_symbolic: + return None + return False + return fuzzy_and(self.set.contains(x) for x in other) + + @classmethod + def _check_dim(cls, dim): + """Helper function to check invalid matrix dimensions""" + ok = not dim.is_Float and check_assumptions( + dim, integer=True, nonnegative=True) + if ok is False: + raise ValueError( + "The dimension specification {} should be " + "a nonnegative integer.".format(dim)) + + def _kind(self): + return SetKind(MatrixKind(NumberKind)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/slice.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/slice.py new file mode 100644 index 0000000000000000000000000000000000000000..1904b49f29c503fb4c0c909532f8342fb0f4b135 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/slice.py @@ -0,0 +1,114 @@ +from sympy.matrices.expressions.matexpr import MatrixExpr +from sympy.core.basic import Basic +from sympy.core.containers import Tuple +from sympy.functions.elementary.integers import floor + +def normalize(i, parentsize): + if isinstance(i, slice): + i = (i.start, i.stop, i.step) + if not isinstance(i, (tuple, list, Tuple)): + if (i < 0) == True: + i += parentsize + i = (i, i+1, 1) + i = list(i) + if len(i) == 2: + i.append(1) + start, stop, step = i + start = start or 0 + if stop is None: + stop = parentsize + if (start < 0) == True: + start += parentsize + if (stop < 0) == True: + stop += parentsize + step = step or 1 + + if ((stop - start) * step < 1) == True: + raise IndexError() + + return (start, stop, step) + +class MatrixSlice(MatrixExpr): + """ A MatrixSlice of a Matrix Expression + + Examples + ======== + + >>> from sympy import MatrixSlice, ImmutableMatrix + >>> M = ImmutableMatrix(4, 4, range(16)) + >>> M + Matrix([ + [ 0, 1, 2, 3], + [ 4, 5, 6, 7], + [ 8, 9, 10, 11], + [12, 13, 14, 15]]) + + >>> B = MatrixSlice(M, (0, 2), (2, 4)) + >>> ImmutableMatrix(B) + Matrix([ + [2, 3], + [6, 7]]) + """ + parent = property(lambda self: self.args[0]) + rowslice = property(lambda self: self.args[1]) + colslice = property(lambda self: self.args[2]) + + def __new__(cls, parent, rowslice, colslice): + rowslice = normalize(rowslice, parent.shape[0]) + colslice = normalize(colslice, parent.shape[1]) + if not (len(rowslice) == len(colslice) == 3): + raise IndexError() + if ((0 > rowslice[0]) == True or + (parent.shape[0] < rowslice[1]) == True or + (0 > colslice[0]) == True or + (parent.shape[1] < colslice[1]) == True): + raise IndexError() + if isinstance(parent, MatrixSlice): + return mat_slice_of_slice(parent, rowslice, colslice) + return Basic.__new__(cls, parent, Tuple(*rowslice), Tuple(*colslice)) + + @property + def shape(self): + rows = self.rowslice[1] - self.rowslice[0] + rows = rows if self.rowslice[2] == 1 else floor(rows/self.rowslice[2]) + cols = self.colslice[1] - self.colslice[0] + cols = cols if self.colslice[2] == 1 else floor(cols/self.colslice[2]) + return rows, cols + + def _entry(self, i, j, **kwargs): + return self.parent._entry(i*self.rowslice[2] + self.rowslice[0], + j*self.colslice[2] + self.colslice[0], + **kwargs) + + @property + def on_diag(self): + return self.rowslice == self.colslice + + +def slice_of_slice(s, t): + start1, stop1, step1 = s + start2, stop2, step2 = t + + start = start1 + start2*step1 + step = step1 * step2 + stop = start1 + step1*stop2 + + if stop > stop1: + raise IndexError() + + return start, stop, step + + +def mat_slice_of_slice(parent, rowslice, colslice): + """ Collapse nested matrix slices + + >>> from sympy import MatrixSymbol + >>> X = MatrixSymbol('X', 10, 10) + >>> X[:, 1:5][5:8, :] + X[5:8, 1:5] + >>> X[1:9:2, 2:6][1:3, 2] + X[3:7:2, 4:5] + """ + row = slice_of_slice(parent.rowslice, rowslice) + col = slice_of_slice(parent.colslice, colslice) + return MatrixSlice(parent.parent, row, col) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/special.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/special.py new file mode 100644 index 0000000000000000000000000000000000000000..d1e426f16ada0e4245b644867974b41b6f86b5cc --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/special.py @@ -0,0 +1,299 @@ +from sympy.assumptions.ask import ask, Q +from sympy.core.relational import Eq +from sympy.core.singleton import S +from sympy.core.sympify import _sympify +from sympy.functions.special.tensor_functions import KroneckerDelta +from sympy.matrices.exceptions import NonInvertibleMatrixError +from .matexpr import MatrixExpr + + +class ZeroMatrix(MatrixExpr): + """The Matrix Zero 0 - additive identity + + Examples + ======== + + >>> from sympy import MatrixSymbol, ZeroMatrix + >>> A = MatrixSymbol('A', 3, 5) + >>> Z = ZeroMatrix(3, 5) + >>> A + Z + A + >>> Z*A.T + 0 + """ + is_ZeroMatrix = True + + def __new__(cls, m, n): + m, n = _sympify(m), _sympify(n) + cls._check_dim(m) + cls._check_dim(n) + + return super().__new__(cls, m, n) + + @property + def shape(self): + return (self.args[0], self.args[1]) + + def _eval_power(self, exp): + # exp = -1, 0, 1 are already handled at this stage + if (exp < 0) == True: + raise NonInvertibleMatrixError("Matrix det == 0; not invertible") + return self + + def _eval_transpose(self): + return ZeroMatrix(self.cols, self.rows) + + def _eval_adjoint(self): + return ZeroMatrix(self.cols, self.rows) + + def _eval_trace(self): + return S.Zero + + def _eval_determinant(self): + return S.Zero + + def _eval_inverse(self): + raise NonInvertibleMatrixError("Matrix det == 0; not invertible.") + + def _eval_as_real_imag(self): + return (self, self) + + def _eval_conjugate(self): + return self + + def _entry(self, i, j, **kwargs): + return S.Zero + + +class GenericZeroMatrix(ZeroMatrix): + """ + A zero matrix without a specified shape + + This exists primarily so MatAdd() with no arguments can return something + meaningful. + """ + def __new__(cls): + # super(ZeroMatrix, cls) instead of super(GenericZeroMatrix, cls) + # because ZeroMatrix.__new__ doesn't have the same signature + return super(ZeroMatrix, cls).__new__(cls) + + @property + def rows(self): + raise TypeError("GenericZeroMatrix does not have a specified shape") + + @property + def cols(self): + raise TypeError("GenericZeroMatrix does not have a specified shape") + + @property + def shape(self): + raise TypeError("GenericZeroMatrix does not have a specified shape") + + # Avoid Matrix.__eq__ which might call .shape + def __eq__(self, other): + return isinstance(other, GenericZeroMatrix) + + def __ne__(self, other): + return not (self == other) + + def __hash__(self): + return super().__hash__() + + + +class Identity(MatrixExpr): + """The Matrix Identity I - multiplicative identity + + Examples + ======== + + >>> from sympy import Identity, MatrixSymbol + >>> A = MatrixSymbol('A', 3, 5) + >>> I = Identity(3) + >>> I*A + A + """ + + is_Identity = True + + def __new__(cls, n): + n = _sympify(n) + cls._check_dim(n) + + return super().__new__(cls, n) + + @property + def rows(self): + return self.args[0] + + @property + def cols(self): + return self.args[0] + + @property + def shape(self): + return (self.args[0], self.args[0]) + + @property + def is_square(self): + return True + + def _eval_transpose(self): + return self + + def _eval_trace(self): + return self.rows + + def _eval_inverse(self): + return self + + def _eval_as_real_imag(self): + return (self, ZeroMatrix(*self.shape)) + + def _eval_conjugate(self): + return self + + def _eval_adjoint(self): + return self + + def _entry(self, i, j, **kwargs): + eq = Eq(i, j) + if eq is S.true: + return S.One + elif eq is S.false: + return S.Zero + return KroneckerDelta(i, j, (0, self.cols-1)) + + def _eval_determinant(self): + return S.One + + def _eval_power(self, exp): + return self + + +class GenericIdentity(Identity): + """ + An identity matrix without a specified shape + + This exists primarily so MatMul() with no arguments can return something + meaningful. + """ + def __new__(cls): + # super(Identity, cls) instead of super(GenericIdentity, cls) because + # Identity.__new__ doesn't have the same signature + return super(Identity, cls).__new__(cls) + + @property + def rows(self): + raise TypeError("GenericIdentity does not have a specified shape") + + @property + def cols(self): + raise TypeError("GenericIdentity does not have a specified shape") + + @property + def shape(self): + raise TypeError("GenericIdentity does not have a specified shape") + + @property + def is_square(self): + return True + + # Avoid Matrix.__eq__ which might call .shape + def __eq__(self, other): + return isinstance(other, GenericIdentity) + + def __ne__(self, other): + return not (self == other) + + def __hash__(self): + return super().__hash__() + + +class OneMatrix(MatrixExpr): + """ + Matrix whose all entries are ones. + """ + def __new__(cls, m, n, evaluate=False): + m, n = _sympify(m), _sympify(n) + cls._check_dim(m) + cls._check_dim(n) + + if evaluate: + condition = Eq(m, 1) & Eq(n, 1) + if condition == True: + return Identity(1) + + obj = super().__new__(cls, m, n) + return obj + + @property + def shape(self): + return self._args + + @property + def is_Identity(self): + return self._is_1x1() == True + + def as_explicit(self): + from sympy.matrices.immutable import ImmutableDenseMatrix + return ImmutableDenseMatrix.ones(*self.shape) + + def doit(self, **hints): + args = self.args + if hints.get('deep', True): + args = [a.doit(**hints) for a in args] + return self.func(*args, evaluate=True) + + def _eval_power(self, exp): + # exp = -1, 0, 1 are already handled at this stage + if self._is_1x1() == True: + return Identity(1) + if (exp < 0) == True: + raise NonInvertibleMatrixError("Matrix det == 0; not invertible") + if ask(Q.integer(exp)): + return self.shape[0] ** (exp - 1) * OneMatrix(*self.shape) + return super()._eval_power(exp) + + def _eval_transpose(self): + return OneMatrix(self.cols, self.rows) + + def _eval_adjoint(self): + return OneMatrix(self.cols, self.rows) + + def _eval_trace(self): + return S.One*self.rows + + def _is_1x1(self): + """Returns true if the matrix is known to be 1x1""" + shape = self.shape + return Eq(shape[0], 1) & Eq(shape[1], 1) + + def _eval_determinant(self): + condition = self._is_1x1() + if condition == True: + return S.One + elif condition == False: + return S.Zero + else: + from sympy.matrices.expressions.determinant import Determinant + return Determinant(self) + + def _eval_inverse(self): + condition = self._is_1x1() + if condition == True: + return Identity(1) + elif condition == False: + raise NonInvertibleMatrixError("Matrix det == 0; not invertible.") + else: + from .inverse import Inverse + return Inverse(self) + + def _eval_as_real_imag(self): + return (self, ZeroMatrix(*self.shape)) + + def _eval_conjugate(self): + return self + + def _entry(self, i, j, **kwargs): + return S.One diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..04a8ce52da4c5fd149af12ab55b254d269aed5a4 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_adjoint.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_adjoint.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bbd95642465012f81f4f4efe77c8ed61172dbc0b Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_adjoint.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_applyfunc.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_applyfunc.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f729c8c126e798ebeba9890f8f112f83525f8915 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_applyfunc.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_blockmatrix.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_blockmatrix.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..919b0ebae78de2ffcacb9faf84a5eba11919a07d Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_blockmatrix.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_companion.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_companion.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..866b01d628ea39c9f34d26611f4cbcbb5a2f3382 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_companion.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_derivatives.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_derivatives.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..49e9d944b7d712f038c55e31722e4d88537310c6 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_derivatives.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_determinant.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_determinant.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d29051227ab8a5c9bb16b012b42a4986f45883ce Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_determinant.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_diagonal.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_diagonal.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0c02946e9a10b3d83064a91d07ffce34f91141ae Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_diagonal.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_dotproduct.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_dotproduct.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fda8e9f0bf44ae7ff0e47b1189f40d64b74f4de3 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_dotproduct.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_factorizations.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_factorizations.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2a83caa73c7936751697df7f9568d28e17138d9d Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_factorizations.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_fourier.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_fourier.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d5ea028ad389145d17a8ec4952d2303a0a570154 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_fourier.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_funcmatrix.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_funcmatrix.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6d788ba56eb020c3a7c5d78ca8aea2fff500ae07 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_funcmatrix.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_hadamard.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_hadamard.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..89443572e21672d9de80c4a364680ea3123fab79 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_hadamard.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_indexing.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_indexing.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..96345ceac08c6348387ca7fde06c09d973cb53c2 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_indexing.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_inverse.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_inverse.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bc86daedae35d63e28b543c45754d0080c6e854e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_inverse.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_kronecker.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_kronecker.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..112855d44accd2140dd8980739746ca522ab2329 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_kronecker.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_matadd.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_matadd.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9dad00cfc50d831830454e1db563d6009e443bf2 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_matadd.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_matexpr.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_matexpr.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f830da926d53fab275d0b3b7af718da8f0026ac9 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_matexpr.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_matmul.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_matmul.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..87a8ccc652bec8e0b75696d71d81344fcb6b83fe Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_matmul.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_matpow.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_matpow.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dd433850347837432b56557e10129b01dfe29071 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_matpow.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_permutation.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_permutation.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8b0c8ba03634aee92d701e672b207e528cca0b03 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_permutation.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_sets.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_sets.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bca7e4f63ca024c5c6261e50af1462c574e185e0 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_sets.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_slice.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_slice.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0b4d2208fe64539e2c9972c99b4da4f0f5749c19 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_slice.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_special.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_special.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fa27753c8a794938e9f8a66fb18d02240ca22c3e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_special.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_trace.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_trace.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8a1c14c549a30f3338dd3b18504e98867b45d85e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_trace.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_transpose.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_transpose.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4fc7d987f94f754a8195f7402ae77c2ec8ab4d75 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/__pycache__/test_transpose.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_adjoint.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_adjoint.py new file mode 100644 index 0000000000000000000000000000000000000000..7106b5740b1dc7c32f2c6f5ecb9d286b5e1dd222 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_adjoint.py @@ -0,0 +1,34 @@ +from sympy.core import symbols, S +from sympy.functions import adjoint, conjugate, transpose +from sympy.matrices.expressions import MatrixSymbol, Adjoint, trace, Transpose +from sympy.matrices import eye, Matrix + +n, m, l, k, p = symbols('n m l k p', integer=True) +A = MatrixSymbol('A', n, m) +B = MatrixSymbol('B', m, l) +C = MatrixSymbol('C', n, n) + + +def test_adjoint(): + Sq = MatrixSymbol('Sq', n, n) + + assert Adjoint(A).shape == (m, n) + assert Adjoint(A*B).shape == (l, n) + assert adjoint(Adjoint(A)) == A + assert isinstance(Adjoint(Adjoint(A)), Adjoint) + + assert conjugate(Adjoint(A)) == Transpose(A) + assert transpose(Adjoint(A)) == Adjoint(Transpose(A)) + + assert Adjoint(eye(3)).doit() == eye(3) + + assert Adjoint(S(5)).doit() == S(5) + + assert Adjoint(Matrix([[1, 2], [3, 4]])).doit() == Matrix([[1, 3], [2, 4]]) + + assert adjoint(trace(Sq)) == conjugate(trace(Sq)) + assert trace(adjoint(Sq)) == conjugate(trace(Sq)) + + assert Adjoint(Sq)[0, 1] == conjugate(Sq[1, 0]) + + assert Adjoint(A*B).doit() == Adjoint(B) * Adjoint(A) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_applyfunc.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_applyfunc.py new file mode 100644 index 0000000000000000000000000000000000000000..d98732e2751e53938d96d7ea56c916e6fee4578e --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_applyfunc.py @@ -0,0 +1,118 @@ +from sympy.core.symbol import symbols, Dummy +from sympy.matrices.expressions.applyfunc import ElementwiseApplyFunction +from sympy.core.function import Lambda +from sympy.functions.elementary.exponential import exp +from sympy.functions.elementary.trigonometric import sin +from sympy.matrices.dense import Matrix +from sympy.matrices.expressions.matexpr import MatrixSymbol +from sympy.matrices.expressions.matmul import MatMul +from sympy.simplify.simplify import simplify + + +X = MatrixSymbol("X", 3, 3) +Y = MatrixSymbol("Y", 3, 3) + +k = symbols("k") +Xk = MatrixSymbol("X", k, k) + +Xd = X.as_explicit() + +x, y, z, t = symbols("x y z t") + + +def test_applyfunc_matrix(): + x = Dummy('x') + double = Lambda(x, x**2) + + expr = ElementwiseApplyFunction(double, Xd) + assert isinstance(expr, ElementwiseApplyFunction) + assert expr.doit() == Xd.applyfunc(lambda x: x**2) + assert expr.shape == (3, 3) + assert expr.func(*expr.args) == expr + assert simplify(expr) == expr + assert expr[0, 0] == double(Xd[0, 0]) + + expr = ElementwiseApplyFunction(double, X) + assert isinstance(expr, ElementwiseApplyFunction) + assert isinstance(expr.doit(), ElementwiseApplyFunction) + assert expr == X.applyfunc(double) + assert expr.func(*expr.args) == expr + + expr = ElementwiseApplyFunction(exp, X*Y) + assert expr.expr == X*Y + assert expr.function.dummy_eq(Lambda(x, exp(x))) + assert expr.dummy_eq((X*Y).applyfunc(exp)) + assert expr.func(*expr.args) == expr + + assert isinstance(X*expr, MatMul) + assert (X*expr).shape == (3, 3) + Z = MatrixSymbol("Z", 2, 3) + assert (Z*expr).shape == (2, 3) + + expr = ElementwiseApplyFunction(exp, Z.T)*ElementwiseApplyFunction(exp, Z) + assert expr.shape == (3, 3) + expr = ElementwiseApplyFunction(exp, Z)*ElementwiseApplyFunction(exp, Z.T) + assert expr.shape == (2, 2) + + M = Matrix([[x, y], [z, t]]) + expr = ElementwiseApplyFunction(sin, M) + assert isinstance(expr, ElementwiseApplyFunction) + assert expr.function.dummy_eq(Lambda(x, sin(x))) + assert expr.expr == M + assert expr.doit() == M.applyfunc(sin) + assert expr.doit() == Matrix([[sin(x), sin(y)], [sin(z), sin(t)]]) + assert expr.func(*expr.args) == expr + + expr = ElementwiseApplyFunction(double, Xk) + assert expr.doit() == expr + assert expr.subs(k, 2).shape == (2, 2) + assert (expr*expr).shape == (k, k) + M = MatrixSymbol("M", k, t) + expr2 = M.T*expr*M + assert isinstance(expr2, MatMul) + assert expr2.args[1] == expr + assert expr2.shape == (t, t) + expr3 = expr*M + assert expr3.shape == (k, t) + + expr1 = ElementwiseApplyFunction(lambda x: x+1, Xk) + expr2 = ElementwiseApplyFunction(lambda x: x, Xk) + assert expr1 != expr2 + + +def test_applyfunc_entry(): + + af = X.applyfunc(sin) + assert af[0, 0] == sin(X[0, 0]) + + af = Xd.applyfunc(sin) + assert af[0, 0] == sin(X[0, 0]) + + +def test_applyfunc_as_explicit(): + + af = X.applyfunc(sin) + assert af.as_explicit() == Matrix([ + [sin(X[0, 0]), sin(X[0, 1]), sin(X[0, 2])], + [sin(X[1, 0]), sin(X[1, 1]), sin(X[1, 2])], + [sin(X[2, 0]), sin(X[2, 1]), sin(X[2, 2])], + ]) + + +def test_applyfunc_transpose(): + + af = Xk.applyfunc(sin) + assert af.T.dummy_eq(Xk.T.applyfunc(sin)) + + +def test_applyfunc_shape_11_matrices(): + M = MatrixSymbol("M", 1, 1) + + double = Lambda(x, x*2) + + expr = M.applyfunc(sin) + assert isinstance(expr, ElementwiseApplyFunction) + + expr = M.applyfunc(double) + assert isinstance(expr, MatMul) + assert expr == 2*M diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_blockmatrix.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_blockmatrix.py new file mode 100644 index 0000000000000000000000000000000000000000..1d4893cd9a4b3e47dd8e84db33031f7f6f3201fd --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_blockmatrix.py @@ -0,0 +1,469 @@ +from sympy.matrices.expressions.trace import Trace +from sympy.testing.pytest import raises, slow +from sympy.matrices.expressions.blockmatrix import ( + block_collapse, bc_matmul, bc_block_plus_ident, BlockDiagMatrix, + BlockMatrix, bc_dist, bc_matadd, bc_transpose, bc_inverse, + blockcut, reblock_2x2, deblock) +from sympy.matrices.expressions import ( + MatrixSymbol, Identity, trace, det, ZeroMatrix, OneMatrix) +from sympy.matrices.expressions.inverse import Inverse +from sympy.matrices.expressions.matpow import MatPow +from sympy.matrices.expressions.transpose import Transpose +from sympy.matrices.exceptions import NonInvertibleMatrixError +from sympy.matrices import ( + Matrix, ImmutableMatrix, ImmutableSparseMatrix, zeros) +from sympy.core import Tuple, Expr, S, Function +from sympy.core.symbol import Symbol, symbols +from sympy.functions import transpose, im, re + +i, j, k, l, m, n, p = symbols('i:n, p', integer=True) +A = MatrixSymbol('A', n, n) +B = MatrixSymbol('B', n, n) +C = MatrixSymbol('C', n, n) +D = MatrixSymbol('D', n, n) +G = MatrixSymbol('G', n, n) +H = MatrixSymbol('H', n, n) +b1 = BlockMatrix([[G, H]]) +b2 = BlockMatrix([[G], [H]]) + +def test_bc_matmul(): + assert bc_matmul(H*b1*b2*G) == BlockMatrix([[(H*G*G + H*H*H)*G]]) + +def test_bc_matadd(): + assert bc_matadd(BlockMatrix([[G, H]]) + BlockMatrix([[H, H]])) == \ + BlockMatrix([[G+H, H+H]]) + +def test_bc_transpose(): + assert bc_transpose(Transpose(BlockMatrix([[A, B], [C, D]]))) == \ + BlockMatrix([[A.T, C.T], [B.T, D.T]]) + +def test_bc_dist_diag(): + A = MatrixSymbol('A', n, n) + B = MatrixSymbol('B', m, m) + C = MatrixSymbol('C', l, l) + X = BlockDiagMatrix(A, B, C) + + assert bc_dist(X+X).equals(BlockDiagMatrix(2*A, 2*B, 2*C)) + +def test_block_plus_ident(): + A = MatrixSymbol('A', n, n) + B = MatrixSymbol('B', n, m) + C = MatrixSymbol('C', m, n) + D = MatrixSymbol('D', m, m) + X = BlockMatrix([[A, B], [C, D]]) + Z = MatrixSymbol('Z', n + m, n + m) + assert bc_block_plus_ident(X + Identity(m + n) + Z) == \ + BlockDiagMatrix(Identity(n), Identity(m)) + X + Z + +def test_BlockMatrix(): + A = MatrixSymbol('A', n, m) + B = MatrixSymbol('B', n, k) + C = MatrixSymbol('C', l, m) + D = MatrixSymbol('D', l, k) + M = MatrixSymbol('M', m + k, p) + N = MatrixSymbol('N', l + n, k + m) + X = BlockMatrix(Matrix([[A, B], [C, D]])) + + assert X.__class__(*X.args) == X + + # block_collapse does nothing on normal inputs + E = MatrixSymbol('E', n, m) + assert block_collapse(A + 2*E) == A + 2*E + F = MatrixSymbol('F', m, m) + assert block_collapse(E.T*A*F) == E.T*A*F + + assert X.shape == (l + n, k + m) + assert X.blockshape == (2, 2) + assert transpose(X) == BlockMatrix(Matrix([[A.T, C.T], [B.T, D.T]])) + assert transpose(X).shape == X.shape[::-1] + + # Test that BlockMatrices and MatrixSymbols can still mix + assert (X*M).is_MatMul + assert X._blockmul(M).is_MatMul + assert (X*M).shape == (n + l, p) + assert (X + N).is_MatAdd + assert X._blockadd(N).is_MatAdd + assert (X + N).shape == X.shape + + E = MatrixSymbol('E', m, 1) + F = MatrixSymbol('F', k, 1) + + Y = BlockMatrix(Matrix([[E], [F]])) + + assert (X*Y).shape == (l + n, 1) + assert block_collapse(X*Y).blocks[0, 0] == A*E + B*F + assert block_collapse(X*Y).blocks[1, 0] == C*E + D*F + + # block_collapse passes down into container objects, transposes, and inverse + assert block_collapse(transpose(X*Y)) == transpose(block_collapse(X*Y)) + assert block_collapse(Tuple(X*Y, 2*X)) == ( + block_collapse(X*Y), block_collapse(2*X)) + + # Make sure that MatrixSymbols will enter 1x1 BlockMatrix if it simplifies + Ab = BlockMatrix([[A]]) + Z = MatrixSymbol('Z', *A.shape) + assert block_collapse(Ab + Z) == A + Z + +def test_block_collapse_explicit_matrices(): + A = Matrix([[1, 2], [3, 4]]) + assert block_collapse(BlockMatrix([[A]])) == A + + A = ImmutableSparseMatrix([[1, 2], [3, 4]]) + assert block_collapse(BlockMatrix([[A]])) == A + +def test_issue_17624(): + a = MatrixSymbol("a", 2, 2) + z = ZeroMatrix(2, 2) + b = BlockMatrix([[a, z], [z, z]]) + assert block_collapse(b * b) == BlockMatrix([[a**2, z], [z, z]]) + assert block_collapse(b * b * b) == BlockMatrix([[a**3, z], [z, z]]) + +def test_issue_18618(): + A = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + assert A == Matrix(BlockDiagMatrix(A)) + +def test_BlockMatrix_trace(): + A, B, C, D = [MatrixSymbol(s, 3, 3) for s in 'ABCD'] + X = BlockMatrix([[A, B], [C, D]]) + assert trace(X) == trace(A) + trace(D) + assert trace(BlockMatrix([ZeroMatrix(n, n)])) == 0 + +def test_BlockMatrix_Determinant(): + A, B, C, D = [MatrixSymbol(s, 3, 3) for s in 'ABCD'] + X = BlockMatrix([[A, B], [C, D]]) + from sympy.assumptions.ask import Q + from sympy.assumptions.assume import assuming + with assuming(Q.invertible(A)): + assert det(X) == det(A) * det(X.schur('A')) + + assert isinstance(det(X), Expr) + assert det(BlockMatrix([A])) == det(A) + assert det(BlockMatrix([ZeroMatrix(n, n)])) == 0 + +def test_squareBlockMatrix(): + A = MatrixSymbol('A', n, n) + B = MatrixSymbol('B', n, m) + C = MatrixSymbol('C', m, n) + D = MatrixSymbol('D', m, m) + X = BlockMatrix([[A, B], [C, D]]) + Y = BlockMatrix([[A]]) + + assert X.is_square + + Q = X + Identity(m + n) + assert (block_collapse(Q) == + BlockMatrix([[A + Identity(n), B], [C, D + Identity(m)]])) + + assert (X + MatrixSymbol('Q', n + m, n + m)).is_MatAdd + assert (X * MatrixSymbol('Q', n + m, n + m)).is_MatMul + + assert block_collapse(Y.I) == A.I + + assert isinstance(X.inverse(), Inverse) + + assert not X.is_Identity + + Z = BlockMatrix([[Identity(n), B], [C, D]]) + assert not Z.is_Identity + + +def test_BlockMatrix_2x2_inverse_symbolic(): + A = MatrixSymbol('A', n, m) + B = MatrixSymbol('B', n, k - m) + C = MatrixSymbol('C', k - n, m) + D = MatrixSymbol('D', k - n, k - m) + X = BlockMatrix([[A, B], [C, D]]) + assert X.is_square and X.shape == (k, k) + assert isinstance(block_collapse(X.I), Inverse) # Can't invert when none of the blocks is square + + # test code path where only A is invertible + A = MatrixSymbol('A', n, n) + B = MatrixSymbol('B', n, m) + C = MatrixSymbol('C', m, n) + D = ZeroMatrix(m, m) + X = BlockMatrix([[A, B], [C, D]]) + assert block_collapse(X.inverse()) == BlockMatrix([ + [A.I + A.I * B * X.schur('A').I * C * A.I, -A.I * B * X.schur('A').I], + [-X.schur('A').I * C * A.I, X.schur('A').I], + ]) + + # test code path where only B is invertible + A = MatrixSymbol('A', n, m) + B = MatrixSymbol('B', n, n) + C = ZeroMatrix(m, m) + D = MatrixSymbol('D', m, n) + X = BlockMatrix([[A, B], [C, D]]) + assert block_collapse(X.inverse()) == BlockMatrix([ + [-X.schur('B').I * D * B.I, X.schur('B').I], + [B.I + B.I * A * X.schur('B').I * D * B.I, -B.I * A * X.schur('B').I], + ]) + + # test code path where only C is invertible + A = MatrixSymbol('A', n, m) + B = ZeroMatrix(n, n) + C = MatrixSymbol('C', m, m) + D = MatrixSymbol('D', m, n) + X = BlockMatrix([[A, B], [C, D]]) + assert block_collapse(X.inverse()) == BlockMatrix([ + [-C.I * D * X.schur('C').I, C.I + C.I * D * X.schur('C').I * A * C.I], + [X.schur('C').I, -X.schur('C').I * A * C.I], + ]) + + # test code path where only D is invertible + A = ZeroMatrix(n, n) + B = MatrixSymbol('B', n, m) + C = MatrixSymbol('C', m, n) + D = MatrixSymbol('D', m, m) + X = BlockMatrix([[A, B], [C, D]]) + assert block_collapse(X.inverse()) == BlockMatrix([ + [X.schur('D').I, -X.schur('D').I * B * D.I], + [-D.I * C * X.schur('D').I, D.I + D.I * C * X.schur('D').I * B * D.I], + ]) + + +def test_BlockMatrix_2x2_inverse_numeric(): + """Test 2x2 block matrix inversion numerically for all 4 formulas""" + M = Matrix([[1, 2], [3, 4]]) + # rank deficient matrices that have full rank when two of them combined + D1 = Matrix([[1, 2], [2, 4]]) + D2 = Matrix([[1, 3], [3, 9]]) + D3 = Matrix([[1, 4], [4, 16]]) + assert D1.rank() == D2.rank() == D3.rank() == 1 + assert (D1 + D2).rank() == (D2 + D3).rank() == (D3 + D1).rank() == 2 + + # Only A is invertible + K = BlockMatrix([[M, D1], [D2, D3]]) + assert block_collapse(K.inv()).as_explicit() == K.as_explicit().inv() + # Only B is invertible + K = BlockMatrix([[D1, M], [D2, D3]]) + assert block_collapse(K.inv()).as_explicit() == K.as_explicit().inv() + # Only C is invertible + K = BlockMatrix([[D1, D2], [M, D3]]) + assert block_collapse(K.inv()).as_explicit() == K.as_explicit().inv() + # Only D is invertible + K = BlockMatrix([[D1, D2], [D3, M]]) + assert block_collapse(K.inv()).as_explicit() == K.as_explicit().inv() + + +@slow +def test_BlockMatrix_3x3_symbolic(): + # Only test one of these, instead of all permutations, because it's slow + rowblocksizes = (n, m, k) + colblocksizes = (m, k, n) + K = BlockMatrix([ + [MatrixSymbol('M%s%s' % (rows, cols), rows, cols) for cols in colblocksizes] + for rows in rowblocksizes + ]) + collapse = block_collapse(K.I) + assert isinstance(collapse, BlockMatrix) + + +def test_BlockDiagMatrix(): + A = MatrixSymbol('A', n, n) + B = MatrixSymbol('B', m, m) + C = MatrixSymbol('C', l, l) + M = MatrixSymbol('M', n + m + l, n + m + l) + + X = BlockDiagMatrix(A, B, C) + Y = BlockDiagMatrix(A, 2*B, 3*C) + + assert X.blocks[1, 1] == B + assert X.shape == (n + m + l, n + m + l) + assert all(X.blocks[i, j].is_ZeroMatrix if i != j else X.blocks[i, j] in [A, B, C] + for i in range(3) for j in range(3)) + assert X.__class__(*X.args) == X + assert X.get_diag_blocks() == (A, B, C) + + assert isinstance(block_collapse(X.I * X), Identity) + + assert bc_matmul(X*X) == BlockDiagMatrix(A*A, B*B, C*C) + assert block_collapse(X*X) == BlockDiagMatrix(A*A, B*B, C*C) + #XXX: should be == ?? + assert block_collapse(X + X).equals(BlockDiagMatrix(2*A, 2*B, 2*C)) + assert block_collapse(X*Y) == BlockDiagMatrix(A*A, 2*B*B, 3*C*C) + assert block_collapse(X + Y) == BlockDiagMatrix(2*A, 3*B, 4*C) + + # Ensure that BlockDiagMatrices can still interact with normal MatrixExprs + assert (X*(2*M)).is_MatMul + assert (X + (2*M)).is_MatAdd + + assert (X._blockmul(M)).is_MatMul + assert (X._blockadd(M)).is_MatAdd + +def test_BlockDiagMatrix_nonsquare(): + A = MatrixSymbol('A', n, m) + B = MatrixSymbol('B', k, l) + X = BlockDiagMatrix(A, B) + assert X.shape == (n + k, m + l) + assert X.shape == (n + k, m + l) + assert X.rowblocksizes == [n, k] + assert X.colblocksizes == [m, l] + C = MatrixSymbol('C', n, m) + D = MatrixSymbol('D', k, l) + Y = BlockDiagMatrix(C, D) + assert block_collapse(X + Y) == BlockDiagMatrix(A + C, B + D) + assert block_collapse(X * Y.T) == BlockDiagMatrix(A * C.T, B * D.T) + raises(NonInvertibleMatrixError, lambda: BlockDiagMatrix(A, C.T).inverse()) + +def test_BlockDiagMatrix_determinant(): + A = MatrixSymbol('A', n, n) + B = MatrixSymbol('B', m, m) + assert det(BlockDiagMatrix()) == 1 + assert det(BlockDiagMatrix(A)) == det(A) + assert det(BlockDiagMatrix(A, B)) == det(A) * det(B) + + # non-square blocks + C = MatrixSymbol('C', m, n) + D = MatrixSymbol('D', n, m) + assert det(BlockDiagMatrix(C, D)) == 0 + +def test_BlockDiagMatrix_trace(): + assert trace(BlockDiagMatrix()) == 0 + assert trace(BlockDiagMatrix(ZeroMatrix(n, n))) == 0 + A = MatrixSymbol('A', n, n) + assert trace(BlockDiagMatrix(A)) == trace(A) + B = MatrixSymbol('B', m, m) + assert trace(BlockDiagMatrix(A, B)) == trace(A) + trace(B) + + # non-square blocks + C = MatrixSymbol('C', m, n) + D = MatrixSymbol('D', n, m) + assert isinstance(trace(BlockDiagMatrix(C, D)), Trace) + +def test_BlockDiagMatrix_transpose(): + A = MatrixSymbol('A', n, m) + B = MatrixSymbol('B', k, l) + assert transpose(BlockDiagMatrix()) == BlockDiagMatrix() + assert transpose(BlockDiagMatrix(A)) == BlockDiagMatrix(A.T) + assert transpose(BlockDiagMatrix(A, B)) == BlockDiagMatrix(A.T, B.T) + +def test_issue_2460(): + bdm1 = BlockDiagMatrix(Matrix([i]), Matrix([j])) + bdm2 = BlockDiagMatrix(Matrix([k]), Matrix([l])) + assert block_collapse(bdm1 + bdm2) == BlockDiagMatrix(Matrix([i + k]), Matrix([j + l])) + +def test_blockcut(): + A = MatrixSymbol('A', n, m) + B = blockcut(A, (n/2, n/2), (m/2, m/2)) + assert B == BlockMatrix([[A[:n/2, :m/2], A[:n/2, m/2:]], + [A[n/2:, :m/2], A[n/2:, m/2:]]]) + + M = ImmutableMatrix(4, 4, range(16)) + B = blockcut(M, (2, 2), (2, 2)) + assert M == ImmutableMatrix(B) + + B = blockcut(M, (1, 3), (2, 2)) + assert ImmutableMatrix(B.blocks[0, 1]) == ImmutableMatrix([[2, 3]]) + +def test_reblock_2x2(): + B = BlockMatrix([[MatrixSymbol('A_%d%d'%(i,j), 2, 2) + for j in range(3)] + for i in range(3)]) + assert B.blocks.shape == (3, 3) + + BB = reblock_2x2(B) + assert BB.blocks.shape == (2, 2) + + assert B.shape == BB.shape + assert B.as_explicit() == BB.as_explicit() + +def test_deblock(): + B = BlockMatrix([[MatrixSymbol('A_%d%d'%(i,j), n, n) + for j in range(4)] + for i in range(4)]) + + assert deblock(reblock_2x2(B)) == B + +def test_block_collapse_type(): + bm1 = BlockDiagMatrix(ImmutableMatrix([1]), ImmutableMatrix([2])) + bm2 = BlockDiagMatrix(ImmutableMatrix([3]), ImmutableMatrix([4])) + + assert bm1.T.__class__ == BlockDiagMatrix + assert block_collapse(bm1 - bm2).__class__ == BlockDiagMatrix + assert block_collapse(Inverse(bm1)).__class__ == BlockDiagMatrix + assert block_collapse(Transpose(bm1)).__class__ == BlockDiagMatrix + assert bc_transpose(Transpose(bm1)).__class__ == BlockDiagMatrix + assert bc_inverse(Inverse(bm1)).__class__ == BlockDiagMatrix + +def test_invalid_block_matrix(): + raises(ValueError, lambda: BlockMatrix([ + [Identity(2), Identity(5)], + ])) + raises(ValueError, lambda: BlockMatrix([ + [Identity(n), Identity(m)], + ])) + raises(ValueError, lambda: BlockMatrix([ + [ZeroMatrix(n, n), ZeroMatrix(n, n)], + [ZeroMatrix(n, n - 1), ZeroMatrix(n, n + 1)], + ])) + raises(ValueError, lambda: BlockMatrix([ + [ZeroMatrix(n - 1, n), ZeroMatrix(n, n)], + [ZeroMatrix(n + 1, n), ZeroMatrix(n, n)], + ])) + +def test_block_lu_decomposition(): + A = MatrixSymbol('A', n, n) + B = MatrixSymbol('B', n, m) + C = MatrixSymbol('C', m, n) + D = MatrixSymbol('D', m, m) + X = BlockMatrix([[A, B], [C, D]]) + + #LDU decomposition + L, D, U = X.LDUdecomposition() + assert block_collapse(L*D*U) == X + + #UDL decomposition + U, D, L = X.UDLdecomposition() + assert block_collapse(U*D*L) == X + + #LU decomposition + L, U = X.LUdecomposition() + assert block_collapse(L*U) == X + +def test_issue_21866(): + n = 10 + I = Identity(n) + O = ZeroMatrix(n, n) + A = BlockMatrix([[ I, O, O, O ], + [ O, I, O, O ], + [ O, O, I, O ], + [ I, O, O, I ]]) + Ainv = block_collapse(A.inv()) + AinvT = BlockMatrix([[ I, O, O, O ], + [ O, I, O, O ], + [ O, O, I, O ], + [ -I, O, O, I ]]) + assert Ainv == AinvT + + +def test_adjoint_and_special_matrices(): + A = Identity(3) + B = OneMatrix(3, 2) + C = ZeroMatrix(2, 3) + D = Identity(2) + X = BlockMatrix([[A, B], [C, D]]) + X2 = BlockMatrix([[A, S.ImaginaryUnit*B], [C, D]]) + assert X.adjoint() == BlockMatrix([[A, ZeroMatrix(3, 2)], [OneMatrix(2, 3), D]]) + assert re(X) == X + assert X2.adjoint() == BlockMatrix([[A, ZeroMatrix(3, 2)], [-S.ImaginaryUnit*OneMatrix(2, 3), D]]) + assert im(X2) == BlockMatrix([[ZeroMatrix(3, 3), OneMatrix(3, 2)], [ZeroMatrix(2, 3), ZeroMatrix(2, 2)]]) + + +def test_block_matrix_derivative(): + x = symbols('x') + A = Matrix(3, 3, [Function(f'a{i}')(x) for i in range(9)]) + bc = BlockMatrix([[A[:2, :2], A[:2, 2]], [A[2, :2], A[2:, 2]]]) + assert Matrix(bc.diff(x)) - A.diff(x) == zeros(3, 3) + + +def test_transpose_inverse_commute(): + n = Symbol('n') + I = Identity(n) + Z = ZeroMatrix(n, n) + A = BlockMatrix([[I, Z], [Z, I]]) + + assert block_collapse(A.transpose().inverse()) == A + assert block_collapse(A.inverse().transpose()) == A + + assert block_collapse(MatPow(A.transpose(), -2)) == MatPow(A, -2) + assert block_collapse(MatPow(A, -2).transpose()) == MatPow(A, -2) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_companion.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_companion.py new file mode 100644 index 0000000000000000000000000000000000000000..edc592c29098eddce0c6352806aa73d5d889e999 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_companion.py @@ -0,0 +1,48 @@ +from sympy.core.expr import unchanged +from sympy.core.symbol import Symbol, symbols +from sympy.matrices.immutable import ImmutableDenseMatrix +from sympy.matrices.expressions.companion import CompanionMatrix +from sympy.polys.polytools import Poly +from sympy.testing.pytest import raises + + +def test_creation(): + x = Symbol('x') + y = Symbol('y') + raises(ValueError, lambda: CompanionMatrix(1)) + raises(ValueError, lambda: CompanionMatrix(Poly([1], x))) + raises(ValueError, lambda: CompanionMatrix(Poly([2, 1], x))) + raises(ValueError, lambda: CompanionMatrix(Poly(x*y, [x, y]))) + assert unchanged(CompanionMatrix, Poly([1, 2, 3], x)) + + +def test_shape(): + c0, c1, c2 = symbols('c0:3') + x = Symbol('x') + assert CompanionMatrix(Poly([1, c0], x)).shape == (1, 1) + assert CompanionMatrix(Poly([1, c1, c0], x)).shape == (2, 2) + assert CompanionMatrix(Poly([1, c2, c1, c0], x)).shape == (3, 3) + + +def test_entry(): + c0, c1, c2 = symbols('c0:3') + x = Symbol('x') + A = CompanionMatrix(Poly([1, c2, c1, c0], x)) + assert A[0, 0] == 0 + assert A[1, 0] == 1 + assert A[1, 1] == 0 + assert A[2, 1] == 1 + assert A[0, 2] == -c0 + assert A[1, 2] == -c1 + assert A[2, 2] == -c2 + + +def test_as_explicit(): + c0, c1, c2 = symbols('c0:3') + x = Symbol('x') + assert CompanionMatrix(Poly([1, c0], x)).as_explicit() == \ + ImmutableDenseMatrix([-c0]) + assert CompanionMatrix(Poly([1, c1, c0], x)).as_explicit() == \ + ImmutableDenseMatrix([[0, -c0], [1, -c1]]) + assert CompanionMatrix(Poly([1, c2, c1, c0], x)).as_explicit() == \ + ImmutableDenseMatrix([[0, 0, -c0], [1, 0, -c1], [0, 1, -c2]]) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_derivatives.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_derivatives.py new file mode 100644 index 0000000000000000000000000000000000000000..77484c994dda62eea9771a76afd8b3caeadacb93 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_derivatives.py @@ -0,0 +1,477 @@ +""" +Some examples have been taken from: + +http://www.math.uwaterloo.ca/~hwolkowi//matrixcookbook.pdf +""" +from sympy import KroneckerProduct +from sympy.combinatorics import Permutation +from sympy.concrete.summations import Sum +from sympy.core.numbers import Rational +from sympy.core.singleton import S +from sympy.core.symbol import symbols +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (cos, sin, tan) +from sympy.functions.special.tensor_functions import KroneckerDelta +from sympy.matrices.expressions.determinant import Determinant +from sympy.matrices.expressions.diagonal import DiagMatrix +from sympy.matrices.expressions.hadamard import (HadamardPower, HadamardProduct, hadamard_product) +from sympy.matrices.expressions.inverse import Inverse +from sympy.matrices.expressions.matexpr import MatrixSymbol +from sympy.matrices.expressions.special import OneMatrix +from sympy.matrices.expressions.trace import Trace +from sympy.matrices.expressions.matadd import MatAdd +from sympy.matrices.expressions.matmul import MatMul +from sympy.matrices.expressions.special import (Identity, ZeroMatrix) +from sympy.tensor.array.array_derivatives import ArrayDerivative +from sympy.matrices.expressions import hadamard_power +from sympy.tensor.array.expressions.array_expressions import ArrayAdd, ArrayTensorProduct, PermuteDims + +i, j, k = symbols("i j k") +m, n = symbols("m n") + +X = MatrixSymbol("X", k, k) +x = MatrixSymbol("x", k, 1) +y = MatrixSymbol("y", k, 1) + +A = MatrixSymbol("A", k, k) +B = MatrixSymbol("B", k, k) +C = MatrixSymbol("C", k, k) +D = MatrixSymbol("D", k, k) + +a = MatrixSymbol("a", k, 1) +b = MatrixSymbol("b", k, 1) +c = MatrixSymbol("c", k, 1) +d = MatrixSymbol("d", k, 1) + + +KDelta = lambda i, j: KroneckerDelta(i, j, (0, k-1)) + + +def _check_derivative_with_explicit_matrix(expr, x, diffexpr, dim=2): + # TODO: this is commented because it slows down the tests. + return + + expr = expr.xreplace({k: dim}) + x = x.xreplace({k: dim}) + diffexpr = diffexpr.xreplace({k: dim}) + + expr = expr.as_explicit() + x = x.as_explicit() + diffexpr = diffexpr.as_explicit() + + assert expr.diff(x).reshape(*diffexpr.shape).tomatrix() == diffexpr + + +def test_matrix_derivative_by_scalar(): + assert A.diff(i) == ZeroMatrix(k, k) + assert (A*(X + B)*c).diff(i) == ZeroMatrix(k, 1) + assert x.diff(i) == ZeroMatrix(k, 1) + assert (x.T*y).diff(i) == ZeroMatrix(1, 1) + assert (x*x.T).diff(i) == ZeroMatrix(k, k) + assert (x + y).diff(i) == ZeroMatrix(k, 1) + assert hadamard_power(x, 2).diff(i) == ZeroMatrix(k, 1) + assert hadamard_power(x, i).diff(i).dummy_eq( + HadamardProduct(x.applyfunc(log), HadamardPower(x, i))) + assert hadamard_product(x, y).diff(i) == ZeroMatrix(k, 1) + assert hadamard_product(i*OneMatrix(k, 1), x, y).diff(i) == hadamard_product(x, y) + assert (i*x).diff(i) == x + assert (sin(i)*A*B*x).diff(i) == cos(i)*A*B*x + assert x.applyfunc(sin).diff(i) == ZeroMatrix(k, 1) + assert Trace(i**2*X).diff(i) == 2*i*Trace(X) + + mu = symbols("mu") + expr = (2*mu*x) + assert expr.diff(x) == 2*mu*Identity(k) + + +def test_one_matrix(): + assert MatMul(x.T, OneMatrix(k, 1)).diff(x) == OneMatrix(k, 1) + + +def test_matrix_derivative_non_matrix_result(): + # This is a 4-dimensional array: + I = Identity(k) + AdA = PermuteDims(ArrayTensorProduct(I, I), Permutation(3)(1, 2)) + assert A.diff(A) == AdA + assert A.T.diff(A) == PermuteDims(ArrayTensorProduct(I, I), Permutation(3)(1, 2, 3)) + assert (2*A).diff(A) == PermuteDims(ArrayTensorProduct(2*I, I), Permutation(3)(1, 2)) + assert MatAdd(A, A).diff(A) == ArrayAdd(AdA, AdA) + assert (A + B).diff(A) == AdA + + +def test_matrix_derivative_trivial_cases(): + # Cookbook example 33: + # TODO: find a way to represent a four-dimensional zero-array: + assert X.diff(A) == ArrayDerivative(X, A) + + +def test_matrix_derivative_with_inverse(): + + # Cookbook example 61: + expr = a.T*Inverse(X)*b + assert expr.diff(X) == -Inverse(X).T*a*b.T*Inverse(X).T + + # Cookbook example 62: + expr = Determinant(Inverse(X)) + # Not implemented yet: + # assert expr.diff(X) == -Determinant(X.inv())*(X.inv()).T + + # Cookbook example 63: + expr = Trace(A*Inverse(X)*B) + assert expr.diff(X) == -(X**(-1)*B*A*X**(-1)).T + + # Cookbook example 64: + expr = Trace(Inverse(X + A)) + assert expr.diff(X) == -(Inverse(X + A)).T**2 + + +def test_matrix_derivative_vectors_and_scalars(): + + assert x.diff(x) == Identity(k) + assert x[i, 0].diff(x[m, 0]).doit() == KDelta(m, i) + + assert x.T.diff(x) == Identity(k) + + # Cookbook example 69: + expr = x.T*a + assert expr.diff(x) == a + assert expr[0, 0].diff(x[m, 0]).doit() == a[m, 0] + expr = a.T*x + assert expr.diff(x) == a + + # Cookbook example 70: + expr = a.T*X*b + assert expr.diff(X) == a*b.T + + # Cookbook example 71: + expr = a.T*X.T*b + assert expr.diff(X) == b*a.T + + # Cookbook example 72: + expr = a.T*X*a + assert expr.diff(X) == a*a.T + expr = a.T*X.T*a + assert expr.diff(X) == a*a.T + + # Cookbook example 77: + expr = b.T*X.T*X*c + assert expr.diff(X) == X*b*c.T + X*c*b.T + + # Cookbook example 78: + expr = (B*x + b).T*C*(D*x + d) + assert expr.diff(x) == B.T*C*(D*x + d) + D.T*C.T*(B*x + b) + + # Cookbook example 81: + expr = x.T*B*x + assert expr.diff(x) == B*x + B.T*x + + # Cookbook example 82: + expr = b.T*X.T*D*X*c + assert expr.diff(X) == D.T*X*b*c.T + D*X*c*b.T + + # Cookbook example 83: + expr = (X*b + c).T*D*(X*b + c) + assert expr.diff(X) == D*(X*b + c)*b.T + D.T*(X*b + c)*b.T + assert str(expr[0, 0].diff(X[m, n]).doit()) == \ + 'b[n, 0]*Sum((c[_i_1, 0] + Sum(X[_i_1, _i_3]*b[_i_3, 0], (_i_3, 0, k - 1)))*D[_i_1, m], (_i_1, 0, k - 1)) + Sum((c[_i_2, 0] + Sum(X[_i_2, _i_4]*b[_i_4, 0], (_i_4, 0, k - 1)))*D[m, _i_2]*b[n, 0], (_i_2, 0, k - 1))' + + # See https://github.com/sympy/sympy/issues/16504#issuecomment-1018339957 + expr = x*x.T*x + I = Identity(k) + assert expr.diff(x) == KroneckerProduct(I, x.T*x) + 2*x*x.T + + +def test_matrix_derivatives_of_traces(): + + expr = Trace(A)*A + I = Identity(k) + assert expr.diff(A) == ArrayAdd(ArrayTensorProduct(I, A), PermuteDims(ArrayTensorProduct(Trace(A)*I, I), Permutation(3)(1, 2))) + assert expr[i, j].diff(A[m, n]).doit() == ( + KDelta(i, m)*KDelta(j, n)*Trace(A) + + KDelta(m, n)*A[i, j] + ) + + ## First order: + + # Cookbook example 99: + expr = Trace(X) + assert expr.diff(X) == Identity(k) + assert expr.rewrite(Sum).diff(X[m, n]).doit() == KDelta(m, n) + + # Cookbook example 100: + expr = Trace(X*A) + assert expr.diff(X) == A.T + assert expr.rewrite(Sum).diff(X[m, n]).doit() == A[n, m] + + # Cookbook example 101: + expr = Trace(A*X*B) + assert expr.diff(X) == A.T*B.T + assert expr.rewrite(Sum).diff(X[m, n]).doit().dummy_eq((A.T*B.T)[m, n]) + + # Cookbook example 102: + expr = Trace(A*X.T*B) + assert expr.diff(X) == B*A + + # Cookbook example 103: + expr = Trace(X.T*A) + assert expr.diff(X) == A + + # Cookbook example 104: + expr = Trace(A*X.T) + assert expr.diff(X) == A + + # Cookbook example 105: + # TODO: TensorProduct is not supported + #expr = Trace(TensorProduct(A, X)) + #assert expr.diff(X) == Trace(A)*Identity(k) + + ## Second order: + + # Cookbook example 106: + expr = Trace(X**2) + assert expr.diff(X) == 2*X.T + + # Cookbook example 107: + expr = Trace(X**2*B) + assert expr.diff(X) == (X*B + B*X).T + expr = Trace(MatMul(X, X, B)) + assert expr.diff(X) == (X*B + B*X).T + + # Cookbook example 108: + expr = Trace(X.T*B*X) + assert expr.diff(X) == B*X + B.T*X + + # Cookbook example 109: + expr = Trace(B*X*X.T) + assert expr.diff(X) == B*X + B.T*X + + # Cookbook example 110: + expr = Trace(X*X.T*B) + assert expr.diff(X) == B*X + B.T*X + + # Cookbook example 111: + expr = Trace(X*B*X.T) + assert expr.diff(X) == X*B.T + X*B + + # Cookbook example 112: + expr = Trace(B*X.T*X) + assert expr.diff(X) == X*B.T + X*B + + # Cookbook example 113: + expr = Trace(X.T*X*B) + assert expr.diff(X) == X*B.T + X*B + + # Cookbook example 114: + expr = Trace(A*X*B*X) + assert expr.diff(X) == A.T*X.T*B.T + B.T*X.T*A.T + + # Cookbook example 115: + expr = Trace(X.T*X) + assert expr.diff(X) == 2*X + expr = Trace(X*X.T) + assert expr.diff(X) == 2*X + + # Cookbook example 116: + expr = Trace(B.T*X.T*C*X*B) + assert expr.diff(X) == C.T*X*B*B.T + C*X*B*B.T + + # Cookbook example 117: + expr = Trace(X.T*B*X*C) + assert expr.diff(X) == B*X*C + B.T*X*C.T + + # Cookbook example 118: + expr = Trace(A*X*B*X.T*C) + assert expr.diff(X) == A.T*C.T*X*B.T + C*A*X*B + + # Cookbook example 119: + expr = Trace((A*X*B + C)*(A*X*B + C).T) + assert expr.diff(X) == 2*A.T*(A*X*B + C)*B.T + + # Cookbook example 120: + # TODO: no support for TensorProduct. + # expr = Trace(TensorProduct(X, X)) + # expr = Trace(X)*Trace(X) + # expr.diff(X) == 2*Trace(X)*Identity(k) + + # Higher Order + + # Cookbook example 121: + expr = Trace(X**k) + #assert expr.diff(X) == k*(X**(k-1)).T + + # Cookbook example 122: + expr = Trace(A*X**k) + #assert expr.diff(X) == # Needs indices + + # Cookbook example 123: + expr = Trace(B.T*X.T*C*X*X.T*C*X*B) + assert expr.diff(X) == C*X*X.T*C*X*B*B.T + C.T*X*B*B.T*X.T*C.T*X + C*X*B*B.T*X.T*C*X + C.T*X*X.T*C.T*X*B*B.T + + # Other + + # Cookbook example 124: + expr = Trace(A*X**(-1)*B) + assert expr.diff(X) == -Inverse(X).T*A.T*B.T*Inverse(X).T + + # Cookbook example 125: + expr = Trace(Inverse(X.T*C*X)*A) + # Warning: result in the cookbook is equivalent if B and C are symmetric: + assert expr.diff(X) == - X.inv().T*A.T*X.inv()*C.inv().T*X.inv().T - X.inv().T*A*X.inv()*C.inv()*X.inv().T + + # Cookbook example 126: + expr = Trace((X.T*C*X).inv()*(X.T*B*X)) + assert expr.diff(X) == -2*C*X*(X.T*C*X).inv()*X.T*B*X*(X.T*C*X).inv() + 2*B*X*(X.T*C*X).inv() + + # Cookbook example 127: + expr = Trace((A + X.T*C*X).inv()*(X.T*B*X)) + # Warning: result in the cookbook is equivalent if B and C are symmetric: + assert expr.diff(X) == B*X*Inverse(A + X.T*C*X) - C*X*Inverse(A + X.T*C*X)*X.T*B*X*Inverse(A + X.T*C*X) - C.T*X*Inverse(A.T + (C*X).T*X)*X.T*B.T*X*Inverse(A.T + (C*X).T*X) + B.T*X*Inverse(A.T + (C*X).T*X) + + +def test_derivatives_of_complicated_matrix_expr(): + expr = a.T*(A*X*(X.T*B + X*A) + B.T*X.T*(a*b.T*(X*D*X.T + X*(X.T*B + A*X)*D*B - X.T*C.T*A)*B + B*(X*D.T + B*A*X*A.T - 3*X*D))*B + 42*X*B*X.T*A.T*(X + X.T))*b + result = (B*(B*A*X*A.T - 3*X*D + X*D.T) + a*b.T*(X*(A*X + X.T*B)*D*B + X*D*X.T - X.T*C.T*A)*B)*B*b*a.T*B.T + B**2*b*a.T*B.T*X.T*a*b.T*X*D + 42*A*X*B.T*X.T*a*b.T + B*D*B**3*b*a.T*B.T*X.T*a*b.T*X + B*b*a.T*A*X + a*b.T*(42*X + 42*X.T)*A*X*B.T + b*a.T*X*B*a*b.T*B.T**2*X*D.T + b*a.T*X*B*a*b.T*B.T**3*D.T*(B.T*X + X.T*A.T) + 42*b*a.T*X*B*X.T*A.T + A.T*(42*X + 42*X.T)*b*a.T*X*B + A.T*B.T**2*X*B*a*b.T*B.T*A + A.T*a*b.T*(A.T*X.T + B.T*X) + A.T*X.T*b*a.T*X*B*a*b.T*B.T**3*D.T + B.T*X*B*a*b.T*B.T*D - 3*B.T*X*B*a*b.T*B.T*D.T - C.T*A*B**2*b*a.T*B.T*X.T*a*b.T + X.T*A.T*a*b.T*A.T + assert expr.diff(X) == result + + +def test_mixed_deriv_mixed_expressions(): + + expr = 3*Trace(A) + assert expr.diff(A) == 3*Identity(k) + + expr = k + deriv = expr.diff(A) + assert isinstance(deriv, ZeroMatrix) + assert deriv == ZeroMatrix(k, k) + + expr = Trace(A)**2 + assert expr.diff(A) == (2*Trace(A))*Identity(k) + + expr = Trace(A)*A + I = Identity(k) + assert expr.diff(A) == ArrayAdd(ArrayTensorProduct(I, A), PermuteDims(ArrayTensorProduct(Trace(A)*I, I), Permutation(3)(1, 2))) + + expr = Trace(Trace(A)*A) + assert expr.diff(A) == (2*Trace(A))*Identity(k) + + expr = Trace(Trace(Trace(A)*A)*A) + assert expr.diff(A) == (3*Trace(A)**2)*Identity(k) + + +def test_derivatives_matrix_norms(): + + expr = x.T*y + assert expr.diff(x) == y + assert expr[0, 0].diff(x[m, 0]).doit() == y[m, 0] + + expr = (x.T*y)**S.Half + assert expr.diff(x) == y/(2*sqrt(x.T*y)) + + expr = (x.T*x)**S.Half + assert expr.diff(x) == x*(x.T*x)**Rational(-1, 2) + + expr = (c.T*a*x.T*b)**S.Half + assert expr.diff(x) == b*a.T*c/sqrt(c.T*a*x.T*b)/2 + + expr = (c.T*a*x.T*b)**Rational(1, 3) + assert expr.diff(x) == b*a.T*c*(c.T*a*x.T*b)**Rational(-2, 3)/3 + + expr = (a.T*X*b)**S.Half + assert expr.diff(X) == a/(2*sqrt(a.T*X*b))*b.T + + expr = d.T*x*(a.T*X*b)**S.Half*y.T*c + assert expr.diff(X) == a/(2*sqrt(a.T*X*b))*x.T*d*y.T*c*b.T + + +def test_derivatives_elementwise_applyfunc(): + + expr = x.applyfunc(tan) + assert expr.diff(x).dummy_eq( + DiagMatrix(x.applyfunc(lambda x: tan(x)**2 + 1))) + assert expr[i, 0].diff(x[m, 0]).doit() == (tan(x[i, 0])**2 + 1)*KDelta(i, m) + _check_derivative_with_explicit_matrix(expr, x, expr.diff(x)) + + expr = (i**2*x).applyfunc(sin) + assert expr.diff(i).dummy_eq( + HadamardProduct((2*i)*x, (i**2*x).applyfunc(cos))) + assert expr[i, 0].diff(i).doit() == 2*i*x[i, 0]*cos(i**2*x[i, 0]) + _check_derivative_with_explicit_matrix(expr, i, expr.diff(i)) + + expr = (log(i)*A*B).applyfunc(sin) + assert expr.diff(i).dummy_eq( + HadamardProduct(A*B/i, (log(i)*A*B).applyfunc(cos))) + _check_derivative_with_explicit_matrix(expr, i, expr.diff(i)) + + expr = A*x.applyfunc(exp) + # TODO: restore this result (currently returning the transpose): + # assert expr.diff(x).dummy_eq(DiagMatrix(x.applyfunc(exp))*A.T) + _check_derivative_with_explicit_matrix(expr, x, expr.diff(x)) + + expr = x.T*A*x + k*y.applyfunc(sin).T*x + assert expr.diff(x).dummy_eq(A.T*x + A*x + k*y.applyfunc(sin)) + _check_derivative_with_explicit_matrix(expr, x, expr.diff(x)) + + expr = x.applyfunc(sin).T*y + # TODO: restore (currently returning the transpose): + # assert expr.diff(x).dummy_eq(DiagMatrix(x.applyfunc(cos))*y) + _check_derivative_with_explicit_matrix(expr, x, expr.diff(x)) + + expr = (a.T * X * b).applyfunc(sin) + assert expr.diff(X).dummy_eq(a*(a.T*X*b).applyfunc(cos)*b.T) + _check_derivative_with_explicit_matrix(expr, X, expr.diff(X)) + + expr = a.T * X.applyfunc(sin) * b + assert expr.diff(X).dummy_eq( + DiagMatrix(a)*X.applyfunc(cos)*DiagMatrix(b)) + _check_derivative_with_explicit_matrix(expr, X, expr.diff(X)) + + expr = a.T * (A*X*B).applyfunc(sin) * b + assert expr.diff(X).dummy_eq( + A.T*DiagMatrix(a)*(A*X*B).applyfunc(cos)*DiagMatrix(b)*B.T) + _check_derivative_with_explicit_matrix(expr, X, expr.diff(X)) + + expr = a.T * (A*X*b).applyfunc(sin) * b.T + # TODO: not implemented + #assert expr.diff(X) == ... + #_check_derivative_with_explicit_matrix(expr, X, expr.diff(X)) + + expr = a.T*A*X.applyfunc(sin)*B*b + assert expr.diff(X).dummy_eq( + HadamardProduct(A.T * a * b.T * B.T, X.applyfunc(cos))) + + expr = a.T * (A*X.applyfunc(sin)*B).applyfunc(log) * b + # TODO: wrong + # assert expr.diff(X) == A.T*DiagMatrix(a)*(A*X.applyfunc(sin)*B).applyfunc(Lambda(k, 1/k))*DiagMatrix(b)*B.T + + expr = a.T * (X.applyfunc(sin)).applyfunc(log) * b + # TODO: wrong + # assert expr.diff(X) == DiagMatrix(a)*X.applyfunc(sin).applyfunc(Lambda(k, 1/k))*DiagMatrix(b) + + +def test_derivatives_of_hadamard_expressions(): + + # Hadamard Product + + expr = hadamard_product(a, x, b) + assert expr.diff(x) == DiagMatrix(hadamard_product(b, a)) + + expr = a.T*hadamard_product(A, X, B)*b + assert expr.diff(X) == HadamardProduct(a*b.T, A, B) + + # Hadamard Power + + expr = hadamard_power(x, 2) + assert expr.diff(x).doit() == 2*DiagMatrix(x) + + expr = hadamard_power(x.T, 2) + assert expr.diff(x).doit() == 2*DiagMatrix(x) + + expr = hadamard_power(x, S.Half) + assert expr.diff(x) == S.Half*DiagMatrix(hadamard_power(x, Rational(-1, 2))) + + expr = hadamard_power(a.T*X*b, 2) + assert expr.diff(X) == 2*a*a.T*X*b*b.T + + expr = hadamard_power(a.T*X*b, S.Half) + assert expr.diff(X) == a/(2*sqrt(a.T*X*b))*b.T diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_determinant.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_determinant.py new file mode 100644 index 0000000000000000000000000000000000000000..d1a66c728f076f8c769d2519ee47c8a9cc90a90e --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_determinant.py @@ -0,0 +1,65 @@ +from sympy.core import S, symbols +from sympy.matrices import eye, ones, Matrix, ShapeError +from sympy.matrices.expressions import ( + Identity, MatrixExpr, MatrixSymbol, Determinant, + det, per, ZeroMatrix, Transpose, + Permanent, MatMul +) +from sympy.matrices.expressions.special import OneMatrix +from sympy.testing.pytest import raises +from sympy.assumptions.ask import Q +from sympy.assumptions.refine import refine + +n = symbols('n', integer=True) +A = MatrixSymbol('A', n, n) +B = MatrixSymbol('B', n, n) +C = MatrixSymbol('C', 3, 4) + + +def test_det(): + assert isinstance(Determinant(A), Determinant) + assert not isinstance(Determinant(A), MatrixExpr) + raises(ShapeError, lambda: Determinant(C)) + assert det(eye(3)) == 1 + assert det(Matrix(3, 3, [1, 3, 2, 4, 1, 3, 2, 5, 2])) == 17 + _ = A / det(A) # Make sure this is possible + + raises(TypeError, lambda: Determinant(S.One)) + + assert Determinant(A).arg is A + + +def test_eval_determinant(): + assert det(Identity(n)) == 1 + assert det(ZeroMatrix(n, n)) == 0 + assert det(OneMatrix(n, n)) == Determinant(OneMatrix(n, n)) + assert det(OneMatrix(1, 1)) == 1 + assert det(OneMatrix(2, 2)) == 0 + assert det(Transpose(A)) == det(A) + assert Determinant(MatMul(eye(2), eye(2))).doit(deep=True) == 1 + + +def test_refine(): + assert refine(det(A), Q.orthogonal(A)) == 1 + assert refine(det(A), Q.singular(A)) == 0 + assert refine(det(A), Q.unit_triangular(A)) == 1 + assert refine(det(A), Q.normal(A)) == det(A) + + +def test_commutative(): + det_a = Determinant(A) + det_b = Determinant(B) + assert det_a.is_commutative + assert det_b.is_commutative + assert det_a * det_b == det_b * det_a + + +def test_permanent(): + assert isinstance(Permanent(A), Permanent) + assert not isinstance(Permanent(A), MatrixExpr) + assert isinstance(Permanent(C), Permanent) + assert Permanent(ones(3, 3)).doit() == 6 + _ = C / per(C) + assert per(Matrix(3, 3, [1, 3, 2, 4, 1, 3, 2, 5, 2])) == 103 + raises(TypeError, lambda: Permanent(S.One)) + assert Permanent(A).arg is A diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_diagonal.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_diagonal.py new file mode 100644 index 0000000000000000000000000000000000000000..3e4f7ea4c178121c33eeb26c09675403d274c1e8 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_diagonal.py @@ -0,0 +1,156 @@ +from sympy.matrices.expressions import MatrixSymbol +from sympy.matrices.expressions.diagonal import DiagonalMatrix, DiagonalOf, DiagMatrix, diagonalize_vector +from sympy.assumptions.ask import (Q, ask) +from sympy.core.symbol import Symbol +from sympy.functions.special.tensor_functions import KroneckerDelta +from sympy.matrices.dense import Matrix +from sympy.matrices.expressions.matmul import MatMul +from sympy.matrices.expressions.special import Identity +from sympy.testing.pytest import raises + + +n = Symbol('n') +m = Symbol('m') + + +def test_DiagonalMatrix(): + x = MatrixSymbol('x', n, m) + D = DiagonalMatrix(x) + assert D.diagonal_length is None + assert D.shape == (n, m) + + x = MatrixSymbol('x', n, n) + D = DiagonalMatrix(x) + assert D.diagonal_length == n + assert D.shape == (n, n) + assert D[1, 2] == 0 + assert D[1, 1] == x[1, 1] + i = Symbol('i') + j = Symbol('j') + x = MatrixSymbol('x', 3, 3) + ij = DiagonalMatrix(x)[i, j] + assert ij != 0 + assert ij.subs({i:0, j:0}) == x[0, 0] + assert ij.subs({i:0, j:1}) == 0 + assert ij.subs({i:1, j:1}) == x[1, 1] + assert ask(Q.diagonal(D)) # affirm that D is diagonal + + x = MatrixSymbol('x', n, 3) + D = DiagonalMatrix(x) + assert D.diagonal_length == 3 + assert D.shape == (n, 3) + assert D[2, m] == KroneckerDelta(2, m)*x[2, m] + assert D[3, m] == 0 + raises(IndexError, lambda: D[m, 3]) + + x = MatrixSymbol('x', 3, n) + D = DiagonalMatrix(x) + assert D.diagonal_length == 3 + assert D.shape == (3, n) + assert D[m, 2] == KroneckerDelta(m, 2)*x[m, 2] + assert D[m, 3] == 0 + raises(IndexError, lambda: D[3, m]) + + x = MatrixSymbol('x', n, m) + D = DiagonalMatrix(x) + assert D.diagonal_length is None + assert D.shape == (n, m) + assert D[m, 4] != 0 + + x = MatrixSymbol('x', 3, 4) + assert [DiagonalMatrix(x)[i] for i in range(12)] == [ + x[0, 0], 0, 0, 0, 0, x[1, 1], 0, 0, 0, 0, x[2, 2], 0] + + # shape is retained, issue 12427 + assert ( + DiagonalMatrix(MatrixSymbol('x', 3, 4))* + DiagonalMatrix(MatrixSymbol('x', 4, 2))).shape == (3, 2) + + +def test_DiagonalOf(): + x = MatrixSymbol('x', n, n) + d = DiagonalOf(x) + assert d.shape == (n, 1) + assert d.diagonal_length == n + assert d[2, 0] == d[2] == x[2, 2] + + x = MatrixSymbol('x', n, m) + d = DiagonalOf(x) + assert d.shape == (None, 1) + assert d.diagonal_length is None + assert d[2, 0] == d[2] == x[2, 2] + + d = DiagonalOf(MatrixSymbol('x', 4, 3)) + assert d.shape == (3, 1) + d = DiagonalOf(MatrixSymbol('x', n, 3)) + assert d.shape == (3, 1) + d = DiagonalOf(MatrixSymbol('x', 3, n)) + assert d.shape == (3, 1) + x = MatrixSymbol('x', n, m) + assert [DiagonalOf(x)[i] for i in range(4)] ==[ + x[0, 0], x[1, 1], x[2, 2], x[3, 3]] + + +def test_DiagMatrix(): + x = MatrixSymbol('x', n, 1) + d = DiagMatrix(x) + assert d.shape == (n, n) + assert d[0, 1] == 0 + assert d[0, 0] == x[0, 0] + + a = MatrixSymbol('a', 1, 1) + d = diagonalize_vector(a) + assert isinstance(d, MatrixSymbol) + assert a == d + assert diagonalize_vector(Identity(3)) == Identity(3) + assert DiagMatrix(Identity(3)).doit() == Identity(3) + assert isinstance(DiagMatrix(Identity(3)), DiagMatrix) + + # A diagonal matrix is equal to its transpose: + assert DiagMatrix(x).T == DiagMatrix(x) + assert diagonalize_vector(x.T) == DiagMatrix(x) + + dx = DiagMatrix(x) + assert dx[0, 0] == x[0, 0] + assert dx[1, 1] == x[1, 0] + assert dx[0, 1] == 0 + assert dx[0, m] == x[0, 0]*KroneckerDelta(0, m) + + z = MatrixSymbol('z', 1, n) + dz = DiagMatrix(z) + assert dz[0, 0] == z[0, 0] + assert dz[1, 1] == z[0, 1] + assert dz[0, 1] == 0 + assert dz[0, m] == z[0, m]*KroneckerDelta(0, m) + + v = MatrixSymbol('v', 3, 1) + dv = DiagMatrix(v) + assert dv.as_explicit() == Matrix([ + [v[0, 0], 0, 0], + [0, v[1, 0], 0], + [0, 0, v[2, 0]], + ]) + + v = MatrixSymbol('v', 1, 3) + dv = DiagMatrix(v) + assert dv.as_explicit() == Matrix([ + [v[0, 0], 0, 0], + [0, v[0, 1], 0], + [0, 0, v[0, 2]], + ]) + + dv = DiagMatrix(3*v) + assert dv.args == (3*v,) + assert dv.doit() == 3*DiagMatrix(v) + assert isinstance(dv.doit(), MatMul) + + a = MatrixSymbol("a", 3, 1).as_explicit() + expr = DiagMatrix(a) + result = Matrix([ + [a[0, 0], 0, 0], + [0, a[1, 0], 0], + [0, 0, a[2, 0]], + ]) + assert expr.doit() == result + expr = DiagMatrix(a.T) + assert expr.doit() == result diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_dotproduct.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_dotproduct.py new file mode 100644 index 0000000000000000000000000000000000000000..abf8ab8e935cbd3039f25f83d3603ac444e5a7bb --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_dotproduct.py @@ -0,0 +1,35 @@ +from sympy.core.expr import unchanged +from sympy.core.mul import Mul +from sympy.matrices import Matrix +from sympy.matrices.expressions.matexpr import MatrixSymbol +from sympy.matrices.expressions.dotproduct import DotProduct +from sympy.testing.pytest import raises + + +A = Matrix(3, 1, [1, 2, 3]) +B = Matrix(3, 1, [1, 3, 5]) +C = Matrix(4, 1, [1, 2, 4, 5]) +D = Matrix(2, 2, [1, 2, 3, 4]) + +def test_docproduct(): + assert DotProduct(A, B).doit() == 22 + assert DotProduct(A.T, B).doit() == 22 + assert DotProduct(A, B.T).doit() == 22 + assert DotProduct(A.T, B.T).doit() == 22 + + raises(TypeError, lambda: DotProduct(1, A)) + raises(TypeError, lambda: DotProduct(A, 1)) + raises(TypeError, lambda: DotProduct(A, D)) + raises(TypeError, lambda: DotProduct(D, A)) + + raises(TypeError, lambda: DotProduct(B, C).doit()) + +def test_dotproduct_symbolic(): + A = MatrixSymbol('A', 3, 1) + B = MatrixSymbol('B', 3, 1) + + dot = DotProduct(A, B) + assert dot.is_scalar == True + assert unchanged(Mul, 2, dot) + # XXX Fix forced evaluation for arithmetics with matrix expressions + assert dot * A == (A[0, 0]*B[0, 0] + A[1, 0]*B[1, 0] + A[2, 0]*B[2, 0])*A diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_factorizations.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_factorizations.py new file mode 100644 index 0000000000000000000000000000000000000000..a0319acabbb7409dfa5c24ceca39e25ff0240618 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_factorizations.py @@ -0,0 +1,29 @@ +from sympy.matrices.expressions.factorizations import lu, LofCholesky, qr, svd +from sympy.assumptions.ask import (Q, ask) +from sympy.core.symbol import Symbol +from sympy.matrices.expressions.matexpr import MatrixSymbol + +n = Symbol('n') +X = MatrixSymbol('X', n, n) + +def test_LU(): + L, U = lu(X) + assert L.shape == U.shape == X.shape + assert ask(Q.lower_triangular(L)) + assert ask(Q.upper_triangular(U)) + +def test_Cholesky(): + LofCholesky(X) + +def test_QR(): + Q_, R = qr(X) + assert Q_.shape == R.shape == X.shape + assert ask(Q.orthogonal(Q_)) + assert ask(Q.upper_triangular(R)) + +def test_svd(): + U, S, V = svd(X) + assert U.shape == S.shape == V.shape == X.shape + assert ask(Q.orthogonal(U)) + assert ask(Q.orthogonal(V)) + assert ask(Q.diagonal(S)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_fourier.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_fourier.py new file mode 100644 index 0000000000000000000000000000000000000000..0230c8a0957ed28fb0a5cc1e9ee77ecae797265b --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_fourier.py @@ -0,0 +1,44 @@ +from sympy.assumptions.ask import (Q, ask) +from sympy.core.numbers import (I, Rational) +from sympy.core.singleton import S +from sympy.functions.elementary.complexes import Abs +from sympy.functions.elementary.exponential import exp +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.simplify.simplify import simplify +from sympy.core.symbol import symbols +from sympy.matrices.expressions.fourier import DFT, IDFT +from sympy.matrices import det, Matrix, Identity +from sympy.testing.pytest import raises + + +def test_dft_creation(): + assert DFT(2) + assert DFT(0) + raises(ValueError, lambda: DFT(-1)) + raises(ValueError, lambda: DFT(2.0)) + raises(ValueError, lambda: DFT(2 + 1j)) + + n = symbols('n') + assert DFT(n) + n = symbols('n', integer=False) + raises(ValueError, lambda: DFT(n)) + n = symbols('n', negative=True) + raises(ValueError, lambda: DFT(n)) + + +def test_dft(): + n, i, j = symbols('n i j') + assert DFT(4).shape == (4, 4) + assert ask(Q.unitary(DFT(4))) + assert Abs(simplify(det(Matrix(DFT(4))))) == 1 + assert DFT(n)*IDFT(n) == Identity(n) + assert DFT(n)[i, j] == exp(-2*S.Pi*I/n)**(i*j) / sqrt(n) + + +def test_dft2(): + assert DFT(1).as_explicit() == Matrix([[1]]) + assert DFT(2).as_explicit() == 1/sqrt(2)*Matrix([[1,1],[1,-1]]) + assert DFT(4).as_explicit() == Matrix([[S.Half, S.Half, S.Half, S.Half], + [S.Half, -I/2, Rational(-1,2), I/2], + [S.Half, Rational(-1,2), S.Half, Rational(-1,2)], + [S.Half, I/2, Rational(-1,2), -I/2]]) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_funcmatrix.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_funcmatrix.py new file mode 100644 index 0000000000000000000000000000000000000000..e4850fe5c739b9390fac6afa10757b5babf821c6 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_funcmatrix.py @@ -0,0 +1,54 @@ +from sympy.core import symbols, Lambda +from sympy.core.sympify import SympifyError +from sympy.functions import KroneckerDelta +from sympy.matrices import Matrix +from sympy.matrices.expressions import FunctionMatrix, MatrixExpr, Identity +from sympy.testing.pytest import raises + + +def test_funcmatrix_creation(): + i, j, k = symbols('i j k') + assert FunctionMatrix(2, 2, Lambda((i, j), 0)) + assert FunctionMatrix(0, 0, Lambda((i, j), 0)) + + raises(ValueError, lambda: FunctionMatrix(-1, 0, Lambda((i, j), 0))) + raises(ValueError, lambda: FunctionMatrix(2.0, 0, Lambda((i, j), 0))) + raises(ValueError, lambda: FunctionMatrix(2j, 0, Lambda((i, j), 0))) + raises(ValueError, lambda: FunctionMatrix(0, -1, Lambda((i, j), 0))) + raises(ValueError, lambda: FunctionMatrix(0, 2.0, Lambda((i, j), 0))) + raises(ValueError, lambda: FunctionMatrix(0, 2j, Lambda((i, j), 0))) + + raises(ValueError, lambda: FunctionMatrix(2, 2, Lambda(i, 0))) + raises(SympifyError, lambda: FunctionMatrix(2, 2, lambda i, j: 0)) + raises(ValueError, lambda: FunctionMatrix(2, 2, Lambda((i,), 0))) + raises(ValueError, lambda: FunctionMatrix(2, 2, Lambda((i, j, k), 0))) + raises(ValueError, lambda: FunctionMatrix(2, 2, i+j)) + assert FunctionMatrix(2, 2, "lambda i, j: 0") == \ + FunctionMatrix(2, 2, Lambda((i, j), 0)) + + m = FunctionMatrix(2, 2, KroneckerDelta) + assert m.as_explicit() == Identity(2).as_explicit() + assert m.args[2].dummy_eq(Lambda((i, j), KroneckerDelta(i, j))) + + n = symbols('n') + assert FunctionMatrix(n, n, Lambda((i, j), 0)) + n = symbols('n', integer=False) + raises(ValueError, lambda: FunctionMatrix(n, n, Lambda((i, j), 0))) + n = symbols('n', negative=True) + raises(ValueError, lambda: FunctionMatrix(n, n, Lambda((i, j), 0))) + + +def test_funcmatrix(): + i, j = symbols('i,j') + X = FunctionMatrix(3, 3, Lambda((i, j), i - j)) + assert X[1, 1] == 0 + assert X[1, 2] == -1 + assert X.shape == (3, 3) + assert X.rows == X.cols == 3 + assert Matrix(X) == Matrix(3, 3, lambda i, j: i - j) + assert isinstance(X*X + X, MatrixExpr) + + +def test_replace_issue(): + X = FunctionMatrix(3, 3, KroneckerDelta) + assert X.replace(lambda x: True, lambda x: x) == X diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_hadamard.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_hadamard.py new file mode 100644 index 0000000000000000000000000000000000000000..800fa830a9b089103d69b372db93ebcea541d02b --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_hadamard.py @@ -0,0 +1,141 @@ +from sympy.matrices.dense import Matrix, eye +from sympy.matrices.exceptions import ShapeError +from sympy.matrices.expressions.matadd import MatAdd +from sympy.matrices.expressions.special import Identity, OneMatrix, ZeroMatrix +from sympy.core import symbols +from sympy.testing.pytest import raises, warns_deprecated_sympy + +from sympy.matrices import MatrixSymbol +from sympy.matrices.expressions import (HadamardProduct, hadamard_product, HadamardPower, hadamard_power) + +n, m, k = symbols('n,m,k') +Z = MatrixSymbol('Z', n, n) +A = MatrixSymbol('A', n, m) +B = MatrixSymbol('B', n, m) +C = MatrixSymbol('C', m, k) + + +def test_HadamardProduct(): + assert HadamardProduct(A, B, A).shape == A.shape + + raises(TypeError, lambda: HadamardProduct(A, n)) + raises(TypeError, lambda: HadamardProduct(A, 1)) + + assert HadamardProduct(A, 2*B, -A)[1, 1] == \ + -2 * A[1, 1] * B[1, 1] * A[1, 1] + + mix = HadamardProduct(Z*A, B)*C + assert mix.shape == (n, k) + + assert set(HadamardProduct(A, B, A).T.args) == {A.T, A.T, B.T} + + +def test_HadamardProduct_isnt_commutative(): + assert HadamardProduct(A, B) != HadamardProduct(B, A) + + +def test_mixed_indexing(): + X = MatrixSymbol('X', 2, 2) + Y = MatrixSymbol('Y', 2, 2) + Z = MatrixSymbol('Z', 2, 2) + + assert (X*HadamardProduct(Y, Z))[0, 0] == \ + X[0, 0]*Y[0, 0]*Z[0, 0] + X[0, 1]*Y[1, 0]*Z[1, 0] + + +def test_canonicalize(): + X = MatrixSymbol('X', 2, 2) + Y = MatrixSymbol('Y', 2, 2) + with warns_deprecated_sympy(): + expr = HadamardProduct(X, check=False) + assert isinstance(expr, HadamardProduct) + expr2 = expr.doit() # unpack is called + assert isinstance(expr2, MatrixSymbol) + Z = ZeroMatrix(2, 2) + U = OneMatrix(2, 2) + assert HadamardProduct(Z, X).doit() == Z + assert HadamardProduct(U, X, X, U).doit() == HadamardPower(X, 2) + assert HadamardProduct(X, U, Y).doit() == HadamardProduct(X, Y) + assert HadamardProduct(X, Z, U, Y).doit() == Z + + +def test_hadamard(): + m, n, p = symbols('m, n, p', integer=True) + A = MatrixSymbol('A', m, n) + B = MatrixSymbol('B', m, n) + X = MatrixSymbol('X', m, m) + I = Identity(m) + + raises(TypeError, lambda: hadamard_product()) + assert hadamard_product(A) == A + assert isinstance(hadamard_product(A, B), HadamardProduct) + assert hadamard_product(A, B).doit() == hadamard_product(A, B) + assert hadamard_product(X, I) == HadamardProduct(I, X) + assert isinstance(hadamard_product(X, I), HadamardProduct) + + a = MatrixSymbol("a", k, 1) + expr = MatAdd(ZeroMatrix(k, 1), OneMatrix(k, 1)) + expr = HadamardProduct(expr, a) + assert expr.doit() == a + + raises(ValueError, lambda: HadamardProduct()) + + +def test_hadamard_product_with_explicit_mat(): + A = MatrixSymbol("A", 3, 3).as_explicit() + B = MatrixSymbol("B", 3, 3).as_explicit() + X = MatrixSymbol("X", 3, 3) + expr = hadamard_product(A, B) + ret = Matrix([i*j for i, j in zip(A, B)]).reshape(3, 3) + assert expr == ret + expr = hadamard_product(A, X, B) + assert expr == HadamardProduct(ret, X) + expr = hadamard_product(eye(3), A) + assert expr == Matrix([[A[0, 0], 0, 0], [0, A[1, 1], 0], [0, 0, A[2, 2]]]) + expr = hadamard_product(eye(3), eye(3)) + assert expr == eye(3) + + +def test_hadamard_power(): + m, n, p = symbols('m, n, p', integer=True) + A = MatrixSymbol('A', m, n) + + assert hadamard_power(A, 1) == A + assert isinstance(hadamard_power(A, 2), HadamardPower) + assert hadamard_power(A, n).T == hadamard_power(A.T, n) + assert hadamard_power(A, n)[0, 0] == A[0, 0]**n + assert hadamard_power(m, n) == m**n + raises(ValueError, lambda: hadamard_power(A, A)) + + +def test_hadamard_power_explicit(): + A = MatrixSymbol('A', 2, 2) + B = MatrixSymbol('B', 2, 2) + a, b = symbols('a b') + + assert HadamardPower(a, b) == a**b + + assert HadamardPower(a, B).as_explicit() == \ + Matrix([ + [a**B[0, 0], a**B[0, 1]], + [a**B[1, 0], a**B[1, 1]]]) + + assert HadamardPower(A, b).as_explicit() == \ + Matrix([ + [A[0, 0]**b, A[0, 1]**b], + [A[1, 0]**b, A[1, 1]**b]]) + + assert HadamardPower(A, B).as_explicit() == \ + Matrix([ + [A[0, 0]**B[0, 0], A[0, 1]**B[0, 1]], + [A[1, 0]**B[1, 0], A[1, 1]**B[1, 1]]]) + + +def test_shape_error(): + A = MatrixSymbol('A', 2, 3) + B = MatrixSymbol('B', 3, 3) + raises(ShapeError, lambda: HadamardProduct(A, B)) + raises(ShapeError, lambda: HadamardPower(A, B)) + A = MatrixSymbol('A', 3, 2) + raises(ShapeError, lambda: HadamardProduct(A, B)) + raises(ShapeError, lambda: HadamardPower(A, B)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_indexing.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_indexing.py new file mode 100644 index 0000000000000000000000000000000000000000..500761f248eef5f627c2a7344a6817aca0b8a802 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_indexing.py @@ -0,0 +1,299 @@ +from sympy.concrete.summations import Sum +from sympy.core.symbol import symbols, Symbol, Dummy +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.special.tensor_functions import KroneckerDelta +from sympy.matrices.dense import eye +from sympy.matrices.expressions.blockmatrix import BlockMatrix +from sympy.matrices.expressions.hadamard import HadamardPower +from sympy.matrices.expressions.matexpr import (MatrixSymbol, + MatrixExpr, MatrixElement) +from sympy.matrices.expressions.matpow import MatPow +from sympy.matrices.expressions.special import (ZeroMatrix, Identity, + OneMatrix) +from sympy.matrices.expressions.trace import Trace, trace +from sympy.matrices.immutable import ImmutableMatrix +from sympy.tensor.array.expressions.array_expressions import ArrayTensorProduct +from sympy.testing.pytest import XFAIL, raises + +k, l, m, n = symbols('k l m n', integer=True) +i, j = symbols('i j', integer=True) + +W = MatrixSymbol('W', k, l) +X = MatrixSymbol('X', l, m) +Y = MatrixSymbol('Y', l, m) +Z = MatrixSymbol('Z', m, n) + +X1 = MatrixSymbol('X1', m, m) +X2 = MatrixSymbol('X2', m, m) +X3 = MatrixSymbol('X3', m, m) +X4 = MatrixSymbol('X4', m, m) + +A = MatrixSymbol('A', 2, 2) +B = MatrixSymbol('B', 2, 2) +x = MatrixSymbol('x', 1, 2) +y = MatrixSymbol('x', 2, 1) + + +def test_symbolic_indexing(): + x12 = X[1, 2] + assert all(s in str(x12) for s in ['1', '2', X.name]) + # We don't care about the exact form of this. We do want to make sure + # that all of these features are present + + +def test_add_index(): + assert (X + Y)[i, j] == X[i, j] + Y[i, j] + + +def test_mul_index(): + assert (A*y)[0, 0] == A[0, 0]*y[0, 0] + A[0, 1]*y[1, 0] + assert (A*B).as_mutable() == (A.as_mutable() * B.as_mutable()) + X = MatrixSymbol('X', n, m) + Y = MatrixSymbol('Y', m, k) + + result = (X*Y)[4,2] + expected = Sum(X[4, i]*Y[i, 2], (i, 0, m - 1)) + assert result.args[0].dummy_eq(expected.args[0], i) + assert result.args[1][1:] == expected.args[1][1:] + + +def test_pow_index(): + Q = MatPow(A, 2) + assert Q[0, 0] == A[0, 0]**2 + A[0, 1]*A[1, 0] + n = symbols("n") + Q2 = A**n + assert Q2[0, 0] == 2*( + -sqrt((A[0, 0] + A[1, 1])**2 - 4*A[0, 0]*A[1, 1] + + 4*A[0, 1]*A[1, 0])/2 + A[0, 0]/2 + A[1, 1]/2 + )**n * \ + A[0, 1]*A[1, 0]/( + (sqrt(A[0, 0]**2 - 2*A[0, 0]*A[1, 1] + 4*A[0, 1]*A[1, 0] + + A[1, 1]**2) + A[0, 0] - A[1, 1])* + sqrt(A[0, 0]**2 - 2*A[0, 0]*A[1, 1] + 4*A[0, 1]*A[1, 0] + A[1, 1]**2) + ) - 2*( + sqrt((A[0, 0] + A[1, 1])**2 - 4*A[0, 0]*A[1, 1] + + 4*A[0, 1]*A[1, 0])/2 + A[0, 0]/2 + A[1, 1]/2 + )**n * A[0, 1]*A[1, 0]/( + (-sqrt(A[0, 0]**2 - 2*A[0, 0]*A[1, 1] + 4*A[0, 1]*A[1, 0] + + A[1, 1]**2) + A[0, 0] - A[1, 1])* + sqrt(A[0, 0]**2 - 2*A[0, 0]*A[1, 1] + 4*A[0, 1]*A[1, 0] + A[1, 1]**2) + ) + + +def test_transpose_index(): + assert X.T[i, j] == X[j, i] + + +def test_Identity_index(): + I = Identity(3) + assert I[0, 0] == I[1, 1] == I[2, 2] == 1 + assert I[1, 0] == I[0, 1] == I[2, 1] == 0 + assert I[i, 0].delta_range == (0, 2) + raises(IndexError, lambda: I[3, 3]) + + +def test_block_index(): + I = Identity(3) + Z = ZeroMatrix(3, 3) + B = BlockMatrix([[I, I], [I, I]]) + e3 = ImmutableMatrix(eye(3)) + BB = BlockMatrix([[e3, e3], [e3, e3]]) + assert B[0, 0] == B[3, 0] == B[0, 3] == B[3, 3] == 1 + assert B[4, 3] == B[5, 1] == 0 + + BB = BlockMatrix([[e3, e3], [e3, e3]]) + assert B.as_explicit() == BB.as_explicit() + + BI = BlockMatrix([[I, Z], [Z, I]]) + + assert BI.as_explicit().equals(eye(6)) + + +def test_block_index_symbolic(): + # Note that these matrices may be zero-sized and indices may be negative, which causes + # all naive simplifications given in the comments to be invalid + A1 = MatrixSymbol('A1', n, k) + A2 = MatrixSymbol('A2', n, l) + A3 = MatrixSymbol('A3', m, k) + A4 = MatrixSymbol('A4', m, l) + A = BlockMatrix([[A1, A2], [A3, A4]]) + assert A[0, 0] == MatrixElement(A, 0, 0) # Cannot be A1[0, 0] + assert A[n - 1, k - 1] == A1[n - 1, k - 1] + assert A[n, k] == A4[0, 0] + assert A[n + m - 1, 0] == MatrixElement(A, n + m - 1, 0) # Cannot be A3[m - 1, 0] + assert A[0, k + l - 1] == MatrixElement(A, 0, k + l - 1) # Cannot be A2[0, l - 1] + assert A[n + m - 1, k + l - 1] == MatrixElement(A, n + m - 1, k + l - 1) # Cannot be A4[m - 1, l - 1] + assert A[i, j] == MatrixElement(A, i, j) + assert A[n + i, k + j] == MatrixElement(A, n + i, k + j) # Cannot be A4[i, j] + assert A[n - i - 1, k - j - 1] == MatrixElement(A, n - i - 1, k - j - 1) # Cannot be A1[n - i - 1, k - j - 1] + + +def test_block_index_symbolic_nonzero(): + # All invalid simplifications from test_block_index_symbolic() that become valid if all + # matrices have nonzero size and all indices are nonnegative + k, l, m, n = symbols('k l m n', integer=True, positive=True) + i, j = symbols('i j', integer=True, nonnegative=True) + A1 = MatrixSymbol('A1', n, k) + A2 = MatrixSymbol('A2', n, l) + A3 = MatrixSymbol('A3', m, k) + A4 = MatrixSymbol('A4', m, l) + A = BlockMatrix([[A1, A2], [A3, A4]]) + assert A[0, 0] == A1[0, 0] + assert A[n + m - 1, 0] == A3[m - 1, 0] + assert A[0, k + l - 1] == A2[0, l - 1] + assert A[n + m - 1, k + l - 1] == A4[m - 1, l - 1] + assert A[i, j] == MatrixElement(A, i, j) + assert A[n + i, k + j] == A4[i, j] + assert A[n - i - 1, k - j - 1] == A1[n - i - 1, k - j - 1] + assert A[2 * n, 2 * k] == A4[n, k] + + +def test_block_index_large(): + n, m, k = symbols('n m k', integer=True, positive=True) + i = symbols('i', integer=True, nonnegative=True) + A1 = MatrixSymbol('A1', n, n) + A2 = MatrixSymbol('A2', n, m) + A3 = MatrixSymbol('A3', n, k) + A4 = MatrixSymbol('A4', m, n) + A5 = MatrixSymbol('A5', m, m) + A6 = MatrixSymbol('A6', m, k) + A7 = MatrixSymbol('A7', k, n) + A8 = MatrixSymbol('A8', k, m) + A9 = MatrixSymbol('A9', k, k) + A = BlockMatrix([[A1, A2, A3], [A4, A5, A6], [A7, A8, A9]]) + assert A[n + i, n + i] == MatrixElement(A, n + i, n + i) + + +@XFAIL +def test_block_index_symbolic_fail(): + # To make this work, symbolic matrix dimensions would need to be somehow assumed nonnegative + # even if the symbols aren't specified as such. Then 2 * n < n would correctly evaluate to + # False in BlockMatrix._entry() + A1 = MatrixSymbol('A1', n, 1) + A2 = MatrixSymbol('A2', m, 1) + A = BlockMatrix([[A1], [A2]]) + assert A[2 * n, 0] == A2[n, 0] + + +def test_slicing(): + A.as_explicit()[0, :] # does not raise an error + + +def test_errors(): + raises(IndexError, lambda: Identity(2)[1, 2, 3, 4, 5]) + raises(IndexError, lambda: Identity(2)[[1, 2, 3, 4, 5]]) + + +def test_matrix_expression_to_indices(): + i, j = symbols("i, j") + i1, i2, i3 = symbols("i_1:4") + + def replace_dummies(expr): + repl = {i: Symbol(i.name) for i in expr.atoms(Dummy)} + return expr.xreplace(repl) + + expr = W*X*Z + assert replace_dummies(expr._entry(i, j)) == \ + Sum(W[i, i1]*X[i1, i2]*Z[i2, j], (i1, 0, l-1), (i2, 0, m-1)) + assert MatrixExpr.from_index_summation(expr._entry(i, j)) == expr + + expr = Z.T*X.T*W.T + assert replace_dummies(expr._entry(i, j)) == \ + Sum(W[j, i2]*X[i2, i1]*Z[i1, i], (i1, 0, m-1), (i2, 0, l-1)) + assert MatrixExpr.from_index_summation(expr._entry(i, j), i) == expr + + expr = W*X*Z + W*Y*Z + assert replace_dummies(expr._entry(i, j)) == \ + Sum(W[i, i1]*X[i1, i2]*Z[i2, j], (i1, 0, l-1), (i2, 0, m-1)) +\ + Sum(W[i, i1]*Y[i1, i2]*Z[i2, j], (i1, 0, l-1), (i2, 0, m-1)) + assert MatrixExpr.from_index_summation(expr._entry(i, j)) == expr + + expr = 2*W*X*Z + 3*W*Y*Z + assert replace_dummies(expr._entry(i, j)) == \ + 2*Sum(W[i, i1]*X[i1, i2]*Z[i2, j], (i1, 0, l-1), (i2, 0, m-1)) +\ + 3*Sum(W[i, i1]*Y[i1, i2]*Z[i2, j], (i1, 0, l-1), (i2, 0, m-1)) + assert MatrixExpr.from_index_summation(expr._entry(i, j)) == expr + + expr = W*(X + Y)*Z + assert replace_dummies(expr._entry(i, j)) == \ + Sum(W[i, i1]*(X[i1, i2] + Y[i1, i2])*Z[i2, j], (i1, 0, l-1), (i2, 0, m-1)) + assert MatrixExpr.from_index_summation(expr._entry(i, j)) == expr + + expr = A*B**2*A + #assert replace_dummies(expr._entry(i, j)) == \ + # Sum(A[i, i1]*B[i1, i2]*B[i2, i3]*A[i3, j], (i1, 0, 1), (i2, 0, 1), (i3, 0, 1)) + + # Check that different dummies are used in sub-multiplications: + expr = (X1*X2 + X2*X1)*X3 + assert replace_dummies(expr._entry(i, j)) == \ + Sum((Sum(X1[i, i2] * X2[i2, i1], (i2, 0, m - 1)) + Sum(X1[i3, i1] * X2[i, i3], (i3, 0, m - 1))) * X3[ + i1, j], (i1, 0, m - 1)) + + +def test_matrix_expression_from_index_summation(): + from sympy.abc import a,b,c,d + A = MatrixSymbol("A", k, k) + B = MatrixSymbol("B", k, k) + C = MatrixSymbol("C", k, k) + w1 = MatrixSymbol("w1", k, 1) + + i0, i1, i2, i3, i4 = symbols("i0:5", cls=Dummy) + + expr = Sum(W[a,b]*X[b,c]*Z[c,d], (b, 0, l-1), (c, 0, m-1)) + assert MatrixExpr.from_index_summation(expr, a) == W*X*Z + expr = Sum(W.T[b,a]*X[b,c]*Z[c,d], (b, 0, l-1), (c, 0, m-1)) + assert MatrixExpr.from_index_summation(expr, a) == W*X*Z + expr = Sum(A[b, a]*B[b, c]*C[c, d], (b, 0, k-1), (c, 0, k-1)) + assert MatrixSymbol.from_index_summation(expr, a) == A.T*B*C + expr = Sum(A[b, a]*B[c, b]*C[c, d], (b, 0, k-1), (c, 0, k-1)) + assert MatrixSymbol.from_index_summation(expr, a) == A.T*B.T*C + expr = Sum(C[c, d]*A[b, a]*B[c, b], (b, 0, k-1), (c, 0, k-1)) + assert MatrixSymbol.from_index_summation(expr, a) == A.T*B.T*C + expr = Sum(A[a, b] + B[a, b], (a, 0, k-1), (b, 0, k-1)) + assert MatrixExpr.from_index_summation(expr, a) == OneMatrix(1, k)*A*OneMatrix(k, 1) + OneMatrix(1, k)*B*OneMatrix(k, 1) + expr = Sum(A[a, b]**2, (a, 0, k - 1), (b, 0, k - 1)) + assert MatrixExpr.from_index_summation(expr, a) == Trace(A * A.T) + expr = Sum(A[a, b]**3, (a, 0, k - 1), (b, 0, k - 1)) + assert MatrixExpr.from_index_summation(expr, a) == Trace(HadamardPower(A.T, 2) * A) + expr = Sum((A[a, b] + B[a, b])*C[b, c], (b, 0, k-1)) + assert MatrixExpr.from_index_summation(expr, a) == (A+B)*C + expr = Sum((A[a, b] + B[b, a])*C[b, c], (b, 0, k-1)) + assert MatrixExpr.from_index_summation(expr, a) == (A+B.T)*C + expr = Sum(A[a, b]*A[b, c]*A[c, d], (b, 0, k-1), (c, 0, k-1)) + assert MatrixExpr.from_index_summation(expr, a) == A**3 + expr = Sum(A[a, b]*A[b, c]*B[c, d], (b, 0, k-1), (c, 0, k-1)) + assert MatrixExpr.from_index_summation(expr, a) == A**2*B + + # Parse the trace of a matrix: + + expr = Sum(A[a, a], (a, 0, k-1)) + assert MatrixExpr.from_index_summation(expr, None) == trace(A) + expr = Sum(A[a, a]*B[b, c]*C[c, d], (a, 0, k-1), (c, 0, k-1)) + assert MatrixExpr.from_index_summation(expr, b) == trace(A)*B*C + + # Check wrong sum ranges (should raise an exception): + + ## Case 1: 0 to m instead of 0 to m-1 + expr = Sum(W[a,b]*X[b,c]*Z[c,d], (b, 0, l-1), (c, 0, m)) + raises(ValueError, lambda: MatrixExpr.from_index_summation(expr, a)) + ## Case 2: 1 to m-1 instead of 0 to m-1 + expr = Sum(W[a,b]*X[b,c]*Z[c,d], (b, 0, l-1), (c, 1, m-1)) + raises(ValueError, lambda: MatrixExpr.from_index_summation(expr, a)) + + # Parse nested sums: + expr = Sum(A[a, b]*Sum(B[b, c]*C[c, d], (c, 0, k-1)), (b, 0, k-1)) + assert MatrixExpr.from_index_summation(expr, a) == A*B*C + + # Test Kronecker delta: + expr = Sum(A[a, b]*KroneckerDelta(b, c)*B[c, d], (b, 0, k-1), (c, 0, k-1)) + assert MatrixExpr.from_index_summation(expr, a) == A*B + + expr = Sum(KroneckerDelta(i1, m)*KroneckerDelta(i2, n)*A[i, i1]*A[j, i2], (i1, 0, k-1), (i2, 0, k-1)) + assert MatrixExpr.from_index_summation(expr, m) == ArrayTensorProduct(A.T, A) + + # Test numbered indices: + expr = Sum(A[i1, i2]*w1[i2, 0], (i2, 0, k-1)) + assert MatrixExpr.from_index_summation(expr, i1) == MatrixElement(A*w1, i1, 0) + + expr = Sum(A[i1, i2]*B[i2, 0], (i2, 0, k-1)) + assert MatrixExpr.from_index_summation(expr, i1) == MatrixElement(A*B, i1, 0) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_inverse.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_inverse.py new file mode 100644 index 0000000000000000000000000000000000000000..4bcc7d4de2b2bee4c4922bda8bc48a52aa205961 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_inverse.py @@ -0,0 +1,69 @@ +from sympy.core import symbols, S +from sympy.matrices.expressions import MatrixSymbol, Inverse, MatPow, ZeroMatrix, OneMatrix +from sympy.matrices.exceptions import NonInvertibleMatrixError, NonSquareMatrixError +from sympy.matrices import eye, Identity +from sympy.testing.pytest import raises +from sympy.assumptions.ask import Q +from sympy.assumptions.refine import refine + +n, m, l = symbols('n m l', integer=True) +A = MatrixSymbol('A', n, m) +B = MatrixSymbol('B', m, l) +C = MatrixSymbol('C', n, n) +D = MatrixSymbol('D', n, n) +E = MatrixSymbol('E', m, n) + + +def test_inverse(): + assert Inverse(C).args == (C, S.NegativeOne) + assert Inverse(C).shape == (n, n) + assert Inverse(A*E).shape == (n, n) + assert Inverse(E*A).shape == (m, m) + assert Inverse(C).inverse() == C + assert Inverse(Inverse(C)).doit() == C + assert isinstance(Inverse(Inverse(C)), Inverse) + + assert Inverse(*Inverse(E*A).args) == Inverse(E*A) + + assert C.inverse().inverse() == C + + assert C.inverse()*C == Identity(C.rows) + + assert Identity(n).inverse() == Identity(n) + assert (3*Identity(n)).inverse() == Identity(n)/3 + + # Simplifies Muls if possible (i.e. submatrices are square) + assert (C*D).inverse() == D.I*C.I + # But still works when not possible + assert isinstance((A*E).inverse(), Inverse) + assert Inverse(C*D).doit(inv_expand=False) == Inverse(C*D) + + assert Inverse(eye(3)).doit() == eye(3) + assert Inverse(eye(3)).doit(deep=False) == eye(3) + + assert OneMatrix(1, 1).I == Identity(1) + assert isinstance(OneMatrix(n, n).I, Inverse) + +def test_inverse_non_invertible(): + raises(NonInvertibleMatrixError, lambda: ZeroMatrix(n, n).I) + raises(NonInvertibleMatrixError, lambda: OneMatrix(2, 2).I) + +def test_refine(): + assert refine(C.I, Q.orthogonal(C)) == C.T + + +def test_inverse_matpow_canonicalization(): + A = MatrixSymbol('A', 3, 3) + assert Inverse(MatPow(A, 3)).doit() == MatPow(Inverse(A), 3).doit() + + +def test_nonsquare_error(): + A = MatrixSymbol('A', 3, 4) + raises(NonSquareMatrixError, lambda: Inverse(A)) + + +def test_adjoint_trnaspose_conjugate(): + A = MatrixSymbol('A', n, n) + assert A.transpose().inverse() == A.inverse().transpose() + assert A.conjugate().inverse() == A.inverse().conjugate() + assert A.adjoint().inverse() == A.inverse().adjoint() diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_kronecker.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_kronecker.py new file mode 100644 index 0000000000000000000000000000000000000000..b4444716a76a52e3638dd7a36238a9f459179083 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_kronecker.py @@ -0,0 +1,150 @@ +from sympy.core.mod import Mod +from sympy.core.numbers import I +from sympy.core.symbol import symbols +from sympy.functions.elementary.integers import floor +from sympy.matrices.dense import (Matrix, eye) +from sympy.matrices import MatrixSymbol, Identity +from sympy.matrices.expressions import det, trace + +from sympy.matrices.expressions.kronecker import (KroneckerProduct, + kronecker_product, + combine_kronecker) + + +mat1 = Matrix([[1, 2 * I], [1 + I, 3]]) +mat2 = Matrix([[2 * I, 3], [4 * I, 2]]) + +i, j, k, n, m, o, p, x = symbols('i,j,k,n,m,o,p,x') +Z = MatrixSymbol('Z', n, n) +W = MatrixSymbol('W', m, m) +A = MatrixSymbol('A', n, m) +B = MatrixSymbol('B', n, m) +C = MatrixSymbol('C', m, k) + + +def test_KroneckerProduct(): + assert isinstance(KroneckerProduct(A, B), KroneckerProduct) + assert KroneckerProduct(A, B).subs(A, C) == KroneckerProduct(C, B) + assert KroneckerProduct(A, C).shape == (n*m, m*k) + assert (KroneckerProduct(A, C) + KroneckerProduct(-A, C)).is_ZeroMatrix + assert (KroneckerProduct(W, Z) * KroneckerProduct(W.I, Z.I)).is_Identity + + +def test_KroneckerProduct_identity(): + assert KroneckerProduct(Identity(m), Identity(n)) == Identity(m*n) + assert KroneckerProduct(eye(2), eye(3)) == eye(6) + + +def test_KroneckerProduct_explicit(): + X = MatrixSymbol('X', 2, 2) + Y = MatrixSymbol('Y', 2, 2) + kp = KroneckerProduct(X, Y) + assert kp.shape == (4, 4) + assert kp.as_explicit() == Matrix( + [ + [X[0, 0]*Y[0, 0], X[0, 0]*Y[0, 1], X[0, 1]*Y[0, 0], X[0, 1]*Y[0, 1]], + [X[0, 0]*Y[1, 0], X[0, 0]*Y[1, 1], X[0, 1]*Y[1, 0], X[0, 1]*Y[1, 1]], + [X[1, 0]*Y[0, 0], X[1, 0]*Y[0, 1], X[1, 1]*Y[0, 0], X[1, 1]*Y[0, 1]], + [X[1, 0]*Y[1, 0], X[1, 0]*Y[1, 1], X[1, 1]*Y[1, 0], X[1, 1]*Y[1, 1]] + ] + ) + + +def test_tensor_product_adjoint(): + assert KroneckerProduct(I*A, B).adjoint() == \ + -I*KroneckerProduct(A.adjoint(), B.adjoint()) + assert KroneckerProduct(mat1, mat2).adjoint() == \ + kronecker_product(mat1.adjoint(), mat2.adjoint()) + + +def test_tensor_product_conjugate(): + assert KroneckerProduct(I*A, B).conjugate() == \ + -I*KroneckerProduct(A.conjugate(), B.conjugate()) + assert KroneckerProduct(mat1, mat2).conjugate() == \ + kronecker_product(mat1.conjugate(), mat2.conjugate()) + + +def test_tensor_product_transpose(): + assert KroneckerProduct(I*A, B).transpose() == \ + I*KroneckerProduct(A.transpose(), B.transpose()) + assert KroneckerProduct(mat1, mat2).transpose() == \ + kronecker_product(mat1.transpose(), mat2.transpose()) + + +def test_KroneckerProduct_is_associative(): + assert kronecker_product(A, kronecker_product( + B, C)) == kronecker_product(kronecker_product(A, B), C) + assert kronecker_product(A, kronecker_product( + B, C)) == KroneckerProduct(A, B, C) + + +def test_KroneckerProduct_is_bilinear(): + assert kronecker_product(x*A, B) == x*kronecker_product(A, B) + assert kronecker_product(A, x*B) == x*kronecker_product(A, B) + + +def test_KroneckerProduct_determinant(): + kp = kronecker_product(W, Z) + assert det(kp) == det(W)**n * det(Z)**m + + +def test_KroneckerProduct_trace(): + kp = kronecker_product(W, Z) + assert trace(kp) == trace(W)*trace(Z) + + +def test_KroneckerProduct_isnt_commutative(): + assert KroneckerProduct(A, B) != KroneckerProduct(B, A) + assert KroneckerProduct(A, B).is_commutative is False + + +def test_KroneckerProduct_extracts_commutative_part(): + assert kronecker_product(x * A, 2 * B) == x * \ + 2 * KroneckerProduct(A, B) + + +def test_KroneckerProduct_inverse(): + kp = kronecker_product(W, Z) + assert kp.inverse() == kronecker_product(W.inverse(), Z.inverse()) + + +def test_KroneckerProduct_combine_add(): + kp1 = kronecker_product(A, B) + kp2 = kronecker_product(C, W) + assert combine_kronecker(kp1*kp2) == kronecker_product(A*C, B*W) + + +def test_KroneckerProduct_combine_mul(): + X = MatrixSymbol('X', m, n) + Y = MatrixSymbol('Y', m, n) + kp1 = kronecker_product(A, X) + kp2 = kronecker_product(B, Y) + assert combine_kronecker(kp1+kp2) == kronecker_product(A+B, X+Y) + + +def test_KroneckerProduct_combine_pow(): + X = MatrixSymbol('X', n, n) + Y = MatrixSymbol('Y', n, n) + assert combine_kronecker(KroneckerProduct( + X, Y)**x) == KroneckerProduct(X**x, Y**x) + assert combine_kronecker(x * KroneckerProduct(X, Y) + ** 2) == x * KroneckerProduct(X**2, Y**2) + assert combine_kronecker( + x * (KroneckerProduct(X, Y)**2) * KroneckerProduct(A, B)) == x * KroneckerProduct(X**2 * A, Y**2 * B) + # cannot simplify because of non-square arguments to kronecker product: + assert combine_kronecker(KroneckerProduct(A, B.T) ** m) == KroneckerProduct(A, B.T) ** m + + +def test_KroneckerProduct_expand(): + X = MatrixSymbol('X', n, n) + Y = MatrixSymbol('Y', n, n) + + assert KroneckerProduct(X + Y, Y + Z).expand(kroneckerproduct=True) == \ + KroneckerProduct(X, Y) + KroneckerProduct(X, Z) + \ + KroneckerProduct(Y, Y) + KroneckerProduct(Y, Z) + +def test_KroneckerProduct_entry(): + A = MatrixSymbol('A', n, m) + B = MatrixSymbol('B', o, p) + + assert KroneckerProduct(A, B)._entry(i, j) == A[Mod(floor(i/o), n), Mod(floor(j/p), m)]*B[Mod(i, o), Mod(j, p)] diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_matadd.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_matadd.py new file mode 100644 index 0000000000000000000000000000000000000000..43229ae8c2e42f0253a5f3eceefa5fffe7a99f29 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_matadd.py @@ -0,0 +1,58 @@ +from sympy.matrices.expressions import MatrixSymbol, MatAdd, MatPow, MatMul +from sympy.matrices.expressions.special import GenericZeroMatrix, ZeroMatrix +from sympy.matrices.exceptions import ShapeError +from sympy.matrices import eye, ImmutableMatrix +from sympy.core import Add, Basic, S +from sympy.core.add import add +from sympy.testing.pytest import XFAIL, raises + +X = MatrixSymbol('X', 2, 2) +Y = MatrixSymbol('Y', 2, 2) + +def test_evaluate(): + assert MatAdd(X, X, evaluate=True) == add(X, X, evaluate=True) == MatAdd(X, X).doit() + +def test_sort_key(): + assert MatAdd(Y, X).doit().args == add(Y, X).doit().args == (X, Y) + + +def test_matadd_sympify(): + assert isinstance(MatAdd(eye(1), eye(1)).args[0], Basic) + assert isinstance(add(eye(1), eye(1)).args[0], Basic) + + +def test_matadd_of_matrices(): + assert MatAdd(eye(2), 4*eye(2), eye(2)).doit() == ImmutableMatrix(6*eye(2)) + assert add(eye(2), 4*eye(2), eye(2)).doit() == ImmutableMatrix(6*eye(2)) + + +def test_doit_args(): + A = ImmutableMatrix([[1, 2], [3, 4]]) + B = ImmutableMatrix([[2, 3], [4, 5]]) + assert MatAdd(A, MatPow(B, 2)).doit() == A + B**2 + assert MatAdd(A, MatMul(A, B)).doit() == A + A*B + assert (MatAdd(A, X, MatMul(A, B), Y, MatAdd(2*A, B)).doit() == + add(A, X, MatMul(A, B), Y, add(2*A, B)).doit() == + MatAdd(3*A + A*B + B, X, Y)) + + +def test_generic_identity(): + assert MatAdd.identity == GenericZeroMatrix() + assert MatAdd.identity != S.Zero + + +def test_zero_matrix_add(): + assert Add(ZeroMatrix(2, 2), ZeroMatrix(2, 2)) == ZeroMatrix(2, 2) + +@XFAIL +def test_matrix_Add_with_scalar(): + raises(TypeError, lambda: Add(0, ZeroMatrix(2, 2))) + + +def test_shape_error(): + A = MatrixSymbol('A', 2, 3) + B = MatrixSymbol('B', 3, 3) + raises(ShapeError, lambda: MatAdd(A, B)) + + A = MatrixSymbol('A', 3, 2) + raises(ShapeError, lambda: MatAdd(A, B)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_matexpr.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_matexpr.py new file mode 100644 index 0000000000000000000000000000000000000000..f2319e8d8097c2ad3519eab783c4665623c55b80 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_matexpr.py @@ -0,0 +1,592 @@ +from sympy.concrete.summations import Sum +from sympy.core.exprtools import gcd_terms +from sympy.core.function import (diff, expand) +from sympy.core.relational import Eq +from sympy.core.symbol import (Dummy, Symbol, Str) +from sympy.functions.special.tensor_functions import KroneckerDelta +from sympy.matrices.dense import zeros +from sympy.polys.polytools import factor + +from sympy.core import (S, symbols, Add, Mul, SympifyError, Rational, + Function) +from sympy.functions import sin, cos, tan, sqrt, cbrt, exp +from sympy.simplify import simplify +from sympy.matrices import (ImmutableMatrix, Inverse, MatAdd, MatMul, + MatPow, Matrix, MatrixExpr, MatrixSymbol, + SparseMatrix, Transpose, Adjoint, MatrixSet) +from sympy.matrices.exceptions import NonSquareMatrixError +from sympy.matrices.expressions.determinant import Determinant, det +from sympy.matrices.expressions.matexpr import MatrixElement +from sympy.matrices.expressions.special import ZeroMatrix, Identity +from sympy.testing.pytest import raises, XFAIL, skip +from importlib.metadata import version + +n, m, l, k, p = symbols('n m l k p', integer=True) +x = symbols('x') +A = MatrixSymbol('A', n, m) +B = MatrixSymbol('B', m, l) +C = MatrixSymbol('C', n, n) +D = MatrixSymbol('D', n, n) +E = MatrixSymbol('E', m, n) +w = MatrixSymbol('w', n, 1) + + +def test_matrix_symbol_creation(): + assert MatrixSymbol('A', 2, 2) + assert MatrixSymbol('A', 0, 0) + raises(ValueError, lambda: MatrixSymbol('A', -1, 2)) + raises(ValueError, lambda: MatrixSymbol('A', 2.0, 2)) + raises(ValueError, lambda: MatrixSymbol('A', 2j, 2)) + raises(ValueError, lambda: MatrixSymbol('A', 2, -1)) + raises(ValueError, lambda: MatrixSymbol('A', 2, 2.0)) + raises(ValueError, lambda: MatrixSymbol('A', 2, 2j)) + + n = symbols('n') + assert MatrixSymbol('A', n, n) + n = symbols('n', integer=False) + raises(ValueError, lambda: MatrixSymbol('A', n, n)) + n = symbols('n', negative=True) + raises(ValueError, lambda: MatrixSymbol('A', n, n)) + + +def test_matexpr_properties(): + assert A.shape == (n, m) + assert (A * B).shape == (n, l) + assert A[0, 1].indices == (0, 1) + assert A[0, 0].symbol == A + assert A[0, 0].symbol.name == 'A' + + +def test_matexpr(): + assert (x*A).shape == A.shape + assert (x*A).__class__ == MatMul + assert 2*A - A - A == ZeroMatrix(*A.shape) + assert (A*B).shape == (n, l) + + +def test_matexpr_subs(): + A = MatrixSymbol('A', n, m) + B = MatrixSymbol('B', m, l) + C = MatrixSymbol('C', m, l) + + assert A.subs(n, m).shape == (m, m) + assert (A*B).subs(B, C) == A*C + assert (A*B).subs(l, n).is_square + + W = MatrixSymbol("W", 3, 3) + X = MatrixSymbol("X", 2, 2) + Y = MatrixSymbol("Y", 1, 2) + Z = MatrixSymbol("Z", n, 2) + # no restrictions on Symbol replacement + assert X.subs(X, Y) == Y + # it might be better to just change the name + y = Str('y') + assert X.subs(Str("X"), y).args == (y, 2, 2) + # it's ok to introduce a wider matrix + assert X[1, 1].subs(X, W) == W[1, 1] + # but for a given MatrixExpression, only change + # name if indexing on the new shape is valid. + # Here, X is 2,2; Y is 1,2 and Y[1, 1] is out + # of range so an error is raised + raises(IndexError, lambda: X[1, 1].subs(X, Y)) + # here, [0, 1] is in range so the subs succeeds + assert X[0, 1].subs(X, Y) == Y[0, 1] + # and here the size of n will accept any index + # in the first position + assert W[2, 1].subs(W, Z) == Z[2, 1] + # but not in the second position + raises(IndexError, lambda: W[2, 2].subs(W, Z)) + # any matrix should raise if invalid + raises(IndexError, lambda: W[2, 2].subs(W, zeros(2))) + + A = SparseMatrix([[1, 2], [3, 4]]) + B = Matrix([[1, 2], [3, 4]]) + C, D = MatrixSymbol('C', 2, 2), MatrixSymbol('D', 2, 2) + + assert (C*D).subs({C: A, D: B}) == MatMul(A, B) + + +def test_addition(): + A = MatrixSymbol('A', n, m) + B = MatrixSymbol('B', n, m) + + assert isinstance(A + B, MatAdd) + assert (A + B).shape == A.shape + assert isinstance(A - A + 2*B, MatMul) + + raises(TypeError, lambda: A + 1) + raises(TypeError, lambda: 5 + A) + raises(TypeError, lambda: 5 - A) + + assert A + ZeroMatrix(n, m) - A == ZeroMatrix(n, m) + raises(TypeError, lambda: ZeroMatrix(n, m) + S.Zero) + + +def test_multiplication(): + A = MatrixSymbol('A', n, m) + B = MatrixSymbol('B', m, l) + C = MatrixSymbol('C', n, n) + + assert (2*A*B).shape == (n, l) + assert (A*0*B) == ZeroMatrix(n, l) + assert (2*A).shape == A.shape + + assert A * ZeroMatrix(m, m) * B == ZeroMatrix(n, l) + + assert C * Identity(n) * C.I == Identity(n) + + assert B/2 == S.Half*B + raises(NotImplementedError, lambda: 2/B) + + A = MatrixSymbol('A', n, n) + B = MatrixSymbol('B', n, n) + assert Identity(n) * (A + B) == A + B + + assert A**2*A == A**3 + assert A**2*(A.I)**3 == A.I + assert A**3*(A.I)**2 == A + + +def test_MatPow(): + A = MatrixSymbol('A', n, n) + + AA = MatPow(A, 2) + assert AA.exp == 2 + assert AA.base == A + assert (A**n).exp == n + + assert A**0 == Identity(n) + assert A**1 == A + assert A**2 == AA + assert A**-1 == Inverse(A) + assert (A**-1)**-1 == A + assert (A**2)**3 == A**6 + assert A**S.Half == sqrt(A) + assert A**Rational(1, 3) == cbrt(A) + raises(NonSquareMatrixError, lambda: MatrixSymbol('B', 3, 2)**2) + + +def test_MatrixSymbol(): + n, m, t = symbols('n,m,t') + X = MatrixSymbol('X', n, m) + assert X.shape == (n, m) + raises(TypeError, lambda: MatrixSymbol('X', n, m)(t)) # issue 5855 + assert X.doit() == X + + +def test_dense_conversion(): + X = MatrixSymbol('X', 2, 2) + assert ImmutableMatrix(X) == ImmutableMatrix(2, 2, lambda i, j: X[i, j]) + assert Matrix(X) == Matrix(2, 2, lambda i, j: X[i, j]) + + +def test_free_symbols(): + assert (C*D).free_symbols == {C, D} + + +def test_zero_matmul(): + assert isinstance(S.Zero * MatrixSymbol('X', 2, 2), MatrixExpr) + + +def test_matadd_simplify(): + A = MatrixSymbol('A', 1, 1) + assert simplify(MatAdd(A, ImmutableMatrix([[sin(x)**2 + cos(x)**2]]))) == \ + MatAdd(A, Matrix([[1]])) + + +def test_matmul_simplify(): + A = MatrixSymbol('A', 1, 1) + assert simplify(MatMul(A, ImmutableMatrix([[sin(x)**2 + cos(x)**2]]))) == \ + MatMul(A, Matrix([[1]])) + + +def test_invariants(): + A = MatrixSymbol('A', n, m) + B = MatrixSymbol('B', m, l) + X = MatrixSymbol('X', n, n) + objs = [Identity(n), ZeroMatrix(m, n), A, MatMul(A, B), MatAdd(A, A), + Transpose(A), Adjoint(A), Inverse(X), MatPow(X, 2), MatPow(X, -1), + MatPow(X, 0)] + for obj in objs: + assert obj == obj.__class__(*obj.args) + + +def test_matexpr_indexing(): + A = MatrixSymbol('A', n, m) + A[1, 2] + A[l, k] + A[l + 1, k + 1] + A = MatrixSymbol('A', 2, 1) + for i in range(-2, 2): + for j in range(-1, 1): + A[i, j] + + +def test_single_indexing(): + A = MatrixSymbol('A', 2, 3) + assert A[1] == A[0, 1] + assert A[int(1)] == A[0, 1] + assert A[3] == A[1, 0] + assert list(A[:2, :2]) == [A[0, 0], A[0, 1], A[1, 0], A[1, 1]] + raises(IndexError, lambda: A[6]) + raises(IndexError, lambda: A[n]) + B = MatrixSymbol('B', n, m) + raises(IndexError, lambda: B[1]) + B = MatrixSymbol('B', n, 3) + assert B[3] == B[1, 0] + + +def test_MatrixElement_commutative(): + assert A[0, 1]*A[1, 0] == A[1, 0]*A[0, 1] + + +def test_MatrixSymbol_determinant(): + A = MatrixSymbol('A', 4, 4) + assert A.as_explicit().det() == A[0, 0]*A[1, 1]*A[2, 2]*A[3, 3] - \ + A[0, 0]*A[1, 1]*A[2, 3]*A[3, 2] - A[0, 0]*A[1, 2]*A[2, 1]*A[3, 3] + \ + A[0, 0]*A[1, 2]*A[2, 3]*A[3, 1] + A[0, 0]*A[1, 3]*A[2, 1]*A[3, 2] - \ + A[0, 0]*A[1, 3]*A[2, 2]*A[3, 1] - A[0, 1]*A[1, 0]*A[2, 2]*A[3, 3] + \ + A[0, 1]*A[1, 0]*A[2, 3]*A[3, 2] + A[0, 1]*A[1, 2]*A[2, 0]*A[3, 3] - \ + A[0, 1]*A[1, 2]*A[2, 3]*A[3, 0] - A[0, 1]*A[1, 3]*A[2, 0]*A[3, 2] + \ + A[0, 1]*A[1, 3]*A[2, 2]*A[3, 0] + A[0, 2]*A[1, 0]*A[2, 1]*A[3, 3] - \ + A[0, 2]*A[1, 0]*A[2, 3]*A[3, 1] - A[0, 2]*A[1, 1]*A[2, 0]*A[3, 3] + \ + A[0, 2]*A[1, 1]*A[2, 3]*A[3, 0] + A[0, 2]*A[1, 3]*A[2, 0]*A[3, 1] - \ + A[0, 2]*A[1, 3]*A[2, 1]*A[3, 0] - A[0, 3]*A[1, 0]*A[2, 1]*A[3, 2] + \ + A[0, 3]*A[1, 0]*A[2, 2]*A[3, 1] + A[0, 3]*A[1, 1]*A[2, 0]*A[3, 2] - \ + A[0, 3]*A[1, 1]*A[2, 2]*A[3, 0] - A[0, 3]*A[1, 2]*A[2, 0]*A[3, 1] + \ + A[0, 3]*A[1, 2]*A[2, 1]*A[3, 0] + + B = MatrixSymbol('B', 4, 4) + assert Determinant(A + B).doit() == det(A + B) == (A + B).det() + + +def test_MatrixElement_diff(): + assert (A[3, 0]*A[0, 0]).diff(A[0, 0]) == A[3, 0] + + +def test_MatrixElement_doit(): + u = MatrixSymbol('u', 2, 1) + v = ImmutableMatrix([3, 5]) + assert u[0, 0].subs(u, v).doit() == v[0, 0] + + +def test_identity_powers(): + M = Identity(n) + assert MatPow(M, 3).doit() == M**3 + assert M**n == M + assert MatPow(M, 0).doit() == M**2 + assert M**-2 == M + assert MatPow(M, -2).doit() == M**0 + N = Identity(3) + assert MatPow(N, 2).doit() == N**n + assert MatPow(N, 3).doit() == N + assert MatPow(N, -2).doit() == N**4 + assert MatPow(N, 2).doit() == N**0 + + +def test_Zero_power(): + z1 = ZeroMatrix(n, n) + assert z1**4 == z1 + raises(ValueError, lambda:z1**-2) + assert z1**0 == Identity(n) + assert MatPow(z1, 2).doit() == z1**2 + raises(ValueError, lambda:MatPow(z1, -2).doit()) + z2 = ZeroMatrix(3, 3) + assert MatPow(z2, 4).doit() == z2**4 + raises(ValueError, lambda:z2**-3) + assert z2**3 == MatPow(z2, 3).doit() + assert z2**0 == Identity(3) + raises(ValueError, lambda:MatPow(z2, -1).doit()) + + +def test_matrixelement_diff(): + dexpr = diff((D*w)[k,0], w[p,0]) + + assert w[k, p].diff(w[k, p]) == 1 + assert w[k, p].diff(w[0, 0]) == KroneckerDelta(0, k, (0, n-1))*KroneckerDelta(0, p, (0, 0)) + _i_1 = Dummy("_i_1") + assert dexpr.dummy_eq(Sum(KroneckerDelta(_i_1, p, (0, n-1))*D[k, _i_1], (_i_1, 0, n - 1))) + assert dexpr.doit() == D[k, p] + + +def test_MatrixElement_with_values(): + x, y, z, w = symbols("x y z w") + M = Matrix([[x, y], [z, w]]) + i, j = symbols("i, j") + Mij = M[i, j] + assert isinstance(Mij, MatrixElement) + Ms = SparseMatrix([[2, 3], [4, 5]]) + msij = Ms[i, j] + assert isinstance(msij, MatrixElement) + for oi, oj in [(0, 0), (0, 1), (1, 0), (1, 1)]: + assert Mij.subs({i: oi, j: oj}) == M[oi, oj] + assert msij.subs({i: oi, j: oj}) == Ms[oi, oj] + A = MatrixSymbol("A", 2, 2) + assert A[0, 0].subs(A, M) == x + assert A[i, j].subs(A, M) == M[i, j] + assert M[i, j].subs(M, A) == A[i, j] + + assert isinstance(M[3*i - 2, j], MatrixElement) + assert M[3*i - 2, j].subs({i: 1, j: 0}) == M[1, 0] + assert isinstance(M[i, 0], MatrixElement) + assert M[i, 0].subs(i, 0) == M[0, 0] + assert M[0, i].subs(i, 1) == M[0, 1] + + assert M[i, j].diff(x) == Matrix([[1, 0], [0, 0]])[i, j] + + raises(ValueError, lambda: M[i, 2]) + raises(ValueError, lambda: M[i, -1]) + raises(ValueError, lambda: M[2, i]) + raises(ValueError, lambda: M[-1, i]) + + +def test_inv(): + B = MatrixSymbol('B', 3, 3) + assert B.inv() == B**-1 + + # https://github.com/sympy/sympy/issues/19162 + X = MatrixSymbol('X', 1, 1).as_explicit() + assert X.inv() == Matrix([[1/X[0, 0]]]) + + X = MatrixSymbol('X', 2, 2).as_explicit() + detX = X[0, 0]*X[1, 1] - X[0, 1]*X[1, 0] + invX = Matrix([[ X[1, 1], -X[0, 1]], + [-X[1, 0], X[0, 0]]]) / detX + assert X.inv() == invX + + +@XFAIL +def test_factor_expand(): + A = MatrixSymbol("A", n, n) + B = MatrixSymbol("B", n, n) + expr1 = (A + B)*(C + D) + expr2 = A*C + B*C + A*D + B*D + assert expr1 != expr2 + assert expand(expr1) == expr2 + assert factor(expr2) == expr1 + + expr = B**(-1)*(A**(-1)*B**(-1) - A**(-1)*C*B**(-1))**(-1)*A**(-1) + I = Identity(n) + # Ideally we get the first, but we at least don't want a wrong answer + assert factor(expr) in [I - C, B**-1*(A**-1*(I - C)*B**-1)**-1*A**-1] + +def test_numpy_conversion(): + try: + from numpy import array, array_equal + except ImportError: + skip('NumPy must be available to test creating matrices from ndarrays') + A = MatrixSymbol('A', 2, 2) + np_array = array([[MatrixElement(A, 0, 0), MatrixElement(A, 0, 1)], + [MatrixElement(A, 1, 0), MatrixElement(A, 1, 1)]]) + assert array_equal(array(A), np_array) + assert array_equal(array(A, copy=True), np_array) + if(int(version('numpy').split('.')[0]) >= 2): #run this test only if numpy is new enough that copy variable is passed properly. + raises(TypeError, lambda: array(A, copy=False)) + +def test_issue_2749(): + A = MatrixSymbol("A", 5, 2) + assert (A.T * A).I.as_explicit() == Matrix([[(A.T * A).I[0, 0], (A.T * A).I[0, 1]], \ + [(A.T * A).I[1, 0], (A.T * A).I[1, 1]]]) + + +def test_issue_2750(): + x = MatrixSymbol('x', 1, 1) + assert (x.T*x).as_explicit()**-1 == Matrix([[x[0, 0]**(-2)]]) + + +def test_issue_7842(): + A = MatrixSymbol('A', 3, 1) + B = MatrixSymbol('B', 2, 1) + assert Eq(A, B) == False + assert Eq(A[1,0], B[1, 0]).func is Eq + A = ZeroMatrix(2, 3) + B = ZeroMatrix(2, 3) + assert Eq(A, B) == True + + +def test_issue_21195(): + t = symbols('t') + x = Function('x')(t) + dx = x.diff(t) + exp1 = cos(x) + cos(x)*dx + exp2 = sin(x) + tan(x)*(dx.diff(t)) + exp3 = sin(x)*sin(t)*(dx.diff(t)).diff(t) + A = Matrix([[exp1], [exp2], [exp3]]) + B = Matrix([[exp1.diff(x)], [exp2.diff(x)], [exp3.diff(x)]]) + assert A.diff(x) == B + + +def test_issue_24859(): + A = MatrixSymbol('A', 2, 3) + B = MatrixSymbol('B', 3, 2) + J = A*B + Jinv = Matrix(J).adjugate() + u = MatrixSymbol('u', 2, 3) + Jk = Jinv.subs(A, A + x*u) + + expected = B[0, 1]*u[1, 0] + B[1, 1]*u[1, 1] + B[2, 1]*u[1, 2] + assert Jk[0, 0].diff(x) == expected + assert diff(Jk[0, 0], x).doit() == expected + + +def test_MatMul_postprocessor(): + z = zeros(2) + z1 = ZeroMatrix(2, 2) + assert Mul(0, z) == Mul(z, 0) in [z, z1] + + M = Matrix([[1, 2], [3, 4]]) + Mx = Matrix([[x, 2*x], [3*x, 4*x]]) + assert Mul(x, M) == Mul(M, x) == Mx + + A = MatrixSymbol("A", 2, 2) + assert Mul(A, M) == MatMul(A, M) + assert Mul(M, A) == MatMul(M, A) + # Scalars should be absorbed into constant matrices + a = Mul(x, M, A) + b = Mul(M, x, A) + c = Mul(M, A, x) + assert a == b == c == MatMul(Mx, A) + a = Mul(x, A, M) + b = Mul(A, x, M) + c = Mul(A, M, x) + assert a == b == c == MatMul(A, Mx) + assert Mul(M, M) == M**2 + assert Mul(A, M, M) == MatMul(A, M**2) + assert Mul(M, M, A) == MatMul(M**2, A) + assert Mul(M, A, M) == MatMul(M, A, M) + + assert Mul(A, x, M, M, x) == MatMul(A, Mx**2) + + +@XFAIL +def test_MatAdd_postprocessor_xfail(): + # This is difficult to get working because of the way that Add processes + # its args. + z = zeros(2) + assert Add(z, S.NaN) == Add(S.NaN, z) + + +def test_MatAdd_postprocessor(): + # Some of these are nonsensical, but we do not raise errors for Add + # because that breaks algorithms that want to replace matrices with dummy + # symbols. + + z = zeros(2) + + assert Add(0, z) == Add(z, 0) == z + + a = Add(S.Infinity, z) + assert a == Add(z, S.Infinity) + assert isinstance(a, Add) + assert a.args == (S.Infinity, z) + + a = Add(S.ComplexInfinity, z) + assert a == Add(z, S.ComplexInfinity) + assert isinstance(a, Add) + assert a.args == (S.ComplexInfinity, z) + + a = Add(z, S.NaN) + # assert a == Add(S.NaN, z) # See the XFAIL above + assert isinstance(a, Add) + assert a.args == (S.NaN, z) + + M = Matrix([[1, 2], [3, 4]]) + a = Add(x, M) + assert a == Add(M, x) + assert isinstance(a, Add) + assert a.args == (x, M) + + A = MatrixSymbol("A", 2, 2) + assert Add(A, M) == Add(M, A) == A + M + + # Scalars should be absorbed into constant matrices (producing an error) + a = Add(x, M, A) + assert a == Add(M, x, A) == Add(M, A, x) == Add(x, A, M) == Add(A, x, M) == Add(A, M, x) + assert isinstance(a, Add) + assert a.args == (x, A + M) + + assert Add(M, M) == 2*M + assert Add(M, A, M) == Add(M, M, A) == Add(A, M, M) == A + 2*M + + a = Add(A, x, M, M, x) + assert isinstance(a, Add) + assert a.args == (2*x, A + 2*M) + + +def test_simplify_matrix_expressions(): + # Various simplification functions + assert type(gcd_terms(C*D + D*C)) == MatAdd + a = gcd_terms(2*C*D + 4*D*C) + assert type(a) == MatAdd + assert a.args == (2*C*D, 4*D*C) + + +def test_exp(): + A = MatrixSymbol('A', 2, 2) + B = MatrixSymbol('B', 2, 2) + expr1 = exp(A)*exp(B) + expr2 = exp(B)*exp(A) + assert expr1 != expr2 + assert expr1 - expr2 != 0 + assert not isinstance(expr1, exp) + assert not isinstance(expr2, exp) + + +def test_invalid_args(): + raises(SympifyError, lambda: MatrixSymbol(1, 2, 'A')) + + +def test_matrixsymbol_from_symbol(): + # The label should be preserved during doit and subs + A_label = Symbol('A', complex=True) + A = MatrixSymbol(A_label, 2, 2) + + A_1 = A.doit() + A_2 = A.subs(2, 3) + assert A_1.args == A.args + assert A_2.args[0] == A.args[0] + + +def test_as_explicit(): + Z = MatrixSymbol('Z', 2, 3) + assert Z.as_explicit() == ImmutableMatrix([ + [Z[0, 0], Z[0, 1], Z[0, 2]], + [Z[1, 0], Z[1, 1], Z[1, 2]], + ]) + raises(ValueError, lambda: A.as_explicit()) + + +def test_MatrixSet(): + M = MatrixSet(2, 2, set=S.Reals) + assert M.shape == (2, 2) + assert M.set == S.Reals + X = Matrix([[1, 2], [3, 4]]) + assert X in M + X = ZeroMatrix(2, 2) + assert X in M + raises(TypeError, lambda: A in M) + raises(TypeError, lambda: 1 in M) + M = MatrixSet(n, m, set=S.Reals) + assert A in M + raises(TypeError, lambda: C in M) + raises(TypeError, lambda: X in M) + M = MatrixSet(2, 2, set={1, 2, 3}) + X = Matrix([[1, 2], [3, 4]]) + Y = Matrix([[1, 2]]) + assert (X in M) == S.false + assert (Y in M) == S.false + raises(ValueError, lambda: MatrixSet(2, -2, S.Reals)) + raises(ValueError, lambda: MatrixSet(2.4, -1, S.Reals)) + raises(TypeError, lambda: MatrixSet(2, 2, (1, 2, 3))) + + +def test_matrixsymbol_solving(): + A = MatrixSymbol('A', 2, 2) + B = MatrixSymbol('B', 2, 2) + Z = ZeroMatrix(2, 2) + assert -(-A + B) - A + B == Z + assert (-(-A + B) - A + B).simplify() == Z + assert (-(-A + B) - A + B).expand() == Z + assert (-(-A + B) - A + B - Z).simplify() == Z + assert (-(-A + B) - A + B - Z).expand() == Z + assert (A*(A + B) + B*(A.T + B.T)).expand() == A**2 + A*B + B*A.T + B*B.T diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_matmul.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_matmul.py new file mode 100644 index 0000000000000000000000000000000000000000..813926e2c83e27716f4f894ebebd09b2a576f046 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_matmul.py @@ -0,0 +1,193 @@ +from sympy.core import I, symbols, Basic, Mul, S +from sympy.core.mul import mul +from sympy.functions import adjoint, transpose +from sympy.matrices.exceptions import ShapeError +from sympy.matrices import (Identity, Inverse, Matrix, MatrixSymbol, ZeroMatrix, + eye, ImmutableMatrix) +from sympy.matrices.expressions import Adjoint, Transpose, det, MatPow +from sympy.matrices.expressions.special import GenericIdentity +from sympy.matrices.expressions.matmul import (factor_in_front, remove_ids, + MatMul, combine_powers, any_zeros, unpack, only_squares) +from sympy.strategies import null_safe +from sympy.assumptions.ask import Q +from sympy.assumptions.refine import refine +from sympy.core.symbol import Symbol + +from sympy.testing.pytest import XFAIL, raises + +n, m, l, k = symbols('n m l k', integer=True) +x = symbols('x') +A = MatrixSymbol('A', n, m) +B = MatrixSymbol('B', m, l) +C = MatrixSymbol('C', n, n) +D = MatrixSymbol('D', n, n) +E = MatrixSymbol('E', m, n) + +def test_evaluate(): + assert MatMul(C, C, evaluate=True) == MatMul(C, C).doit() + +def test_adjoint(): + assert adjoint(A*B) == Adjoint(B)*Adjoint(A) + assert adjoint(2*A*B) == 2*Adjoint(B)*Adjoint(A) + assert adjoint(2*I*C) == -2*I*Adjoint(C) + + M = Matrix(2, 2, [1, 2 + I, 3, 4]) + MA = Matrix(2, 2, [1, 3, 2 - I, 4]) + assert adjoint(M) == MA + assert adjoint(2*M) == 2*MA + assert adjoint(MatMul(2, M)) == MatMul(2, MA).doit() + + +def test_transpose(): + assert transpose(A*B) == Transpose(B)*Transpose(A) + assert transpose(2*A*B) == 2*Transpose(B)*Transpose(A) + assert transpose(2*I*C) == 2*I*Transpose(C) + + M = Matrix(2, 2, [1, 2 + I, 3, 4]) + MT = Matrix(2, 2, [1, 3, 2 + I, 4]) + assert transpose(M) == MT + assert transpose(2*M) == 2*MT + assert transpose(x*M) == x*MT + assert transpose(MatMul(2, M)) == MatMul(2, MT).doit() + + +def test_factor_in_front(): + assert factor_in_front(MatMul(A, 2, B, evaluate=False)) ==\ + MatMul(2, A, B, evaluate=False) + + +def test_remove_ids(): + assert remove_ids(MatMul(A, Identity(m), B, evaluate=False)) == \ + MatMul(A, B, evaluate=False) + assert null_safe(remove_ids)(MatMul(Identity(n), evaluate=False)) == \ + MatMul(Identity(n), evaluate=False) + + +def test_combine_powers(): + assert combine_powers(MatMul(D, Inverse(D), D, evaluate=False)) == \ + MatMul(Identity(n), D, evaluate=False) + assert combine_powers(MatMul(B.T, Inverse(E*A), E, A, B, evaluate=False)) == \ + MatMul(B.T, Identity(m), B, evaluate=False) + assert combine_powers(MatMul(A, E, Inverse(A*E), D, evaluate=False)) == \ + MatMul(Identity(n), D, evaluate=False) + + +def test_any_zeros(): + assert any_zeros(MatMul(A, ZeroMatrix(m, k), evaluate=False)) == \ + ZeroMatrix(n, k) + + +def test_unpack(): + assert unpack(MatMul(A, evaluate=False)) == A + x = MatMul(A, B) + assert unpack(x) == x + + +def test_only_squares(): + assert only_squares(C) == [C] + assert only_squares(C, D) == [C, D] + assert only_squares(C, A, A.T, D) == [C, A*A.T, D] + + +def test_determinant(): + assert det(2*C) == 2**n*det(C) + assert det(2*C*D) == 2**n*det(C)*det(D) + assert det(3*C*A*A.T*D) == 3**n*det(C)*det(A*A.T)*det(D) + + +def test_doit(): + assert MatMul(C, 2, D).args == (C, 2, D) + assert MatMul(C, 2, D).doit().args == (2, C, D) + assert MatMul(C, Transpose(D*C)).args == (C, Transpose(D*C)) + assert MatMul(C, Transpose(D*C)).doit(deep=True).args == (C, C.T, D.T) + + +def test_doit_drills_down(): + X = ImmutableMatrix([[1, 2], [3, 4]]) + Y = ImmutableMatrix([[2, 3], [4, 5]]) + assert MatMul(X, MatPow(Y, 2)).doit() == X*Y**2 + assert MatMul(C, Transpose(D*C)).doit().args == (C, C.T, D.T) + + +def test_doit_deep_false_still_canonical(): + assert (MatMul(C, Transpose(D*C), 2).doit(deep=False).args == + (2, C, Transpose(D*C))) + + +def test_matmul_scalar_Matrix_doit(): + # Issue 9053 + X = Matrix([[1, 2], [3, 4]]) + assert MatMul(2, X).doit() == 2*X + + +def test_matmul_sympify(): + assert isinstance(MatMul(eye(1), eye(1)).args[0], Basic) + + +def test_collapse_MatrixBase(): + A = Matrix([[1, 1], [1, 1]]) + B = Matrix([[1, 2], [3, 4]]) + assert MatMul(A, B).doit() == ImmutableMatrix([[4, 6], [4, 6]]) + + +def test_refine(): + assert refine(C*C.T*D, Q.orthogonal(C)).doit() == D + + kC = k*C + assert refine(kC*C.T, Q.orthogonal(C)).doit() == k*Identity(n) + assert refine(kC* kC.T, Q.orthogonal(C)).doit() == (k**2)*Identity(n) + +def test_matmul_no_matrices(): + assert MatMul(1) == 1 + assert MatMul(n, m) == n*m + assert not isinstance(MatMul(n, m), MatMul) + +def test_matmul_args_cnc(): + assert MatMul(n, A, A.T).args_cnc() == [[n], [A, A.T]] + assert MatMul(A, A.T).args_cnc() == [[], [A, A.T]] + +@XFAIL +def test_matmul_args_cnc_symbols(): + # Not currently supported + a, b = symbols('a b', commutative=False) + assert MatMul(n, a, b, A, A.T).args_cnc() == [[n], [a, b, A, A.T]] + assert MatMul(n, a, A, b, A.T).args_cnc() == [[n], [a, A, b, A.T]] + +def test_issue_12950(): + M = Matrix([[Symbol("x")]]) * MatrixSymbol("A", 1, 1) + assert MatrixSymbol("A", 1, 1).as_explicit()[0]*Symbol('x') == M.as_explicit()[0] + +def test_construction_with_Mul(): + assert Mul(C, D) == MatMul(C, D) + assert Mul(D, C) == MatMul(D, C) + +def test_construction_with_mul(): + assert mul(C, D) == MatMul(C, D) + assert mul(D, C) == MatMul(D, C) + assert mul(C, D) != MatMul(D, C) + +def test_generic_identity(): + assert MatMul.identity == GenericIdentity() + assert MatMul.identity != S.One + + +def test_issue_23519(): + N = Symbol("N", integer=True) + M1 = MatrixSymbol("M1", N, N) + M2 = MatrixSymbol("M2", N, N) + I = Identity(N) + z = (M2 + 2 * (M2 + I) * M1 + I) + assert z.coeff(M1) == 2*I + 2*M2 + + +def test_shape_error(): + A = MatrixSymbol('A', 2, 2) + B = MatrixSymbol('B', 3, 3) + raises(ShapeError, lambda: MatMul(A, B)) + + +def test_matmul_transpose(): + # https://github.com/sympy/sympy/issues/9503 + M = Matrix(2, 2, [1, 2 + I, 3, 4]) + a = Symbol('a') + assert (MatMul(a, M).T).expand() == (a*Matrix([[1, 3],[2 + I, 4]])).expand() diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_matpow.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_matpow.py new file mode 100644 index 0000000000000000000000000000000000000000..2afb5fdc2aa652c321de52aba43db63da60941fd --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_matpow.py @@ -0,0 +1,217 @@ +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.simplify.powsimp import powsimp +from sympy.testing.pytest import raises +from sympy.core.expr import unchanged +from sympy.core import symbols, S +from sympy.matrices import Identity, MatrixSymbol, ImmutableMatrix, ZeroMatrix, OneMatrix, Matrix +from sympy.matrices.exceptions import NonSquareMatrixError +from sympy.matrices.expressions import MatPow, MatAdd, MatMul +from sympy.matrices.expressions.inverse import Inverse +from sympy.matrices.expressions.matexpr import MatrixElement + +n, m, l, k = symbols('n m l k', integer=True) +A = MatrixSymbol('A', n, m) +B = MatrixSymbol('B', m, l) +C = MatrixSymbol('C', n, n) +D = MatrixSymbol('D', n, n) +E = MatrixSymbol('E', m, n) + + +def test_entry_matrix(): + X = ImmutableMatrix([[1, 2], [3, 4]]) + assert MatPow(X, 0)[0, 0] == 1 + assert MatPow(X, 0)[0, 1] == 0 + assert MatPow(X, 1)[0, 0] == 1 + assert MatPow(X, 1)[0, 1] == 2 + assert MatPow(X, 2)[0, 0] == 7 + + +def test_entry_symbol(): + from sympy.concrete import Sum + assert MatPow(C, 0)[0, 0] == 1 + assert MatPow(C, 0)[0, 1] == 0 + assert MatPow(C, 1)[0, 0] == C[0, 0] + assert isinstance(MatPow(C, 2)[0, 0], Sum) + assert isinstance(MatPow(C, n)[0, 0], MatrixElement) + + +def test_as_explicit_symbol(): + X = MatrixSymbol('X', 2, 2) + assert MatPow(X, 0).as_explicit() == ImmutableMatrix(Identity(2)) + assert MatPow(X, 1).as_explicit() == X.as_explicit() + assert MatPow(X, 2).as_explicit() == (X.as_explicit())**2 + assert MatPow(X, n).as_explicit() == ImmutableMatrix([ + [(X ** n)[0, 0], (X ** n)[0, 1]], + [(X ** n)[1, 0], (X ** n)[1, 1]], + ]) + + a = MatrixSymbol("a", 3, 1) + b = MatrixSymbol("b", 3, 1) + c = MatrixSymbol("c", 3, 1) + + expr = (a.T*b)**S.Half + assert expr.as_explicit() == Matrix([[sqrt(a[0, 0]*b[0, 0] + a[1, 0]*b[1, 0] + a[2, 0]*b[2, 0])]]) + + expr = c*(a.T*b)**S.Half + m = sqrt(a[0, 0]*b[0, 0] + a[1, 0]*b[1, 0] + a[2, 0]*b[2, 0]) + assert expr.as_explicit() == Matrix([[c[0, 0]*m], [c[1, 0]*m], [c[2, 0]*m]]) + + expr = (a*b.T)**S.Half + denom = sqrt(a[0, 0]*b[0, 0] + a[1, 0]*b[1, 0] + a[2, 0]*b[2, 0]) + expected = (a*b.T).as_explicit()/denom + assert expr.as_explicit() == expected + + expr = X**-1 + det = X[0, 0]*X[1, 1] - X[1, 0]*X[0, 1] + expected = Matrix([[X[1, 1], -X[0, 1]], [-X[1, 0], X[0, 0]]])/det + assert expr.as_explicit() == expected + + expr = X**m + assert expr.as_explicit() == X.as_explicit()**m + + +def test_as_explicit_matrix(): + A = ImmutableMatrix([[1, 2], [3, 4]]) + assert MatPow(A, 0).as_explicit() == ImmutableMatrix(Identity(2)) + assert MatPow(A, 1).as_explicit() == A + assert MatPow(A, 2).as_explicit() == A**2 + assert MatPow(A, -1).as_explicit() == A.inv() + assert MatPow(A, -2).as_explicit() == (A.inv())**2 + # less expensive than testing on a 2x2 + A = ImmutableMatrix([4]) + assert MatPow(A, S.Half).as_explicit() == A**S.Half + + +def test_doit_symbol(): + assert MatPow(C, 0).doit() == Identity(n) + assert MatPow(C, 1).doit() == C + assert MatPow(C, -1).doit() == C.I + for r in [2, S.Half, S.Pi, n]: + assert MatPow(C, r).doit() == MatPow(C, r) + + +def test_doit_matrix(): + X = ImmutableMatrix([[1, 2], [3, 4]]) + assert MatPow(X, 0).doit() == ImmutableMatrix(Identity(2)) + assert MatPow(X, 1).doit() == X + assert MatPow(X, 2).doit() == X**2 + assert MatPow(X, -1).doit() == X.inv() + assert MatPow(X, -2).doit() == (X.inv())**2 + # less expensive than testing on a 2x2 + assert MatPow(ImmutableMatrix([4]), S.Half).doit() == ImmutableMatrix([2]) + X = ImmutableMatrix([[0, 2], [0, 4]]) # det() == 0 + raises(ValueError, lambda: MatPow(X,-1).doit()) + raises(ValueError, lambda: MatPow(X,-2).doit()) + + +def test_nonsquare(): + A = MatrixSymbol('A', 2, 3) + B = ImmutableMatrix([[1, 2, 3], [4, 5, 6]]) + for r in [-1, 0, 1, 2, S.Half, S.Pi, n]: + raises(NonSquareMatrixError, lambda: MatPow(A, r)) + raises(NonSquareMatrixError, lambda: MatPow(B, r)) + + +def test_doit_equals_pow(): #17179 + X = ImmutableMatrix ([[1,0],[0,1]]) + assert MatPow(X, n).doit() == X**n == X + + +def test_doit_nested_MatrixExpr(): + X = ImmutableMatrix([[1, 2], [3, 4]]) + Y = ImmutableMatrix([[2, 3], [4, 5]]) + assert MatPow(MatMul(X, Y), 2).doit() == (X*Y)**2 + assert MatPow(MatAdd(X, Y), 2).doit() == (X + Y)**2 + + +def test_identity_power(): + k = Identity(n) + assert MatPow(k, 4).doit() == k + assert MatPow(k, n).doit() == k + assert MatPow(k, -3).doit() == k + assert MatPow(k, 0).doit() == k + l = Identity(3) + assert MatPow(l, n).doit() == l + assert MatPow(l, -1).doit() == l + assert MatPow(l, 0).doit() == l + + +def test_zero_power(): + z1 = ZeroMatrix(n, n) + assert MatPow(z1, 3).doit() == z1 + raises(ValueError, lambda:MatPow(z1, -1).doit()) + assert MatPow(z1, 0).doit() == Identity(n) + assert MatPow(z1, n).doit() == z1 + raises(ValueError, lambda:MatPow(z1, -2).doit()) + z2 = ZeroMatrix(4, 4) + assert MatPow(z2, n).doit() == z2 + raises(ValueError, lambda:MatPow(z2, -3).doit()) + assert MatPow(z2, 2).doit() == z2 + assert MatPow(z2, 0).doit() == Identity(4) + raises(ValueError, lambda:MatPow(z2, -1).doit()) + + +def test_OneMatrix_power(): + o = OneMatrix(3, 3) + assert o ** 0 == Identity(3) + assert o ** 1 == o + assert o * o == o ** 2 == 3 * o + assert o * o * o == o ** 3 == 9 * o + + o = OneMatrix(n, n) + assert o * o == o ** 2 == n * o + # powsimp necessary as n ** (n - 2) * n does not produce n ** (n - 1) + assert powsimp(o ** (n - 1) * o) == o ** n == n ** (n - 1) * o + + +def test_transpose_power(): + from sympy.matrices.expressions.transpose import Transpose as TP + + assert (C*D).T**5 == ((C*D)**5).T == (D.T * C.T)**5 + assert ((C*D).T**5).T == (C*D)**5 + + assert (C.T.I.T)**7 == C**-7 + assert (C.T**l).T**k == C**(l*k) + + assert ((E.T * A.T)**5).T == (A*E)**5 + assert ((A*E).T**5).T**7 == (A*E)**35 + assert TP(TP(C**2 * D**3)**5).doit() == (C**2 * D**3)**5 + + assert ((D*C)**-5).T**-5 == ((D*C)**25).T + assert (((D*C)**l).T**k).T == (D*C)**(l*k) + + +def test_Inverse(): + assert Inverse(MatPow(C, 0)).doit() == Identity(n) + assert Inverse(MatPow(C, 1)).doit() == Inverse(C) + assert Inverse(MatPow(C, 2)).doit() == MatPow(C, -2) + assert Inverse(MatPow(C, -1)).doit() == C + + assert MatPow(Inverse(C), 0).doit() == Identity(n) + assert MatPow(Inverse(C), 1).doit() == Inverse(C) + assert MatPow(Inverse(C), 2).doit() == MatPow(C, -2) + assert MatPow(Inverse(C), -1).doit() == C + + +def test_combine_powers(): + assert (C ** 1) ** 1 == C + assert (C ** 2) ** 3 == MatPow(C, 6) + assert (C ** -2) ** -3 == MatPow(C, 6) + assert (C ** -1) ** -1 == C + assert (((C ** 2) ** 3) ** 4) ** 5 == MatPow(C, 120) + assert (C ** n) ** n == C ** (n ** 2) + + +def test_unchanged(): + assert unchanged(MatPow, C, 0) + assert unchanged(MatPow, C, 1) + assert unchanged(MatPow, Inverse(C), -1) + assert unchanged(Inverse, MatPow(C, -1), -1) + assert unchanged(MatPow, MatPow(C, -1), -1) + assert unchanged(MatPow, MatPow(C, 1), 1) + + +def test_no_exponentiation(): + # if this passes, Pow.as_numer_denom should recognize + # MatAdd as exponent + raises(NotImplementedError, lambda: 3**(-2*C)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_permutation.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_permutation.py new file mode 100644 index 0000000000000000000000000000000000000000..41a924f6636afb2e5b6560987e38a0fa0c861f1e --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_permutation.py @@ -0,0 +1,166 @@ +from sympy.combinatorics import Permutation +from sympy.core.expr import unchanged +from sympy.matrices import Matrix +from sympy.matrices.expressions import \ + MatMul, BlockDiagMatrix, Determinant, Inverse +from sympy.matrices.expressions.matexpr import MatrixSymbol +from sympy.matrices.expressions.special import ZeroMatrix, OneMatrix, Identity +from sympy.matrices.expressions.permutation import \ + MatrixPermute, PermutationMatrix +from sympy.testing.pytest import raises +from sympy.core.symbol import Symbol + + +def test_PermutationMatrix_basic(): + p = Permutation([1, 0]) + assert unchanged(PermutationMatrix, p) + raises(ValueError, lambda: PermutationMatrix((0, 1, 2))) + assert PermutationMatrix(p).as_explicit() == Matrix([[0, 1], [1, 0]]) + assert isinstance(PermutationMatrix(p)*MatrixSymbol('A', 2, 2), MatMul) + + +def test_PermutationMatrix_matmul(): + p = Permutation([1, 2, 0]) + P = PermutationMatrix(p) + M = Matrix([[0, 1, 2], [3, 4, 5], [6, 7, 8]]) + assert (P*M).as_explicit() == P.as_explicit()*M + assert (M*P).as_explicit() == M*P.as_explicit() + + P1 = PermutationMatrix(Permutation([1, 2, 0])) + P2 = PermutationMatrix(Permutation([2, 1, 0])) + P3 = PermutationMatrix(Permutation([1, 0, 2])) + assert P1*P2 == P3 + + +def test_PermutationMatrix_matpow(): + p1 = Permutation([1, 2, 0]) + P1 = PermutationMatrix(p1) + p2 = Permutation([2, 0, 1]) + P2 = PermutationMatrix(p2) + assert P1**2 == P2 + assert P1**3 == Identity(3) + + +def test_PermutationMatrix_identity(): + p = Permutation([0, 1]) + assert PermutationMatrix(p).is_Identity + + p = Permutation([1, 0]) + assert not PermutationMatrix(p).is_Identity + + +def test_PermutationMatrix_determinant(): + P = PermutationMatrix(Permutation([0, 1, 2])) + assert Determinant(P).doit() == 1 + P = PermutationMatrix(Permutation([0, 2, 1])) + assert Determinant(P).doit() == -1 + P = PermutationMatrix(Permutation([2, 0, 1])) + assert Determinant(P).doit() == 1 + + +def test_PermutationMatrix_inverse(): + P = PermutationMatrix(Permutation(0, 1, 2)) + assert Inverse(P).doit() == PermutationMatrix(Permutation(0, 2, 1)) + + +def test_PermutationMatrix_rewrite_BlockDiagMatrix(): + P = PermutationMatrix(Permutation([0, 1, 2, 3, 4, 5])) + P0 = PermutationMatrix(Permutation([0])) + assert P.rewrite(BlockDiagMatrix) == \ + BlockDiagMatrix(P0, P0, P0, P0, P0, P0) + + P = PermutationMatrix(Permutation([0, 1, 3, 2, 4, 5])) + P10 = PermutationMatrix(Permutation(0, 1)) + assert P.rewrite(BlockDiagMatrix) == \ + BlockDiagMatrix(P0, P0, P10, P0, P0) + + P = PermutationMatrix(Permutation([1, 0, 3, 2, 5, 4])) + assert P.rewrite(BlockDiagMatrix) == \ + BlockDiagMatrix(P10, P10, P10) + + P = PermutationMatrix(Permutation([0, 4, 3, 2, 1, 5])) + P3210 = PermutationMatrix(Permutation([3, 2, 1, 0])) + assert P.rewrite(BlockDiagMatrix) == \ + BlockDiagMatrix(P0, P3210, P0) + + P = PermutationMatrix(Permutation([0, 4, 2, 3, 1, 5])) + P3120 = PermutationMatrix(Permutation([3, 1, 2, 0])) + assert P.rewrite(BlockDiagMatrix) == \ + BlockDiagMatrix(P0, P3120, P0) + + P = PermutationMatrix(Permutation(0, 3)(1, 4)(2, 5)) + assert P.rewrite(BlockDiagMatrix) == BlockDiagMatrix(P) + + +def test_MartrixPermute_basic(): + p = Permutation(0, 1) + P = PermutationMatrix(p) + A = MatrixSymbol('A', 2, 2) + + raises(ValueError, lambda: MatrixPermute(Symbol('x'), p)) + raises(ValueError, lambda: MatrixPermute(A, Symbol('x'))) + + assert MatrixPermute(A, P) == MatrixPermute(A, p) + raises(ValueError, lambda: MatrixPermute(A, p, 2)) + + pp = Permutation(0, 1, size=3) + assert MatrixPermute(A, pp) == MatrixPermute(A, p) + pp = Permutation(0, 1, 2) + raises(ValueError, lambda: MatrixPermute(A, pp)) + + +def test_MatrixPermute_shape(): + p = Permutation(0, 1) + A = MatrixSymbol('A', 2, 3) + assert MatrixPermute(A, p).shape == (2, 3) + + +def test_MatrixPermute_explicit(): + p = Permutation(0, 1, 2) + A = MatrixSymbol('A', 3, 3) + AA = A.as_explicit() + assert MatrixPermute(A, p, 0).as_explicit() == \ + AA.permute(p, orientation='rows') + assert MatrixPermute(A, p, 1).as_explicit() == \ + AA.permute(p, orientation='cols') + + +def test_MatrixPermute_rewrite_MatMul(): + p = Permutation(0, 1, 2) + A = MatrixSymbol('A', 3, 3) + + assert MatrixPermute(A, p, 0).rewrite(MatMul).as_explicit() == \ + MatrixPermute(A, p, 0).as_explicit() + assert MatrixPermute(A, p, 1).rewrite(MatMul).as_explicit() == \ + MatrixPermute(A, p, 1).as_explicit() + + +def test_MatrixPermute_doit(): + p = Permutation(0, 1, 2) + A = MatrixSymbol('A', 3, 3) + assert MatrixPermute(A, p).doit() == MatrixPermute(A, p) + + p = Permutation(0, size=3) + A = MatrixSymbol('A', 3, 3) + assert MatrixPermute(A, p).doit().as_explicit() == \ + MatrixPermute(A, p).as_explicit() + + p = Permutation(0, 1, 2) + A = Identity(3) + assert MatrixPermute(A, p, 0).doit().as_explicit() == \ + MatrixPermute(A, p, 0).as_explicit() + assert MatrixPermute(A, p, 1).doit().as_explicit() == \ + MatrixPermute(A, p, 1).as_explicit() + + A = ZeroMatrix(3, 3) + assert MatrixPermute(A, p).doit() == A + A = OneMatrix(3, 3) + assert MatrixPermute(A, p).doit() == A + + A = MatrixSymbol('A', 4, 4) + p1 = Permutation(0, 1, 2, 3) + p2 = Permutation(0, 2, 3, 1) + expr = MatrixPermute(MatrixPermute(A, p1, 0), p2, 0) + assert expr.as_explicit() == expr.doit().as_explicit() + expr = MatrixPermute(MatrixPermute(A, p1, 1), p2, 1) + assert expr.as_explicit() == expr.doit().as_explicit() diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_sets.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_sets.py new file mode 100644 index 0000000000000000000000000000000000000000..e811c7968c5a22d65f1c99e995aaa7e5e59d15c4 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_sets.py @@ -0,0 +1,42 @@ +from sympy.core.singleton import S +from sympy.core.symbol import symbols +from sympy.matrices import Matrix +from sympy.matrices.expressions.matexpr import MatrixSymbol +from sympy.matrices.expressions.sets import MatrixSet +from sympy.matrices.expressions.special import ZeroMatrix +from sympy.testing.pytest import raises +from sympy.sets.sets import SetKind +from sympy.matrices.kind import MatrixKind +from sympy.core.kind import NumberKind + + +def test_MatrixSet(): + n, m = symbols('n m', integer=True) + A = MatrixSymbol('A', n, m) + C = MatrixSymbol('C', n, n) + + M = MatrixSet(2, 2, set=S.Reals) + assert M.shape == (2, 2) + assert M.set == S.Reals + X = Matrix([[1, 2], [3, 4]]) + assert X in M + X = ZeroMatrix(2, 2) + assert X in M + raises(TypeError, lambda: A in M) + raises(TypeError, lambda: 1 in M) + M = MatrixSet(n, m, set=S.Reals) + assert A in M + raises(TypeError, lambda: C in M) + raises(TypeError, lambda: X in M) + M = MatrixSet(2, 2, set={1, 2, 3}) + X = Matrix([[1, 2], [3, 4]]) + Y = Matrix([[1, 2]]) + assert (X in M) == S.false + assert (Y in M) == S.false + raises(ValueError, lambda: MatrixSet(2, -2, S.Reals)) + raises(ValueError, lambda: MatrixSet(2.4, -1, S.Reals)) + raises(TypeError, lambda: MatrixSet(2, 2, (1, 2, 3))) + + +def test_SetKind_MatrixSet(): + assert MatrixSet(2, 2, set=S.Reals).kind is SetKind(MatrixKind(NumberKind)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_slice.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_slice.py new file mode 100644 index 0000000000000000000000000000000000000000..36490719e26908b9e913ed99b7673d602647c492 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_slice.py @@ -0,0 +1,65 @@ +from sympy.matrices.expressions.slice import MatrixSlice +from sympy.matrices.expressions import MatrixSymbol +from sympy.abc import a, b, c, d, k, l, m, n +from sympy.testing.pytest import raises, XFAIL +from sympy.functions.elementary.integers import floor +from sympy.assumptions import assuming, Q + + +X = MatrixSymbol('X', n, m) +Y = MatrixSymbol('Y', m, k) + +def test_shape(): + B = MatrixSlice(X, (a, b), (c, d)) + assert B.shape == (b - a, d - c) + +def test_entry(): + B = MatrixSlice(X, (a, b), (c, d)) + assert B[0,0] == X[a, c] + assert B[k,l] == X[a+k, c+l] + raises(IndexError, lambda : MatrixSlice(X, 1, (2, 5))[1, 0]) + + assert X[1::2, :][1, 3] == X[1+2, 3] + assert X[:, 1::2][3, 1] == X[3, 1+2] + +def test_on_diag(): + assert not MatrixSlice(X, (a, b), (c, d)).on_diag + assert MatrixSlice(X, (a, b), (a, b)).on_diag + +def test_inputs(): + assert MatrixSlice(X, 1, (2, 5)) == MatrixSlice(X, (1, 2), (2, 5)) + assert MatrixSlice(X, 1, (2, 5)).shape == (1, 3) + +def test_slicing(): + assert X[1:5, 2:4] == MatrixSlice(X, (1, 5), (2, 4)) + assert X[1, 2:4] == MatrixSlice(X, 1, (2, 4)) + assert X[1:5, :].shape == (4, X.shape[1]) + assert X[:, 1:5].shape == (X.shape[0], 4) + + assert X[::2, ::2].shape == (floor(n/2), floor(m/2)) + assert X[2, :] == MatrixSlice(X, 2, (0, m)) + assert X[k, :] == MatrixSlice(X, k, (0, m)) + +def test_exceptions(): + X = MatrixSymbol('x', 10, 20) + raises(IndexError, lambda: X[0:12, 2]) + raises(IndexError, lambda: X[0:9, 22]) + raises(IndexError, lambda: X[-1:5, 2]) + +@XFAIL +def test_symmetry(): + X = MatrixSymbol('x', 10, 10) + Y = X[:5, 5:] + with assuming(Q.symmetric(X)): + assert Y.T == X[5:, :5] + +def test_slice_of_slice(): + X = MatrixSymbol('x', 10, 10) + assert X[2, :][:, 3][0, 0] == X[2, 3] + assert X[:5, :5][:4, :4] == X[:4, :4] + assert X[1:5, 2:6][1:3, 2] == X[2:4, 4] + assert X[1:9:2, 2:6][1:3, 2] == X[3:7:2, 4] + +def test_negative_index(): + X = MatrixSymbol('x', 10, 10) + assert X[-1, :] == X[9, :] diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_special.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_special.py new file mode 100644 index 0000000000000000000000000000000000000000..beeaf1d76a63673b6622709cda598dfcb295bba4 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_special.py @@ -0,0 +1,228 @@ +from sympy.core.add import Add +from sympy.core.expr import unchanged +from sympy.core.mul import Mul +from sympy.core.symbol import symbols +from sympy.core.relational import Eq +from sympy.concrete.summations import Sum +from sympy.functions.elementary.complexes import im, re +from sympy.functions.elementary.piecewise import Piecewise +from sympy.matrices.immutable import ImmutableDenseMatrix +from sympy.matrices.expressions.matexpr import MatrixSymbol +from sympy.matrices.expressions.matadd import MatAdd +from sympy.matrices.expressions.special import ( + ZeroMatrix, GenericZeroMatrix, Identity, GenericIdentity, OneMatrix) +from sympy.matrices.expressions.matmul import MatMul +from sympy.testing.pytest import raises + + +def test_zero_matrix_creation(): + assert unchanged(ZeroMatrix, 2, 2) + assert unchanged(ZeroMatrix, 0, 0) + raises(ValueError, lambda: ZeroMatrix(-1, 2)) + raises(ValueError, lambda: ZeroMatrix(2.0, 2)) + raises(ValueError, lambda: ZeroMatrix(2j, 2)) + raises(ValueError, lambda: ZeroMatrix(2, -1)) + raises(ValueError, lambda: ZeroMatrix(2, 2.0)) + raises(ValueError, lambda: ZeroMatrix(2, 2j)) + + n = symbols('n') + assert unchanged(ZeroMatrix, n, n) + n = symbols('n', integer=False) + raises(ValueError, lambda: ZeroMatrix(n, n)) + n = symbols('n', negative=True) + raises(ValueError, lambda: ZeroMatrix(n, n)) + + +def test_generic_zero_matrix(): + z = GenericZeroMatrix() + n = symbols('n', integer=True) + A = MatrixSymbol("A", n, n) + + assert z == z + assert z != A + assert A != z + + assert z.is_ZeroMatrix + + raises(TypeError, lambda: z.shape) + raises(TypeError, lambda: z.rows) + raises(TypeError, lambda: z.cols) + + assert MatAdd() == z + assert MatAdd(z, A) == MatAdd(A) + # Make sure it is hashable + hash(z) + + +def test_identity_matrix_creation(): + assert Identity(2) + assert Identity(0) + raises(ValueError, lambda: Identity(-1)) + raises(ValueError, lambda: Identity(2.0)) + raises(ValueError, lambda: Identity(2j)) + + n = symbols('n') + assert Identity(n) + n = symbols('n', integer=False) + raises(ValueError, lambda: Identity(n)) + n = symbols('n', negative=True) + raises(ValueError, lambda: Identity(n)) + + +def test_generic_identity(): + I = GenericIdentity() + n = symbols('n', integer=True) + A = MatrixSymbol("A", n, n) + + assert I == I + assert I != A + assert A != I + + assert I.is_Identity + assert I**-1 == I + + raises(TypeError, lambda: I.shape) + raises(TypeError, lambda: I.rows) + raises(TypeError, lambda: I.cols) + + assert MatMul() == I + assert MatMul(I, A) == MatMul(A) + # Make sure it is hashable + hash(I) + + +def test_one_matrix_creation(): + assert OneMatrix(2, 2) + assert OneMatrix(0, 0) + assert Eq(OneMatrix(1, 1), Identity(1)) + raises(ValueError, lambda: OneMatrix(-1, 2)) + raises(ValueError, lambda: OneMatrix(2.0, 2)) + raises(ValueError, lambda: OneMatrix(2j, 2)) + raises(ValueError, lambda: OneMatrix(2, -1)) + raises(ValueError, lambda: OneMatrix(2, 2.0)) + raises(ValueError, lambda: OneMatrix(2, 2j)) + + n = symbols('n') + assert OneMatrix(n, n) + n = symbols('n', integer=False) + raises(ValueError, lambda: OneMatrix(n, n)) + n = symbols('n', negative=True) + raises(ValueError, lambda: OneMatrix(n, n)) + + +def test_ZeroMatrix(): + n, m = symbols('n m', integer=True) + A = MatrixSymbol('A', n, m) + Z = ZeroMatrix(n, m) + + assert A + Z == A + assert A*Z.T == ZeroMatrix(n, n) + assert Z*A.T == ZeroMatrix(n, n) + assert A - A == ZeroMatrix(*A.shape) + + assert Z + + assert Z.transpose() == ZeroMatrix(m, n) + assert Z.conjugate() == Z + assert Z.adjoint() == ZeroMatrix(m, n) + assert re(Z) == Z + assert im(Z) == Z + + assert ZeroMatrix(n, n)**0 == Identity(n) + assert ZeroMatrix(3, 3).as_explicit() == ImmutableDenseMatrix.zeros(3, 3) + + +def test_ZeroMatrix_doit(): + n = symbols('n', integer=True) + Znn = ZeroMatrix(Add(n, n, evaluate=False), n) + assert isinstance(Znn.rows, Add) + assert Znn.doit() == ZeroMatrix(2*n, n) + assert isinstance(Znn.doit().rows, Mul) + + +def test_OneMatrix(): + n, m = symbols('n m', integer=True) + A = MatrixSymbol('A', n, m) + U = OneMatrix(n, m) + + assert U.shape == (n, m) + assert isinstance(A + U, Add) + assert U.transpose() == OneMatrix(m, n) + assert U.conjugate() == U + assert U.adjoint() == OneMatrix(m, n) + assert re(U) == U + assert im(U) == ZeroMatrix(n, m) + + assert OneMatrix(n, n) ** 0 == Identity(n) + + U = OneMatrix(n, n) + assert U[1, 2] == 1 + + U = OneMatrix(2, 3) + assert U.as_explicit() == ImmutableDenseMatrix.ones(2, 3) + + +def test_OneMatrix_doit(): + n = symbols('n', integer=True) + Unn = OneMatrix(Add(n, n, evaluate=False), n) + assert isinstance(Unn.rows, Add) + assert Unn.doit() == OneMatrix(2 * n, n) + assert isinstance(Unn.doit().rows, Mul) + + +def test_OneMatrix_mul(): + n, m, k = symbols('n m k', integer=True) + w = MatrixSymbol('w', n, 1) + assert OneMatrix(n, m) * OneMatrix(m, k) == OneMatrix(n, k) * m + assert w * OneMatrix(1, 1) == w + assert OneMatrix(1, 1) * w.T == w.T + + +def test_Identity(): + n, m = symbols('n m', integer=True) + A = MatrixSymbol('A', n, m) + i, j = symbols('i j') + + In = Identity(n) + Im = Identity(m) + + assert A*Im == A + assert In*A == A + + assert In.transpose() == In + assert In.inverse() == In + assert In.conjugate() == In + assert In.adjoint() == In + assert re(In) == In + assert im(In) == ZeroMatrix(n, n) + + assert In[i, j] != 0 + assert Sum(In[i, j], (i, 0, n-1), (j, 0, n-1)).subs(n,3).doit() == 3 + assert Sum(Sum(In[i, j], (i, 0, n-1)), (j, 0, n-1)).subs(n,3).doit() == 3 + + # If range exceeds the limit `(0, n-1)`, do not remove `Piecewise`: + expr = Sum(In[i, j], (i, 0, n-1)) + assert expr.doit() == 1 + expr = Sum(In[i, j], (i, 0, n-2)) + assert expr.doit().dummy_eq( + Piecewise( + (1, (j >= 0) & (j <= n-2)), + (0, True) + ) + ) + expr = Sum(In[i, j], (i, 1, n-1)) + assert expr.doit().dummy_eq( + Piecewise( + (1, (j >= 1) & (j <= n-1)), + (0, True) + ) + ) + assert Identity(3).as_explicit() == ImmutableDenseMatrix.eye(3) + + +def test_Identity_doit(): + n = symbols('n', integer=True) + Inn = Identity(Add(n, n, evaluate=False)) + assert isinstance(Inn.rows, Add) + assert Inn.doit() == Identity(2*n) + assert isinstance(Inn.doit().rows, Mul) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_trace.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_trace.py new file mode 100644 index 0000000000000000000000000000000000000000..3bd66bec2377dae634ff486f42cc474eda7b23b1 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_trace.py @@ -0,0 +1,116 @@ +from sympy.core import Lambda, S, symbols +from sympy.concrete import Sum +from sympy.functions import adjoint, conjugate, transpose +from sympy.matrices import eye, Matrix, ShapeError, ImmutableMatrix +from sympy.matrices.expressions import ( + Adjoint, Identity, FunctionMatrix, MatrixExpr, MatrixSymbol, Trace, + ZeroMatrix, trace, MatPow, MatAdd, MatMul +) +from sympy.matrices.expressions.special import OneMatrix +from sympy.testing.pytest import raises +from sympy.abc import i + + +n = symbols('n', integer=True) +A = MatrixSymbol('A', n, n) +B = MatrixSymbol('B', n, n) +C = MatrixSymbol('C', 3, 4) + + +def test_Trace(): + assert isinstance(Trace(A), Trace) + assert not isinstance(Trace(A), MatrixExpr) + raises(ShapeError, lambda: Trace(C)) + assert trace(eye(3)) == 3 + assert trace(Matrix(3, 3, [1, 2, 3, 4, 5, 6, 7, 8, 9])) == 15 + + assert adjoint(Trace(A)) == trace(Adjoint(A)) + assert conjugate(Trace(A)) == trace(Adjoint(A)) + assert transpose(Trace(A)) == Trace(A) + + _ = A / Trace(A) # Make sure this is possible + + # Some easy simplifications + assert trace(Identity(5)) == 5 + assert trace(ZeroMatrix(5, 5)) == 0 + assert trace(OneMatrix(1, 1)) == 1 + assert trace(OneMatrix(2, 2)) == 2 + assert trace(OneMatrix(n, n)) == n + assert trace(2*A*B) == 2*Trace(A*B) + assert trace(A.T) == trace(A) + + i, j = symbols('i j') + F = FunctionMatrix(3, 3, Lambda((i, j), i + j)) + assert trace(F) == (0 + 0) + (1 + 1) + (2 + 2) + + raises(TypeError, lambda: Trace(S.One)) + + assert Trace(A).arg is A + + assert str(trace(A)) == str(Trace(A).doit()) + + assert Trace(A).is_commutative is True + +def test_Trace_A_plus_B(): + assert trace(A + B) == Trace(A) + Trace(B) + assert Trace(A + B).arg == MatAdd(A, B) + assert Trace(A + B).doit() == Trace(A) + Trace(B) + + +def test_Trace_MatAdd_doit(): + # See issue #9028 + X = ImmutableMatrix([[1, 2, 3]]*3) + Y = MatrixSymbol('Y', 3, 3) + q = MatAdd(X, 2*X, Y, -3*Y) + assert Trace(q).arg == q + assert Trace(q).doit() == 18 - 2*Trace(Y) + + +def test_Trace_MatPow_doit(): + X = Matrix([[1, 2], [3, 4]]) + assert Trace(X).doit() == 5 + q = MatPow(X, 2) + assert Trace(q).arg == q + assert Trace(q).doit() == 29 + + +def test_Trace_MutableMatrix_plus(): + # See issue #9043 + X = Matrix([[1, 2], [3, 4]]) + assert Trace(X) + Trace(X) == 2*Trace(X) + + +def test_Trace_doit_deep_False(): + X = Matrix([[1, 2], [3, 4]]) + q = MatPow(X, 2) + assert Trace(q).doit(deep=False).arg == q + q = MatAdd(X, 2*X) + assert Trace(q).doit(deep=False).arg == q + q = MatMul(X, 2*X) + assert Trace(q).doit(deep=False).arg == q + + +def test_trace_constant_factor(): + # Issue 9052: gave 2*Trace(MatMul(A)) instead of 2*Trace(A) + assert trace(2*A) == 2*Trace(A) + X = ImmutableMatrix([[1, 2], [3, 4]]) + assert trace(MatMul(2, X)) == 10 + + +def test_trace_rewrite(): + assert trace(A).rewrite(Sum) == Sum(A[i, i], (i, 0, n - 1)) + assert trace(eye(3)).rewrite(Sum) == 3 + + +def test_trace_normalize(): + assert Trace(B*A) != Trace(A*B) + assert Trace(B*A)._normalize() == Trace(A*B) + assert Trace(B*A.T)._normalize() == Trace(A*B.T) + + +def test_trace_as_explicit(): + raises(ValueError, lambda: Trace(A).as_explicit()) + + X = MatrixSymbol("X", 3, 3) + assert Trace(X).as_explicit() == X[0, 0] + X[1, 1] + X[2, 2] + assert Trace(eye(3)).as_explicit() == 3 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_transpose.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_transpose.py new file mode 100644 index 0000000000000000000000000000000000000000..a1a6113873426d99bacf85484d3b66781f300af7 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/tests/test_transpose.py @@ -0,0 +1,69 @@ +from sympy.functions import adjoint, conjugate, transpose +from sympy.matrices.expressions import MatrixSymbol, Adjoint, trace, Transpose +from sympy.matrices import eye, Matrix +from sympy.assumptions.ask import Q +from sympy.assumptions.refine import refine +from sympy.core.singleton import S +from sympy.core.symbol import symbols + +n, m, l, k, p = symbols('n m l k p', integer=True) +A = MatrixSymbol('A', n, m) +B = MatrixSymbol('B', m, l) +C = MatrixSymbol('C', n, n) + + +def test_transpose(): + Sq = MatrixSymbol('Sq', n, n) + + assert transpose(A) == Transpose(A) + assert Transpose(A).shape == (m, n) + assert Transpose(A*B).shape == (l, n) + assert transpose(Transpose(A)) == A + assert isinstance(Transpose(Transpose(A)), Transpose) + + assert adjoint(Transpose(A)) == Adjoint(Transpose(A)) + assert conjugate(Transpose(A)) == Adjoint(A) + + assert Transpose(eye(3)).doit() == eye(3) + + assert Transpose(S(5)).doit() == S(5) + + assert Transpose(Matrix([[1, 2], [3, 4]])).doit() == Matrix([[1, 3], [2, 4]]) + + assert transpose(trace(Sq)) == trace(Sq) + assert trace(Transpose(Sq)) == trace(Sq) + + assert Transpose(Sq)[0, 1] == Sq[1, 0] + + assert Transpose(A*B).doit() == Transpose(B) * Transpose(A) + + +def test_transpose_MatAdd_MatMul(): + # Issue 16807 + from sympy.functions.elementary.trigonometric import cos + + x = symbols('x') + M = MatrixSymbol('M', 3, 3) + N = MatrixSymbol('N', 3, 3) + + assert (N + (cos(x) * M)).T == cos(x)*M.T + N.T + + +def test_refine(): + assert refine(C.T, Q.symmetric(C)) == C + + +def test_transpose1x1(): + m = MatrixSymbol('m', 1, 1) + assert m == refine(m.T) + assert m == refine(m.T.T) + +def test_issue_9817(): + from sympy.matrices.expressions import Identity + v = MatrixSymbol('v', 3, 1) + A = MatrixSymbol('A', 3, 3) + x = Matrix([i + 1 for i in range(3)]) + X = Identity(3) + quadratic = v.T * A * v + subbed = quadratic.xreplace({v:x, A:X}) + assert subbed.as_explicit() == Matrix([[14]]) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/trace.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/trace.py new file mode 100644 index 0000000000000000000000000000000000000000..b5f9f94ea7486dc21b47c2e2e783a93280b180e0 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/trace.py @@ -0,0 +1,167 @@ +from sympy.core.basic import Basic +from sympy.core.expr import Expr, ExprBuilder +from sympy.core.singleton import S +from sympy.core.sorting import default_sort_key +from sympy.core.symbol import uniquely_named_symbol +from sympy.core.sympify import sympify +from sympy.matrices.matrixbase import MatrixBase +from sympy.matrices.exceptions import NonSquareMatrixError + + +class Trace(Expr): + """Matrix Trace + + Represents the trace of a matrix expression. + + Examples + ======== + + >>> from sympy import MatrixSymbol, Trace, eye + >>> A = MatrixSymbol('A', 3, 3) + >>> Trace(A) + Trace(A) + >>> Trace(eye(3)) + Trace(Matrix([ + [1, 0, 0], + [0, 1, 0], + [0, 0, 1]])) + >>> Trace(eye(3)).simplify() + 3 + """ + is_Trace = True + is_commutative = True + + def __new__(cls, mat): + mat = sympify(mat) + + if not mat.is_Matrix: + raise TypeError("input to Trace, %s, is not a matrix" % str(mat)) + + if mat.is_square is False: + raise NonSquareMatrixError("Trace of a non-square matrix") + + return Basic.__new__(cls, mat) + + def _eval_transpose(self): + return self + + def _eval_derivative(self, v): + from sympy.concrete.summations import Sum + from .matexpr import MatrixElement + if isinstance(v, MatrixElement): + return self.rewrite(Sum).diff(v) + expr = self.doit() + if isinstance(expr, Trace): + # Avoid looping infinitely: + raise NotImplementedError + return expr._eval_derivative(v) + + def _eval_derivative_matrix_lines(self, x): + from sympy.tensor.array.expressions.array_expressions import ArrayTensorProduct, ArrayContraction + r = self.args[0]._eval_derivative_matrix_lines(x) + for lr in r: + if lr.higher == 1: + lr.higher = ExprBuilder( + ArrayContraction, + [ + ExprBuilder( + ArrayTensorProduct, + [ + lr._lines[0], + lr._lines[1], + ] + ), + (1, 3), + ], + validator=ArrayContraction._validate + ) + else: + # This is not a matrix line: + lr.higher = ExprBuilder( + ArrayContraction, + [ + ExprBuilder( + ArrayTensorProduct, + [ + lr._lines[0], + lr._lines[1], + lr.higher, + ] + ), + (1, 3), (0, 2) + ] + ) + lr._lines = [S.One, S.One] + lr._first_pointer_parent = lr._lines + lr._second_pointer_parent = lr._lines + lr._first_pointer_index = 0 + lr._second_pointer_index = 1 + return r + + @property + def arg(self): + return self.args[0] + + def doit(self, **hints): + if hints.get('deep', True): + arg = self.arg.doit(**hints) + result = arg._eval_trace() + if result is not None: + return result + else: + return Trace(arg) + else: + # _eval_trace would go too deep here + if isinstance(self.arg, MatrixBase): + return trace(self.arg) + else: + return Trace(self.arg) + + def as_explicit(self): + return Trace(self.arg.as_explicit()).doit() + + def _normalize(self): + # Normalization of trace of matrix products. Use transposition and + # cyclic properties of traces to make sure the arguments of the matrix + # product are sorted and the first argument is not a transposition. + from sympy.matrices.expressions.matmul import MatMul + from sympy.matrices.expressions.transpose import Transpose + trace_arg = self.arg + if isinstance(trace_arg, MatMul): + + def get_arg_key(x): + a = trace_arg.args[x] + if isinstance(a, Transpose): + a = a.arg + return default_sort_key(a) + + indmin = min(range(len(trace_arg.args)), key=get_arg_key) + if isinstance(trace_arg.args[indmin], Transpose): + trace_arg = Transpose(trace_arg).doit() + indmin = min(range(len(trace_arg.args)), key=lambda x: default_sort_key(trace_arg.args[x])) + trace_arg = MatMul.fromiter(trace_arg.args[indmin:] + trace_arg.args[:indmin]) + return Trace(trace_arg) + return self + + def _eval_rewrite_as_Sum(self, expr, **kwargs): + from sympy.concrete.summations import Sum + i = uniquely_named_symbol('i', [expr]) + s = Sum(self.arg[i, i], (i, 0, self.arg.rows - 1)) + return s.doit() + + +def trace(expr): + """Trace of a Matrix. Sum of the diagonal elements. + + Examples + ======== + + >>> from sympy import trace, Symbol, MatrixSymbol, eye + >>> n = Symbol('n') + >>> X = MatrixSymbol('X', n, n) # A square matrix + >>> trace(2*X) + 2*Trace(X) + >>> trace(eye(3)) + 3 + """ + return Trace(expr).doit() diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/transpose.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/transpose.py new file mode 100644 index 0000000000000000000000000000000000000000..b11f7fc21490aab219420610ca529d81d6995d40 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/expressions/transpose.py @@ -0,0 +1,103 @@ +from sympy.core.basic import Basic +from sympy.matrices.expressions.matexpr import MatrixExpr + + +class Transpose(MatrixExpr): + """ + The transpose of a matrix expression. + + This is a symbolic object that simply stores its argument without + evaluating it. To actually compute the transpose, use the ``transpose()`` + function, or the ``.T`` attribute of matrices. + + Examples + ======== + + >>> from sympy import MatrixSymbol, Transpose, transpose + >>> A = MatrixSymbol('A', 3, 5) + >>> B = MatrixSymbol('B', 5, 3) + >>> Transpose(A) + A.T + >>> A.T == transpose(A) == Transpose(A) + True + >>> Transpose(A*B) + (A*B).T + >>> transpose(A*B) + B.T*A.T + + """ + is_Transpose = True + + def doit(self, **hints): + arg = self.arg + if hints.get('deep', True) and isinstance(arg, Basic): + arg = arg.doit(**hints) + _eval_transpose = getattr(arg, '_eval_transpose', None) + if _eval_transpose is not None: + result = _eval_transpose() + return result if result is not None else Transpose(arg) + else: + return Transpose(arg) + + @property + def arg(self): + return self.args[0] + + @property + def shape(self): + return self.arg.shape[::-1] + + def _entry(self, i, j, expand=False, **kwargs): + return self.arg._entry(j, i, expand=expand, **kwargs) + + def _eval_adjoint(self): + return self.arg.conjugate() + + def _eval_conjugate(self): + return self.arg.adjoint() + + def _eval_transpose(self): + return self.arg + + def _eval_trace(self): + from .trace import Trace + return Trace(self.arg) # Trace(X.T) => Trace(X) + + def _eval_determinant(self): + from sympy.matrices.expressions.determinant import det + return det(self.arg) + + def _eval_derivative(self, x): + # x is a scalar: + return self.arg._eval_derivative(x) + + def _eval_derivative_matrix_lines(self, x): + lines = self.args[0]._eval_derivative_matrix_lines(x) + return [i.transpose() for i in lines] + + +def transpose(expr): + """Matrix transpose""" + return Transpose(expr).doit(deep=False) + + +from sympy.assumptions.ask import ask, Q +from sympy.assumptions.refine import handlers_dict + + +def refine_Transpose(expr, assumptions): + """ + >>> from sympy import MatrixSymbol, Q, assuming, refine + >>> X = MatrixSymbol('X', 2, 2) + >>> X.T + X.T + >>> with assuming(Q.symmetric(X)): + ... print(refine(X.T)) + X + """ + if ask(Q.symmetric(expr), assumptions): + return expr.arg + + return expr + +handlers_dict['Transpose'] = refine_Transpose diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5b48612fbf31cbb1345957471ca73e5e41a575bc Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_commonmatrix.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_commonmatrix.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0f03ac0fac310f380b2b62c3dfb000e2cc73d575 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_commonmatrix.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_decompositions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_decompositions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3c51c86deb95eff7e6d4afed59497d922d27579a Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_decompositions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_determinant.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_determinant.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..de58d10e9b5c755be317ede2d05872ffcfaeffa7 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_determinant.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_domains.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_domains.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..27aa83a1c255c3482a006b3066aeb81f488e5373 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_domains.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_eigen.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_eigen.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3e70a1dede1916a779a1cf68f619142da72eb182 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_eigen.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_graph.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_graph.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9fdde1d41b6979e4bcbb34736cb5df3bd14bdbe9 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_graph.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_immutable.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_immutable.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c7f85d6f5e41aa0386347c28b4592be91ccd3214 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_immutable.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_interactions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_interactions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bc7ea03e9539f441747c2b807c3c872867aa46d6 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_interactions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_normalforms.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_normalforms.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c10ae127a97f3b41ecd9a462526893aa80775190 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_normalforms.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_reductions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_reductions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cbcc03453684df64ef25ab8225b8d1710442cd25 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_reductions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_repmatrix.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_repmatrix.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..68313c802e482fd0446069d9061e12bbedb176a9 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_repmatrix.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_solvers.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_solvers.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..54f21c5068b7f298d6550294b2ac24f50c320f95 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_solvers.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_sparse.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_sparse.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5c4d196284b6552605ff5f0b76802c789d5efe77 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_sparse.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_sparsetools.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_sparsetools.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a98a89e1bef510a19e38838e8637de2ae09fc438 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_sparsetools.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_subspaces.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_subspaces.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3b8fd0fb72c50cda0e74fdb7d83f9db15ce69229 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/__pycache__/test_subspaces.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_commonmatrix.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_commonmatrix.py new file mode 100644 index 0000000000000000000000000000000000000000..6735adc1a9d4f9934a55c7ee70b087a19d3a48b4 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_commonmatrix.py @@ -0,0 +1,1266 @@ +# +# Code for testing deprecated matrix classes. New test code should not be added +# here. Instead, add it to test_matrixbase.py. +# +# This entire test module and the corresponding sympy/matrices/common.py +# module will be removed in a future release. +# +from sympy.testing.pytest import raises, XFAIL, warns_deprecated_sympy + +from sympy.assumptions import Q +from sympy.core.expr import Expr +from sympy.core.add import Add +from sympy.core.function import Function +from sympy.core.kind import NumberKind, UndefinedKind +from sympy.core.numbers import I, Integer, oo, pi, Rational +from sympy.core.singleton import S +from sympy.core.symbol import Symbol, symbols +from sympy.functions.elementary.complexes import Abs +from sympy.functions.elementary.exponential import exp +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import cos, sin +from sympy.matrices.exceptions import ShapeError, NonSquareMatrixError +from sympy.matrices.kind import MatrixKind +from sympy.matrices.common import ( + _MinimalMatrix, _CastableMatrix, MatrixShaping, MatrixProperties, + MatrixOperations, MatrixArithmetic, MatrixSpecial) +from sympy.matrices.matrices import MatrixCalculus +from sympy.matrices import (Matrix, diag, eye, + matrix_multiply_elementwise, ones, zeros, SparseMatrix, banded, + MutableDenseMatrix, MutableSparseMatrix, ImmutableDenseMatrix, + ImmutableSparseMatrix) +from sympy.polys.polytools import Poly +from sympy.utilities.iterables import flatten +from sympy.tensor.array.dense_ndim_array import ImmutableDenseNDimArray as Array + +from sympy.abc import x, y, z + + +def test_matrix_deprecated_isinstance(): + + # Test that e.g. isinstance(M, MatrixCommon) still gives True when M is a + # Matrix for each of the deprecated matrix classes. + + from sympy.matrices.common import ( + MatrixRequired, + MatrixShaping, + MatrixSpecial, + MatrixProperties, + MatrixOperations, + MatrixArithmetic, + MatrixCommon + ) + from sympy.matrices.matrices import ( + MatrixDeterminant, + MatrixReductions, + MatrixSubspaces, + MatrixEigen, + MatrixCalculus, + MatrixDeprecated + ) + from sympy import ( + Matrix, + ImmutableMatrix, + SparseMatrix, + ImmutableSparseMatrix + ) + all_mixins = ( + MatrixRequired, + MatrixShaping, + MatrixSpecial, + MatrixProperties, + MatrixOperations, + MatrixArithmetic, + MatrixCommon, + MatrixDeterminant, + MatrixReductions, + MatrixSubspaces, + MatrixEigen, + MatrixCalculus, + MatrixDeprecated + ) + all_matrices = ( + Matrix, + ImmutableMatrix, + SparseMatrix, + ImmutableSparseMatrix + ) + + Ms = [M([[1, 2], [3, 4]]) for M in all_matrices] + t = () + + for mixin in all_mixins: + for M in Ms: + with warns_deprecated_sympy(): + assert isinstance(M, mixin) is True + with warns_deprecated_sympy(): + assert isinstance(t, mixin) is False + + +# classes to test the deprecated matrix classes. We use warns_deprecated_sympy +# to suppress the deprecation warnings because subclassing the deprecated +# classes causes a warning to be raised. + +with warns_deprecated_sympy(): + class ShapingOnlyMatrix(_MinimalMatrix, _CastableMatrix, MatrixShaping): + pass + + +def eye_Shaping(n): + return ShapingOnlyMatrix(n, n, lambda i, j: int(i == j)) + + +def zeros_Shaping(n): + return ShapingOnlyMatrix(n, n, lambda i, j: 0) + + +with warns_deprecated_sympy(): + class PropertiesOnlyMatrix(_MinimalMatrix, _CastableMatrix, MatrixProperties): + pass + + +def eye_Properties(n): + return PropertiesOnlyMatrix(n, n, lambda i, j: int(i == j)) + + +def zeros_Properties(n): + return PropertiesOnlyMatrix(n, n, lambda i, j: 0) + + +with warns_deprecated_sympy(): + class OperationsOnlyMatrix(_MinimalMatrix, _CastableMatrix, MatrixOperations): + pass + + +def eye_Operations(n): + return OperationsOnlyMatrix(n, n, lambda i, j: int(i == j)) + + +def zeros_Operations(n): + return OperationsOnlyMatrix(n, n, lambda i, j: 0) + + +with warns_deprecated_sympy(): + class ArithmeticOnlyMatrix(_MinimalMatrix, _CastableMatrix, MatrixArithmetic): + pass + + +def eye_Arithmetic(n): + return ArithmeticOnlyMatrix(n, n, lambda i, j: int(i == j)) + + +def zeros_Arithmetic(n): + return ArithmeticOnlyMatrix(n, n, lambda i, j: 0) + + +with warns_deprecated_sympy(): + class SpecialOnlyMatrix(_MinimalMatrix, _CastableMatrix, MatrixSpecial): + pass + + +with warns_deprecated_sympy(): + class CalculusOnlyMatrix(_MinimalMatrix, _CastableMatrix, MatrixCalculus): + pass + + +def test__MinimalMatrix(): + x = _MinimalMatrix(2, 3, [1, 2, 3, 4, 5, 6]) + assert x.rows == 2 + assert x.cols == 3 + assert x[2] == 3 + assert x[1, 1] == 5 + assert list(x) == [1, 2, 3, 4, 5, 6] + assert list(x[1, :]) == [4, 5, 6] + assert list(x[:, 1]) == [2, 5] + assert list(x[:, :]) == list(x) + assert x[:, :] == x + assert _MinimalMatrix(x) == x + assert _MinimalMatrix([[1, 2, 3], [4, 5, 6]]) == x + assert _MinimalMatrix(([1, 2, 3], [4, 5, 6])) == x + assert _MinimalMatrix([(1, 2, 3), (4, 5, 6)]) == x + assert _MinimalMatrix(((1, 2, 3), (4, 5, 6))) == x + assert not (_MinimalMatrix([[1, 2], [3, 4], [5, 6]]) == x) + + +def test_kind(): + assert Matrix([[1, 2], [3, 4]]).kind == MatrixKind(NumberKind) + assert Matrix([[0, 0], [0, 0]]).kind == MatrixKind(NumberKind) + assert Matrix(0, 0, []).kind == MatrixKind(NumberKind) + assert Matrix([[x]]).kind == MatrixKind(NumberKind) + assert Matrix([[1, Matrix([[1]])]]).kind == MatrixKind(UndefinedKind) + assert SparseMatrix([[1]]).kind == MatrixKind(NumberKind) + assert SparseMatrix([[1, Matrix([[1]])]]).kind == MatrixKind(UndefinedKind) + + +# ShapingOnlyMatrix tests +def test_vec(): + m = ShapingOnlyMatrix(2, 2, [1, 3, 2, 4]) + m_vec = m.vec() + assert m_vec.cols == 1 + for i in range(4): + assert m_vec[i] == i + 1 + + +def test_todok(): + a, b, c, d = symbols('a:d') + m1 = MutableDenseMatrix([[a, b], [c, d]]) + m2 = ImmutableDenseMatrix([[a, b], [c, d]]) + m3 = MutableSparseMatrix([[a, b], [c, d]]) + m4 = ImmutableSparseMatrix([[a, b], [c, d]]) + assert m1.todok() == m2.todok() == m3.todok() == m4.todok() == \ + {(0, 0): a, (0, 1): b, (1, 0): c, (1, 1): d} + + +def test_tolist(): + lst = [[S.One, S.Half, x*y, S.Zero], [x, y, z, x**2], [y, -S.One, z*x, 3]] + flat_lst = [S.One, S.Half, x*y, S.Zero, x, y, z, x**2, y, -S.One, z*x, 3] + m = ShapingOnlyMatrix(3, 4, flat_lst) + assert m.tolist() == lst + +def test_todod(): + m = ShapingOnlyMatrix(3, 2, [[S.One, 0], [0, S.Half], [x, 0]]) + dict = {0: {0: S.One}, 1: {1: S.Half}, 2: {0: x}} + assert m.todod() == dict + +def test_row_col_del(): + e = ShapingOnlyMatrix(3, 3, [1, 2, 3, 4, 5, 6, 7, 8, 9]) + raises(IndexError, lambda: e.row_del(5)) + raises(IndexError, lambda: e.row_del(-5)) + raises(IndexError, lambda: e.col_del(5)) + raises(IndexError, lambda: e.col_del(-5)) + + assert e.row_del(2) == e.row_del(-1) == Matrix([[1, 2, 3], [4, 5, 6]]) + assert e.col_del(2) == e.col_del(-1) == Matrix([[1, 2], [4, 5], [7, 8]]) + + assert e.row_del(1) == e.row_del(-2) == Matrix([[1, 2, 3], [7, 8, 9]]) + assert e.col_del(1) == e.col_del(-2) == Matrix([[1, 3], [4, 6], [7, 9]]) + + +def test_get_diag_blocks1(): + a = Matrix([[1, 2], [2, 3]]) + b = Matrix([[3, x], [y, 3]]) + c = Matrix([[3, x, 3], [y, 3, z], [x, y, z]]) + assert a.get_diag_blocks() == [a] + assert b.get_diag_blocks() == [b] + assert c.get_diag_blocks() == [c] + + +def test_get_diag_blocks2(): + a = Matrix([[1, 2], [2, 3]]) + b = Matrix([[3, x], [y, 3]]) + c = Matrix([[3, x, 3], [y, 3, z], [x, y, z]]) + A, B, C, D = diag(a, b, b), diag(a, b, c), diag(a, c, b), diag(c, c, b) + A = ShapingOnlyMatrix(A.rows, A.cols, A) + B = ShapingOnlyMatrix(B.rows, B.cols, B) + C = ShapingOnlyMatrix(C.rows, C.cols, C) + D = ShapingOnlyMatrix(D.rows, D.cols, D) + + assert A.get_diag_blocks() == [a, b, b] + assert B.get_diag_blocks() == [a, b, c] + assert C.get_diag_blocks() == [a, c, b] + assert D.get_diag_blocks() == [c, c, b] + + +def test_shape(): + m = ShapingOnlyMatrix(1, 2, [0, 0]) + assert m.shape == (1, 2) + + +def test_reshape(): + m0 = eye_Shaping(3) + assert m0.reshape(1, 9) == Matrix(1, 9, (1, 0, 0, 0, 1, 0, 0, 0, 1)) + m1 = ShapingOnlyMatrix(3, 4, lambda i, j: i + j) + assert m1.reshape( + 4, 3) == Matrix(((0, 1, 2), (3, 1, 2), (3, 4, 2), (3, 4, 5))) + assert m1.reshape(2, 6) == Matrix(((0, 1, 2, 3, 1, 2), (3, 4, 2, 3, 4, 5))) + + +def test_row_col(): + m = ShapingOnlyMatrix(3, 3, [1, 2, 3, 4, 5, 6, 7, 8, 9]) + assert m.row(0) == Matrix(1, 3, [1, 2, 3]) + assert m.col(0) == Matrix(3, 1, [1, 4, 7]) + + +def test_row_join(): + assert eye_Shaping(3).row_join(Matrix([7, 7, 7])) == \ + Matrix([[1, 0, 0, 7], + [0, 1, 0, 7], + [0, 0, 1, 7]]) + + +def test_col_join(): + assert eye_Shaping(3).col_join(Matrix([[7, 7, 7]])) == \ + Matrix([[1, 0, 0], + [0, 1, 0], + [0, 0, 1], + [7, 7, 7]]) + + +def test_row_insert(): + r4 = Matrix([[4, 4, 4]]) + for i in range(-4, 5): + l = [1, 0, 0] + l.insert(i, 4) + assert flatten(eye_Shaping(3).row_insert(i, r4).col(0).tolist()) == l + + +def test_col_insert(): + c4 = Matrix([4, 4, 4]) + for i in range(-4, 5): + l = [0, 0, 0] + l.insert(i, 4) + assert flatten(zeros_Shaping(3).col_insert(i, c4).row(0).tolist()) == l + # issue 13643 + assert eye_Shaping(6).col_insert(3, Matrix([[2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2]])) == \ + Matrix([[1, 0, 0, 2, 2, 0, 0, 0], + [0, 1, 0, 2, 2, 0, 0, 0], + [0, 0, 1, 2, 2, 0, 0, 0], + [0, 0, 0, 2, 2, 1, 0, 0], + [0, 0, 0, 2, 2, 0, 1, 0], + [0, 0, 0, 2, 2, 0, 0, 1]]) + + +def test_extract(): + m = ShapingOnlyMatrix(4, 3, lambda i, j: i*3 + j) + assert m.extract([0, 1, 3], [0, 1]) == Matrix(3, 2, [0, 1, 3, 4, 9, 10]) + assert m.extract([0, 3], [0, 0, 2]) == Matrix(2, 3, [0, 0, 2, 9, 9, 11]) + assert m.extract(range(4), range(3)) == m + raises(IndexError, lambda: m.extract([4], [0])) + raises(IndexError, lambda: m.extract([0], [3])) + + +def test_hstack(): + m = ShapingOnlyMatrix(4, 3, lambda i, j: i*3 + j) + m2 = ShapingOnlyMatrix(3, 4, lambda i, j: i*3 + j) + assert m == m.hstack(m) + assert m.hstack(m, m, m) == ShapingOnlyMatrix.hstack(m, m, m) == Matrix([ + [0, 1, 2, 0, 1, 2, 0, 1, 2], + [3, 4, 5, 3, 4, 5, 3, 4, 5], + [6, 7, 8, 6, 7, 8, 6, 7, 8], + [9, 10, 11, 9, 10, 11, 9, 10, 11]]) + raises(ShapeError, lambda: m.hstack(m, m2)) + assert Matrix.hstack() == Matrix() + + # test regression #12938 + M1 = Matrix.zeros(0, 0) + M2 = Matrix.zeros(0, 1) + M3 = Matrix.zeros(0, 2) + M4 = Matrix.zeros(0, 3) + m = ShapingOnlyMatrix.hstack(M1, M2, M3, M4) + assert m.rows == 0 and m.cols == 6 + + +def test_vstack(): + m = ShapingOnlyMatrix(4, 3, lambda i, j: i*3 + j) + m2 = ShapingOnlyMatrix(3, 4, lambda i, j: i*3 + j) + assert m == m.vstack(m) + assert m.vstack(m, m, m) == ShapingOnlyMatrix.vstack(m, m, m) == Matrix([ + [0, 1, 2], + [3, 4, 5], + [6, 7, 8], + [9, 10, 11], + [0, 1, 2], + [3, 4, 5], + [6, 7, 8], + [9, 10, 11], + [0, 1, 2], + [3, 4, 5], + [6, 7, 8], + [9, 10, 11]]) + raises(ShapeError, lambda: m.vstack(m, m2)) + assert Matrix.vstack() == Matrix() + + +# PropertiesOnlyMatrix tests +def test_atoms(): + m = PropertiesOnlyMatrix(2, 2, [1, 2, x, 1 - 1/x]) + assert m.atoms() == {S.One, S(2), S.NegativeOne, x} + assert m.atoms(Symbol) == {x} + + +def test_free_symbols(): + assert PropertiesOnlyMatrix([[x], [0]]).free_symbols == {x} + + +def test_has(): + A = PropertiesOnlyMatrix(((x, y), (2, 3))) + assert A.has(x) + assert not A.has(z) + assert A.has(Symbol) + + A = PropertiesOnlyMatrix(((2, y), (2, 3))) + assert not A.has(x) + + +def test_is_anti_symmetric(): + x = symbols('x') + assert PropertiesOnlyMatrix(2, 1, [1, 2]).is_anti_symmetric() is False + m = PropertiesOnlyMatrix(3, 3, [0, x**2 + 2*x + 1, y, -(x + 1)**2, 0, x*y, -y, -x*y, 0]) + assert m.is_anti_symmetric() is True + assert m.is_anti_symmetric(simplify=False) is False + assert m.is_anti_symmetric(simplify=lambda x: x) is False + + m = PropertiesOnlyMatrix(3, 3, [x.expand() for x in m]) + assert m.is_anti_symmetric(simplify=False) is True + m = PropertiesOnlyMatrix(3, 3, [x.expand() for x in [S.One] + list(m)[1:]]) + assert m.is_anti_symmetric() is False + + +def test_diagonal_symmetrical(): + m = PropertiesOnlyMatrix(2, 2, [0, 1, 1, 0]) + assert not m.is_diagonal() + assert m.is_symmetric() + assert m.is_symmetric(simplify=False) + + m = PropertiesOnlyMatrix(2, 2, [1, 0, 0, 1]) + assert m.is_diagonal() + + m = PropertiesOnlyMatrix(3, 3, diag(1, 2, 3)) + assert m.is_diagonal() + assert m.is_symmetric() + + m = PropertiesOnlyMatrix(3, 3, [1, 0, 0, 0, 2, 0, 0, 0, 3]) + assert m == diag(1, 2, 3) + + m = PropertiesOnlyMatrix(2, 3, zeros(2, 3)) + assert not m.is_symmetric() + assert m.is_diagonal() + + m = PropertiesOnlyMatrix(((5, 0), (0, 6), (0, 0))) + assert m.is_diagonal() + + m = PropertiesOnlyMatrix(((5, 0, 0), (0, 6, 0))) + assert m.is_diagonal() + + m = Matrix(3, 3, [1, x**2 + 2*x + 1, y, (x + 1)**2, 2, 0, y, 0, 3]) + assert m.is_symmetric() + assert not m.is_symmetric(simplify=False) + assert m.expand().is_symmetric(simplify=False) + + +def test_is_hermitian(): + a = PropertiesOnlyMatrix([[1, I], [-I, 1]]) + assert a.is_hermitian + a = PropertiesOnlyMatrix([[2*I, I], [-I, 1]]) + assert a.is_hermitian is False + a = PropertiesOnlyMatrix([[x, I], [-I, 1]]) + assert a.is_hermitian is None + a = PropertiesOnlyMatrix([[x, 1], [-I, 1]]) + assert a.is_hermitian is False + + +def test_is_Identity(): + assert eye_Properties(3).is_Identity + assert not PropertiesOnlyMatrix(zeros(3)).is_Identity + assert not PropertiesOnlyMatrix(ones(3)).is_Identity + # issue 6242 + assert not PropertiesOnlyMatrix([[1, 0, 0]]).is_Identity + + +def test_is_symbolic(): + a = PropertiesOnlyMatrix([[x, x], [x, x]]) + assert a.is_symbolic() is True + a = PropertiesOnlyMatrix([[1, 2, 3, 4], [5, 6, 7, 8]]) + assert a.is_symbolic() is False + a = PropertiesOnlyMatrix([[1, 2, 3, 4], [5, 6, x, 8]]) + assert a.is_symbolic() is True + a = PropertiesOnlyMatrix([[1, x, 3]]) + assert a.is_symbolic() is True + a = PropertiesOnlyMatrix([[1, 2, 3]]) + assert a.is_symbolic() is False + a = PropertiesOnlyMatrix([[1], [x], [3]]) + assert a.is_symbolic() is True + a = PropertiesOnlyMatrix([[1], [2], [3]]) + assert a.is_symbolic() is False + + +def test_is_upper(): + a = PropertiesOnlyMatrix([[1, 2, 3]]) + assert a.is_upper is True + a = PropertiesOnlyMatrix([[1], [2], [3]]) + assert a.is_upper is False + + +def test_is_lower(): + a = PropertiesOnlyMatrix([[1, 2, 3]]) + assert a.is_lower is False + a = PropertiesOnlyMatrix([[1], [2], [3]]) + assert a.is_lower is True + + +def test_is_square(): + m = PropertiesOnlyMatrix([[1], [1]]) + m2 = PropertiesOnlyMatrix([[2, 2], [2, 2]]) + assert not m.is_square + assert m2.is_square + + +def test_is_symmetric(): + m = PropertiesOnlyMatrix(2, 2, [0, 1, 1, 0]) + assert m.is_symmetric() + m = PropertiesOnlyMatrix(2, 2, [0, 1, 0, 1]) + assert not m.is_symmetric() + + +def test_is_hessenberg(): + A = PropertiesOnlyMatrix([[3, 4, 1], [2, 4, 5], [0, 1, 2]]) + assert A.is_upper_hessenberg + A = PropertiesOnlyMatrix(3, 3, [3, 2, 0, 4, 4, 1, 1, 5, 2]) + assert A.is_lower_hessenberg + A = PropertiesOnlyMatrix(3, 3, [3, 2, -1, 4, 4, 1, 1, 5, 2]) + assert A.is_lower_hessenberg is False + assert A.is_upper_hessenberg is False + + A = PropertiesOnlyMatrix([[3, 4, 1], [2, 4, 5], [3, 1, 2]]) + assert not A.is_upper_hessenberg + + +def test_is_zero(): + assert PropertiesOnlyMatrix(0, 0, []).is_zero_matrix + assert PropertiesOnlyMatrix([[0, 0], [0, 0]]).is_zero_matrix + assert PropertiesOnlyMatrix(zeros(3, 4)).is_zero_matrix + assert not PropertiesOnlyMatrix(eye(3)).is_zero_matrix + assert PropertiesOnlyMatrix([[x, 0], [0, 0]]).is_zero_matrix == None + assert PropertiesOnlyMatrix([[x, 1], [0, 0]]).is_zero_matrix == False + a = Symbol('a', nonzero=True) + assert PropertiesOnlyMatrix([[a, 0], [0, 0]]).is_zero_matrix == False + + +def test_values(): + assert set(PropertiesOnlyMatrix(2, 2, [0, 1, 2, 3] + ).values()) == {1, 2, 3} + x = Symbol('x', real=True) + assert set(PropertiesOnlyMatrix(2, 2, [x, 0, 0, 1] + ).values()) == {x, 1} + + +# OperationsOnlyMatrix tests +def test_applyfunc(): + m0 = OperationsOnlyMatrix(eye(3)) + assert m0.applyfunc(lambda x: 2*x) == eye(3)*2 + assert m0.applyfunc(lambda x: 0) == zeros(3) + assert m0.applyfunc(lambda x: 1) == ones(3) + + +def test_adjoint(): + dat = [[0, I], [1, 0]] + ans = OperationsOnlyMatrix([[0, 1], [-I, 0]]) + assert ans.adjoint() == Matrix(dat) + + +def test_as_real_imag(): + m1 = OperationsOnlyMatrix(2, 2, [1, 2, 3, 4]) + m3 = OperationsOnlyMatrix(2, 2, + [1 + S.ImaginaryUnit, 2 + 2*S.ImaginaryUnit, + 3 + 3*S.ImaginaryUnit, 4 + 4*S.ImaginaryUnit]) + + a, b = m3.as_real_imag() + assert a == m1 + assert b == m1 + + +def test_conjugate(): + M = OperationsOnlyMatrix([[0, I, 5], + [1, 2, 0]]) + + assert M.T == Matrix([[0, 1], + [I, 2], + [5, 0]]) + + assert M.C == Matrix([[0, -I, 5], + [1, 2, 0]]) + assert M.C == M.conjugate() + + assert M.H == M.T.C + assert M.H == Matrix([[ 0, 1], + [-I, 2], + [ 5, 0]]) + + +def test_doit(): + a = OperationsOnlyMatrix([[Add(x, x, evaluate=False)]]) + assert a[0] != 2*x + assert a.doit() == Matrix([[2*x]]) + + +def test_evalf(): + a = OperationsOnlyMatrix(2, 1, [sqrt(5), 6]) + assert all(a.evalf()[i] == a[i].evalf() for i in range(2)) + assert all(a.evalf(2)[i] == a[i].evalf(2) for i in range(2)) + assert all(a.n(2)[i] == a[i].n(2) for i in range(2)) + + +def test_expand(): + m0 = OperationsOnlyMatrix([[x*(x + y), 2], [((x + y)*y)*x, x*(y + x*(x + y))]]) + # Test if expand() returns a matrix + m1 = m0.expand() + assert m1 == Matrix( + [[x*y + x**2, 2], [x*y**2 + y*x**2, x*y + y*x**2 + x**3]]) + + a = Symbol('a', real=True) + + assert OperationsOnlyMatrix(1, 1, [exp(I*a)]).expand(complex=True) == \ + Matrix([cos(a) + I*sin(a)]) + + +def test_refine(): + m0 = OperationsOnlyMatrix([[Abs(x)**2, sqrt(x**2)], + [sqrt(x**2)*Abs(y)**2, sqrt(y**2)*Abs(x)**2]]) + m1 = m0.refine(Q.real(x) & Q.real(y)) + assert m1 == Matrix([[x**2, Abs(x)], [y**2*Abs(x), x**2*Abs(y)]]) + + m1 = m0.refine(Q.positive(x) & Q.positive(y)) + assert m1 == Matrix([[x**2, x], [x*y**2, x**2*y]]) + + m1 = m0.refine(Q.negative(x) & Q.negative(y)) + assert m1 == Matrix([[x**2, -x], [-x*y**2, -x**2*y]]) + + +def test_replace(): + F, G = symbols('F, G', cls=Function) + K = OperationsOnlyMatrix(2, 2, lambda i, j: G(i+j)) + M = OperationsOnlyMatrix(2, 2, lambda i, j: F(i+j)) + N = M.replace(F, G) + assert N == K + + +def test_replace_map(): + F, G = symbols('F, G', cls=Function) + K = OperationsOnlyMatrix(2, 2, [(G(0), {F(0): G(0)}), (G(1), {F(1): G(1)}), (G(1), {F(1) \ + : G(1)}), (G(2), {F(2): G(2)})]) + M = OperationsOnlyMatrix(2, 2, lambda i, j: F(i+j)) + N = M.replace(F, G, True) + assert N == K + + +def test_rot90(): + A = Matrix([[1, 2], [3, 4]]) + assert A == A.rot90(0) == A.rot90(4) + assert A.rot90(2) == A.rot90(-2) == A.rot90(6) == Matrix(((4, 3), (2, 1))) + assert A.rot90(3) == A.rot90(-1) == A.rot90(7) == Matrix(((2, 4), (1, 3))) + assert A.rot90() == A.rot90(-7) == A.rot90(-3) == Matrix(((3, 1), (4, 2))) + +def test_simplify(): + n = Symbol('n') + f = Function('f') + + M = OperationsOnlyMatrix([[ 1/x + 1/y, (x + x*y) / x ], + [ (f(x) + y*f(x))/f(x), 2 * (1/n - cos(n * pi)/n) / pi ]]) + assert M.simplify() == Matrix([[ (x + y)/(x * y), 1 + y ], + [ 1 + y, 2*((1 - 1*cos(pi*n))/(pi*n)) ]]) + eq = (1 + x)**2 + M = OperationsOnlyMatrix([[eq]]) + assert M.simplify() == Matrix([[eq]]) + assert M.simplify(ratio=oo) == Matrix([[eq.simplify(ratio=oo)]]) + + # https://github.com/sympy/sympy/issues/19353 + m = Matrix([[30, 2], [3, 4]]) + assert (1/(m.trace())).simplify() == Rational(1, 34) + + +def test_subs(): + assert OperationsOnlyMatrix([[1, x], [x, 4]]).subs(x, 5) == Matrix([[1, 5], [5, 4]]) + assert OperationsOnlyMatrix([[x, 2], [x + y, 4]]).subs([[x, -1], [y, -2]]) == \ + Matrix([[-1, 2], [-3, 4]]) + assert OperationsOnlyMatrix([[x, 2], [x + y, 4]]).subs([(x, -1), (y, -2)]) == \ + Matrix([[-1, 2], [-3, 4]]) + assert OperationsOnlyMatrix([[x, 2], [x + y, 4]]).subs({x: -1, y: -2}) == \ + Matrix([[-1, 2], [-3, 4]]) + assert OperationsOnlyMatrix([[x*y]]).subs({x: y - 1, y: x - 1}, simultaneous=True) == \ + Matrix([[(x - 1)*(y - 1)]]) + + +def test_trace(): + M = OperationsOnlyMatrix([[1, 0, 0], + [0, 5, 0], + [0, 0, 8]]) + assert M.trace() == 14 + + +def test_xreplace(): + assert OperationsOnlyMatrix([[1, x], [x, 4]]).xreplace({x: 5}) == \ + Matrix([[1, 5], [5, 4]]) + assert OperationsOnlyMatrix([[x, 2], [x + y, 4]]).xreplace({x: -1, y: -2}) == \ + Matrix([[-1, 2], [-3, 4]]) + + +def test_permute(): + a = OperationsOnlyMatrix(3, 4, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]) + + raises(IndexError, lambda: a.permute([[0, 5]])) + raises(ValueError, lambda: a.permute(Symbol('x'))) + b = a.permute_rows([[0, 2], [0, 1]]) + assert a.permute([[0, 2], [0, 1]]) == b == Matrix([ + [5, 6, 7, 8], + [9, 10, 11, 12], + [1, 2, 3, 4]]) + + b = a.permute_cols([[0, 2], [0, 1]]) + assert a.permute([[0, 2], [0, 1]], orientation='cols') == b ==\ + Matrix([ + [ 2, 3, 1, 4], + [ 6, 7, 5, 8], + [10, 11, 9, 12]]) + + b = a.permute_cols([[0, 2], [0, 1]], direction='backward') + assert a.permute([[0, 2], [0, 1]], orientation='cols', direction='backward') == b ==\ + Matrix([ + [ 3, 1, 2, 4], + [ 7, 5, 6, 8], + [11, 9, 10, 12]]) + + assert a.permute([1, 2, 0, 3]) == Matrix([ + [5, 6, 7, 8], + [9, 10, 11, 12], + [1, 2, 3, 4]]) + + from sympy.combinatorics import Permutation + assert a.permute(Permutation([1, 2, 0, 3])) == Matrix([ + [5, 6, 7, 8], + [9, 10, 11, 12], + [1, 2, 3, 4]]) + +def test_upper_triangular(): + + A = OperationsOnlyMatrix([ + [1, 1, 1, 1], + [1, 1, 1, 1], + [1, 1, 1, 1], + [1, 1, 1, 1] + ]) + + R = A.upper_triangular(2) + assert R == OperationsOnlyMatrix([ + [0, 0, 1, 1], + [0, 0, 0, 1], + [0, 0, 0, 0], + [0, 0, 0, 0] + ]) + + R = A.upper_triangular(-2) + assert R == OperationsOnlyMatrix([ + [1, 1, 1, 1], + [1, 1, 1, 1], + [1, 1, 1, 1], + [0, 1, 1, 1] + ]) + + R = A.upper_triangular() + assert R == OperationsOnlyMatrix([ + [1, 1, 1, 1], + [0, 1, 1, 1], + [0, 0, 1, 1], + [0, 0, 0, 1] + ]) + +def test_lower_triangular(): + A = OperationsOnlyMatrix([ + [1, 1, 1, 1], + [1, 1, 1, 1], + [1, 1, 1, 1], + [1, 1, 1, 1] + ]) + + L = A.lower_triangular() + assert L == ArithmeticOnlyMatrix([ + [1, 0, 0, 0], + [1, 1, 0, 0], + [1, 1, 1, 0], + [1, 1, 1, 1]]) + + L = A.lower_triangular(2) + assert L == ArithmeticOnlyMatrix([ + [1, 1, 1, 0], + [1, 1, 1, 1], + [1, 1, 1, 1], + [1, 1, 1, 1] + ]) + + L = A.lower_triangular(-2) + assert L == ArithmeticOnlyMatrix([ + [0, 0, 0, 0], + [0, 0, 0, 0], + [1, 0, 0, 0], + [1, 1, 0, 0] + ]) + + +# ArithmeticOnlyMatrix tests +def test_abs(): + m = ArithmeticOnlyMatrix([[1, -2], [x, y]]) + assert abs(m) == ArithmeticOnlyMatrix([[1, 2], [Abs(x), Abs(y)]]) + + +def test_add(): + m = ArithmeticOnlyMatrix([[1, 2, 3], [x, y, x], [2*y, -50, z*x]]) + assert m + m == ArithmeticOnlyMatrix([[2, 4, 6], [2*x, 2*y, 2*x], [4*y, -100, 2*z*x]]) + n = ArithmeticOnlyMatrix(1, 2, [1, 2]) + raises(ShapeError, lambda: m + n) + + +def test_multiplication(): + a = ArithmeticOnlyMatrix(( + (1, 2), + (3, 1), + (0, 6), + )) + + b = ArithmeticOnlyMatrix(( + (1, 2), + (3, 0), + )) + + raises(ShapeError, lambda: b*a) + raises(TypeError, lambda: a*{}) + + c = a*b + assert c[0, 0] == 7 + assert c[0, 1] == 2 + assert c[1, 0] == 6 + assert c[1, 1] == 6 + assert c[2, 0] == 18 + assert c[2, 1] == 0 + + try: + eval('c = a @ b') + except SyntaxError: + pass + else: + assert c[0, 0] == 7 + assert c[0, 1] == 2 + assert c[1, 0] == 6 + assert c[1, 1] == 6 + assert c[2, 0] == 18 + assert c[2, 1] == 0 + + h = a.multiply_elementwise(c) + assert h == matrix_multiply_elementwise(a, c) + assert h[0, 0] == 7 + assert h[0, 1] == 4 + assert h[1, 0] == 18 + assert h[1, 1] == 6 + assert h[2, 0] == 0 + assert h[2, 1] == 0 + raises(ShapeError, lambda: a.multiply_elementwise(b)) + + c = b * Symbol("x") + assert isinstance(c, ArithmeticOnlyMatrix) + assert c[0, 0] == x + assert c[0, 1] == 2*x + assert c[1, 0] == 3*x + assert c[1, 1] == 0 + + c2 = x * b + assert c == c2 + + c = 5 * b + assert isinstance(c, ArithmeticOnlyMatrix) + assert c[0, 0] == 5 + assert c[0, 1] == 2*5 + assert c[1, 0] == 3*5 + assert c[1, 1] == 0 + + try: + eval('c = 5 @ b') + except SyntaxError: + pass + else: + assert isinstance(c, ArithmeticOnlyMatrix) + assert c[0, 0] == 5 + assert c[0, 1] == 2*5 + assert c[1, 0] == 3*5 + assert c[1, 1] == 0 + + # https://github.com/sympy/sympy/issues/22353 + A = Matrix(ones(3, 1)) + _h = -Rational(1, 2) + B = Matrix([_h, _h, _h]) + assert A.multiply_elementwise(B) == Matrix([ + [_h], + [_h], + [_h]]) + + +def test_matmul(): + a = Matrix([[1, 2], [3, 4]]) + + assert a.__matmul__(2) == NotImplemented + + assert a.__rmatmul__(2) == NotImplemented + + #This is done this way because @ is only supported in Python 3.5+ + #To check 2@a case + try: + eval('2 @ a') + except SyntaxError: + pass + except TypeError: #TypeError is raised in case of NotImplemented is returned + pass + + #Check a@2 case + try: + eval('a @ 2') + except SyntaxError: + pass + except TypeError: #TypeError is raised in case of NotImplemented is returned + pass + + +def test_non_matmul(): + """ + Test that if explicitly specified as non-matrix, mul reverts + to scalar multiplication. + """ + class foo(Expr): + is_Matrix=False + is_MatrixLike=False + shape = (1, 1) + + A = Matrix([[1, 2], [3, 4]]) + b = foo() + assert b*A == Matrix([[b, 2*b], [3*b, 4*b]]) + assert A*b == Matrix([[b, 2*b], [3*b, 4*b]]) + + +def test_power(): + raises(NonSquareMatrixError, lambda: Matrix((1, 2))**2) + + A = ArithmeticOnlyMatrix([[2, 3], [4, 5]]) + assert (A**5)[:] == (6140, 8097, 10796, 14237) + A = ArithmeticOnlyMatrix([[2, 1, 3], [4, 2, 4], [6, 12, 1]]) + assert (A**3)[:] == (290, 262, 251, 448, 440, 368, 702, 954, 433) + assert A**0 == eye(3) + assert A**1 == A + assert (ArithmeticOnlyMatrix([[2]]) ** 100)[0, 0] == 2**100 + assert ArithmeticOnlyMatrix([[1, 2], [3, 4]])**Integer(2) == ArithmeticOnlyMatrix([[7, 10], [15, 22]]) + A = Matrix([[1,2],[4,5]]) + assert A.pow(20, method='cayley') == A.pow(20, method='multiply') + +def test_neg(): + n = ArithmeticOnlyMatrix(1, 2, [1, 2]) + assert -n == ArithmeticOnlyMatrix(1, 2, [-1, -2]) + + +def test_sub(): + n = ArithmeticOnlyMatrix(1, 2, [1, 2]) + assert n - n == ArithmeticOnlyMatrix(1, 2, [0, 0]) + + +def test_div(): + n = ArithmeticOnlyMatrix(1, 2, [1, 2]) + assert n/2 == ArithmeticOnlyMatrix(1, 2, [S.Half, S(2)/2]) + +# SpecialOnlyMatrix tests +def test_eye(): + assert list(SpecialOnlyMatrix.eye(2, 2)) == [1, 0, 0, 1] + assert list(SpecialOnlyMatrix.eye(2)) == [1, 0, 0, 1] + assert type(SpecialOnlyMatrix.eye(2)) == SpecialOnlyMatrix + assert type(SpecialOnlyMatrix.eye(2, cls=Matrix)) == Matrix + + +def test_ones(): + assert list(SpecialOnlyMatrix.ones(2, 2)) == [1, 1, 1, 1] + assert list(SpecialOnlyMatrix.ones(2)) == [1, 1, 1, 1] + assert SpecialOnlyMatrix.ones(2, 3) == Matrix([[1, 1, 1], [1, 1, 1]]) + assert type(SpecialOnlyMatrix.ones(2)) == SpecialOnlyMatrix + assert type(SpecialOnlyMatrix.ones(2, cls=Matrix)) == Matrix + + +def test_zeros(): + assert list(SpecialOnlyMatrix.zeros(2, 2)) == [0, 0, 0, 0] + assert list(SpecialOnlyMatrix.zeros(2)) == [0, 0, 0, 0] + assert SpecialOnlyMatrix.zeros(2, 3) == Matrix([[0, 0, 0], [0, 0, 0]]) + assert type(SpecialOnlyMatrix.zeros(2)) == SpecialOnlyMatrix + assert type(SpecialOnlyMatrix.zeros(2, cls=Matrix)) == Matrix + + +def test_diag_make(): + diag = SpecialOnlyMatrix.diag + a = Matrix([[1, 2], [2, 3]]) + b = Matrix([[3, x], [y, 3]]) + c = Matrix([[3, x, 3], [y, 3, z], [x, y, z]]) + assert diag(a, b, b) == Matrix([ + [1, 2, 0, 0, 0, 0], + [2, 3, 0, 0, 0, 0], + [0, 0, 3, x, 0, 0], + [0, 0, y, 3, 0, 0], + [0, 0, 0, 0, 3, x], + [0, 0, 0, 0, y, 3], + ]) + assert diag(a, b, c) == Matrix([ + [1, 2, 0, 0, 0, 0, 0], + [2, 3, 0, 0, 0, 0, 0], + [0, 0, 3, x, 0, 0, 0], + [0, 0, y, 3, 0, 0, 0], + [0, 0, 0, 0, 3, x, 3], + [0, 0, 0, 0, y, 3, z], + [0, 0, 0, 0, x, y, z], + ]) + assert diag(a, c, b) == Matrix([ + [1, 2, 0, 0, 0, 0, 0], + [2, 3, 0, 0, 0, 0, 0], + [0, 0, 3, x, 3, 0, 0], + [0, 0, y, 3, z, 0, 0], + [0, 0, x, y, z, 0, 0], + [0, 0, 0, 0, 0, 3, x], + [0, 0, 0, 0, 0, y, 3], + ]) + a = Matrix([x, y, z]) + b = Matrix([[1, 2], [3, 4]]) + c = Matrix([[5, 6]]) + # this "wandering diagonal" is what makes this + # a block diagonal where each block is independent + # of the others + assert diag(a, 7, b, c) == Matrix([ + [x, 0, 0, 0, 0, 0], + [y, 0, 0, 0, 0, 0], + [z, 0, 0, 0, 0, 0], + [0, 7, 0, 0, 0, 0], + [0, 0, 1, 2, 0, 0], + [0, 0, 3, 4, 0, 0], + [0, 0, 0, 0, 5, 6]]) + raises(ValueError, lambda: diag(a, 7, b, c, rows=5)) + assert diag(1) == Matrix([[1]]) + assert diag(1, rows=2) == Matrix([[1, 0], [0, 0]]) + assert diag(1, cols=2) == Matrix([[1, 0], [0, 0]]) + assert diag(1, rows=3, cols=2) == Matrix([[1, 0], [0, 0], [0, 0]]) + assert diag(*[2, 3]) == Matrix([ + [2, 0], + [0, 3]]) + assert diag(Matrix([2, 3])) == Matrix([ + [2], + [3]]) + assert diag([1, [2, 3], 4], unpack=False) == \ + diag([[1], [2, 3], [4]], unpack=False) == Matrix([ + [1, 0], + [2, 3], + [4, 0]]) + assert type(diag(1)) == SpecialOnlyMatrix + assert type(diag(1, cls=Matrix)) == Matrix + assert Matrix.diag([1, 2, 3]) == Matrix.diag(1, 2, 3) + assert Matrix.diag([1, 2, 3], unpack=False).shape == (3, 1) + assert Matrix.diag([[1, 2, 3]]).shape == (3, 1) + assert Matrix.diag([[1, 2, 3]], unpack=False).shape == (1, 3) + assert Matrix.diag([[[1, 2, 3]]]).shape == (1, 3) + # kerning can be used to move the starting point + assert Matrix.diag(ones(0, 2), 1, 2) == Matrix([ + [0, 0, 1, 0], + [0, 0, 0, 2]]) + assert Matrix.diag(ones(2, 0), 1, 2) == Matrix([ + [0, 0], + [0, 0], + [1, 0], + [0, 2]]) + + +def test_diagonal(): + m = Matrix(3, 3, range(9)) + d = m.diagonal() + assert d == m.diagonal(0) + assert tuple(d) == (0, 4, 8) + assert tuple(m.diagonal(1)) == (1, 5) + assert tuple(m.diagonal(-1)) == (3, 7) + assert tuple(m.diagonal(2)) == (2,) + assert type(m.diagonal()) == type(m) + s = SparseMatrix(3, 3, {(1, 1): 1}) + assert type(s.diagonal()) == type(s) + assert type(m) != type(s) + raises(ValueError, lambda: m.diagonal(3)) + raises(ValueError, lambda: m.diagonal(-3)) + raises(ValueError, lambda: m.diagonal(pi)) + M = ones(2, 3) + assert banded({i: list(M.diagonal(i)) + for i in range(1-M.rows, M.cols)}) == M + + +def test_jordan_block(): + assert SpecialOnlyMatrix.jordan_block(3, 2) == SpecialOnlyMatrix.jordan_block(3, eigenvalue=2) \ + == SpecialOnlyMatrix.jordan_block(size=3, eigenvalue=2) \ + == SpecialOnlyMatrix.jordan_block(3, 2, band='upper') \ + == SpecialOnlyMatrix.jordan_block( + size=3, eigenval=2, eigenvalue=2) \ + == Matrix([ + [2, 1, 0], + [0, 2, 1], + [0, 0, 2]]) + + assert SpecialOnlyMatrix.jordan_block(3, 2, band='lower') == Matrix([ + [2, 0, 0], + [1, 2, 0], + [0, 1, 2]]) + # missing eigenvalue + raises(ValueError, lambda: SpecialOnlyMatrix.jordan_block(2)) + # non-integral size + raises(ValueError, lambda: SpecialOnlyMatrix.jordan_block(3.5, 2)) + # size not specified + raises(ValueError, lambda: SpecialOnlyMatrix.jordan_block(eigenvalue=2)) + # inconsistent eigenvalue + raises(ValueError, + lambda: SpecialOnlyMatrix.jordan_block( + eigenvalue=2, eigenval=4)) + + # Using alias keyword + assert SpecialOnlyMatrix.jordan_block(size=3, eigenvalue=2) == \ + SpecialOnlyMatrix.jordan_block(size=3, eigenval=2) + + +def test_orthogonalize(): + m = Matrix([[1, 2], [3, 4]]) + assert m.orthogonalize(Matrix([[2], [1]])) == [Matrix([[2], [1]])] + assert m.orthogonalize(Matrix([[2], [1]]), normalize=True) == \ + [Matrix([[2*sqrt(5)/5], [sqrt(5)/5]])] + assert m.orthogonalize(Matrix([[1], [2]]), Matrix([[-1], [4]])) == \ + [Matrix([[1], [2]]), Matrix([[Rational(-12, 5)], [Rational(6, 5)]])] + assert m.orthogonalize(Matrix([[0], [0]]), Matrix([[-1], [4]])) == \ + [Matrix([[-1], [4]])] + assert m.orthogonalize(Matrix([[0], [0]])) == [] + + n = Matrix([[9, 1, 9], [3, 6, 10], [8, 5, 2]]) + vecs = [Matrix([[-5], [1]]), Matrix([[-5], [2]]), Matrix([[-5], [-2]])] + assert n.orthogonalize(*vecs) == \ + [Matrix([[-5], [1]]), Matrix([[Rational(5, 26)], [Rational(25, 26)]])] + + vecs = [Matrix([0, 0, 0]), Matrix([1, 2, 3]), Matrix([1, 4, 5])] + raises(ValueError, lambda: Matrix.orthogonalize(*vecs, rankcheck=True)) + + vecs = [Matrix([1, 2, 3]), Matrix([4, 5, 6]), Matrix([7, 8, 9])] + raises(ValueError, lambda: Matrix.orthogonalize(*vecs, rankcheck=True)) + +def test_wilkinson(): + + wminus, wplus = Matrix.wilkinson(1) + assert wminus == Matrix([ + [-1, 1, 0], + [1, 0, 1], + [0, 1, 1]]) + assert wplus == Matrix([ + [1, 1, 0], + [1, 0, 1], + [0, 1, 1]]) + + wminus, wplus = Matrix.wilkinson(3) + assert wminus == Matrix([ + [-3, 1, 0, 0, 0, 0, 0], + [1, -2, 1, 0, 0, 0, 0], + [0, 1, -1, 1, 0, 0, 0], + [0, 0, 1, 0, 1, 0, 0], + [0, 0, 0, 1, 1, 1, 0], + [0, 0, 0, 0, 1, 2, 1], + + [0, 0, 0, 0, 0, 1, 3]]) + + assert wplus == Matrix([ + [3, 1, 0, 0, 0, 0, 0], + [1, 2, 1, 0, 0, 0, 0], + [0, 1, 1, 1, 0, 0, 0], + [0, 0, 1, 0, 1, 0, 0], + [0, 0, 0, 1, 1, 1, 0], + [0, 0, 0, 0, 1, 2, 1], + [0, 0, 0, 0, 0, 1, 3]]) + + +# CalculusOnlyMatrix tests +@XFAIL +def test_diff(): + x, y = symbols('x y') + m = CalculusOnlyMatrix(2, 1, [x, y]) + # TODO: currently not working as ``_MinimalMatrix`` cannot be sympified: + assert m.diff(x) == Matrix(2, 1, [1, 0]) + + +def test_integrate(): + x, y = symbols('x y') + m = CalculusOnlyMatrix(2, 1, [x, y]) + assert m.integrate(x) == Matrix(2, 1, [x**2/2, y*x]) + + +def test_jacobian2(): + rho, phi = symbols("rho,phi") + X = CalculusOnlyMatrix(3, 1, [rho*cos(phi), rho*sin(phi), rho**2]) + Y = CalculusOnlyMatrix(2, 1, [rho, phi]) + J = Matrix([ + [cos(phi), -rho*sin(phi)], + [sin(phi), rho*cos(phi)], + [ 2*rho, 0], + ]) + assert X.jacobian(Y) == J + + m = CalculusOnlyMatrix(2, 2, [1, 2, 3, 4]) + m2 = CalculusOnlyMatrix(4, 1, [1, 2, 3, 4]) + raises(TypeError, lambda: m.jacobian(Matrix([1, 2]))) + raises(TypeError, lambda: m2.jacobian(m)) + + +def test_limit(): + x, y = symbols('x y') + m = CalculusOnlyMatrix(2, 1, [1/x, y]) + assert m.limit(x, 5) == Matrix(2, 1, [Rational(1, 5), y]) + + +def test_issue_13774(): + M = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + v = [1, 1, 1] + raises(TypeError, lambda: M*v) + raises(TypeError, lambda: v*M) + +def test_companion(): + x = Symbol('x') + y = Symbol('y') + raises(ValueError, lambda: Matrix.companion(1)) + raises(ValueError, lambda: Matrix.companion(Poly([1], x))) + raises(ValueError, lambda: Matrix.companion(Poly([2, 1], x))) + raises(ValueError, lambda: Matrix.companion(Poly(x*y, [x, y]))) + + c0, c1, c2 = symbols('c0:3') + assert Matrix.companion(Poly([1, c0], x)) == Matrix([-c0]) + assert Matrix.companion(Poly([1, c1, c0], x)) == \ + Matrix([[0, -c0], [1, -c1]]) + assert Matrix.companion(Poly([1, c2, c1, c0], x)) == \ + Matrix([[0, 0, -c0], [1, 0, -c1], [0, 1, -c2]]) + +def test_issue_10589(): + x, y, z = symbols("x, y z") + M1 = Matrix([x, y, z]) + M1 = M1.subs(zip([x, y, z], [1, 2, 3])) + assert M1 == Matrix([[1], [2], [3]]) + + M2 = Matrix([[x, x, x, x, x], [x, x, x, x, x], [x, x, x, x, x]]) + M2 = M2.subs(zip([x], [1])) + assert M2 == Matrix([[1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1]]) + +def test_rmul_pr19860(): + class Foo(ImmutableDenseMatrix): + _op_priority = MutableDenseMatrix._op_priority + 0.01 + + a = Matrix(2, 2, [1, 2, 3, 4]) + b = Foo(2, 2, [1, 2, 3, 4]) + + # This would throw a RecursionError: maximum recursion depth + # since b always has higher priority even after a.as_mutable() + c = a*b + + assert isinstance(c, Foo) + assert c == Matrix([[7, 10], [15, 22]]) + + +def test_issue_18956(): + A = Array([[1, 2], [3, 4]]) + B = Matrix([[1,2],[3,4]]) + raises(TypeError, lambda: B + A) + raises(TypeError, lambda: A + B) + + +def test__eq__(): + class My(object): + def __iter__(self): + yield 1 + yield 2 + return + def __getitem__(self, i): + return list(self)[i] + a = Matrix(2, 1, [1, 2]) + assert a != My() + class My_sympy(My): + def _sympy_(self): + return Matrix(self) + assert a == My_sympy() diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_decompositions.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_decompositions.py new file mode 100644 index 0000000000000000000000000000000000000000..d169ec3a8846fed786981e62d932fd860b6d4951 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_decompositions.py @@ -0,0 +1,474 @@ +from sympy.core.function import expand_mul +from sympy.core.numbers import I, Rational +from sympy.core.singleton import S +from sympy.core.symbol import Symbol +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.complexes import Abs +from sympy.simplify.simplify import simplify +from sympy.matrices.exceptions import NonSquareMatrixError +from sympy.matrices import Matrix, zeros, eye, SparseMatrix +from sympy.abc import x, y, z +from sympy.testing.pytest import raises, slow +from sympy.testing.matrices import allclose + + +def test_LUdecomp(): + testmat = Matrix([[0, 2, 5, 3], + [3, 3, 7, 4], + [8, 4, 0, 2], + [-2, 6, 3, 4]]) + L, U, p = testmat.LUdecomposition() + assert L.is_lower + assert U.is_upper + assert (L*U).permute_rows(p, 'backward') - testmat == zeros(4) + + testmat = Matrix([[6, -2, 7, 4], + [0, 3, 6, 7], + [1, -2, 7, 4], + [-9, 2, 6, 3]]) + L, U, p = testmat.LUdecomposition() + assert L.is_lower + assert U.is_upper + assert (L*U).permute_rows(p, 'backward') - testmat == zeros(4) + + # non-square + testmat = Matrix([[1, 2, 3], + [4, 5, 6], + [7, 8, 9], + [10, 11, 12]]) + L, U, p = testmat.LUdecomposition(rankcheck=False) + assert L.is_lower + assert U.is_upper + assert (L*U).permute_rows(p, 'backward') - testmat == zeros(4, 3) + + # square and singular + testmat = Matrix([[1, 2, 3], + [2, 4, 6], + [4, 5, 6]]) + L, U, p = testmat.LUdecomposition(rankcheck=False) + assert L.is_lower + assert U.is_upper + assert (L*U).permute_rows(p, 'backward') - testmat == zeros(3) + + M = Matrix(((1, x, 1), (2, y, 0), (y, 0, z))) + L, U, p = M.LUdecomposition() + assert L.is_lower + assert U.is_upper + assert (L*U).permute_rows(p, 'backward') - M == zeros(3) + + mL = Matrix(( + (1, 0, 0), + (2, 3, 0), + )) + assert mL.is_lower is True + assert mL.is_upper is False + mU = Matrix(( + (1, 2, 3), + (0, 4, 5), + )) + assert mU.is_lower is False + assert mU.is_upper is True + + # test FF LUdecomp + M = Matrix([[1, 3, 3], + [3, 2, 6], + [3, 2, 2]]) + P, L, Dee, U = M.LUdecompositionFF() + assert P*M == L*Dee.inv()*U + + M = Matrix([[1, 2, 3, 4], + [3, -1, 2, 3], + [3, 1, 3, -2], + [6, -1, 0, 2]]) + P, L, Dee, U = M.LUdecompositionFF() + assert P*M == L*Dee.inv()*U + + M = Matrix([[0, 0, 1], + [2, 3, 0], + [3, 1, 4]]) + P, L, Dee, U = M.LUdecompositionFF() + assert P*M == L*Dee.inv()*U + + # issue 15794 + M = Matrix( + [[1, 2, 3], + [4, 5, 6], + [7, 8, 9]] + ) + raises(ValueError, lambda : M.LUdecomposition_Simple(rankcheck=True)) + +def test_singular_value_decompositionD(): + A = Matrix([[1, 2], [2, 1]]) + U, S, V = A.singular_value_decomposition() + assert U * S * V.T == A + assert U.T * U == eye(U.cols) + assert V.T * V == eye(V.cols) + + B = Matrix([[1, 2]]) + U, S, V = B.singular_value_decomposition() + + assert U * S * V.T == B + assert U.T * U == eye(U.cols) + assert V.T * V == eye(V.cols) + + C = Matrix([ + [1, 0, 0, 0, 2], + [0, 0, 3, 0, 0], + [0, 0, 0, 0, 0], + [0, 2, 0, 0, 0], + ]) + + U, S, V = C.singular_value_decomposition() + + assert U * S * V.T == C + assert U.T * U == eye(U.cols) + assert V.T * V == eye(V.cols) + + D = Matrix([[Rational(1, 3), sqrt(2)], [0, Rational(1, 4)]]) + U, S, V = D.singular_value_decomposition() + assert simplify(U.T * U) == eye(U.cols) + assert simplify(V.T * V) == eye(V.cols) + assert simplify(U * S * V.T) == D + + +def test_QR(): + A = Matrix([[1, 2], [2, 3]]) + Q, S = A.QRdecomposition() + R = Rational + assert Q == Matrix([ + [ 5**R(-1, 2), (R(2)/5)*(R(1)/5)**R(-1, 2)], + [2*5**R(-1, 2), (-R(1)/5)*(R(1)/5)**R(-1, 2)]]) + assert S == Matrix([[5**R(1, 2), 8*5**R(-1, 2)], [0, (R(1)/5)**R(1, 2)]]) + assert Q*S == A + assert Q.T * Q == eye(2) + + A = Matrix([[1, 1, 1], [1, 1, 3], [2, 3, 4]]) + Q, R = A.QRdecomposition() + assert Q.T * Q == eye(Q.cols) + assert R.is_upper + assert A == Q*R + + A = Matrix([[12, 0, -51], [6, 0, 167], [-4, 0, 24]]) + Q, R = A.QRdecomposition() + assert Q.T * Q == eye(Q.cols) + assert R.is_upper + assert A == Q*R + + x = Symbol('x') + A = Matrix([x]) + Q, R = A.QRdecomposition() + assert Q == Matrix([x / Abs(x)]) + assert R == Matrix([Abs(x)]) + + A = Matrix([[x, 0], [0, x]]) + Q, R = A.QRdecomposition() + assert Q == x / Abs(x) * Matrix([[1, 0], [0, 1]]) + assert R == Abs(x) * Matrix([[1, 0], [0, 1]]) + + +def test_QR_non_square(): + # Narrow (cols < rows) matrices + A = Matrix([[9, 0, 26], [12, 0, -7], [0, 4, 4], [0, -3, -3]]) + Q, R = A.QRdecomposition() + assert Q.T * Q == eye(Q.cols) + assert R.is_upper + assert A == Q*R + + A = Matrix([[1, -1, 4], [1, 4, -2], [1, 4, 2], [1, -1, 0]]) + Q, R = A.QRdecomposition() + assert Q.T * Q == eye(Q.cols) + assert R.is_upper + assert A == Q*R + + A = Matrix(2, 1, [1, 2]) + Q, R = A.QRdecomposition() + assert Q.T * Q == eye(Q.cols) + assert R.is_upper + assert A == Q*R + + # Wide (cols > rows) matrices + A = Matrix([[1, 2, 3], [4, 5, 6]]) + Q, R = A.QRdecomposition() + assert Q.T * Q == eye(Q.cols) + assert R.is_upper + assert A == Q*R + + A = Matrix([[1, 2, 3, 4], [1, 4, 9, 16], [1, 8, 27, 64]]) + Q, R = A.QRdecomposition() + assert Q.T * Q == eye(Q.cols) + assert R.is_upper + assert A == Q*R + + A = Matrix(1, 2, [1, 2]) + Q, R = A.QRdecomposition() + assert Q.T * Q == eye(Q.cols) + assert R.is_upper + assert A == Q*R + +def test_QR_trivial(): + # Rank deficient matrices + A = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + Q, R = A.QRdecomposition() + assert Q.T * Q == eye(Q.cols) + assert R.is_upper + assert A == Q*R + + A = Matrix([[1, 1, 1], [2, 2, 2], [3, 3, 3], [4, 4, 4]]) + Q, R = A.QRdecomposition() + assert Q.T * Q == eye(Q.cols) + assert R.is_upper + assert A == Q*R + + A = Matrix([[1, 1, 1], [2, 2, 2], [3, 3, 3], [4, 4, 4]]).T + Q, R = A.QRdecomposition() + assert Q.T * Q == eye(Q.cols) + assert R.is_upper + assert A == Q*R + + # Zero rank matrices + A = Matrix([[0, 0, 0]]) + Q, R = A.QRdecomposition() + assert Q.T * Q == eye(Q.cols) + assert R.is_upper + assert A == Q*R + + A = Matrix([[0, 0, 0]]).T + Q, R = A.QRdecomposition() + assert Q.T * Q == eye(Q.cols) + assert R.is_upper + assert A == Q*R + + A = Matrix([[0, 0, 0], [0, 0, 0]]) + Q, R = A.QRdecomposition() + assert Q.T * Q == eye(Q.cols) + assert R.is_upper + assert A == Q*R + + A = Matrix([[0, 0, 0], [0, 0, 0]]).T + Q, R = A.QRdecomposition() + assert Q.T * Q == eye(Q.cols) + assert R.is_upper + assert A == Q*R + + # Rank deficient matrices with zero norm from beginning columns + A = Matrix([[0, 0, 0], [1, 2, 3]]).T + Q, R = A.QRdecomposition() + assert Q.T * Q == eye(Q.cols) + assert R.is_upper + assert A == Q*R + + A = Matrix([[0, 0, 0, 0], [1, 2, 3, 4], [0, 0, 0, 0]]).T + Q, R = A.QRdecomposition() + assert Q.T * Q == eye(Q.cols) + assert R.is_upper + assert A == Q*R + + A = Matrix([[0, 0, 0, 0], [1, 2, 3, 4], [0, 0, 0, 0], [2, 4, 6, 8]]).T + Q, R = A.QRdecomposition() + assert Q.T * Q == eye(Q.cols) + assert R.is_upper + assert A == Q*R + + A = Matrix([[0, 0, 0], [0, 0, 0], [0, 0, 0], [1, 2, 3]]).T + Q, R = A.QRdecomposition() + assert Q.T * Q == eye(Q.cols) + assert R.is_upper + assert A == Q*R + + +def test_QR_float(): + A = Matrix([[1, 1], [1, 1.01]]) + Q, R = A.QRdecomposition() + assert allclose(Q * R, A) + assert allclose(Q * Q.T, Matrix.eye(2)) + assert allclose(Q.T * Q, Matrix.eye(2)) + + A = Matrix([[1, 1], [1, 1.001]]) + Q, R = A.QRdecomposition() + assert allclose(Q * R, A) + assert allclose(Q * Q.T, Matrix.eye(2)) + assert allclose(Q.T * Q, Matrix.eye(2)) + + +def test_LUdecomposition_Simple_iszerofunc(): + # Test if callable passed to matrices.LUdecomposition_Simple() as iszerofunc keyword argument is used inside + # matrices.LUdecomposition_Simple() + magic_string = "I got passed in!" + def goofyiszero(value): + raise ValueError(magic_string) + + try: + lu, p = Matrix([[1, 0], [0, 1]]).LUdecomposition_Simple(iszerofunc=goofyiszero) + except ValueError as err: + assert magic_string == err.args[0] + return + + assert False + +def test_LUdecomposition_iszerofunc(): + # Test if callable passed to matrices.LUdecomposition() as iszerofunc keyword argument is used inside + # matrices.LUdecomposition_Simple() + magic_string = "I got passed in!" + def goofyiszero(value): + raise ValueError(magic_string) + + try: + l, u, p = Matrix([[1, 0], [0, 1]]).LUdecomposition(iszerofunc=goofyiszero) + except ValueError as err: + assert magic_string == err.args[0] + return + + assert False + +def test_LDLdecomposition(): + raises(NonSquareMatrixError, lambda: Matrix((1, 2)).LDLdecomposition()) + raises(ValueError, lambda: Matrix(((1, 2), (3, 4))).LDLdecomposition()) + raises(ValueError, lambda: Matrix(((5 + I, 0), (0, 1))).LDLdecomposition()) + raises(ValueError, lambda: Matrix(((1, 5), (5, 1))).LDLdecomposition()) + raises(ValueError, lambda: Matrix(((1, 2), (3, 4))).LDLdecomposition(hermitian=False)) + A = Matrix(((1, 5), (5, 1))) + L, D = A.LDLdecomposition(hermitian=False) + assert L * D * L.T == A + A = Matrix(((25, 15, -5), (15, 18, 0), (-5, 0, 11))) + L, D = A.LDLdecomposition() + assert L * D * L.T == A + assert L.is_lower + assert L == Matrix([[1, 0, 0], [ Rational(3, 5), 1, 0], [Rational(-1, 5), Rational(1, 3), 1]]) + assert D.is_diagonal() + assert D == Matrix([[25, 0, 0], [0, 9, 0], [0, 0, 9]]) + A = Matrix(((4, -2*I, 2 + 2*I), (2*I, 2, -1 + I), (2 - 2*I, -1 - I, 11))) + L, D = A.LDLdecomposition() + assert expand_mul(L * D * L.H) == A + assert L.expand() == Matrix([[1, 0, 0], [I/2, 1, 0], [S.Half - I/2, 0, 1]]) + assert D.expand() == Matrix(((4, 0, 0), (0, 1, 0), (0, 0, 9))) + + raises(NonSquareMatrixError, lambda: SparseMatrix((1, 2)).LDLdecomposition()) + raises(ValueError, lambda: SparseMatrix(((1, 2), (3, 4))).LDLdecomposition()) + raises(ValueError, lambda: SparseMatrix(((5 + I, 0), (0, 1))).LDLdecomposition()) + raises(ValueError, lambda: SparseMatrix(((1, 5), (5, 1))).LDLdecomposition()) + raises(ValueError, lambda: SparseMatrix(((1, 2), (3, 4))).LDLdecomposition(hermitian=False)) + A = SparseMatrix(((1, 5), (5, 1))) + L, D = A.LDLdecomposition(hermitian=False) + assert L * D * L.T == A + A = SparseMatrix(((25, 15, -5), (15, 18, 0), (-5, 0, 11))) + L, D = A.LDLdecomposition() + assert L * D * L.T == A + assert L.is_lower + assert L == Matrix([[1, 0, 0], [ Rational(3, 5), 1, 0], [Rational(-1, 5), Rational(1, 3), 1]]) + assert D.is_diagonal() + assert D == Matrix([[25, 0, 0], [0, 9, 0], [0, 0, 9]]) + A = SparseMatrix(((4, -2*I, 2 + 2*I), (2*I, 2, -1 + I), (2 - 2*I, -1 - I, 11))) + L, D = A.LDLdecomposition() + assert expand_mul(L * D * L.H) == A + assert L == Matrix(((1, 0, 0), (I/2, 1, 0), (S.Half - I/2, 0, 1))) + assert D == Matrix(((4, 0, 0), (0, 1, 0), (0, 0, 9))) + +def test_pinv_succeeds_with_rank_decomposition_method(): + # Test rank decomposition method of pseudoinverse succeeding + As = [Matrix([ + [61, 89, 55, 20, 71, 0], + [62, 96, 85, 85, 16, 0], + [69, 56, 17, 4, 54, 0], + [10, 54, 91, 41, 71, 0], + [ 7, 30, 10, 48, 90, 0], + [0,0,0,0,0,0]])] + for A in As: + A_pinv = A.pinv(method="RD") + AAp = A * A_pinv + ApA = A_pinv * A + assert simplify(AAp * A) == A + assert simplify(ApA * A_pinv) == A_pinv + assert AAp.H == AAp + assert ApA.H == ApA + +def test_rank_decomposition(): + a = Matrix(0, 0, []) + c, f = a.rank_decomposition() + assert f.is_echelon + assert c.cols == f.rows == a.rank() + assert c * f == a + + a = Matrix(1, 1, [5]) + c, f = a.rank_decomposition() + assert f.is_echelon + assert c.cols == f.rows == a.rank() + assert c * f == a + + a = Matrix(3, 3, [1, 2, 3, 1, 2, 3, 1, 2, 3]) + c, f = a.rank_decomposition() + assert f.is_echelon + assert c.cols == f.rows == a.rank() + assert c * f == a + + a = Matrix([ + [0, 0, 1, 2, 2, -5, 3], + [-1, 5, 2, 2, 1, -7, 5], + [0, 0, -2, -3, -3, 8, -5], + [-1, 5, 0, -1, -2, 1, 0]]) + c, f = a.rank_decomposition() + assert f.is_echelon + assert c.cols == f.rows == a.rank() + assert c * f == a + + +@slow +def test_upper_hessenberg_decomposition(): + A = Matrix([ + [1, 0, sqrt(3)], + [sqrt(2), Rational(1, 2), 2], + [1, Rational(1, 4), 3], + ]) + H, P = A.upper_hessenberg_decomposition() + assert simplify(P * P.H) == eye(P.cols) + assert simplify(P.H * P) == eye(P.cols) + assert H.is_upper_hessenberg + assert (simplify(P * H * P.H)) == A + + + B = Matrix([ + [1, 2, 10], + [8, 2, 5], + [3, 12, 34], + ]) + H, P = B.upper_hessenberg_decomposition() + assert simplify(P * P.H) == eye(P.cols) + assert simplify(P.H * P) == eye(P.cols) + assert H.is_upper_hessenberg + assert simplify(P * H * P.H) == B + + C = Matrix([ + [1, sqrt(2), 2, 3], + [0, 5, 3, 4], + [1, 1, 4, sqrt(5)], + [0, 2, 2, 3] + ]) + + H, P = C.upper_hessenberg_decomposition() + assert simplify(P * P.H) == eye(P.cols) + assert simplify(P.H * P) == eye(P.cols) + assert H.is_upper_hessenberg + assert simplify(P * H * P.H) == C + + D = Matrix([ + [1, 2, 3], + [-3, 5, 6], + [4, -8, 9], + ]) + H, P = D.upper_hessenberg_decomposition() + assert simplify(P * P.H) == eye(P.cols) + assert simplify(P.H * P) == eye(P.cols) + assert H.is_upper_hessenberg + assert simplify(P * H * P.H) == D + + E = Matrix([ + [1, 0, 0, 0], + [0, 1, 0, 0], + [1, 1, 0, 1], + [1, 1, 1, 0] + ]) + + H, P = E.upper_hessenberg_decomposition() + assert simplify(P * P.H) == eye(P.cols) + assert simplify(P.H * P) == eye(P.cols) + assert H.is_upper_hessenberg + assert simplify(P * H * P.H) == E diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_determinant.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_determinant.py new file mode 100644 index 0000000000000000000000000000000000000000..82b42ccf67efa4757bf270782bdf1d65e0efa306 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_determinant.py @@ -0,0 +1,280 @@ +import random +import pytest +from sympy.core.numbers import I +from sympy.core.numbers import Rational +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.polys.polytools import Poly +from sympy.matrices import Matrix, eye, ones +from sympy.abc import x, y, z +from sympy.testing.pytest import raises +from sympy.matrices.exceptions import NonSquareMatrixError +from sympy.functions.combinatorial.factorials import factorial, subfactorial + + +@pytest.mark.parametrize("method", [ + # Evaluating these directly because they are never reached via M.det() + Matrix._eval_det_bareiss, Matrix._eval_det_berkowitz, + Matrix._eval_det_bird, Matrix._eval_det_laplace, Matrix._eval_det_lu +]) +@pytest.mark.parametrize("M, sol", [ + (Matrix(), 1), + (Matrix([[0]]), 0), + (Matrix([[5]]), 5), +]) +def test_eval_determinant(method, M, sol): + assert method(M) == sol + + +@pytest.mark.parametrize("method", [ + "domain-ge", "bareiss", "berkowitz", "bird", "laplace", "lu"]) +@pytest.mark.parametrize("M, sol", [ + (Matrix(( (-3, 2), + ( 8, -5) )), -1), + (Matrix(( (x, 1), + (y, 2*y) )), 2*x*y - y), + (Matrix(( (1, 1, 1), + (1, 2, 3), + (1, 3, 6) )), 1), + (Matrix(( ( 3, -2, 0, 5), + (-2, 1, -2, 2), + ( 0, -2, 5, 0), + ( 5, 0, 3, 4) )), -289), + (Matrix(( ( 1, 2, 3, 4), + ( 5, 6, 7, 8), + ( 9, 10, 11, 12), + (13, 14, 15, 16) )), 0), + (Matrix(( (3, 2, 0, 0, 0), + (0, 3, 2, 0, 0), + (0, 0, 3, 2, 0), + (0, 0, 0, 3, 2), + (2, 0, 0, 0, 3) )), 275), + (Matrix(( ( 3, 0, 0, 0), + (-2, 1, 0, 0), + ( 0, -2, 5, 0), + ( 5, 0, 3, 4) )), 60), + (Matrix(( ( 1, 0, 0, 0), + ( 5, 0, 0, 0), + ( 9, 10, 11, 0), + (13, 14, 15, 16) )), 0), + (Matrix(( (3, 2, 0, 0, 0), + (0, 3, 2, 0, 0), + (0, 0, 3, 2, 0), + (0, 0, 0, 3, 2), + (0, 0, 0, 0, 3) )), 243), + (Matrix(( (1, 0, 1, 2, 12), + (2, 0, 1, 1, 4), + (2, 1, 1, -1, 3), + (3, 2, -1, 1, 8), + (1, 1, 1, 0, 6) )), -55), + (Matrix(( (-5, 2, 3, 4, 5), + ( 1, -4, 3, 4, 5), + ( 1, 2, -3, 4, 5), + ( 1, 2, 3, -2, 5), + ( 1, 2, 3, 4, -1) )), 11664), + (Matrix(( ( 2, 7, -1, 3, 2), + ( 0, 0, 1, 0, 1), + (-2, 0, 7, 0, 2), + (-3, -2, 4, 5, 3), + ( 1, 0, 0, 0, 1) )), 123), + (Matrix(( (x, y, z), + (1, 0, 0), + (y, z, x) )), z**2 - x*y), +]) +def test_determinant(method, M, sol): + assert M.det(method=method) == sol + + +def test_issue_13835(): + a = symbols('a') + M = lambda n: Matrix([[i + a*j for i in range(n)] + for j in range(n)]) + assert M(5).det() == 0 + assert M(6).det() == 0 + assert M(7).det() == 0 + + +def test_issue_14517(): + M = Matrix([ + [ 0, 10*I, 10*I, 0], + [10*I, 0, 0, 10*I], + [10*I, 0, 5 + 2*I, 10*I], + [ 0, 10*I, 10*I, 5 + 2*I]]) + ev = M.eigenvals() + # test one random eigenvalue, the computation is a little slow + test_ev = random.choice(list(ev.keys())) + assert (M - test_ev*eye(4)).det() == 0 + + +@pytest.mark.parametrize("method", [ + "bareis", "det_lu", "det_LU", "Bareis", "BAREISS", "BERKOWITZ", "LU"]) +@pytest.mark.parametrize("M, sol", [ + (Matrix(( ( 3, -2, 0, 5), + (-2, 1, -2, 2), + ( 0, -2, 5, 0), + ( 5, 0, 3, 4) )), -289), + (Matrix(( (-5, 2, 3, 4, 5), + ( 1, -4, 3, 4, 5), + ( 1, 2, -3, 4, 5), + ( 1, 2, 3, -2, 5), + ( 1, 2, 3, 4, -1) )), 11664), +]) +def test_legacy_det(method, M, sol): + # Minimal support for legacy keys for 'method' in det() + # Partially copied from test_determinant() + assert M.det(method=method) == sol + + +def eye_Determinant(n): + return Matrix(n, n, lambda i, j: int(i == j)) + +def zeros_Determinant(n): + return Matrix(n, n, lambda i, j: 0) + +def test_det(): + a = Matrix(2, 3, [1, 2, 3, 4, 5, 6]) + raises(NonSquareMatrixError, lambda: a.det()) + + z = zeros_Determinant(2) + ey = eye_Determinant(2) + assert z.det() == 0 + assert ey.det() == 1 + + x = Symbol('x') + a = Matrix(0, 0, []) + b = Matrix(1, 1, [5]) + c = Matrix(2, 2, [1, 2, 3, 4]) + d = Matrix(3, 3, [1, 2, 3, 4, 5, 6, 7, 8, 8]) + e = Matrix(4, 4, + [x, 1, 2, 3, 4, 5, 6, 7, 2, 9, 10, 11, 12, 13, 14, 14]) + from sympy.abc import i, j, k, l, m, n + f = Matrix(3, 3, [i, l, m, 0, j, n, 0, 0, k]) + g = Matrix(3, 3, [i, 0, 0, l, j, 0, m, n, k]) + h = Matrix(3, 3, [x**3, 0, 0, i, x**-1, 0, j, k, x**-2]) + # the method keyword for `det` doesn't kick in until 4x4 matrices, + # so there is no need to test all methods on smaller ones + + assert a.det() == 1 + assert b.det() == 5 + assert c.det() == -2 + assert d.det() == 3 + assert e.det() == 4*x - 24 + assert e.det(method="domain-ge") == 4*x - 24 + assert e.det(method='bareiss') == 4*x - 24 + assert e.det(method='berkowitz') == 4*x - 24 + assert f.det() == i*j*k + assert g.det() == i*j*k + assert h.det() == 1 + raises(ValueError, lambda: e.det(iszerofunc="test")) + +def test_permanent(): + M = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + assert M.per() == 450 + for i in range(1, 12): + assert ones(i, i).per() == ones(i, i).T.per() == factorial(i) + assert (ones(i, i)-eye(i)).per() == (ones(i, i)-eye(i)).T.per() == subfactorial(i) + + a1, a2, a3, a4, a5 = symbols('a_1 a_2 a_3 a_4 a_5') + M = Matrix([a1, a2, a3, a4, a5]) + assert M.per() == M.T.per() == a1 + a2 + a3 + a4 + a5 + +def test_adjugate(): + x = Symbol('x') + e = Matrix(4, 4, + [x, 1, 2, 3, 4, 5, 6, 7, 2, 9, 10, 11, 12, 13, 14, 14]) + + adj = Matrix([ + [ 4, -8, 4, 0], + [ 76, -14*x - 68, 14*x - 8, -4*x + 24], + [-122, 17*x + 142, -21*x + 4, 8*x - 48], + [ 48, -4*x - 72, 8*x, -4*x + 24]]) + assert e.adjugate() == adj + assert e.adjugate(method='bareiss') == adj + assert e.adjugate(method='berkowitz') == adj + assert e.adjugate(method='bird') == adj + assert e.adjugate(method='laplace') == adj + + a = Matrix(2, 3, [1, 2, 3, 4, 5, 6]) + raises(NonSquareMatrixError, lambda: a.adjugate()) + +def test_util(): + R = Rational + + v1 = Matrix(1, 3, [1, 2, 3]) + v2 = Matrix(1, 3, [3, 4, 5]) + assert v1.norm() == sqrt(14) + assert v1.project(v2) == Matrix(1, 3, [R(39)/25, R(52)/25, R(13)/5]) + assert Matrix.zeros(1, 2) == Matrix(1, 2, [0, 0]) + assert ones(1, 2) == Matrix(1, 2, [1, 1]) + assert v1.copy() == v1 + # cofactor + assert eye(3) == eye(3).cofactor_matrix() + test = Matrix([[1, 3, 2], [2, 6, 3], [2, 3, 6]]) + assert test.cofactor_matrix() == \ + Matrix([[27, -6, -6], [-12, 2, 3], [-3, 1, 0]]) + test = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + assert test.cofactor_matrix() == \ + Matrix([[-3, 6, -3], [6, -12, 6], [-3, 6, -3]]) + +def test_cofactor_and_minors(): + x = Symbol('x') + e = Matrix(4, 4, + [x, 1, 2, 3, 4, 5, 6, 7, 2, 9, 10, 11, 12, 13, 14, 14]) + + m = Matrix([ + [ x, 1, 3], + [ 2, 9, 11], + [12, 13, 14]]) + cm = Matrix([ + [ 4, 76, -122, 48], + [-8, -14*x - 68, 17*x + 142, -4*x - 72], + [ 4, 14*x - 8, -21*x + 4, 8*x], + [ 0, -4*x + 24, 8*x - 48, -4*x + 24]]) + sub = Matrix([ + [x, 1, 2], + [4, 5, 6], + [2, 9, 10]]) + + assert e.minor_submatrix(1, 2) == m + assert e.minor_submatrix(-1, -1) == sub + assert e.minor(1, 2) == -17*x - 142 + assert e.cofactor(1, 2) == 17*x + 142 + assert e.cofactor_matrix() == cm + assert e.cofactor_matrix(method="bareiss") == cm + assert e.cofactor_matrix(method="berkowitz") == cm + assert e.cofactor_matrix(method="bird") == cm + assert e.cofactor_matrix(method="laplace") == cm + + raises(ValueError, lambda: e.cofactor(4, 5)) + raises(ValueError, lambda: e.minor(4, 5)) + raises(ValueError, lambda: e.minor_submatrix(4, 5)) + + a = Matrix(2, 3, [1, 2, 3, 4, 5, 6]) + assert a.minor_submatrix(0, 0) == Matrix([[5, 6]]) + + raises(ValueError, lambda: + Matrix(0, 0, []).minor_submatrix(0, 0)) + raises(NonSquareMatrixError, lambda: a.cofactor(0, 0)) + raises(NonSquareMatrixError, lambda: a.minor(0, 0)) + raises(NonSquareMatrixError, lambda: a.cofactor_matrix()) + +def test_charpoly(): + x, y = Symbol('x'), Symbol('y') + z, t = Symbol('z'), Symbol('t') + + from sympy.abc import a,b,c + + m = Matrix(3, 3, [1, 2, 3, 4, 5, 6, 7, 8, 9]) + + assert eye_Determinant(3).charpoly(x) == Poly((x - 1)**3, x) + assert eye_Determinant(3).charpoly(y) == Poly((y - 1)**3, y) + assert m.charpoly() == Poly(x**3 - 15*x**2 - 18*x, x) + raises(NonSquareMatrixError, lambda: Matrix([[1], [2]]).charpoly()) + n = Matrix(4, 4, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) + assert n.charpoly() == Poly(x**4, x) + + n = Matrix(4, 4, [45, 0, 0, 0, 0, 23, 0, 0, 0, 0, 87, 0, 0, 0, 0, 12]) + assert n.charpoly() == Poly(x**4 - 167*x**3 + 8811*x**2 - 173457*x + 1080540, x) + + n = Matrix(3, 3, [x, 0, 0, a, y, 0, b, c, z]) + assert n.charpoly() == Poly(t**3 - (x+y+z)*t**2 + t*(x*y+y*z+x*z) - x*y*z, t) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_domains.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_domains.py new file mode 100644 index 0000000000000000000000000000000000000000..26a54b8879a5c65f3a01b4886d223c08309e733d --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_domains.py @@ -0,0 +1,113 @@ +# Test Matrix/DomainMatrix interaction. + + +from sympy import GF, ZZ, QQ, EXRAW +from sympy.polys.matrices import DomainMatrix, DM + +from sympy import ( + Matrix, + MutableMatrix, + ImmutableMatrix, + SparseMatrix, + MutableDenseMatrix, + ImmutableDenseMatrix, + MutableSparseMatrix, + ImmutableSparseMatrix, +) +from sympy import symbols, S, sqrt + +from sympy.testing.pytest import raises + + +x, y = symbols('x y') + + +MATRIX_TYPES = ( + Matrix, + MutableMatrix, + ImmutableMatrix, + SparseMatrix, + MutableDenseMatrix, + ImmutableDenseMatrix, + MutableSparseMatrix, + ImmutableSparseMatrix, +) +IMMUTABLE = ( + ImmutableMatrix, + ImmutableDenseMatrix, + ImmutableSparseMatrix, +) + + +def DMs(items, domain): + return DM(items, domain).to_sparse() + + +def test_Matrix_rep_domain(): + + for Mat in MATRIX_TYPES: + + M = Mat([[1, 2], [3, 4]]) + assert M._rep == DMs([[1, 2], [3, 4]], ZZ) + assert (M / 2)._rep == DMs([[(1,2), 1], [(3,2), 2]], QQ) + if not isinstance(M, IMMUTABLE): + M[0, 0] = x + assert M._rep == DMs([[x, 2], [3, 4]], EXRAW) + + M = Mat([[S(1)/2, 2], [3, 4]]) + assert M._rep == DMs([[(1,2), 2], [3, 4]], QQ) + if not isinstance(M, IMMUTABLE): + M[0, 0] = x + assert M._rep == DMs([[x, 2], [3, 4]], EXRAW) + + dM = DMs([[1, 2], [3, 4]], ZZ) + assert Mat._fromrep(dM)._rep == dM + + # XXX: This is not intended. Perhaps it should be coerced to EXRAW? + # The private _fromrep method is never called like this but perhaps it + # should be guarded. + # + # It is not clear how to integrate domains other than ZZ, QQ and EXRAW with + # the rest of Matrix or if the public type for this needs to be something + # different from Matrix somehow. + K = QQ.algebraic_field(sqrt(2)) + dM = DM([[1, 2], [3, 4]], K) + assert Mat._fromrep(dM)._rep.domain == K + + +def test_Matrix_to_DM(): + + M = Matrix([[1, 2], [3, 4]]) + assert M.to_DM() == DMs([[1, 2], [3, 4]], ZZ) + assert M.to_DM() is not M._rep + assert M.to_DM(field=True) == DMs([[1, 2], [3, 4]], QQ) + assert M.to_DM(domain=QQ) == DMs([[1, 2], [3, 4]], QQ) + assert M.to_DM(domain=QQ[x]) == DMs([[1, 2], [3, 4]], QQ[x]) + assert M.to_DM(domain=GF(3)) == DMs([[1, 2], [0, 1]], GF(3)) + + M = Matrix([[1, 2], [3, 4]]) + M[0, 0] = x + assert M._rep.domain == EXRAW + M[0, 0] = 1 + assert M.to_DM() == DMs([[1, 2], [3, 4]], ZZ) + + M = Matrix([[S(1)/2, 2], [3, 4]]) + assert M.to_DM() == DMs([[QQ(1,2), 2], [3, 4]], QQ) + + M = Matrix([[x, 2], [3, 4]]) + assert M.to_DM() == DMs([[x, 2], [3, 4]], ZZ[x]) + assert M.to_DM(field=True) == DMs([[x, 2], [3, 4]], ZZ.frac_field(x)) + + M = Matrix([[1/x, 2], [3, 4]]) + assert M.to_DM() == DMs([[1/x, 2], [3, 4]], ZZ.frac_field(x)) + + M = Matrix([[1, sqrt(2)], [3, 4]]) + K = QQ.algebraic_field(sqrt(2)) + sqrt2 = K.from_sympy(sqrt(2)) # XXX: Maybe K(sqrt(2)) should work + M_K = DomainMatrix([[K(1), sqrt2], [K(3), K(4)]], (2, 2), K) + assert M.to_DM() == DMs([[1, sqrt(2)], [3, 4]], EXRAW) + assert M.to_DM(extension=True) == M_K.to_sparse() + + # Options cannot be used with the domain parameter + M = Matrix([[1, 2], [3, 4]]) + raises(TypeError, lambda: M.to_DM(domain=QQ, field=True)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_eigen.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_eigen.py new file mode 100644 index 0000000000000000000000000000000000000000..fcf96325519879e0683d29e2ddc32db7bf83baa4 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_eigen.py @@ -0,0 +1,712 @@ +from sympy.core.evalf import N +from sympy.core.numbers import (Float, I, Rational) +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.elementary.complexes import Abs +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.matrices import eye, Matrix +from sympy.core.singleton import S +from sympy.testing.pytest import raises, XFAIL +from sympy.matrices.exceptions import NonSquareMatrixError, MatrixError +from sympy.matrices.expressions.fourier import DFT +from sympy.simplify.simplify import simplify +from sympy.matrices.immutable import ImmutableMatrix +from sympy.testing.pytest import slow +from sympy.testing.matrices import allclose + + +def test_eigen(): + R = Rational + M = Matrix.eye(3) + assert M.eigenvals(multiple=False) == {S.One: 3} + assert M.eigenvals(multiple=True) == [1, 1, 1] + + assert M.eigenvects() == ( + [(1, 3, [Matrix([1, 0, 0]), + Matrix([0, 1, 0]), + Matrix([0, 0, 1])])]) + + assert M.left_eigenvects() == ( + [(1, 3, [Matrix([[1, 0, 0]]), + Matrix([[0, 1, 0]]), + Matrix([[0, 0, 1]])])]) + + M = Matrix([[0, 1, 1], + [1, 0, 0], + [1, 1, 1]]) + + assert M.eigenvals() == {2*S.One: 1, -S.One: 1, S.Zero: 1} + + assert M.eigenvects() == ( + [ + (-1, 1, [Matrix([-1, 1, 0])]), + ( 0, 1, [Matrix([0, -1, 1])]), + ( 2, 1, [Matrix([R(2, 3), R(1, 3), 1])]) + ]) + + assert M.left_eigenvects() == ( + [ + (-1, 1, [Matrix([[-2, 1, 1]])]), + (0, 1, [Matrix([[-1, -1, 1]])]), + (2, 1, [Matrix([[1, 1, 1]])]) + ]) + + a = Symbol('a') + M = Matrix([[a, 0], + [0, 1]]) + + assert M.eigenvals() == {a: 1, S.One: 1} + + M = Matrix([[1, -1], + [1, 3]]) + assert M.eigenvects() == ([(2, 2, [Matrix(2, 1, [-1, 1])])]) + assert M.left_eigenvects() == ([(2, 2, [Matrix([[1, 1]])])]) + + M = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + a = R(15, 2) + b = 3*33**R(1, 2) + c = R(13, 2) + d = (R(33, 8) + 3*b/8) + e = (R(33, 8) - 3*b/8) + + def NS(e, n): + return str(N(e, n)) + r = [ + (a - b/2, 1, [Matrix([(12 + 24/(c - b/2))/((c - b/2)*e) + 3/(c - b/2), + (6 + 12/(c - b/2))/e, 1])]), + ( 0, 1, [Matrix([1, -2, 1])]), + (a + b/2, 1, [Matrix([(12 + 24/(c + b/2))/((c + b/2)*d) + 3/(c + b/2), + (6 + 12/(c + b/2))/d, 1])]), + ] + r1 = [(NS(r[i][0], 2), NS(r[i][1], 2), + [NS(j, 2) for j in r[i][2][0]]) for i in range(len(r))] + r = M.eigenvects() + r2 = [(NS(r[i][0], 2), NS(r[i][1], 2), + [NS(j, 2) for j in r[i][2][0]]) for i in range(len(r))] + assert sorted(r1) == sorted(r2) + + eps = Symbol('eps', real=True) + + M = Matrix([[abs(eps), I*eps ], + [-I*eps, abs(eps) ]]) + + assert M.eigenvects() == ( + [ + ( 0, 1, [Matrix([[-I*eps/abs(eps)], [1]])]), + ( 2*abs(eps), 1, [ Matrix([[I*eps/abs(eps)], [1]]) ] ), + ]) + + assert M.left_eigenvects() == ( + [ + (0, 1, [Matrix([[I*eps/Abs(eps), 1]])]), + (2*Abs(eps), 1, [Matrix([[-I*eps/Abs(eps), 1]])]) + ]) + + M = Matrix(3, 3, [1, 2, 0, 0, 3, 0, 2, -4, 2]) + M._eigenvects = M.eigenvects(simplify=False) + assert max(i.q for i in M._eigenvects[0][2][0]) > 1 + M._eigenvects = M.eigenvects(simplify=True) + assert max(i.q for i in M._eigenvects[0][2][0]) == 1 + + M = Matrix([[Rational(1, 4), 1], [1, 1]]) + assert M.eigenvects() == [ + (Rational(5, 8) - sqrt(73)/8, 1, [Matrix([[-sqrt(73)/8 - Rational(3, 8)], [1]])]), + (Rational(5, 8) + sqrt(73)/8, 1, [Matrix([[Rational(-3, 8) + sqrt(73)/8], [1]])])] + + # issue 10719 + assert Matrix([]).eigenvals() == {} + assert Matrix([]).eigenvals(multiple=True) == [] + assert Matrix([]).eigenvects() == [] + + # issue 15119 + raises(NonSquareMatrixError, + lambda: Matrix([[1, 2], [0, 4], [0, 0]]).eigenvals()) + raises(NonSquareMatrixError, + lambda: Matrix([[1, 0], [3, 4], [5, 6]]).eigenvals()) + raises(NonSquareMatrixError, + lambda: Matrix([[1, 2, 3], [0, 5, 6]]).eigenvals()) + raises(NonSquareMatrixError, + lambda: Matrix([[1, 0, 0], [4, 5, 0]]).eigenvals()) + raises(NonSquareMatrixError, + lambda: Matrix([[1, 2, 3], [0, 5, 6]]).eigenvals( + error_when_incomplete = False)) + raises(NonSquareMatrixError, + lambda: Matrix([[1, 0, 0], [4, 5, 0]]).eigenvals( + error_when_incomplete = False)) + + m = Matrix([[1, 2], [3, 4]]) + assert isinstance(m.eigenvals(simplify=True, multiple=False), dict) + assert isinstance(m.eigenvals(simplify=True, multiple=True), list) + assert isinstance(m.eigenvals(simplify=lambda x: x, multiple=False), dict) + assert isinstance(m.eigenvals(simplify=lambda x: x, multiple=True), list) + + +def test_float_eigenvals(): + m = Matrix([[1, .6, .6], [.6, .9, .9], [.9, .6, .6]]) + evals = [ + Rational(5, 4) - sqrt(385)/20, + sqrt(385)/20 + Rational(5, 4), + S.Zero] + + n_evals = m.eigenvals(rational=True, multiple=True) + n_evals = sorted(n_evals) + s_evals = [x.evalf() for x in evals] + s_evals = sorted(s_evals) + + for x, y in zip(n_evals, s_evals): + assert abs(x-y) < 10**-9 + + +@XFAIL +def test_eigen_vects(): + m = Matrix(2, 2, [1, 0, 0, I]) + raises(NotImplementedError, lambda: m.is_diagonalizable(True)) + # !!! bug because of eigenvects() or roots(x**2 + (-1 - I)*x + I, x) + # see issue 5292 + assert not m.is_diagonalizable(True) + raises(MatrixError, lambda: m.diagonalize(True)) + (P, D) = m.diagonalize(True) + +def test_issue_8240(): + # Eigenvalues of large triangular matrices + x, y = symbols('x y') + n = 200 + + diagonal_variables = [Symbol('x%s' % i) for i in range(n)] + M = [[0 for i in range(n)] for j in range(n)] + for i in range(n): + M[i][i] = diagonal_variables[i] + M = Matrix(M) + + eigenvals = M.eigenvals() + assert len(eigenvals) == n + for i in range(n): + assert eigenvals[diagonal_variables[i]] == 1 + + eigenvals = M.eigenvals(multiple=True) + assert set(eigenvals) == set(diagonal_variables) + + # with multiplicity + M = Matrix([[x, 0, 0], [1, y, 0], [2, 3, x]]) + eigenvals = M.eigenvals() + assert eigenvals == {x: 2, y: 1} + + eigenvals = M.eigenvals(multiple=True) + assert len(eigenvals) == 3 + assert eigenvals.count(x) == 2 + assert eigenvals.count(y) == 1 + + +def test_eigenvals(): + M = Matrix([[0, 1, 1], + [1, 0, 0], + [1, 1, 1]]) + assert M.eigenvals() == {2*S.One: 1, -S.One: 1, S.Zero: 1} + + m = Matrix([ + [3, 0, 0, 0, -3], + [0, -3, -3, 0, 3], + [0, 3, 0, 3, 0], + [0, 0, 3, 0, 3], + [3, 0, 0, 3, 0]]) + + # XXX Used dry-run test because arbitrary symbol that appears in + # CRootOf may not be unique. + assert m.eigenvals() + + +def test_eigenvects(): + M = Matrix([[0, 1, 1], + [1, 0, 0], + [1, 1, 1]]) + vecs = M.eigenvects() + for val, mult, vec_list in vecs: + assert len(vec_list) == 1 + assert M*vec_list[0] == val*vec_list[0] + + +def test_left_eigenvects(): + M = Matrix([[0, 1, 1], + [1, 0, 0], + [1, 1, 1]]) + vecs = M.left_eigenvects() + for val, mult, vec_list in vecs: + assert len(vec_list) == 1 + assert vec_list[0]*M == val*vec_list[0] + + +@slow +def test_bidiagonalize(): + M = Matrix([[1, 0, 0], + [0, 1, 0], + [0, 0, 1]]) + assert M.bidiagonalize() == M + assert M.bidiagonalize(upper=False) == M + assert M.bidiagonalize() == M + assert M.bidiagonal_decomposition() == (M, M, M) + assert M.bidiagonal_decomposition(upper=False) == (M, M, M) + assert M.bidiagonalize() == M + + import random + #Real Tests + for real_test in range(2): + test_values = [] + row = 2 + col = 2 + for _ in range(row * col): + value = random.randint(-1000000000, 1000000000) + test_values = test_values + [value] + # L -> Lower Bidiagonalization + # M -> Mutable Matrix + # N -> Immutable Matrix + # 0 -> Bidiagonalized form + # 1,2,3 -> Bidiagonal_decomposition matrices + # 4 -> Product of 1 2 3 + M = Matrix(row, col, test_values) + N = ImmutableMatrix(M) + + N1, N2, N3 = N.bidiagonal_decomposition() + M1, M2, M3 = M.bidiagonal_decomposition() + M0 = M.bidiagonalize() + N0 = N.bidiagonalize() + + N4 = N1 * N2 * N3 + M4 = M1 * M2 * M3 + + N2.simplify() + N4.simplify() + N0.simplify() + + M0.simplify() + M2.simplify() + M4.simplify() + + LM0 = M.bidiagonalize(upper=False) + LM1, LM2, LM3 = M.bidiagonal_decomposition(upper=False) + LN0 = N.bidiagonalize(upper=False) + LN1, LN2, LN3 = N.bidiagonal_decomposition(upper=False) + + LN4 = LN1 * LN2 * LN3 + LM4 = LM1 * LM2 * LM3 + + LN2.simplify() + LN4.simplify() + LN0.simplify() + + LM0.simplify() + LM2.simplify() + LM4.simplify() + + assert M == M4 + assert M2 == M0 + assert N == N4 + assert N2 == N0 + assert M == LM4 + assert LM2 == LM0 + assert N == LN4 + assert LN2 == LN0 + + #Complex Tests + for complex_test in range(2): + test_values = [] + size = 2 + for _ in range(size * size): + real = random.randint(-1000000000, 1000000000) + comp = random.randint(-1000000000, 1000000000) + value = real + comp * I + test_values = test_values + [value] + M = Matrix(size, size, test_values) + N = ImmutableMatrix(M) + # L -> Lower Bidiagonalization + # M -> Mutable Matrix + # N -> Immutable Matrix + # 0 -> Bidiagonalized form + # 1,2,3 -> Bidiagonal_decomposition matrices + # 4 -> Product of 1 2 3 + N1, N2, N3 = N.bidiagonal_decomposition() + M1, M2, M3 = M.bidiagonal_decomposition() + M0 = M.bidiagonalize() + N0 = N.bidiagonalize() + + N4 = N1 * N2 * N3 + M4 = M1 * M2 * M3 + + N2.simplify() + N4.simplify() + N0.simplify() + + M0.simplify() + M2.simplify() + M4.simplify() + + LM0 = M.bidiagonalize(upper=False) + LM1, LM2, LM3 = M.bidiagonal_decomposition(upper=False) + LN0 = N.bidiagonalize(upper=False) + LN1, LN2, LN3 = N.bidiagonal_decomposition(upper=False) + + LN4 = LN1 * LN2 * LN3 + LM4 = LM1 * LM2 * LM3 + + LN2.simplify() + LN4.simplify() + LN0.simplify() + + LM0.simplify() + LM2.simplify() + LM4.simplify() + + assert M == M4 + assert M2 == M0 + assert N == N4 + assert N2 == N0 + assert M == LM4 + assert LM2 == LM0 + assert N == LN4 + assert LN2 == LN0 + + M = Matrix(18, 8, range(1, 145)) + M = M.applyfunc(lambda i: Float(i)) + assert M.bidiagonal_decomposition()[1] == M.bidiagonalize() + assert M.bidiagonal_decomposition(upper=False)[1] == M.bidiagonalize(upper=False) + a, b, c = M.bidiagonal_decomposition() + diff = a * b * c - M + assert abs(max(diff)) < 10**-12 + + +def test_diagonalize(): + m = Matrix(2, 2, [0, -1, 1, 0]) + raises(MatrixError, lambda: m.diagonalize(reals_only=True)) + P, D = m.diagonalize() + assert D.is_diagonal() + assert D == Matrix([ + [-I, 0], + [ 0, I]]) + + # make sure we use floats out if floats are passed in + m = Matrix(2, 2, [0, .5, .5, 0]) + P, D = m.diagonalize() + assert all(isinstance(e, Float) for e in D.values()) + assert all(isinstance(e, Float) for e in P.values()) + + _, D2 = m.diagonalize(reals_only=True) + assert D == D2 + + m = Matrix( + [[0, 1, 0, 0], [1, 0, 0, 0.002], [0.002, 0, 0, 1], [0, 0, 1, 0]]) + P, D = m.diagonalize() + assert allclose(P*D, m*P) + + +def test_is_diagonalizable(): + a, b, c = symbols('a b c') + m = Matrix(2, 2, [a, c, c, b]) + assert m.is_symmetric() + assert m.is_diagonalizable() + assert not Matrix(2, 2, [1, 1, 0, 1]).is_diagonalizable() + + m = Matrix(2, 2, [0, -1, 1, 0]) + assert m.is_diagonalizable() + assert not m.is_diagonalizable(reals_only=True) + + +def test_jordan_form(): + m = Matrix(3, 2, [-3, 1, -3, 20, 3, 10]) + raises(NonSquareMatrixError, lambda: m.jordan_form()) + + # the next two tests test the cases where the old + # algorithm failed due to the fact that the block structure can + # *NOT* be determined from algebraic and geometric multiplicity alone + # This can be seen most easily when one lets compute the J.c.f. of a matrix that + # is in J.c.f already. + m = Matrix(4, 4, [2, 1, 0, 0, + 0, 2, 1, 0, + 0, 0, 2, 0, + 0, 0, 0, 2 + ]) + P, J = m.jordan_form() + assert m == J + + m = Matrix(4, 4, [2, 1, 0, 0, + 0, 2, 0, 0, + 0, 0, 2, 1, + 0, 0, 0, 2 + ]) + P, J = m.jordan_form() + assert m == J + + A = Matrix([[ 2, 4, 1, 0], + [-4, 2, 0, 1], + [ 0, 0, 2, 4], + [ 0, 0, -4, 2]]) + P, J = A.jordan_form() + assert simplify(P*J*P.inv()) == A + + assert Matrix(1, 1, [1]).jordan_form() == (Matrix([1]), Matrix([1])) + assert Matrix(1, 1, [1]).jordan_form(calc_transform=False) == Matrix([1]) + + # If we have eigenvalues in CRootOf form, raise errors + m = Matrix([[3, 0, 0, 0, -3], [0, -3, -3, 0, 3], [0, 3, 0, 3, 0], [0, 0, 3, 0, 3], [3, 0, 0, 3, 0]]) + raises(MatrixError, lambda: m.jordan_form()) + + # make sure that if the input has floats, the output does too + m = Matrix([ + [ 0.6875, 0.125 + 0.1875*sqrt(3)], + [0.125 + 0.1875*sqrt(3), 0.3125]]) + P, J = m.jordan_form() + assert all(isinstance(x, Float) or x == 0 for x in P) + assert all(isinstance(x, Float) or x == 0 for x in J) + + +def test_singular_values(): + x = Symbol('x', real=True) + + A = Matrix([[0, 1*I], [2, 0]]) + # if singular values can be sorted, they should be in decreasing order + assert A.singular_values() == [2, 1] + + A = eye(3) + A[1, 1] = x + A[2, 2] = 5 + vals = A.singular_values() + # since Abs(x) cannot be sorted, test set equality + assert set(vals) == {5, 1, Abs(x)} + + A = Matrix([[sin(x), cos(x)], [-cos(x), sin(x)]]) + vals = [sv.trigsimp() for sv in A.singular_values()] + assert vals == [S.One, S.One] + + A = Matrix([ + [2, 4], + [1, 3], + [0, 0], + [0, 0] + ]) + assert A.singular_values() == \ + [sqrt(sqrt(221) + 15), sqrt(15 - sqrt(221))] + assert A.T.singular_values() == \ + [sqrt(sqrt(221) + 15), sqrt(15 - sqrt(221)), 0, 0] + +def test___eq__(): + assert (Matrix( + [[0, 1, 1], + [1, 0, 0], + [1, 1, 1]]) == {}) is False + + +def test_definite(): + # Examples from Gilbert Strang, "Introduction to Linear Algebra" + # Positive definite matrices + m = Matrix([[2, -1, 0], [-1, 2, -1], [0, -1, 2]]) + assert m.is_positive_definite == True + assert m.is_positive_semidefinite == True + assert m.is_negative_definite == False + assert m.is_negative_semidefinite == False + assert m.is_indefinite == False + + m = Matrix([[5, 4], [4, 5]]) + assert m.is_positive_definite == True + assert m.is_positive_semidefinite == True + assert m.is_negative_definite == False + assert m.is_negative_semidefinite == False + assert m.is_indefinite == False + + # Positive semidefinite matrices + m = Matrix([[2, -1, -1], [-1, 2, -1], [-1, -1, 2]]) + assert m.is_positive_definite == False + assert m.is_positive_semidefinite == True + assert m.is_negative_definite == False + assert m.is_negative_semidefinite == False + assert m.is_indefinite == False + + m = Matrix([[1, 2], [2, 4]]) + assert m.is_positive_definite == False + assert m.is_positive_semidefinite == True + assert m.is_negative_definite == False + assert m.is_negative_semidefinite == False + assert m.is_indefinite == False + + # Examples from Mathematica documentation + # Non-hermitian positive definite matrices + m = Matrix([[2, 3], [4, 8]]) + assert m.is_positive_definite == True + assert m.is_positive_semidefinite == True + assert m.is_negative_definite == False + assert m.is_negative_semidefinite == False + assert m.is_indefinite == False + + # Hermetian matrices + m = Matrix([[1, 2*I], [-I, 4]]) + assert m.is_positive_definite == True + assert m.is_positive_semidefinite == True + assert m.is_negative_definite == False + assert m.is_negative_semidefinite == False + assert m.is_indefinite == False + + # Symbolic matrices examples + a = Symbol('a', positive=True) + b = Symbol('b', negative=True) + m = Matrix([[a, 0, 0], [0, a, 0], [0, 0, a]]) + assert m.is_positive_definite == True + assert m.is_positive_semidefinite == True + assert m.is_negative_definite == False + assert m.is_negative_semidefinite == False + assert m.is_indefinite == False + + m = Matrix([[b, 0, 0], [0, b, 0], [0, 0, b]]) + assert m.is_positive_definite == False + assert m.is_positive_semidefinite == False + assert m.is_negative_definite == True + assert m.is_negative_semidefinite == True + assert m.is_indefinite == False + + m = Matrix([[a, 0], [0, b]]) + assert m.is_positive_definite == False + assert m.is_positive_semidefinite == False + assert m.is_negative_definite == False + assert m.is_negative_semidefinite == False + assert m.is_indefinite == True + + m = Matrix([ + [0.0228202735623867, 0.00518748979085398, + -0.0743036351048907, -0.00709135324903921], + [0.00518748979085398, 0.0349045359786350, + 0.0830317991056637, 0.00233147902806909], + [-0.0743036351048907, 0.0830317991056637, + 1.15859676366277, 0.340359081555988], + [-0.00709135324903921, 0.00233147902806909, + 0.340359081555988, 0.928147644848199] + ]) + assert m.is_positive_definite == True + assert m.is_positive_semidefinite == True + assert m.is_indefinite == False + + # test for issue 19547: https://github.com/sympy/sympy/issues/19547 + m = Matrix([ + [0, 0, 0], + [0, 1, 2], + [0, 2, 1] + ]) + assert not m.is_positive_definite + assert not m.is_positive_semidefinite + + +def test_positive_semidefinite_cholesky(): + from sympy.matrices.eigen import _is_positive_semidefinite_cholesky + + m = Matrix([[0, 0, 0], [0, 0, 0], [0, 0, 0]]) + assert _is_positive_semidefinite_cholesky(m) == True + m = Matrix([[0, 0, 0], [0, 5, -10*I], [0, 10*I, 5]]) + assert _is_positive_semidefinite_cholesky(m) == False + m = Matrix([[1, 0, 0], [0, 0, 0], [0, 0, -1]]) + assert _is_positive_semidefinite_cholesky(m) == False + m = Matrix([[0, 1], [1, 0]]) + assert _is_positive_semidefinite_cholesky(m) == False + + # https://www.value-at-risk.net/cholesky-factorization/ + m = Matrix([[4, -2, -6], [-2, 10, 9], [-6, 9, 14]]) + assert _is_positive_semidefinite_cholesky(m) == True + m = Matrix([[9, -3, 3], [-3, 2, 1], [3, 1, 6]]) + assert _is_positive_semidefinite_cholesky(m) == True + m = Matrix([[4, -2, 2], [-2, 1, -1], [2, -1, 5]]) + assert _is_positive_semidefinite_cholesky(m) == True + m = Matrix([[1, 2, -1], [2, 5, 1], [-1, 1, 9]]) + assert _is_positive_semidefinite_cholesky(m) == False + + +def test_issue_20582(): + A = Matrix([ + [5, -5, -3, 2, -7], + [-2, -5, 0, 2, 1], + [-2, -7, -5, -2, -6], + [7, 10, 3, 9, -2], + [4, -10, 3, -8, -4] + ]) + # XXX Used dry-run test because arbitrary symbol that appears in + # CRootOf may not be unique. + assert A.eigenvects() + +def test_issue_19210(): + t = Symbol('t') + H = Matrix([[3, 0, 0, 0], [0, 1 , 2, 0], [0, 2, 2, 0], [0, 0, 0, 4]]) + A = (-I * H * t).jordan_form() + assert A == (Matrix([ + [0, 1, 0, 0], + [0, 0, -4/(-1 + sqrt(17)), 4/(1 + sqrt(17))], + [0, 0, 1, 1], + [1, 0, 0, 0]]), Matrix([ + [-4*I*t, 0, 0, 0], + [ 0, -3*I*t, 0, 0], + [ 0, 0, t*(-3*I/2 + sqrt(17)*I/2), 0], + [ 0, 0, 0, t*(-sqrt(17)*I/2 - 3*I/2)]])) + + +def test_issue_20275(): + # XXX We use complex expansions because complex exponentials are not + # recognized by polys.domains + A = DFT(3).as_explicit().expand(complex=True) + eigenvects = A.eigenvects() + assert eigenvects[0] == ( + -1, 1, + [Matrix([[1 - sqrt(3)], [1], [1]])] + ) + assert eigenvects[1] == ( + 1, 1, + [Matrix([[1 + sqrt(3)], [1], [1]])] + ) + assert eigenvects[2] == ( + -I, 1, + [Matrix([[0], [-1], [1]])] + ) + + A = DFT(4).as_explicit().expand(complex=True) + eigenvects = A.eigenvects() + assert eigenvects[0] == ( + -1, 1, + [Matrix([[-1], [1], [1], [1]])] + ) + assert eigenvects[1] == ( + 1, 2, + [Matrix([[1], [0], [1], [0]]), Matrix([[2], [1], [0], [1]])] + ) + assert eigenvects[2] == ( + -I, 1, + [Matrix([[0], [-1], [0], [1]])] + ) + + # XXX We skip test for some parts of eigenvectors which are very + # complicated and fragile under expression tree changes + A = DFT(5).as_explicit().expand(complex=True) + eigenvects = A.eigenvects() + assert eigenvects[0] == ( + -1, 1, + [Matrix([[1 - sqrt(5)], [1], [1], [1], [1]])] + ) + assert eigenvects[1] == ( + 1, 2, + [Matrix([[S(1)/2 + sqrt(5)/2], [0], [1], [1], [0]]), + Matrix([[S(1)/2 + sqrt(5)/2], [1], [0], [0], [1]])] + ) + + +def test_issue_20752(): + b = symbols('b', nonzero=True) + m = Matrix([[0, 0, 0], [0, b, 0], [0, 0, b]]) + assert m.is_positive_semidefinite is None + + +def test_issue_25282(): + dd = sd = [0] * 11 + [1] + ds = [2, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0] + ss = ds.copy() + ss[8] = 2 + + def rotate(x, i): + return x[i:] + x[:i] + + mat = [] + for i in range(12): + mat.append(rotate(ss, i) + rotate(sd, i)) + for i in range(12): + mat.append(rotate(ds, i) + rotate(dd, i)) + + assert sum(Matrix(mat).eigenvals().values()) == 24 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_graph.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_graph.py new file mode 100644 index 0000000000000000000000000000000000000000..0bf3c819a9477387f53560a034d7949fd76a654f --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_graph.py @@ -0,0 +1,108 @@ +from sympy.combinatorics import Permutation +from sympy.core.symbol import symbols +from sympy.matrices import Matrix +from sympy.matrices.expressions import ( + PermutationMatrix, BlockDiagMatrix, BlockMatrix) + + +def test_connected_components(): + a, b, c, d, e, f, g, h, i, j, k, l, m = symbols('a:m') + + M = Matrix([ + [a, 0, 0, 0, b, 0, 0, 0, 0, 0, c, 0, 0], + [0, d, 0, 0, 0, e, 0, 0, 0, 0, 0, f, 0], + [0, 0, g, 0, 0, 0, h, 0, 0, 0, 0, 0, i], + [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [m, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], + [0, m, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], + [0, 0, m, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], + [j, 0, 0, 0, k, 0, 0, 1, 0, 0, l, 0, 0], + [0, j, 0, 0, 0, k, 0, 0, 1, 0, 0, l, 0], + [0, 0, j, 0, 0, 0, k, 0, 0, 1, 0, 0, l], + [0, 0, 0, 0, d, 0, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 0, 0, 0, d, 0, 0, 0, 0, 0, 1, 0], + [0, 0, 0, 0, 0, 0, d, 0, 0, 0, 0, 0, 1]]) + cc = M.connected_components() + assert cc == [[0, 4, 7, 10], [1, 5, 8, 11], [2, 6, 9, 12], [3]] + + P, B = M.connected_components_decomposition() + p = Permutation([0, 4, 7, 10, 1, 5, 8, 11, 2, 6, 9, 12, 3]) + assert P == PermutationMatrix(p) + + B0 = Matrix([ + [a, b, 0, c], + [m, 1, 0, 0], + [j, k, 1, l], + [0, d, 0, 1]]) + B1 = Matrix([ + [d, e, 0, f], + [m, 1, 0, 0], + [j, k, 1, l], + [0, d, 0, 1]]) + B2 = Matrix([ + [g, h, 0, i], + [m, 1, 0, 0], + [j, k, 1, l], + [0, d, 0, 1]]) + B3 = Matrix([[1]]) + assert B == BlockDiagMatrix(B0, B1, B2, B3) + + +def test_strongly_connected_components(): + M = Matrix([ + [11, 14, 10, 0, 15, 0], + [0, 44, 0, 0, 45, 0], + [1, 4, 0, 0, 5, 0], + [0, 0, 0, 22, 0, 23], + [0, 54, 0, 0, 55, 0], + [0, 0, 0, 32, 0, 33]]) + scc = M.strongly_connected_components() + assert scc == [[1, 4], [0, 2], [3, 5]] + + P, B = M.strongly_connected_components_decomposition() + p = Permutation([1, 4, 0, 2, 3, 5]) + assert P == PermutationMatrix(p) + assert B == BlockMatrix([ + [ + Matrix([[44, 45], [54, 55]]), + Matrix.zeros(2, 2), + Matrix.zeros(2, 2) + ], + [ + Matrix([[14, 15], [4, 5]]), + Matrix([[11, 10], [1, 0]]), + Matrix.zeros(2, 2) + ], + [ + Matrix.zeros(2, 2), + Matrix.zeros(2, 2), + Matrix([[22, 23], [32, 33]]) + ] + ]) + P = P.as_explicit() + B = B.as_explicit() + assert P.T * B * P == M + + P, B = M.strongly_connected_components_decomposition(lower=False) + p = Permutation([3, 5, 0, 2, 1, 4]) + assert P == PermutationMatrix(p) + assert B == BlockMatrix([ + [ + Matrix([[22, 23], [32, 33]]), + Matrix.zeros(2, 2), + Matrix.zeros(2, 2) + ], + [ + Matrix.zeros(2, 2), + Matrix([[11, 10], [1, 0]]), + Matrix([[14, 15], [4, 5]]) + ], + [ + Matrix.zeros(2, 2), + Matrix.zeros(2, 2), + Matrix([[44, 45], [54, 55]]) + ] + ]) + P = P.as_explicit() + B = B.as_explicit() + assert P.T * B * P == M diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_immutable.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_immutable.py new file mode 100644 index 0000000000000000000000000000000000000000..2b83c1f9fae7f83be9d5f7dd4b484781dc128faf --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_immutable.py @@ -0,0 +1,136 @@ +from itertools import product + +from sympy.core.relational import (Equality, Unequality) +from sympy.core.singleton import S +from sympy.core.sympify import sympify +from sympy.integrals.integrals import integrate +from sympy.matrices.dense import (Matrix, eye, zeros) +from sympy.matrices.immutable import ImmutableMatrix +from sympy.matrices import SparseMatrix +from sympy.matrices.immutable import \ + ImmutableDenseMatrix, ImmutableSparseMatrix +from sympy.abc import x, y +from sympy.testing.pytest import raises + +IM = ImmutableDenseMatrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) +ISM = ImmutableSparseMatrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) +ieye = ImmutableDenseMatrix(eye(3)) + + +def test_creation(): + assert IM.shape == ISM.shape == (3, 3) + assert IM[1, 2] == ISM[1, 2] == 6 + assert IM[2, 2] == ISM[2, 2] == 9 + + +def test_immutability(): + with raises(TypeError): + IM[2, 2] = 5 + with raises(TypeError): + ISM[2, 2] = 5 + + +def test_slicing(): + assert IM[1, :] == ImmutableDenseMatrix([[4, 5, 6]]) + assert IM[:2, :2] == ImmutableDenseMatrix([[1, 2], [4, 5]]) + assert ISM[1, :] == ImmutableSparseMatrix([[4, 5, 6]]) + assert ISM[:2, :2] == ImmutableSparseMatrix([[1, 2], [4, 5]]) + + +def test_subs(): + A = ImmutableMatrix([[1, 2], [3, 4]]) + B = ImmutableMatrix([[1, 2], [x, 4]]) + C = ImmutableMatrix([[-x, x*y], [-(x + y), y**2]]) + assert B.subs(x, 3) == A + assert (x*B).subs(x, 3) == 3*A + assert (x*eye(2) + B).subs(x, 3) == 3*eye(2) + A + assert C.subs([[x, -1], [y, -2]]) == A + assert C.subs([(x, -1), (y, -2)]) == A + assert C.subs({x: -1, y: -2}) == A + assert C.subs({x: y - 1, y: x - 1}, simultaneous=True) == \ + ImmutableMatrix([[1 - y, (x - 1)*(y - 1)], [2 - x - y, (x - 1)**2]]) + + +def test_as_immutable(): + data = [[1, 2], [3, 4]] + X = Matrix(data) + assert sympify(X) == X.as_immutable() == ImmutableMatrix(data) + + data = {(0, 0): 1, (0, 1): 2, (1, 0): 3, (1, 1): 4} + X = SparseMatrix(2, 2, data) + assert sympify(X) == X.as_immutable() == ImmutableSparseMatrix(2, 2, data) + + +def test_function_return_types(): + # Lets ensure that decompositions of immutable matrices remain immutable + # I.e. do MatrixBase methods return the correct class? + X = ImmutableMatrix([[1, 2], [3, 4]]) + Y = ImmutableMatrix([[1], [0]]) + q, r = X.QRdecomposition() + assert (type(q), type(r)) == (ImmutableMatrix, ImmutableMatrix) + + assert type(X.LUsolve(Y)) == ImmutableMatrix + assert type(X.QRsolve(Y)) == ImmutableMatrix + + X = ImmutableMatrix([[5, 2], [2, 7]]) + assert X.T == X + assert X.is_symmetric + assert type(X.cholesky()) == ImmutableMatrix + L, D = X.LDLdecomposition() + assert (type(L), type(D)) == (ImmutableMatrix, ImmutableMatrix) + + X = ImmutableMatrix([[1, 2], [2, 1]]) + assert X.is_diagonalizable() + assert X.det() == -3 + assert X.norm(2) == 3 + + assert type(X.eigenvects()[0][2][0]) == ImmutableMatrix + + assert type(zeros(3, 3).as_immutable().nullspace()[0]) == ImmutableMatrix + + X = ImmutableMatrix([[1, 0], [2, 1]]) + assert type(X.lower_triangular_solve(Y)) == ImmutableMatrix + assert type(X.T.upper_triangular_solve(Y)) == ImmutableMatrix + + assert type(X.minor_submatrix(0, 0)) == ImmutableMatrix + +# issue 6279 +# https://github.com/sympy/sympy/issues/6279 +# Test that Immutable _op_ Immutable => Immutable and not MatExpr + + +def test_immutable_evaluation(): + X = ImmutableMatrix(eye(3)) + A = ImmutableMatrix(3, 3, range(9)) + assert isinstance(X + A, ImmutableMatrix) + assert isinstance(X * A, ImmutableMatrix) + assert isinstance(X * 2, ImmutableMatrix) + assert isinstance(2 * X, ImmutableMatrix) + assert isinstance(A**2, ImmutableMatrix) + + +def test_deterimant(): + assert ImmutableMatrix(4, 4, lambda i, j: i + j).det() == 0 + + +def test_Equality(): + assert Equality(IM, IM) is S.true + assert Unequality(IM, IM) is S.false + assert Equality(IM, IM.subs(1, 2)) is S.false + assert Unequality(IM, IM.subs(1, 2)) is S.true + assert Equality(IM, 2) is S.false + assert Unequality(IM, 2) is S.true + M = ImmutableMatrix([x, y]) + assert Equality(M, IM) is S.false + assert Unequality(M, IM) is S.true + assert Equality(M, M.subs(x, 2)).subs(x, 2) is S.true + assert Unequality(M, M.subs(x, 2)).subs(x, 2) is S.false + assert Equality(M, M.subs(x, 2)).subs(x, 3) is S.false + assert Unequality(M, M.subs(x, 2)).subs(x, 3) is S.true + + +def test_integrate(): + intIM = integrate(IM, x) + assert intIM.shape == IM.shape + assert all(intIM[i, j] == (1 + j + 3*i)*x for i, j in + product(range(3), range(3))) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_interactions.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_interactions.py new file mode 100644 index 0000000000000000000000000000000000000000..f4fc3268368e8dd632fc0df187d57ea5e845120c --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_interactions.py @@ -0,0 +1,77 @@ +""" +We have a few different kind of Matrices +Matrix, ImmutableMatrix, MatrixExpr + +Here we test the extent to which they cooperate +""" + +from sympy.core.symbol import symbols +from sympy.matrices import (Matrix, MatrixSymbol, eye, Identity, + ImmutableMatrix) +from sympy.matrices.expressions import MatrixExpr, MatAdd +from sympy.matrices.matrixbase import classof +from sympy.testing.pytest import raises + +SM = MatrixSymbol('X', 3, 3) +SV = MatrixSymbol('v', 3, 1) +MM = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) +IM = ImmutableMatrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) +meye = eye(3) +imeye = ImmutableMatrix(eye(3)) +ideye = Identity(3) +a, b, c = symbols('a,b,c') + + +def test_IM_MM(): + assert isinstance(MM + IM, ImmutableMatrix) + assert isinstance(IM + MM, ImmutableMatrix) + assert isinstance(2*IM + MM, ImmutableMatrix) + assert MM.equals(IM) + + +def test_ME_MM(): + assert isinstance(Identity(3) + MM, MatrixExpr) + assert isinstance(SM + MM, MatAdd) + assert isinstance(MM + SM, MatAdd) + assert (Identity(3) + MM)[1, 1] == 6 + + +def test_equality(): + a, b, c = Identity(3), eye(3), ImmutableMatrix(eye(3)) + for x in [a, b, c]: + for y in [a, b, c]: + assert x.equals(y) + + +def test_matrix_symbol_MM(): + X = MatrixSymbol('X', 3, 3) + Y = eye(3) + X + assert Y[1, 1] == 1 + X[1, 1] + + +def test_matrix_symbol_vector_matrix_multiplication(): + A = MM * SV + B = IM * SV + assert A == B + C = (SV.T * MM.T).T + assert B == C + D = (SV.T * IM.T).T + assert C == D + + +def test_indexing_interactions(): + assert (a * IM)[1, 1] == 5*a + assert (SM + IM)[1, 1] == SM[1, 1] + IM[1, 1] + assert (SM * IM)[1, 1] == SM[1, 0]*IM[0, 1] + SM[1, 1]*IM[1, 1] + \ + SM[1, 2]*IM[2, 1] + + +def test_classof(): + A = Matrix(3, 3, range(9)) + B = ImmutableMatrix(3, 3, range(9)) + C = MatrixSymbol('C', 3, 3) + assert classof(A, A) == Matrix + assert classof(B, B) == ImmutableMatrix + assert classof(A, B) == ImmutableMatrix + assert classof(B, A) == ImmutableMatrix + raises(TypeError, lambda: classof(A, C)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_matrices.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_matrices.py new file mode 100644 index 0000000000000000000000000000000000000000..d9d97341de570e078d652dddce58fb8f5cb99e43 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_matrices.py @@ -0,0 +1,3487 @@ +# +# Code for testing deprecated matrix classes. New test code should not be added +# here. Instead, add it to test_matrixbase.py. +# +# This entire test module and the corresponding sympy/matrices/matrices.py +# module will be removed in a future release. +# +import random +import concurrent.futures +from collections.abc import Hashable + +from sympy.core.add import Add +from sympy.core.function import Function, diff, expand +from sympy.core.numbers import (E, Float, I, Integer, Rational, nan, oo, pi) +from sympy.core.power import Pow +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.core.sympify import sympify +from sympy.functions.elementary.complexes import Abs +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.miscellaneous import (Max, Min, sqrt) +from sympy.functions.elementary.trigonometric import (cos, sin, tan) +from sympy.integrals.integrals import integrate +from sympy.matrices.expressions.transpose import transpose +from sympy.physics.quantum.operator import HermitianOperator, Operator, Dagger +from sympy.polys.polytools import (Poly, PurePoly) +from sympy.polys.rootoftools import RootOf +from sympy.printing.str import sstr +from sympy.sets.sets import FiniteSet +from sympy.simplify.simplify import (signsimp, simplify) +from sympy.simplify.trigsimp import trigsimp +from sympy.matrices.exceptions import (ShapeError, MatrixError, + NonSquareMatrixError) +from sympy.matrices.matrixbase import DeferredVector +from sympy.matrices.determinant import _find_reasonable_pivot_naive +from sympy.matrices.utilities import _simplify +from sympy.matrices import ( + GramSchmidt, ImmutableMatrix, ImmutableSparseMatrix, Matrix, + SparseMatrix, casoratian, diag, eye, hessian, + matrix_multiply_elementwise, ones, randMatrix, rot_axis1, rot_axis2, + rot_axis3, wronskian, zeros, MutableDenseMatrix, ImmutableDenseMatrix, + MatrixSymbol, dotprodsimp, rot_ccw_axis1, rot_ccw_axis2, rot_ccw_axis3) +from sympy.matrices.utilities import _dotprodsimp_state +from sympy.core import Tuple, Wild +from sympy.functions.special.tensor_functions import KroneckerDelta +from sympy.utilities.iterables import flatten, capture, iterable +from sympy.utilities.exceptions import ignore_warnings +from sympy.testing.pytest import (raises, XFAIL, slow, skip, skip_under_pyodide, + warns_deprecated_sympy) +from sympy.assumptions import Q +from sympy.tensor.array import Array +from sympy.tensor.array.array_derivatives import ArrayDerivative +from sympy.matrices.expressions import MatPow +from sympy.algebras import Quaternion + +from sympy import O + +from sympy.abc import a, b, c, d, x, y, z, t + + +# don't re-order this list +classes = (Matrix, SparseMatrix, ImmutableMatrix, ImmutableSparseMatrix) + + +# Test the deprecated matrixmixins +from sympy.matrices.common import _MinimalMatrix, _CastableMatrix +from sympy.matrices.matrices import MatrixSubspaces, MatrixReductions + + +with warns_deprecated_sympy(): + class SubspaceOnlyMatrix(_MinimalMatrix, _CastableMatrix, MatrixSubspaces): + pass + + +with warns_deprecated_sympy(): + class ReductionsOnlyMatrix(_MinimalMatrix, _CastableMatrix, MatrixReductions): + pass + + +def eye_Reductions(n): + return ReductionsOnlyMatrix(n, n, lambda i, j: int(i == j)) + + +def zeros_Reductions(n): + return ReductionsOnlyMatrix(n, n, lambda i, j: 0) + + +def test_args(): + for n, cls in enumerate(classes): + m = cls.zeros(3, 2) + # all should give back the same type of arguments, e.g. ints for shape + assert m.shape == (3, 2) and all(type(i) is int for i in m.shape) + assert m.rows == 3 and type(m.rows) is int + assert m.cols == 2 and type(m.cols) is int + if not n % 2: + assert type(m.flat()) in (list, tuple, Tuple) + else: + assert type(m.todok()) is dict + + +def test_deprecated_mat_smat(): + for cls in Matrix, ImmutableMatrix: + m = cls.zeros(3, 2) + with warns_deprecated_sympy(): + mat = m._mat + assert mat == m.flat() + for cls in SparseMatrix, ImmutableSparseMatrix: + m = cls.zeros(3, 2) + with warns_deprecated_sympy(): + smat = m._smat + assert smat == m.todok() + + +def test_division(): + v = Matrix(1, 2, [x, y]) + assert v/z == Matrix(1, 2, [x/z, y/z]) + + +def test_sum(): + m = Matrix([[1, 2, 3], [x, y, x], [2*y, -50, z*x]]) + assert m + m == Matrix([[2, 4, 6], [2*x, 2*y, 2*x], [4*y, -100, 2*z*x]]) + n = Matrix(1, 2, [1, 2]) + raises(ShapeError, lambda: m + n) + +def test_abs(): + m = Matrix(1, 2, [-3, x]) + n = Matrix(1, 2, [3, Abs(x)]) + assert abs(m) == n + +def test_addition(): + a = Matrix(( + (1, 2), + (3, 1), + )) + + b = Matrix(( + (1, 2), + (3, 0), + )) + + assert a + b == a.add(b) == Matrix([[2, 4], [6, 1]]) + + +def test_fancy_index_matrix(): + for M in (Matrix, SparseMatrix): + a = M(3, 3, range(9)) + assert a == a[:, :] + assert a[1, :] == Matrix(1, 3, [3, 4, 5]) + assert a[:, 1] == Matrix([1, 4, 7]) + assert a[[0, 1], :] == Matrix([[0, 1, 2], [3, 4, 5]]) + assert a[[0, 1], 2] == a[[0, 1], [2]] + assert a[2, [0, 1]] == a[[2], [0, 1]] + assert a[:, [0, 1]] == Matrix([[0, 1], [3, 4], [6, 7]]) + assert a[0, 0] == 0 + assert a[0:2, :] == Matrix([[0, 1, 2], [3, 4, 5]]) + assert a[:, 0:2] == Matrix([[0, 1], [3, 4], [6, 7]]) + assert a[::2, 1] == a[[0, 2], 1] + assert a[1, ::2] == a[1, [0, 2]] + a = M(3, 3, range(9)) + assert a[[0, 2, 1, 2, 1], :] == Matrix([ + [0, 1, 2], + [6, 7, 8], + [3, 4, 5], + [6, 7, 8], + [3, 4, 5]]) + assert a[:, [0,2,1,2,1]] == Matrix([ + [0, 2, 1, 2, 1], + [3, 5, 4, 5, 4], + [6, 8, 7, 8, 7]]) + + a = SparseMatrix.zeros(3) + a[1, 2] = 2 + a[0, 1] = 3 + a[2, 0] = 4 + assert a.extract([1, 1], [2]) == Matrix([ + [2], + [2]]) + assert a.extract([1, 0], [2, 2, 2]) == Matrix([ + [2, 2, 2], + [0, 0, 0]]) + assert a.extract([1, 0, 1, 2], [2, 0, 1, 0]) == Matrix([ + [2, 0, 0, 0], + [0, 0, 3, 0], + [2, 0, 0, 0], + [0, 4, 0, 4]]) + + +def test_multiplication(): + a = Matrix(( + (1, 2), + (3, 1), + (0, 6), + )) + + b = Matrix(( + (1, 2), + (3, 0), + )) + + c = a*b + assert c[0, 0] == 7 + assert c[0, 1] == 2 + assert c[1, 0] == 6 + assert c[1, 1] == 6 + assert c[2, 0] == 18 + assert c[2, 1] == 0 + + try: + eval('c = a @ b') + except SyntaxError: + pass + else: + assert c[0, 0] == 7 + assert c[0, 1] == 2 + assert c[1, 0] == 6 + assert c[1, 1] == 6 + assert c[2, 0] == 18 + assert c[2, 1] == 0 + + h = matrix_multiply_elementwise(a, c) + assert h == a.multiply_elementwise(c) + assert h[0, 0] == 7 + assert h[0, 1] == 4 + assert h[1, 0] == 18 + assert h[1, 1] == 6 + assert h[2, 0] == 0 + assert h[2, 1] == 0 + raises(ShapeError, lambda: matrix_multiply_elementwise(a, b)) + + c = b * Symbol("x") + assert isinstance(c, Matrix) + assert c[0, 0] == x + assert c[0, 1] == 2*x + assert c[1, 0] == 3*x + assert c[1, 1] == 0 + + c2 = x * b + assert c == c2 + + c = 5 * b + assert isinstance(c, Matrix) + assert c[0, 0] == 5 + assert c[0, 1] == 2*5 + assert c[1, 0] == 3*5 + assert c[1, 1] == 0 + + try: + eval('c = 5 @ b') + except SyntaxError: + pass + else: + assert isinstance(c, Matrix) + assert c[0, 0] == 5 + assert c[0, 1] == 2*5 + assert c[1, 0] == 3*5 + assert c[1, 1] == 0 + + +def test_multiplication_inf_zero(): + + M = Matrix([[oo, 0], [0, oo]]) + assert M ** 2 == M + + M = Matrix([[oo, oo], [0, 0]]) + assert M ** 2 == Matrix([[nan, nan], [nan, nan]]) + + A = Matrix([ + [0, 0, 0, -S(1)/2], + [0, 1, 0, 0], + [0, 0, 1, 0], + [-S(1)/2, 0, 0, 0]]) + + B = Matrix([ + [pi*x**2, 0, pi*b*x**4/8 + pi*a*x**4/8 + O(x**5), pi*x**4/2 + pi*b**2*x**6/32 + pi*a*b*x**6/48 + pi*a**2*x**6/32 + O(x**7)], + [0, pi*x**4/4, O(x**6), O(x**8)], + [pi*b*x**4/8 + pi*a*x**4/8 + O(x**5), O(x**6), pi*b**2*x**6/32 + pi*a*b*x**6/48 + pi*a**2*x**6/32 + O(x**7), pi*b*x**6/12 + pi*a*x**6/12 + O(x**7)], + [pi*x**4/2 + pi*b**2*x**6/32 + pi*a*b*x**6/48 + pi*a**2*x**6/32 + O(x**7), O(x**8), pi*b*x**6/12 + pi*a*x**6/12 + O(x**7), pi*x**6/3 + 3*pi*b**2*x**8/64 + pi*a*b*x**8/32 + 3*pi*a**2*x**8/64 + O(x**9)]]) + + C = Matrix([ + [-pi*x**4/4 - pi*b**2*x**6/64 - pi*a*b*x**6/96 - pi*a**2*x**6/64 + O(x**7), O(x**8), -pi*b*x**6/24 - pi*a*x**6/24 + O(x**7), -pi*x**6/6 - 3*pi*b**2*x**8/128 - pi*a*b*x**8/64 - 3*pi*a**2*x**8/128 + O(x**9)], + [ 0, pi*x**4/4, O(x**6), O(x**8)], + [ pi*b*x**4/8 + pi*a*x**4/8 + O(x**5), O(x**6), pi*b**2*x**6/32 + pi*a*b*x**6/48 + pi*a**2*x**6/32 + O(x**7), pi*b*x**6/12 + pi*a*x**6/12 + O(x**7)], + [ -pi*x**2/2, 0, -pi*b*x**4/16 - pi*a*x**4/16 + O(x**5), -pi*x**4/4 - pi*b**2*x**6/64 - pi*a*b*x**6/96 - pi*a**2*x**6/64 + O(x**7)]]) + + C2 = Matrix(4, 4, lambda i, j: Add(*(A[i,k]*B[k,j] for k in range(4)))) + + assert A*B == C == C2 + + +def test_power(): + raises(NonSquareMatrixError, lambda: Matrix((1, 2))**2) + + R = Rational + A = Matrix([[2, 3], [4, 5]]) + assert (A**-3)[:] == [R(-269)/8, R(153)/8, R(51)/2, R(-29)/2] + assert (A**5)[:] == [6140, 8097, 10796, 14237] + A = Matrix([[2, 1, 3], [4, 2, 4], [6, 12, 1]]) + assert (A**3)[:] == [290, 262, 251, 448, 440, 368, 702, 954, 433] + assert A**0 == eye(3) + assert A**1 == A + assert (Matrix([[2]]) ** 100)[0, 0] == 2**100 + assert eye(2)**10000000 == eye(2) + assert Matrix([[1, 2], [3, 4]])**Integer(2) == Matrix([[7, 10], [15, 22]]) + + A = Matrix([[33, 24], [48, 57]]) + assert (A**S.Half)[:] == [5, 2, 4, 7] + A = Matrix([[0, 4], [-1, 5]]) + assert (A**S.Half)**2 == A + + assert Matrix([[1, 0], [1, 1]])**S.Half == Matrix([[1, 0], [S.Half, 1]]) + assert Matrix([[1, 0], [1, 1]])**0.5 == Matrix([[1, 0], [0.5, 1]]) + from sympy.abc import n + assert Matrix([[1, a], [0, 1]])**n == Matrix([[1, a*n], [0, 1]]) + assert Matrix([[b, a], [0, b]])**n == Matrix([[b**n, a*b**(n-1)*n], [0, b**n]]) + assert Matrix([ + [a**n, a**(n - 1)*n, (a**n*n**2 - a**n*n)/(2*a**2)], + [ 0, a**n, a**(n - 1)*n], + [ 0, 0, a**n]]) + assert Matrix([[a, 1, 0], [0, a, 0], [0, 0, b]])**n == Matrix([ + [a**n, a**(n-1)*n, 0], + [0, a**n, 0], + [0, 0, b**n]]) + + A = Matrix([[1, 0], [1, 7]]) + assert A._matrix_pow_by_jordan_blocks(S(3)) == A._eval_pow_by_recursion(3) + A = Matrix([[2]]) + assert A**10 == Matrix([[2**10]]) == A._matrix_pow_by_jordan_blocks(S(10)) == \ + A._eval_pow_by_recursion(10) + + # testing a matrix that cannot be jordan blocked issue 11766 + m = Matrix([[3, 0, 0, 0, -3], [0, -3, -3, 0, 3], [0, 3, 0, 3, 0], [0, 0, 3, 0, 3], [3, 0, 0, 3, 0]]) + raises(MatrixError, lambda: m._matrix_pow_by_jordan_blocks(S(10))) + + # test issue 11964 + raises(MatrixError, lambda: Matrix([[1, 1], [3, 3]])._matrix_pow_by_jordan_blocks(S(-10))) + A = Matrix([[0, 1, 0], [0, 0, 1], [0, 0, 0]]) # Nilpotent jordan block size 3 + assert A**10.0 == Matrix([[0, 0, 0], [0, 0, 0], [0, 0, 0]]) + raises(ValueError, lambda: A**2.1) + raises(ValueError, lambda: A**Rational(3, 2)) + A = Matrix([[8, 1], [3, 2]]) + assert A**10.0 == Matrix([[1760744107, 272388050], [817164150, 126415807]]) + A = Matrix([[0, 0, 1], [0, 0, 1], [0, 0, 1]]) # Nilpotent jordan block size 1 + assert A**10.0 == Matrix([[0, 0, 1], [0, 0, 1], [0, 0, 1]]) + A = Matrix([[0, 1, 0], [0, 0, 1], [0, 0, 1]]) # Nilpotent jordan block size 2 + assert A**10.0 == Matrix([[0, 0, 1], [0, 0, 1], [0, 0, 1]]) + n = Symbol('n', integer=True) + assert isinstance(A**n, MatPow) + n = Symbol('n', integer=True, negative=True) + raises(ValueError, lambda: A**n) + n = Symbol('n', integer=True, nonnegative=True) + assert A**n == Matrix([ + [KroneckerDelta(0, n), KroneckerDelta(1, n), -KroneckerDelta(0, n) - KroneckerDelta(1, n) + 1], + [ 0, KroneckerDelta(0, n), 1 - KroneckerDelta(0, n)], + [ 0, 0, 1]]) + assert A**(n + 2) == Matrix([[0, 0, 1], [0, 0, 1], [0, 0, 1]]) + raises(ValueError, lambda: A**Rational(3, 2)) + A = Matrix([[0, 0, 1], [3, 0, 1], [4, 3, 1]]) + assert A**5.0 == Matrix([[168, 72, 89], [291, 144, 161], [572, 267, 329]]) + assert A**5.0 == A**5 + A = Matrix([[0, 1, 0],[-1, 0, 0],[0, 0, 0]]) + n = Symbol("n") + An = A**n + assert An.subs(n, 2).doit() == A**2 + raises(ValueError, lambda: An.subs(n, -2).doit()) + assert An * An == A**(2*n) + + # concretizing behavior for non-integer and complex powers + A = Matrix([[0,0,0],[0,0,0],[0,0,0]]) + n = Symbol('n', integer=True, positive=True) + assert A**n == A + n = Symbol('n', integer=True, nonnegative=True) + assert A**n == diag(0**n, 0**n, 0**n) + assert (A**n).subs(n, 0) == eye(3) + assert (A**n).subs(n, 1) == zeros(3) + A = Matrix ([[2,0,0],[0,2,0],[0,0,2]]) + assert A**2.1 == diag (2**2.1, 2**2.1, 2**2.1) + assert A**I == diag (2**I, 2**I, 2**I) + A = Matrix([[0, 1, 0], [0, 0, 1], [0, 0, 1]]) + raises(ValueError, lambda: A**2.1) + raises(ValueError, lambda: A**I) + A = Matrix([[S.Half, S.Half], [S.Half, S.Half]]) + assert A**S.Half == A + A = Matrix([[1, 1],[3, 3]]) + assert A**S.Half == Matrix ([[S.Half, S.Half], [3*S.Half, 3*S.Half]]) + + +def test_issue_17247_expression_blowup_1(): + M = Matrix([[1+x, 1-x], [1-x, 1+x]]) + with dotprodsimp(True): + assert M.exp().expand() == Matrix([ + [ (exp(2*x) + exp(2))/2, (-exp(2*x) + exp(2))/2], + [(-exp(2*x) + exp(2))/2, (exp(2*x) + exp(2))/2]]) + +def test_issue_17247_expression_blowup_2(): + M = Matrix([[1+x, 1-x], [1-x, 1+x]]) + with dotprodsimp(True): + P, J = M.jordan_form () + assert P*J*P.inv() + +def test_issue_17247_expression_blowup_3(): + M = Matrix([[1+x, 1-x], [1-x, 1+x]]) + with dotprodsimp(True): + assert M**100 == Matrix([ + [633825300114114700748351602688*x**100 + 633825300114114700748351602688, 633825300114114700748351602688 - 633825300114114700748351602688*x**100], + [633825300114114700748351602688 - 633825300114114700748351602688*x**100, 633825300114114700748351602688*x**100 + 633825300114114700748351602688]]) + +def test_issue_17247_expression_blowup_4(): +# This matrix takes extremely long on current master even with intermediate simplification so an abbreviated version is used. It is left here for test in case of future optimizations. +# M = Matrix(S('''[ +# [ -3/4, 45/32 - 37*I/16, 1/4 + I/2, -129/64 - 9*I/64, 1/4 - 5*I/16, 65/128 + 87*I/64, -9/32 - I/16, 183/256 - 97*I/128, 3/64 + 13*I/64, -23/32 - 59*I/256, 15/128 - 3*I/32, 19/256 + 551*I/1024], +# [-149/64 + 49*I/32, -177/128 - 1369*I/128, 125/64 + 87*I/64, -2063/256 + 541*I/128, 85/256 - 33*I/16, 805/128 + 2415*I/512, -219/128 + 115*I/256, 6301/4096 - 6609*I/1024, 119/128 + 143*I/128, -10879/2048 + 4343*I/4096, 129/256 - 549*I/512, 42533/16384 + 29103*I/8192], +# [ 1/2 - I, 9/4 + 55*I/16, -3/4, 45/32 - 37*I/16, 1/4 + I/2, -129/64 - 9*I/64, 1/4 - 5*I/16, 65/128 + 87*I/64, -9/32 - I/16, 183/256 - 97*I/128, 3/64 + 13*I/64, -23/32 - 59*I/256], +# [ -5/8 - 39*I/16, 2473/256 + 137*I/64, -149/64 + 49*I/32, -177/128 - 1369*I/128, 125/64 + 87*I/64, -2063/256 + 541*I/128, 85/256 - 33*I/16, 805/128 + 2415*I/512, -219/128 + 115*I/256, 6301/4096 - 6609*I/1024, 119/128 + 143*I/128, -10879/2048 + 4343*I/4096], +# [ 1 + I, -19/4 + 5*I/4, 1/2 - I, 9/4 + 55*I/16, -3/4, 45/32 - 37*I/16, 1/4 + I/2, -129/64 - 9*I/64, 1/4 - 5*I/16, 65/128 + 87*I/64, -9/32 - I/16, 183/256 - 97*I/128], +# [ 21/8 + I, -537/64 + 143*I/16, -5/8 - 39*I/16, 2473/256 + 137*I/64, -149/64 + 49*I/32, -177/128 - 1369*I/128, 125/64 + 87*I/64, -2063/256 + 541*I/128, 85/256 - 33*I/16, 805/128 + 2415*I/512, -219/128 + 115*I/256, 6301/4096 - 6609*I/1024], +# [ -2, 17/4 - 13*I/2, 1 + I, -19/4 + 5*I/4, 1/2 - I, 9/4 + 55*I/16, -3/4, 45/32 - 37*I/16, 1/4 + I/2, -129/64 - 9*I/64, 1/4 - 5*I/16, 65/128 + 87*I/64], +# [ 1/4 + 13*I/4, -825/64 - 147*I/32, 21/8 + I, -537/64 + 143*I/16, -5/8 - 39*I/16, 2473/256 + 137*I/64, -149/64 + 49*I/32, -177/128 - 1369*I/128, 125/64 + 87*I/64, -2063/256 + 541*I/128, 85/256 - 33*I/16, 805/128 + 2415*I/512], +# [ -4*I, 27/2 + 6*I, -2, 17/4 - 13*I/2, 1 + I, -19/4 + 5*I/4, 1/2 - I, 9/4 + 55*I/16, -3/4, 45/32 - 37*I/16, 1/4 + I/2, -129/64 - 9*I/64], +# [ 1/4 + 5*I/2, -23/8 - 57*I/16, 1/4 + 13*I/4, -825/64 - 147*I/32, 21/8 + I, -537/64 + 143*I/16, -5/8 - 39*I/16, 2473/256 + 137*I/64, -149/64 + 49*I/32, -177/128 - 1369*I/128, 125/64 + 87*I/64, -2063/256 + 541*I/128], +# [ -4, 9 - 5*I, -4*I, 27/2 + 6*I, -2, 17/4 - 13*I/2, 1 + I, -19/4 + 5*I/4, 1/2 - I, 9/4 + 55*I/16, -3/4, 45/32 - 37*I/16], +# [ -2*I, 119/8 + 29*I/4, 1/4 + 5*I/2, -23/8 - 57*I/16, 1/4 + 13*I/4, -825/64 - 147*I/32, 21/8 + I, -537/64 + 143*I/16, -5/8 - 39*I/16, 2473/256 + 137*I/64, -149/64 + 49*I/32, -177/128 - 1369*I/128]]''')) +# assert M**10 == Matrix([ +# [ 7*(-221393644768594642173548179825793834595 - 1861633166167425978847110897013541127952*I)/9671406556917033397649408, 15*(31670992489131684885307005100073928751695 + 10329090958303458811115024718207404523808*I)/77371252455336267181195264, 7*(-3710978679372178839237291049477017392703 + 1377706064483132637295566581525806894169*I)/19342813113834066795298816, (9727707023582419994616144751727760051598 - 59261571067013123836477348473611225724433*I)/9671406556917033397649408, (31896723509506857062605551443641668183707 + 54643444538699269118869436271152084599580*I)/38685626227668133590597632, (-2024044860947539028275487595741003997397402 + 130959428791783397562960461903698670485863*I)/309485009821345068724781056, 3*(26190251453797590396533756519358368860907 - 27221191754180839338002754608545400941638*I)/77371252455336267181195264, (1154643595139959842768960128434994698330461 + 3385496216250226964322872072260446072295634*I)/618970019642690137449562112, 3*(-31849347263064464698310044805285774295286 - 11877437776464148281991240541742691164309*I)/77371252455336267181195264, (4661330392283532534549306589669150228040221 - 4171259766019818631067810706563064103956871*I)/1237940039285380274899124224, (9598353794289061833850770474812760144506 + 358027153990999990968244906482319780943983*I)/309485009821345068724781056, (-9755135335127734571547571921702373498554177 - 4837981372692695195747379349593041939686540*I)/2475880078570760549798248448], +# [(-379516731607474268954110071392894274962069 - 422272153179747548473724096872271700878296*I)/77371252455336267181195264, (41324748029613152354787280677832014263339501 - 12715121258662668420833935373453570749288074*I)/1237940039285380274899124224, (-339216903907423793947110742819264306542397 + 494174755147303922029979279454787373566517*I)/77371252455336267181195264, (-18121350839962855576667529908850640619878381 - 37413012454129786092962531597292531089199003*I)/1237940039285380274899124224, (2489661087330511608618880408199633556675926 + 1137821536550153872137379935240732287260863*I)/309485009821345068724781056, (-136644109701594123227587016790354220062972119 + 110130123468183660555391413889600443583585272*I)/4951760157141521099596496896, (1488043981274920070468141664150073426459593 - 9691968079933445130866371609614474474327650*I)/1237940039285380274899124224, 27*(4636797403026872518131756991410164760195942 + 3369103221138229204457272860484005850416533*I)/4951760157141521099596496896, (-8534279107365915284081669381642269800472363 + 2241118846262661434336333368511372725482742*I)/1237940039285380274899124224, (60923350128174260992536531692058086830950875 - 263673488093551053385865699805250505661590126*I)/9903520314283042199192993792, (18520943561240714459282253753348921824172569 + 24846649186468656345966986622110971925703604*I)/4951760157141521099596496896, (-232781130692604829085973604213529649638644431 + 35981505277760667933017117949103953338570617*I)/9903520314283042199192993792], +# [ (8742968295129404279528270438201520488950 + 3061473358639249112126847237482570858327*I)/4835703278458516698824704, (-245657313712011778432792959787098074935273 + 253113767861878869678042729088355086740856*I)/38685626227668133590597632, (1947031161734702327107371192008011621193 - 19462330079296259148177542369999791122762*I)/9671406556917033397649408, (552856485625209001527688949522750288619217 + 392928441196156725372494335248099016686580*I)/77371252455336267181195264, (-44542866621905323121630214897126343414629 + 3265340021421335059323962377647649632959*I)/19342813113834066795298816, (136272594005759723105646069956434264218730 - 330975364731707309489523680957584684763587*I)/38685626227668133590597632, (27392593965554149283318732469825168894401 + 75157071243800133880129376047131061115278*I)/38685626227668133590597632, 7*(-357821652913266734749960136017214096276154 - 45509144466378076475315751988405961498243*I)/309485009821345068724781056, (104485001373574280824835174390219397141149 - 99041000529599568255829489765415726168162*I)/77371252455336267181195264, (1198066993119982409323525798509037696321291 + 4249784165667887866939369628840569844519936*I)/618970019642690137449562112, (-114985392587849953209115599084503853611014 - 52510376847189529234864487459476242883449*I)/77371252455336267181195264, (6094620517051332877965959223269600650951573 - 4683469779240530439185019982269137976201163*I)/1237940039285380274899124224], +# [ (611292255597977285752123848828590587708323 - 216821743518546668382662964473055912169502*I)/77371252455336267181195264, (-1144023204575811464652692396337616594307487 + 12295317806312398617498029126807758490062855*I)/309485009821345068724781056, (-374093027769390002505693378578475235158281 - 573533923565898290299607461660384634333639*I)/77371252455336267181195264, (47405570632186659000138546955372796986832987 - 2837476058950808941605000274055970055096534*I)/1237940039285380274899124224, (-571573207393621076306216726219753090535121 + 533381457185823100878764749236639320783831*I)/77371252455336267181195264, (-7096548151856165056213543560958582513797519 - 24035731898756040059329175131592138642195366*I)/618970019642690137449562112, (2396762128833271142000266170154694033849225 + 1448501087375679588770230529017516492953051*I)/309485009821345068724781056, (-150609293845161968447166237242456473262037053 + 92581148080922977153207018003184520294188436*I)/4951760157141521099596496896, 5*(270278244730804315149356082977618054486347 - 1997830155222496880429743815321662710091562*I)/1237940039285380274899124224, (62978424789588828258068912690172109324360330 + 44803641177219298311493356929537007630129097*I)/2475880078570760549798248448, 19*(-451431106327656743945775812536216598712236 + 114924966793632084379437683991151177407937*I)/1237940039285380274899124224, (63417747628891221594106738815256002143915995 - 261508229397507037136324178612212080871150958*I)/9903520314283042199192993792], +# [ (-2144231934021288786200752920446633703357 + 2305614436009705803670842248131563850246*I)/1208925819614629174706176, (-90720949337459896266067589013987007078153 - 221951119475096403601562347412753844534569*I)/19342813113834066795298816, (11590973613116630788176337262688659880376 + 6514520676308992726483494976339330626159*I)/4835703278458516698824704, 3*(-131776217149000326618649542018343107657237 + 79095042939612668486212006406818285287004*I)/38685626227668133590597632, (10100577916793945997239221374025741184951 - 28631383488085522003281589065994018550748*I)/9671406556917033397649408, 67*(10090295594251078955008130473573667572549 + 10449901522697161049513326446427839676762*I)/77371252455336267181195264, (-54270981296988368730689531355811033930513 - 3413683117592637309471893510944045467443*I)/19342813113834066795298816, (440372322928679910536575560069973699181278 - 736603803202303189048085196176918214409081*I)/77371252455336267181195264, (33220374714789391132887731139763250155295 + 92055083048787219934030779066298919603554*I)/38685626227668133590597632, 5*(-594638554579967244348856981610805281527116 - 82309245323128933521987392165716076704057*I)/309485009821345068724781056, (128056368815300084550013708313312073721955 - 114619107488668120303579745393765245911404*I)/77371252455336267181195264, 21*(59839959255173222962789517794121843393573 + 241507883613676387255359616163487405826334*I)/618970019642690137449562112], +# [ (-13454485022325376674626653802541391955147 + 184471402121905621396582628515905949793486*I)/19342813113834066795298816, (-6158730123400322562149780662133074862437105 - 3416173052604643794120262081623703514107476*I)/154742504910672534362390528, (770558003844914708453618983120686116100419 - 127758381209767638635199674005029818518766*I)/77371252455336267181195264, (-4693005771813492267479835161596671660631703 + 12703585094750991389845384539501921531449948*I)/309485009821345068724781056, (-295028157441149027913545676461260860036601 - 841544569970643160358138082317324743450770*I)/77371252455336267181195264, (56716442796929448856312202561538574275502893 + 7216818824772560379753073185990186711454778*I)/1237940039285380274899124224, 15*(-87061038932753366532685677510172566368387 + 61306141156647596310941396434445461895538*I)/154742504910672534362390528, (-3455315109680781412178133042301025723909347 - 24969329563196972466388460746447646686670670*I)/618970019642690137449562112, (2453418854160886481106557323699250865361849 + 1497886802326243014471854112161398141242514*I)/309485009821345068724781056, (-151343224544252091980004429001205664193082173 + 90471883264187337053549090899816228846836628*I)/4951760157141521099596496896, (1652018205533026103358164026239417416432989 - 9959733619236515024261775397109724431400162*I)/1237940039285380274899124224, 3*(40676374242956907656984876692623172736522006 + 31023357083037817469535762230872667581366205*I)/4951760157141521099596496896], +# [ (-1226990509403328460274658603410696548387 - 4131739423109992672186585941938392788458*I)/1208925819614629174706176, (162392818524418973411975140074368079662703 + 23706194236915374831230612374344230400704*I)/9671406556917033397649408, (-3935678233089814180000602553655565621193 + 2283744757287145199688061892165659502483*I)/1208925819614629174706176, (-2400210250844254483454290806930306285131 - 315571356806370996069052930302295432758205*I)/19342813113834066795298816, (13365917938215281056563183751673390817910 + 15911483133819801118348625831132324863881*I)/4835703278458516698824704, 3*(-215950551370668982657516660700301003897855 + 51684341999223632631602864028309400489378*I)/38685626227668133590597632, (20886089946811765149439844691320027184765 - 30806277083146786592790625980769214361844*I)/9671406556917033397649408, (562180634592713285745940856221105667874855 + 1031543963988260765153550559766662245114916*I)/77371252455336267181195264, (-65820625814810177122941758625652476012867 - 12429918324787060890804395323920477537595*I)/19342813113834066795298816, (319147848192012911298771180196635859221089 - 402403304933906769233365689834404519960394*I)/38685626227668133590597632, (23035615120921026080284733394359587955057 + 115351677687031786114651452775242461310624*I)/38685626227668133590597632, (-3426830634881892756966440108592579264936130 - 1022954961164128745603407283836365128598559*I)/309485009821345068724781056], +# [ (-192574788060137531023716449082856117537757 - 69222967328876859586831013062387845780692*I)/19342813113834066795298816, (2736383768828013152914815341491629299773262 - 2773252698016291897599353862072533475408743*I)/77371252455336267181195264, (-23280005281223837717773057436155921656805 + 214784953368021840006305033048142888879224*I)/19342813113834066795298816, (-3035247484028969580570400133318947903462326 - 2195168903335435855621328554626336958674325*I)/77371252455336267181195264, (984552428291526892214541708637840971548653 - 64006622534521425620714598573494988589378*I)/77371252455336267181195264, (-3070650452470333005276715136041262898509903 + 7286424705750810474140953092161794621989080*I)/154742504910672534362390528, (-147848877109756404594659513386972921139270 - 416306113044186424749331418059456047650861*I)/38685626227668133590597632, (55272118474097814260289392337160619494260781 + 7494019668394781211907115583302403519488058*I)/1237940039285380274899124224, (-581537886583682322424771088996959213068864 + 542191617758465339135308203815256798407429*I)/77371252455336267181195264, (-6422548983676355789975736799494791970390991 - 23524183982209004826464749309156698827737702*I)/618970019642690137449562112, 7*(180747195387024536886923192475064903482083 + 84352527693562434817771649853047924991804*I)/154742504910672534362390528, (-135485179036717001055310712747643466592387031 + 102346575226653028836678855697782273460527608*I)/4951760157141521099596496896], +# [ (3384238362616083147067025892852431152105 + 156724444932584900214919898954874618256*I)/604462909807314587353088, (-59558300950677430189587207338385764871866 + 114427143574375271097298201388331237478857*I)/4835703278458516698824704, (-1356835789870635633517710130971800616227 - 7023484098542340388800213478357340875410*I)/1208925819614629174706176, (234884918567993750975181728413524549575881 + 79757294640629983786895695752733890213506*I)/9671406556917033397649408, (-7632732774935120473359202657160313866419 + 2905452608512927560554702228553291839465*I)/1208925819614629174706176, (52291747908702842344842889809762246649489 - 520996778817151392090736149644507525892649*I)/19342813113834066795298816, (17472406829219127839967951180375981717322 + 23464704213841582137898905375041819568669*I)/4835703278458516698824704, (-911026971811893092350229536132730760943307 + 150799318130900944080399439626714846752360*I)/38685626227668133590597632, (26234457233977042811089020440646443590687 - 45650293039576452023692126463683727692890*I)/9671406556917033397649408, 3*(288348388717468992528382586652654351121357 + 454526517721403048270274049572136109264668*I)/77371252455336267181195264, (-91583492367747094223295011999405657956347 - 12704691128268298435362255538069612411331*I)/19342813113834066795298816, (411208730251327843849027957710164064354221 - 569898526380691606955496789378230959965898*I)/38685626227668133590597632], +# [ (27127513117071487872628354831658811211795 - 37765296987901990355760582016892124833857*I)/4835703278458516698824704, (1741779916057680444272938534338833170625435 + 3083041729779495966997526404685535449810378*I)/77371252455336267181195264, 3*(-60642236251815783728374561836962709533401 - 24630301165439580049891518846174101510744*I)/19342813113834066795298816, 3*(445885207364591681637745678755008757483408 - 350948497734812895032502179455610024541643*I)/38685626227668133590597632, (-47373295621391195484367368282471381775684 + 219122969294089357477027867028071400054973*I)/19342813113834066795298816, (-2801565819673198722993348253876353741520438 - 2250142129822658548391697042460298703335701*I)/77371252455336267181195264, (801448252275607253266997552356128790317119 - 50890367688077858227059515894356594900558*I)/77371252455336267181195264, (-5082187758525931944557763799137987573501207 + 11610432359082071866576699236013484487676124*I)/309485009821345068724781056, (-328925127096560623794883760398247685166830 - 643447969697471610060622160899409680422019*I)/77371252455336267181195264, 15*(2954944669454003684028194956846659916299765 + 33434406416888505837444969347824812608566*I)/1237940039285380274899124224, (-415749104352001509942256567958449835766827 + 479330966144175743357171151440020955412219*I)/77371252455336267181195264, 3*(-4639987285852134369449873547637372282914255 - 11994411888966030153196659207284951579243273*I)/1237940039285380274899124224], +# [ (-478846096206269117345024348666145495601 + 1249092488629201351470551186322814883283*I)/302231454903657293676544, (-17749319421930878799354766626365926894989 - 18264580106418628161818752318217357231971*I)/1208925819614629174706176, (2801110795431528876849623279389579072819 + 363258850073786330770713557775566973248*I)/604462909807314587353088, (-59053496693129013745775512127095650616252 + 78143588734197260279248498898321500167517*I)/4835703278458516698824704, (-283186724922498212468162690097101115349 - 6443437753863179883794497936345437398276*I)/1208925819614629174706176, (188799118826748909206887165661384998787543 + 84274736720556630026311383931055307398820*I)/9671406556917033397649408, (-5482217151670072904078758141270295025989 + 1818284338672191024475557065444481298568*I)/1208925819614629174706176, (56564463395350195513805521309731217952281 - 360208541416798112109946262159695452898431*I)/19342813113834066795298816, 11*(1259539805728870739006416869463689438068 + 1409136581547898074455004171305324917387*I)/4835703278458516698824704, 5*(-123701190701414554945251071190688818343325 + 30997157322590424677294553832111902279712*I)/38685626227668133590597632, (16130917381301373033736295883982414239781 - 32752041297570919727145380131926943374516*I)/9671406556917033397649408, (650301385108223834347093740500375498354925 + 899526407681131828596801223402866051809258*I)/77371252455336267181195264], +# [ (9011388245256140876590294262420614839483 + 8167917972423946282513000869327525382672*I)/1208925819614629174706176, (-426393174084720190126376382194036323028924 + 180692224825757525982858693158209545430621*I)/9671406556917033397649408, (24588556702197802674765733448108154175535 - 45091766022876486566421953254051868331066*I)/4835703278458516698824704, (1872113939365285277373877183750416985089691 + 3030392393733212574744122057679633775773130*I)/77371252455336267181195264, (-222173405538046189185754954524429864167549 - 75193157893478637039381059488387511299116*I)/19342813113834066795298816, (2670821320766222522963689317316937579844558 - 2645837121493554383087981511645435472169191*I)/77371252455336267181195264, 5*(-2100110309556476773796963197283876204940 + 41957457246479840487980315496957337371937*I)/19342813113834066795298816, (-5733743755499084165382383818991531258980593 - 3328949988392698205198574824396695027195732*I)/154742504910672534362390528, (707827994365259025461378911159398206329247 - 265730616623227695108042528694302299777294*I)/77371252455336267181195264, (-1442501604682933002895864804409322823788319 + 11504137805563265043376405214378288793343879*I)/309485009821345068724781056, (-56130472299445561499538726459719629522285 - 61117552419727805035810982426639329818864*I)/9671406556917033397649408, (39053692321126079849054272431599539429908717 - 10209127700342570953247177602860848130710666*I)/1237940039285380274899124224]]) + M = Matrix(S('''[ + [ -3/4, 45/32 - 37*I/16, 1/4 + I/2, -129/64 - 9*I/64, 1/4 - 5*I/16, 65/128 + 87*I/64], + [-149/64 + 49*I/32, -177/128 - 1369*I/128, 125/64 + 87*I/64, -2063/256 + 541*I/128, 85/256 - 33*I/16, 805/128 + 2415*I/512], + [ 1/2 - I, 9/4 + 55*I/16, -3/4, 45/32 - 37*I/16, 1/4 + I/2, -129/64 - 9*I/64], + [ -5/8 - 39*I/16, 2473/256 + 137*I/64, -149/64 + 49*I/32, -177/128 - 1369*I/128, 125/64 + 87*I/64, -2063/256 + 541*I/128], + [ 1 + I, -19/4 + 5*I/4, 1/2 - I, 9/4 + 55*I/16, -3/4, 45/32 - 37*I/16], + [ 21/8 + I, -537/64 + 143*I/16, -5/8 - 39*I/16, 2473/256 + 137*I/64, -149/64 + 49*I/32, -177/128 - 1369*I/128]]''')) + with dotprodsimp(True): + assert M**10 == Matrix(S('''[ + [ 7369525394972778926719607798014571861/604462909807314587353088 - 229284202061790301477392339912557559*I/151115727451828646838272, -19704281515163975949388435612632058035/1208925819614629174706176 + 14319858347987648723768698170712102887*I/302231454903657293676544, -3623281909451783042932142262164941211/604462909807314587353088 - 6039240602494288615094338643452320495*I/604462909807314587353088, 109260497799140408739847239685705357695/2417851639229258349412352 - 7427566006564572463236368211555511431*I/2417851639229258349412352, -16095803767674394244695716092817006641/2417851639229258349412352 + 10336681897356760057393429626719177583*I/1208925819614629174706176, -42207883340488041844332828574359769743/2417851639229258349412352 - 182332262671671273188016400290188468499*I/4835703278458516698824704], + [50566491050825573392726324995779608259/1208925819614629174706176 - 90047007594468146222002432884052362145*I/2417851639229258349412352, 74273703462900000967697427843983822011/1208925819614629174706176 + 265947522682943571171988741842776095421*I/1208925819614629174706176, -116900341394390200556829767923360888429/2417851639229258349412352 - 53153263356679268823910621474478756845*I/2417851639229258349412352, 195407378023867871243426523048612490249/1208925819614629174706176 - 1242417915995360200584837585002906728929*I/9671406556917033397649408, -863597594389821970177319682495878193/302231454903657293676544 + 476936100741548328800725360758734300481*I/9671406556917033397649408, -3154451590535653853562472176601754835575/19342813113834066795298816 - 232909875490506237386836489998407329215*I/2417851639229258349412352], + [ -1715444997702484578716037230949868543/302231454903657293676544 + 5009695651321306866158517287924120777*I/302231454903657293676544, -30551582497996879620371947949342101301/604462909807314587353088 - 7632518367986526187139161303331519629*I/151115727451828646838272, 312680739924495153190604170938220575/18889465931478580854784 - 108664334509328818765959789219208459*I/75557863725914323419136, -14693696966703036206178521686918865509/604462909807314587353088 + 72345386220900843930147151999899692401*I/1208925819614629174706176, -8218872496728882299722894680635296519/1208925819614629174706176 - 16776782833358893712645864791807664983*I/1208925819614629174706176, 143237839169380078671242929143670635137/2417851639229258349412352 + 2883817094806115974748882735218469447*I/2417851639229258349412352], + [ 3087979417831061365023111800749855987/151115727451828646838272 + 34441942370802869368851419102423997089*I/604462909807314587353088, -148309181940158040917731426845476175667/604462909807314587353088 - 263987151804109387844966835369350904919*I/9671406556917033397649408, 50259518594816377378747711930008883165/1208925819614629174706176 - 95713974916869240305450001443767979653*I/2417851639229258349412352, 153466447023875527996457943521467271119/2417851639229258349412352 + 517285524891117105834922278517084871349*I/2417851639229258349412352, -29184653615412989036678939366291205575/604462909807314587353088 - 27551322282526322041080173287022121083*I/1208925819614629174706176, 196404220110085511863671393922447671649/1208925819614629174706176 - 1204712019400186021982272049902206202145*I/9671406556917033397649408], + [ -2632581805949645784625606590600098779/151115727451828646838272 - 589957435912868015140272627522612771*I/37778931862957161709568, 26727850893953715274702844733506310247/302231454903657293676544 - 10825791956782128799168209600694020481*I/302231454903657293676544, -1036348763702366164044671908440791295/151115727451828646838272 + 3188624571414467767868303105288107375*I/151115727451828646838272, -36814959939970644875593411585393242449/604462909807314587353088 - 18457555789119782404850043842902832647*I/302231454903657293676544, 12454491297984637815063964572803058647/604462909807314587353088 - 340489532842249733975074349495329171*I/302231454903657293676544, -19547211751145597258386735573258916681/604462909807314587353088 + 87299583775782199663414539883938008933*I/1208925819614629174706176], + [ -40281994229560039213253423262678393183/604462909807314587353088 - 2939986850065527327299273003299736641*I/604462909807314587353088, 331940684638052085845743020267462794181/2417851639229258349412352 - 284574901963624403933361315517248458969*I/1208925819614629174706176, 6453843623051745485064693628073010961/302231454903657293676544 + 36062454107479732681350914931391590957*I/604462909807314587353088, -147665869053634695632880753646441962067/604462909807314587353088 - 305987938660447291246597544085345123927*I/9671406556917033397649408, 107821369195275772166593879711259469423/2417851639229258349412352 - 11645185518211204108659001435013326687*I/302231454903657293676544, 64121228424717666402009446088588091619/1208925819614629174706176 + 265557133337095047883844369272389762133*I/1208925819614629174706176]]''')) + +def test_issue_17247_expression_blowup_5(): + M = Matrix(6, 6, lambda i, j: 1 + (-1)**(i+j)*I) + with dotprodsimp(True): + assert M.charpoly('x') == PurePoly(x**6 + (-6 - 6*I)*x**5 + 36*I*x**4, x, domain='EX') + +def test_issue_17247_expression_blowup_6(): + M = Matrix(8, 8, [x+i for i in range (64)]) + with dotprodsimp(True): + assert M.det('bareiss') == 0 + +def test_issue_17247_expression_blowup_7(): + M = Matrix(6, 6, lambda i, j: 1 + (-1)**(i+j)*I) + with dotprodsimp(True): + assert M.det('berkowitz') == 0 + +def test_issue_17247_expression_blowup_8(): + M = Matrix(8, 8, [x+i for i in range (64)]) + with dotprodsimp(True): + assert M.det('lu') == 0 + +def test_issue_17247_expression_blowup_9(): + M = Matrix(8, 8, [x+i for i in range (64)]) + with dotprodsimp(True): + assert M.rref() == (Matrix([ + [1, 0, -1, -2, -3, -4, -5, -6], + [0, 1, 2, 3, 4, 5, 6, 7], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0]]), (0, 1)) + +def test_issue_17247_expression_blowup_10(): + M = Matrix(6, 6, lambda i, j: 1 + (-1)**(i+j)*I) + with dotprodsimp(True): + assert M.cofactor(0, 0) == 0 + +def test_issue_17247_expression_blowup_11(): + M = Matrix(6, 6, lambda i, j: 1 + (-1)**(i+j)*I) + with dotprodsimp(True): + assert M.cofactor_matrix() == Matrix(6, 6, [0]*36) + +def test_issue_17247_expression_blowup_12(): + M = Matrix(6, 6, lambda i, j: 1 + (-1)**(i+j)*I) + with dotprodsimp(True): + assert M.eigenvals() == {6: 1, 6*I: 1, 0: 4} + +def test_issue_17247_expression_blowup_13(): + M = Matrix([ + [ 0, 1 - x, x + 1, 1 - x], + [1 - x, x + 1, 0, x + 1], + [ 0, 1 - x, x + 1, 1 - x], + [ 0, 0, 1 - x, 0]]) + + ev = M.eigenvects() + assert ev[0] == (0, 2, [Matrix([0, -1, 0, 1])]) + assert ev[1][0] == x - sqrt(2)*(x - 1) + 1 + assert ev[1][1] == 1 + assert ev[1][2][0].expand(deep=False, numer=True) == Matrix([ + [(-x + sqrt(2)*(x - 1) - 1)/(x - 1)], + [-4*x/(x**2 - 2*x + 1) + (x + 1)*(x - sqrt(2)*(x - 1) + 1)/(x**2 - 2*x + 1)], + [(-x + sqrt(2)*(x - 1) - 1)/(x - 1)], + [1] + ]) + + assert ev[2][0] == x + sqrt(2)*(x - 1) + 1 + assert ev[2][1] == 1 + assert ev[2][2][0].expand(deep=False, numer=True) == Matrix([ + [(-x - sqrt(2)*(x - 1) - 1)/(x - 1)], + [-4*x/(x**2 - 2*x + 1) + (x + 1)*(x + sqrt(2)*(x - 1) + 1)/(x**2 - 2*x + 1)], + [(-x - sqrt(2)*(x - 1) - 1)/(x - 1)], + [1] + ]) + + +def test_issue_17247_expression_blowup_14(): + M = Matrix(8, 8, ([1+x, 1-x]*4 + [1-x, 1+x]*4)*4) + with dotprodsimp(True): + assert M.echelon_form() == Matrix([ + [x + 1, 1 - x, x + 1, 1 - x, x + 1, 1 - x, x + 1, 1 - x], + [ 0, 4*x, 0, 4*x, 0, 4*x, 0, 4*x], + [ 0, 0, 0, 0, 0, 0, 0, 0], + [ 0, 0, 0, 0, 0, 0, 0, 0], + [ 0, 0, 0, 0, 0, 0, 0, 0], + [ 0, 0, 0, 0, 0, 0, 0, 0], + [ 0, 0, 0, 0, 0, 0, 0, 0], + [ 0, 0, 0, 0, 0, 0, 0, 0]]) + +def test_issue_17247_expression_blowup_15(): + M = Matrix(8, 8, ([1+x, 1-x]*4 + [1-x, 1+x]*4)*4) + with dotprodsimp(True): + assert M.rowspace() == [Matrix([[x + 1, 1 - x, x + 1, 1 - x, x + 1, 1 - x, x + 1, 1 - x]]), Matrix([[0, 4*x, 0, 4*x, 0, 4*x, 0, 4*x]])] + +def test_issue_17247_expression_blowup_16(): + M = Matrix(8, 8, ([1+x, 1-x]*4 + [1-x, 1+x]*4)*4) + with dotprodsimp(True): + assert M.columnspace() == [Matrix([[x + 1],[1 - x],[x + 1],[1 - x],[x + 1],[1 - x],[x + 1],[1 - x]]), Matrix([[1 - x],[x + 1],[1 - x],[x + 1],[1 - x],[x + 1],[1 - x],[x + 1]])] + +def test_issue_17247_expression_blowup_17(): + M = Matrix(8, 8, [x+i for i in range (64)]) + with dotprodsimp(True): + assert M.nullspace() == [ + Matrix([[1],[-2],[1],[0],[0],[0],[0],[0]]), + Matrix([[2],[-3],[0],[1],[0],[0],[0],[0]]), + Matrix([[3],[-4],[0],[0],[1],[0],[0],[0]]), + Matrix([[4],[-5],[0],[0],[0],[1],[0],[0]]), + Matrix([[5],[-6],[0],[0],[0],[0],[1],[0]]), + Matrix([[6],[-7],[0],[0],[0],[0],[0],[1]])] + +def test_issue_17247_expression_blowup_18(): + M = Matrix(6, 6, ([1+x, 1-x]*3 + [1-x, 1+x]*3)*3) + with dotprodsimp(True): + assert not M.is_nilpotent() + +def test_issue_17247_expression_blowup_19(): + M = Matrix(S('''[ + [ -3/4, 0, 1/4 + I/2, 0], + [ 0, -177/128 - 1369*I/128, 0, -2063/256 + 541*I/128], + [ 1/2 - I, 0, 0, 0], + [ 0, 0, 0, -177/128 - 1369*I/128]]''')) + with dotprodsimp(True): + assert not M.is_diagonalizable() + +def test_issue_17247_expression_blowup_20(): + M = Matrix([ + [x + 1, 1 - x, 0, 0], + [1 - x, x + 1, 0, x + 1], + [ 0, 1 - x, x + 1, 0], + [ 0, 0, 0, x + 1]]) + with dotprodsimp(True): + assert M.diagonalize() == (Matrix([ + [1, 1, 0, (x + 1)/(x - 1)], + [1, -1, 0, 0], + [1, 1, 1, 0], + [0, 0, 0, 1]]), + Matrix([ + [2, 0, 0, 0], + [0, 2*x, 0, 0], + [0, 0, x + 1, 0], + [0, 0, 0, x + 1]])) + +def test_issue_17247_expression_blowup_21(): + M = Matrix(S('''[ + [ -3/4, 45/32 - 37*I/16, 0, 0], + [-149/64 + 49*I/32, -177/128 - 1369*I/128, 0, -2063/256 + 541*I/128], + [ 0, 9/4 + 55*I/16, 2473/256 + 137*I/64, 0], + [ 0, 0, 0, -177/128 - 1369*I/128]]''')) + with dotprodsimp(True): + assert M.inv(method='GE') == Matrix(S('''[ + [-26194832/3470993 - 31733264*I/3470993, 156352/3470993 + 10325632*I/3470993, 0, -7741283181072/3306971225785 + 2999007604624*I/3306971225785], + [4408224/3470993 - 9675328*I/3470993, -2422272/3470993 + 1523712*I/3470993, 0, -1824666489984/3306971225785 - 1401091949952*I/3306971225785], + [-26406945676288/22270005630769 + 10245925485056*I/22270005630769, 7453523312640/22270005630769 + 1601616519168*I/22270005630769, 633088/6416033 - 140288*I/6416033, 872209227109521408/21217636514687010905 + 6066405081802389504*I/21217636514687010905], + [0, 0, 0, -11328/952745 + 87616*I/952745]]''')) + +def test_issue_17247_expression_blowup_22(): + M = Matrix(S('''[ + [ -3/4, 45/32 - 37*I/16, 0, 0], + [-149/64 + 49*I/32, -177/128 - 1369*I/128, 0, -2063/256 + 541*I/128], + [ 0, 9/4 + 55*I/16, 2473/256 + 137*I/64, 0], + [ 0, 0, 0, -177/128 - 1369*I/128]]''')) + with dotprodsimp(True): + assert M.inv(method='LU') == Matrix(S('''[ + [-26194832/3470993 - 31733264*I/3470993, 156352/3470993 + 10325632*I/3470993, 0, -7741283181072/3306971225785 + 2999007604624*I/3306971225785], + [4408224/3470993 - 9675328*I/3470993, -2422272/3470993 + 1523712*I/3470993, 0, -1824666489984/3306971225785 - 1401091949952*I/3306971225785], + [-26406945676288/22270005630769 + 10245925485056*I/22270005630769, 7453523312640/22270005630769 + 1601616519168*I/22270005630769, 633088/6416033 - 140288*I/6416033, 872209227109521408/21217636514687010905 + 6066405081802389504*I/21217636514687010905], + [0, 0, 0, -11328/952745 + 87616*I/952745]]''')) + +def test_issue_17247_expression_blowup_23(): + M = Matrix(S('''[ + [ -3/4, 45/32 - 37*I/16, 0, 0], + [-149/64 + 49*I/32, -177/128 - 1369*I/128, 0, -2063/256 + 541*I/128], + [ 0, 9/4 + 55*I/16, 2473/256 + 137*I/64, 0], + [ 0, 0, 0, -177/128 - 1369*I/128]]''')) + with dotprodsimp(True): + assert M.inv(method='ADJ').expand() == Matrix(S('''[ + [-26194832/3470993 - 31733264*I/3470993, 156352/3470993 + 10325632*I/3470993, 0, -7741283181072/3306971225785 + 2999007604624*I/3306971225785], + [4408224/3470993 - 9675328*I/3470993, -2422272/3470993 + 1523712*I/3470993, 0, -1824666489984/3306971225785 - 1401091949952*I/3306971225785], + [-26406945676288/22270005630769 + 10245925485056*I/22270005630769, 7453523312640/22270005630769 + 1601616519168*I/22270005630769, 633088/6416033 - 140288*I/6416033, 872209227109521408/21217636514687010905 + 6066405081802389504*I/21217636514687010905], + [0, 0, 0, -11328/952745 + 87616*I/952745]]''')) + +def test_issue_17247_expression_blowup_24(): + M = SparseMatrix(S('''[ + [ -3/4, 45/32 - 37*I/16, 0, 0], + [-149/64 + 49*I/32, -177/128 - 1369*I/128, 0, -2063/256 + 541*I/128], + [ 0, 9/4 + 55*I/16, 2473/256 + 137*I/64, 0], + [ 0, 0, 0, -177/128 - 1369*I/128]]''')) + with dotprodsimp(True): + assert M.inv(method='CH') == Matrix(S('''[ + [-26194832/3470993 - 31733264*I/3470993, 156352/3470993 + 10325632*I/3470993, 0, -7741283181072/3306971225785 + 2999007604624*I/3306971225785], + [4408224/3470993 - 9675328*I/3470993, -2422272/3470993 + 1523712*I/3470993, 0, -1824666489984/3306971225785 - 1401091949952*I/3306971225785], + [-26406945676288/22270005630769 + 10245925485056*I/22270005630769, 7453523312640/22270005630769 + 1601616519168*I/22270005630769, 633088/6416033 - 140288*I/6416033, 872209227109521408/21217636514687010905 + 6066405081802389504*I/21217636514687010905], + [0, 0, 0, -11328/952745 + 87616*I/952745]]''')) + +def test_issue_17247_expression_blowup_25(): + M = SparseMatrix(S('''[ + [ -3/4, 45/32 - 37*I/16, 0, 0], + [-149/64 + 49*I/32, -177/128 - 1369*I/128, 0, -2063/256 + 541*I/128], + [ 0, 9/4 + 55*I/16, 2473/256 + 137*I/64, 0], + [ 0, 0, 0, -177/128 - 1369*I/128]]''')) + with dotprodsimp(True): + assert M.inv(method='LDL') == Matrix(S('''[ + [-26194832/3470993 - 31733264*I/3470993, 156352/3470993 + 10325632*I/3470993, 0, -7741283181072/3306971225785 + 2999007604624*I/3306971225785], + [4408224/3470993 - 9675328*I/3470993, -2422272/3470993 + 1523712*I/3470993, 0, -1824666489984/3306971225785 - 1401091949952*I/3306971225785], + [-26406945676288/22270005630769 + 10245925485056*I/22270005630769, 7453523312640/22270005630769 + 1601616519168*I/22270005630769, 633088/6416033 - 140288*I/6416033, 872209227109521408/21217636514687010905 + 6066405081802389504*I/21217636514687010905], + [0, 0, 0, -11328/952745 + 87616*I/952745]]''')) + +def test_issue_17247_expression_blowup_26(): + M = Matrix(S('''[ + [ -3/4, 45/32 - 37*I/16, 1/4 + I/2, -129/64 - 9*I/64, 1/4 - 5*I/16, 65/128 + 87*I/64, -9/32 - I/16, 183/256 - 97*I/128], + [-149/64 + 49*I/32, -177/128 - 1369*I/128, 125/64 + 87*I/64, -2063/256 + 541*I/128, 85/256 - 33*I/16, 805/128 + 2415*I/512, -219/128 + 115*I/256, 6301/4096 - 6609*I/1024], + [ 1/2 - I, 9/4 + 55*I/16, -3/4, 45/32 - 37*I/16, 1/4 + I/2, -129/64 - 9*I/64, 1/4 - 5*I/16, 65/128 + 87*I/64], + [ -5/8 - 39*I/16, 2473/256 + 137*I/64, -149/64 + 49*I/32, -177/128 - 1369*I/128, 125/64 + 87*I/64, -2063/256 + 541*I/128, 85/256 - 33*I/16, 805/128 + 2415*I/512], + [ 1 + I, -19/4 + 5*I/4, 1/2 - I, 9/4 + 55*I/16, -3/4, 45/32 - 37*I/16, 1/4 + I/2, -129/64 - 9*I/64], + [ 21/8 + I, -537/64 + 143*I/16, -5/8 - 39*I/16, 2473/256 + 137*I/64, -149/64 + 49*I/32, -177/128 - 1369*I/128, 125/64 + 87*I/64, -2063/256 + 541*I/128], + [ -2, 17/4 - 13*I/2, 1 + I, -19/4 + 5*I/4, 1/2 - I, 9/4 + 55*I/16, -3/4, 45/32 - 37*I/16], + [ 1/4 + 13*I/4, -825/64 - 147*I/32, 21/8 + I, -537/64 + 143*I/16, -5/8 - 39*I/16, 2473/256 + 137*I/64, -149/64 + 49*I/32, -177/128 - 1369*I/128]]''')) + with dotprodsimp(True): + assert M.rank() == 4 + +def test_issue_17247_expression_blowup_27(): + M = Matrix([ + [ 0, 1 - x, x + 1, 1 - x], + [1 - x, x + 1, 0, x + 1], + [ 0, 1 - x, x + 1, 1 - x], + [ 0, 0, 1 - x, 0]]) + with dotprodsimp(True): + P, J = M.jordan_form() + assert P.expand() == Matrix(S('''[ + [ 0, 4*x/(x**2 - 2*x + 1), -(-17*x**4 + 12*sqrt(2)*x**4 - 4*sqrt(2)*x**3 + 6*x**3 - 6*x - 4*sqrt(2)*x + 12*sqrt(2) + 17)/(-7*x**4 + 5*sqrt(2)*x**4 - 6*sqrt(2)*x**3 + 8*x**3 - 2*x**2 + 8*x + 6*sqrt(2)*x - 5*sqrt(2) - 7), -(12*sqrt(2)*x**4 + 17*x**4 - 6*x**3 - 4*sqrt(2)*x**3 - 4*sqrt(2)*x + 6*x - 17 + 12*sqrt(2))/(7*x**4 + 5*sqrt(2)*x**4 - 6*sqrt(2)*x**3 - 8*x**3 + 2*x**2 - 8*x + 6*sqrt(2)*x - 5*sqrt(2) + 7)], + [x - 1, x/(x - 1) + 1/(x - 1), (-7*x**3 + 5*sqrt(2)*x**3 - x**2 + sqrt(2)*x**2 - sqrt(2)*x - x - 5*sqrt(2) - 7)/(-3*x**3 + 2*sqrt(2)*x**3 - 2*sqrt(2)*x**2 + 3*x**2 + 2*sqrt(2)*x + 3*x - 3 - 2*sqrt(2)), (7*x**3 + 5*sqrt(2)*x**3 + x**2 + sqrt(2)*x**2 - sqrt(2)*x + x - 5*sqrt(2) + 7)/(2*sqrt(2)*x**3 + 3*x**3 - 3*x**2 - 2*sqrt(2)*x**2 - 3*x + 2*sqrt(2)*x - 2*sqrt(2) + 3)], + [ 0, 1, -(-3*x**2 + 2*sqrt(2)*x**2 + 2*x - 3 - 2*sqrt(2))/(-x**2 + sqrt(2)*x**2 - 2*sqrt(2)*x + 1 + sqrt(2)), -(2*sqrt(2)*x**2 + 3*x**2 - 2*x - 2*sqrt(2) + 3)/(x**2 + sqrt(2)*x**2 - 2*sqrt(2)*x - 1 + sqrt(2))], + [1 - x, 0, 1, 1]]''')).expand() + assert J == Matrix(S('''[ + [0, 1, 0, 0], + [0, 0, 0, 0], + [0, 0, x - sqrt(2)*(x - 1) + 1, 0], + [0, 0, 0, x + sqrt(2)*(x - 1) + 1]]''')) + +def test_issue_17247_expression_blowup_28(): + M = Matrix(S('''[ + [ -3/4, 45/32 - 37*I/16, 0, 0], + [-149/64 + 49*I/32, -177/128 - 1369*I/128, 0, -2063/256 + 541*I/128], + [ 0, 9/4 + 55*I/16, 2473/256 + 137*I/64, 0], + [ 0, 0, 0, -177/128 - 1369*I/128]]''')) + with dotprodsimp(True): + assert M.singular_values() == S('''[ + sqrt(14609315/131072 + sqrt(64789115132571/2147483648 - 2*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3) + 76627253330829751075/(35184372088832*sqrt(64789115132571/4294967296 + 3546944054712886603889144627/(110680464442257309696*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3)) + 2*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3))) - 3546944054712886603889144627/(110680464442257309696*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3)))/2 + sqrt(64789115132571/4294967296 + 3546944054712886603889144627/(110680464442257309696*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3)) + 2*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3))/2), + sqrt(14609315/131072 - sqrt(64789115132571/2147483648 - 2*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3) + 76627253330829751075/(35184372088832*sqrt(64789115132571/4294967296 + 3546944054712886603889144627/(110680464442257309696*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3)) + 2*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3))) - 3546944054712886603889144627/(110680464442257309696*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3)))/2 + sqrt(64789115132571/4294967296 + 3546944054712886603889144627/(110680464442257309696*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3)) + 2*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3))/2), + sqrt(14609315/131072 - sqrt(64789115132571/4294967296 + 3546944054712886603889144627/(110680464442257309696*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3)) + 2*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3))/2 + sqrt(64789115132571/2147483648 - 2*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3) - 76627253330829751075/(35184372088832*sqrt(64789115132571/4294967296 + 3546944054712886603889144627/(110680464442257309696*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3)) + 2*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3))) - 3546944054712886603889144627/(110680464442257309696*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3)))/2), + sqrt(14609315/131072 - sqrt(64789115132571/4294967296 + 3546944054712886603889144627/(110680464442257309696*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3)) + 2*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3))/2 - sqrt(64789115132571/2147483648 - 2*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3) - 76627253330829751075/(35184372088832*sqrt(64789115132571/4294967296 + 3546944054712886603889144627/(110680464442257309696*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3)) + 2*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3))) - 3546944054712886603889144627/(110680464442257309696*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3)))/2)]''') + + +def test_issue_16823(): + # This still needs to be fixed if not using dotprodsimp. + M = Matrix(S('''[ + [1+I,-19/4+5/4*I,1/2-I,9/4+55/16*I,-3/4,45/32-37/16*I,1/4+1/2*I,-129/64-9/64*I,1/4-5/16*I,65/128+87/64*I,-9/32-1/16*I,183/256-97/128*I,3/64+13/64*I,-23/32-59/256*I,15/128-3/32*I,19/256+551/1024*I], + [21/8+I,-537/64+143/16*I,-5/8-39/16*I,2473/256+137/64*I,-149/64+49/32*I,-177/128-1369/128*I,125/64+87/64*I,-2063/256+541/128*I,85/256-33/16*I,805/128+2415/512*I,-219/128+115/256*I,6301/4096-6609/1024*I,119/128+143/128*I,-10879/2048+4343/4096*I,129/256-549/512*I,42533/16384+29103/8192*I], + [-2,17/4-13/2*I,1+I,-19/4+5/4*I,1/2-I,9/4+55/16*I,-3/4,45/32-37/16*I,1/4+1/2*I,-129/64-9/64*I,1/4-5/16*I,65/128+87/64*I,-9/32-1/16*I,183/256-97/128*I,3/64+13/64*I,-23/32-59/256*I], + [1/4+13/4*I,-825/64-147/32*I,21/8+I,-537/64+143/16*I,-5/8-39/16*I,2473/256+137/64*I,-149/64+49/32*I,-177/128-1369/128*I,125/64+87/64*I,-2063/256+541/128*I,85/256-33/16*I,805/128+2415/512*I,-219/128+115/256*I,6301/4096-6609/1024*I,119/128+143/128*I,-10879/2048+4343/4096*I], + [-4*I,27/2+6*I,-2,17/4-13/2*I,1+I,-19/4+5/4*I,1/2-I,9/4+55/16*I,-3/4,45/32-37/16*I,1/4+1/2*I,-129/64-9/64*I,1/4-5/16*I,65/128+87/64*I,-9/32-1/16*I,183/256-97/128*I], + [1/4+5/2*I,-23/8-57/16*I,1/4+13/4*I,-825/64-147/32*I,21/8+I,-537/64+143/16*I,-5/8-39/16*I,2473/256+137/64*I,-149/64+49/32*I,-177/128-1369/128*I,125/64+87/64*I,-2063/256+541/128*I,85/256-33/16*I,805/128+2415/512*I,-219/128+115/256*I,6301/4096-6609/1024*I], + [-4,9-5*I,-4*I,27/2+6*I,-2,17/4-13/2*I,1+I,-19/4+5/4*I,1/2-I,9/4+55/16*I,-3/4,45/32-37/16*I,1/4+1/2*I,-129/64-9/64*I,1/4-5/16*I,65/128+87/64*I], + [-2*I,119/8+29/4*I,1/4+5/2*I,-23/8-57/16*I,1/4+13/4*I,-825/64-147/32*I,21/8+I,-537/64+143/16*I,-5/8-39/16*I,2473/256+137/64*I,-149/64+49/32*I,-177/128-1369/128*I,125/64+87/64*I,-2063/256+541/128*I,85/256-33/16*I,805/128+2415/512*I], + [0,-6,-4,9-5*I,-4*I,27/2+6*I,-2,17/4-13/2*I,1+I,-19/4+5/4*I,1/2-I,9/4+55/16*I,-3/4,45/32-37/16*I,1/4+1/2*I,-129/64-9/64*I], + [1,-9/4+3*I,-2*I,119/8+29/4*I,1/4+5/2*I,-23/8-57/16*I,1/4+13/4*I,-825/64-147/32*I,21/8+I,-537/64+143/16*I,-5/8-39/16*I,2473/256+137/64*I,-149/64+49/32*I,-177/128-1369/128*I,125/64+87/64*I,-2063/256+541/128*I], + [0,-4*I,0,-6,-4,9-5*I,-4*I,27/2+6*I,-2,17/4-13/2*I,1+I,-19/4+5/4*I,1/2-I,9/4+55/16*I,-3/4,45/32-37/16*I], + [0,1/4+1/2*I,1,-9/4+3*I,-2*I,119/8+29/4*I,1/4+5/2*I,-23/8-57/16*I,1/4+13/4*I,-825/64-147/32*I,21/8+I,-537/64+143/16*I,-5/8-39/16*I,2473/256+137/64*I,-149/64+49/32*I,-177/128-1369/128*I]]''')) + with dotprodsimp(True): + assert M.rank() == 8 + + +def test_issue_18531(): + # solve_linear_system still needs fixing but the rref works. + M = Matrix([ + [1, 1, 1, 1, 1, 0, 1, 0, 0], + [1 + sqrt(2), -1 + sqrt(2), 1 - sqrt(2), -sqrt(2) - 1, 1, 1, -1, 1, 1], + [-5 + 2*sqrt(2), -5 - 2*sqrt(2), -5 - 2*sqrt(2), -5 + 2*sqrt(2), -7, 2, -7, -2, 0], + [-3*sqrt(2) - 1, 1 - 3*sqrt(2), -1 + 3*sqrt(2), 1 + 3*sqrt(2), -7, -5, 7, -5, 3], + [7 - 4*sqrt(2), 4*sqrt(2) + 7, 4*sqrt(2) + 7, 7 - 4*sqrt(2), 7, -12, 7, 12, 0], + [-1 + 3*sqrt(2), 1 + 3*sqrt(2), -3*sqrt(2) - 1, 1 - 3*sqrt(2), 7, -5, -7, -5, 3], + [-3 + 2*sqrt(2), -3 - 2*sqrt(2), -3 - 2*sqrt(2), -3 + 2*sqrt(2), -1, 2, -1, -2, 0], + [1 - sqrt(2), -sqrt(2) - 1, 1 + sqrt(2), -1 + sqrt(2), -1, 1, 1, 1, 1] + ]) + with dotprodsimp(True): + assert M.rref() == (Matrix([ + [1, 0, 0, 0, 0, 0, 0, 0, S(1)/2], + [0, 1, 0, 0, 0, 0, 0, 0, -S(1)/2], + [0, 0, 1, 0, 0, 0, 0, 0, S(1)/2], + [0, 0, 0, 1, 0, 0, 0, 0, -S(1)/2], + [0, 0, 0, 0, 1, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 1, 0, 0, -S(1)/2], + [0, 0, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 1, -S(1)/2]]), (0, 1, 2, 3, 4, 5, 6, 7)) + + +def test_creation(): + raises(ValueError, lambda: Matrix(5, 5, range(20))) + raises(ValueError, lambda: Matrix(5, -1, [])) + raises(IndexError, lambda: Matrix((1, 2))[2]) + with raises(IndexError): + Matrix((1, 2))[3] = 5 + + assert Matrix() == Matrix([]) == Matrix(0, 0, []) + assert Matrix([[]]) == Matrix(1, 0, []) + assert Matrix([[], []]) == Matrix(2, 0, []) + + # anything used to be allowed in a matrix + with warns_deprecated_sympy(): + assert Matrix([[[1], (2,)]]).tolist() == [[[1], (2,)]] + with warns_deprecated_sympy(): + assert Matrix([[[1], (2,)]]).T.tolist() == [[[1]], [(2,)]] + M = Matrix([[0]]) + with warns_deprecated_sympy(): + M[0, 0] = S.EmptySet + + a = Matrix([[x, 0], [0, 0]]) + m = a + assert m.cols == m.rows + assert m.cols == 2 + assert m[:] == [x, 0, 0, 0] + + b = Matrix(2, 2, [x, 0, 0, 0]) + m = b + assert m.cols == m.rows + assert m.cols == 2 + assert m[:] == [x, 0, 0, 0] + + assert a == b + + assert Matrix(b) == b + + c23 = Matrix(2, 3, range(1, 7)) + c13 = Matrix(1, 3, range(7, 10)) + c = Matrix([c23, c13]) + assert c.cols == 3 + assert c.rows == 3 + assert c[:] == [1, 2, 3, 4, 5, 6, 7, 8, 9] + + assert Matrix(eye(2)) == eye(2) + assert ImmutableMatrix(ImmutableMatrix(eye(2))) == ImmutableMatrix(eye(2)) + assert ImmutableMatrix(c) == c.as_immutable() + assert Matrix(ImmutableMatrix(c)) == ImmutableMatrix(c).as_mutable() + + assert c is not Matrix(c) + + dat = [[ones(3,2), ones(3,3)*2], [ones(2,3)*3, ones(2,2)*4]] + M = Matrix(dat) + assert M == Matrix([ + [1, 1, 2, 2, 2], + [1, 1, 2, 2, 2], + [1, 1, 2, 2, 2], + [3, 3, 3, 4, 4], + [3, 3, 3, 4, 4]]) + assert M.tolist() != dat + # keep block form if evaluate=False + assert Matrix(dat, evaluate=False).tolist() == dat + A = MatrixSymbol("A", 2, 2) + dat = [ones(2), A] + assert Matrix(dat) == Matrix([ + [ 1, 1], + [ 1, 1], + [A[0, 0], A[0, 1]], + [A[1, 0], A[1, 1]]]) + with warns_deprecated_sympy(): + assert Matrix(dat, evaluate=False).tolist() == [[i] for i in dat] + + # 0-dim tolerance + assert Matrix([ones(2), ones(0)]) == Matrix([ones(2)]) + raises(ValueError, lambda: Matrix([ones(2), ones(0, 3)])) + raises(ValueError, lambda: Matrix([ones(2), ones(3, 0)])) + + # mix of Matrix and iterable + M = Matrix([[1, 2], [3, 4]]) + M2 = Matrix([M, (5, 6)]) + assert M2 == Matrix([[1, 2], [3, 4], [5, 6]]) + + +def test_irregular_block(): + assert Matrix.irregular(3, ones(2,1), ones(3,3)*2, ones(2,2)*3, + ones(1,1)*4, ones(2,2)*5, ones(1,2)*6, ones(1,2)*7) == Matrix([ + [1, 2, 2, 2, 3, 3], + [1, 2, 2, 2, 3, 3], + [4, 2, 2, 2, 5, 5], + [6, 6, 7, 7, 5, 5]]) + + +def test_tolist(): + lst = [[S.One, S.Half, x*y, S.Zero], [x, y, z, x**2], [y, -S.One, z*x, 3]] + m = Matrix(lst) + assert m.tolist() == lst + + +def test_as_mutable(): + assert zeros(0, 3).as_mutable() == zeros(0, 3) + assert zeros(0, 3).as_immutable() == ImmutableMatrix(zeros(0, 3)) + assert zeros(3, 0).as_immutable() == ImmutableMatrix(zeros(3, 0)) + + +def test_slicing(): + m0 = eye(4) + assert m0[:3, :3] == eye(3) + assert m0[2:4, 0:2] == zeros(2) + + m1 = Matrix(3, 3, lambda i, j: i + j) + assert m1[0, :] == Matrix(1, 3, (0, 1, 2)) + assert m1[1:3, 1] == Matrix(2, 1, (2, 3)) + + m2 = Matrix([[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]]) + assert m2[:, -1] == Matrix(4, 1, [3, 7, 11, 15]) + assert m2[-2:, :] == Matrix([[8, 9, 10, 11], [12, 13, 14, 15]]) + + +def test_submatrix_assignment(): + m = zeros(4) + m[2:4, 2:4] = eye(2) + assert m == Matrix(((0, 0, 0, 0), + (0, 0, 0, 0), + (0, 0, 1, 0), + (0, 0, 0, 1))) + m[:2, :2] = eye(2) + assert m == eye(4) + m[:, 0] = Matrix(4, 1, (1, 2, 3, 4)) + assert m == Matrix(((1, 0, 0, 0), + (2, 1, 0, 0), + (3, 0, 1, 0), + (4, 0, 0, 1))) + m[:, :] = zeros(4) + assert m == zeros(4) + m[:, :] = [(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12), (13, 14, 15, 16)] + assert m == Matrix(((1, 2, 3, 4), + (5, 6, 7, 8), + (9, 10, 11, 12), + (13, 14, 15, 16))) + m[:2, 0] = [0, 0] + assert m == Matrix(((0, 2, 3, 4), + (0, 6, 7, 8), + (9, 10, 11, 12), + (13, 14, 15, 16))) + + +def test_extract(): + m = Matrix(4, 3, lambda i, j: i*3 + j) + assert m.extract([0, 1, 3], [0, 1]) == Matrix(3, 2, [0, 1, 3, 4, 9, 10]) + assert m.extract([0, 3], [0, 0, 2]) == Matrix(2, 3, [0, 0, 2, 9, 9, 11]) + assert m.extract(range(4), range(3)) == m + raises(IndexError, lambda: m.extract([4], [0])) + raises(IndexError, lambda: m.extract([0], [3])) + + +def test_reshape(): + m0 = eye(3) + assert m0.reshape(1, 9) == Matrix(1, 9, (1, 0, 0, 0, 1, 0, 0, 0, 1)) + m1 = Matrix(3, 4, lambda i, j: i + j) + assert m1.reshape( + 4, 3) == Matrix(((0, 1, 2), (3, 1, 2), (3, 4, 2), (3, 4, 5))) + assert m1.reshape(2, 6) == Matrix(((0, 1, 2, 3, 1, 2), (3, 4, 2, 3, 4, 5))) + + +def test_applyfunc(): + m0 = eye(3) + assert m0.applyfunc(lambda x: 2*x) == eye(3)*2 + assert m0.applyfunc(lambda x: 0) == zeros(3) + + +def test_expand(): + m0 = Matrix([[x*(x + y), 2], [((x + y)*y)*x, x*(y + x*(x + y))]]) + # Test if expand() returns a matrix + m1 = m0.expand() + assert m1 == Matrix( + [[x*y + x**2, 2], [x*y**2 + y*x**2, x*y + y*x**2 + x**3]]) + + a = Symbol('a', real=True) + + assert Matrix([exp(I*a)]).expand(complex=True) == \ + Matrix([cos(a) + I*sin(a)]) + + assert Matrix([[0, 1, 2], [0, 0, -1], [0, 0, 0]]).exp() == Matrix([ + [1, 1, Rational(3, 2)], + [0, 1, -1], + [0, 0, 1]] + ) + +def test_refine(): + m0 = Matrix([[Abs(x)**2, sqrt(x**2)], + [sqrt(x**2)*Abs(y)**2, sqrt(y**2)*Abs(x)**2]]) + m1 = m0.refine(Q.real(x) & Q.real(y)) + assert m1 == Matrix([[x**2, Abs(x)], [y**2*Abs(x), x**2*Abs(y)]]) + + m1 = m0.refine(Q.positive(x) & Q.positive(y)) + assert m1 == Matrix([[x**2, x], [x*y**2, x**2*y]]) + + m1 = m0.refine(Q.negative(x) & Q.negative(y)) + assert m1 == Matrix([[x**2, -x], [-x*y**2, -x**2*y]]) + +def test_random(): + M = randMatrix(3, 3) + M = randMatrix(3, 3, seed=3) + assert M == randMatrix(3, 3, seed=3) + + M = randMatrix(3, 4, 0, 150) + M = randMatrix(3, seed=4, symmetric=True) + assert M == randMatrix(3, seed=4, symmetric=True) + + S = M.copy() + S.simplify() + assert S == M # doesn't fail when elements are Numbers, not int + + rng = random.Random(4) + assert M == randMatrix(3, symmetric=True, prng=rng) + + # Ensure symmetry + for size in (10, 11): # Test odd and even + for percent in (100, 70, 30): + M = randMatrix(size, symmetric=True, percent=percent, prng=rng) + assert M == M.T + + M = randMatrix(10, min=1, percent=70) + zero_count = 0 + for i in range(M.shape[0]): + for j in range(M.shape[1]): + if M[i, j] == 0: + zero_count += 1 + assert zero_count == 30 + +def test_inverse(): + A = eye(4) + assert A.inv() == eye(4) + assert A.inv(method="LU") == eye(4) + assert A.inv(method="ADJ") == eye(4) + assert A.inv(method="CH") == eye(4) + assert A.inv(method="LDL") == eye(4) + assert A.inv(method="QR") == eye(4) + A = Matrix([[2, 3, 5], + [3, 6, 2], + [8, 3, 6]]) + Ainv = A.inv() + assert A*Ainv == eye(3) + assert A.inv(method="LU") == Ainv + assert A.inv(method="ADJ") == Ainv + assert A.inv(method="CH") == Ainv + assert A.inv(method="LDL") == Ainv + assert A.inv(method="QR") == Ainv + + AA = Matrix([[0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0], + [1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0], + [1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1], + [1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0], + [1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0], + [1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1], + [0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0], + [1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1], + [0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1], + [1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0], + [0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0], + [1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0], + [0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1], + [1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0], + [0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0], + [1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0], + [0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1], + [0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1], + [1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1], + [0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1], + [0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1], + [0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0], + [0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0], + [0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0]]) + assert AA.inv(method="BLOCK") * AA == eye(AA.shape[0]) + # test that immutability is not a problem + cls = ImmutableMatrix + m = cls([[48, 49, 31], + [ 9, 71, 94], + [59, 28, 65]]) + assert all(type(m.inv(s)) is cls for s in 'GE ADJ LU CH LDL QR'.split()) + cls = ImmutableSparseMatrix + m = cls([[48, 49, 31], + [ 9, 71, 94], + [59, 28, 65]]) + assert all(type(m.inv(s)) is cls for s in 'GE ADJ LU CH LDL QR'.split()) + + +def test_jacobian_hessian(): + L = Matrix(1, 2, [x**2*y, 2*y**2 + x*y]) + syms = [x, y] + assert L.jacobian(syms) == Matrix([[2*x*y, x**2], [y, 4*y + x]]) + + L = Matrix(1, 2, [x, x**2*y**3]) + assert L.jacobian(syms) == Matrix([[1, 0], [2*x*y**3, x**2*3*y**2]]) + + f = x**2*y + syms = [x, y] + assert hessian(f, syms) == Matrix([[2*y, 2*x], [2*x, 0]]) + + f = x**2*y**3 + assert hessian(f, syms) == \ + Matrix([[2*y**3, 6*x*y**2], [6*x*y**2, 6*x**2*y]]) + + f = z + x*y**2 + g = x**2 + 2*y**3 + ans = Matrix([[0, 2*y], + [2*y, 2*x]]) + assert ans == hessian(f, Matrix([x, y])) + assert ans == hessian(f, Matrix([x, y]).T) + assert hessian(f, (y, x), [g]) == Matrix([ + [ 0, 6*y**2, 2*x], + [6*y**2, 2*x, 2*y], + [ 2*x, 2*y, 0]]) + + +def test_wronskian(): + assert wronskian([cos(x), sin(x)], x) == cos(x)**2 + sin(x)**2 + assert wronskian([exp(x), exp(2*x)], x) == exp(3*x) + assert wronskian([exp(x), x], x) == exp(x) - x*exp(x) + assert wronskian([1, x, x**2], x) == 2 + w1 = -6*exp(x)*sin(x)*x + 6*cos(x)*exp(x)*x**2 - 6*exp(x)*cos(x)*x - \ + exp(x)*cos(x)*x**3 + exp(x)*sin(x)*x**3 + assert wronskian([exp(x), cos(x), x**3], x).expand() == w1 + assert wronskian([exp(x), cos(x), x**3], x, method='berkowitz').expand() \ + == w1 + w2 = -x**3*cos(x)**2 - x**3*sin(x)**2 - 6*x*cos(x)**2 - 6*x*sin(x)**2 + assert wronskian([sin(x), cos(x), x**3], x).expand() == w2 + assert wronskian([sin(x), cos(x), x**3], x, method='berkowitz').expand() \ + == w2 + assert wronskian([], x) == 1 + + +def test_subs(): + assert Matrix([[1, x], [x, 4]]).subs(x, 5) == Matrix([[1, 5], [5, 4]]) + assert Matrix([[x, 2], [x + y, 4]]).subs([[x, -1], [y, -2]]) == \ + Matrix([[-1, 2], [-3, 4]]) + assert Matrix([[x, 2], [x + y, 4]]).subs([(x, -1), (y, -2)]) == \ + Matrix([[-1, 2], [-3, 4]]) + assert Matrix([[x, 2], [x + y, 4]]).subs({x: -1, y: -2}) == \ + Matrix([[-1, 2], [-3, 4]]) + assert Matrix([x*y]).subs({x: y - 1, y: x - 1}, simultaneous=True) == \ + Matrix([(x - 1)*(y - 1)]) + + for cls in classes: + assert Matrix([[2, 0], [0, 2]]) == cls.eye(2).subs(1, 2) + +def test_xreplace(): + assert Matrix([[1, x], [x, 4]]).xreplace({x: 5}) == \ + Matrix([[1, 5], [5, 4]]) + assert Matrix([[x, 2], [x + y, 4]]).xreplace({x: -1, y: -2}) == \ + Matrix([[-1, 2], [-3, 4]]) + for cls in classes: + assert Matrix([[2, 0], [0, 2]]) == cls.eye(2).xreplace({1: 2}) + +def test_simplify(): + n = Symbol('n') + f = Function('f') + + M = Matrix([[ 1/x + 1/y, (x + x*y) / x ], + [ (f(x) + y*f(x))/f(x), 2 * (1/n - cos(n * pi)/n) / pi ]]) + M.simplify() + assert M == Matrix([[ (x + y)/(x * y), 1 + y ], + [ 1 + y, 2*((1 - 1*cos(pi*n))/(pi*n)) ]]) + eq = (1 + x)**2 + M = Matrix([[eq]]) + M.simplify() + assert M == Matrix([[eq]]) + M.simplify(ratio=oo) + assert M == Matrix([[eq.simplify(ratio=oo)]]) + + +def test_transpose(): + M = Matrix([[1, 2, 3, 4, 5, 6, 7, 8, 9, 0], + [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]]) + assert M.T == Matrix( [ [1, 1], + [2, 2], + [3, 3], + [4, 4], + [5, 5], + [6, 6], + [7, 7], + [8, 8], + [9, 9], + [0, 0] ]) + assert M.T.T == M + assert M.T == M.transpose() + + +def test_conjugate(): + M = Matrix([[0, I, 5], + [1, 2, 0]]) + + assert M.T == Matrix([[0, 1], + [I, 2], + [5, 0]]) + + assert M.C == Matrix([[0, -I, 5], + [1, 2, 0]]) + assert M.C == M.conjugate() + + assert M.H == M.T.C + assert M.H == Matrix([[ 0, 1], + [-I, 2], + [ 5, 0]]) + + +def test_conj_dirac(): + raises(AttributeError, lambda: eye(3).D) + + M = Matrix([[1, I, I, I], + [0, 1, I, I], + [0, 0, 1, I], + [0, 0, 0, 1]]) + + assert M.D == Matrix([[ 1, 0, 0, 0], + [-I, 1, 0, 0], + [-I, -I, -1, 0], + [-I, -I, I, -1]]) + + +def test_trace(): + M = Matrix([[1, 0, 0], + [0, 5, 0], + [0, 0, 8]]) + assert M.trace() == 14 + + +def test_shape(): + M = Matrix([[x, 0, 0], + [0, y, 0]]) + assert M.shape == (2, 3) + + +def test_col_row_op(): + M = Matrix([[x, 0, 0], + [0, y, 0]]) + M.row_op(1, lambda r, j: r + j + 1) + assert M == Matrix([[x, 0, 0], + [1, y + 2, 3]]) + + M.col_op(0, lambda c, j: c + y**j) + assert M == Matrix([[x + 1, 0, 0], + [1 + y, y + 2, 3]]) + + # neither row nor slice give copies that allow the original matrix to + # be changed + assert M.row(0) == Matrix([[x + 1, 0, 0]]) + r1 = M.row(0) + r1[0] = 42 + assert M[0, 0] == x + 1 + r1 = M[0, :-1] # also testing negative slice + r1[0] = 42 + assert M[0, 0] == x + 1 + c1 = M.col(0) + assert c1 == Matrix([x + 1, 1 + y]) + c1[0] = 0 + assert M[0, 0] == x + 1 + c1 = M[:, 0] + c1[0] = 42 + assert M[0, 0] == x + 1 + + +def test_row_mult(): + M = Matrix([[1,2,3], + [4,5,6]]) + M.row_mult(1,3) + assert M[1,0] == 12 + assert M[0,0] == 1 + assert M[1,2] == 18 + + +def test_row_add(): + M = Matrix([[1,2,3], + [4,5,6], + [1,1,1]]) + M.row_add(2,0,5) + assert M[0,0] == 6 + assert M[1,0] == 4 + assert M[0,2] == 8 + + +def test_zip_row_op(): + for cls in classes[:2]: # XXX: immutable matrices don't support row ops + M = cls.eye(3) + M.zip_row_op(1, 0, lambda v, u: v + 2*u) + assert M == cls([[1, 0, 0], + [2, 1, 0], + [0, 0, 1]]) + + M = cls.eye(3)*2 + M[0, 1] = -1 + M.zip_row_op(1, 0, lambda v, u: v + 2*u); M + assert M == cls([[2, -1, 0], + [4, 0, 0], + [0, 0, 2]]) + +def test_issue_3950(): + m = Matrix([1, 2, 3]) + a = Matrix([1, 2, 3]) + b = Matrix([2, 2, 3]) + assert not (m in []) + assert not (m in [1]) + assert m != 1 + assert m == a + assert m != b + + +def test_issue_3981(): + class Index1: + def __index__(self): + return 1 + + class Index2: + def __index__(self): + return 2 + index1 = Index1() + index2 = Index2() + + m = Matrix([1, 2, 3]) + + assert m[index2] == 3 + + m[index2] = 5 + assert m[2] == 5 + + m = Matrix([[1, 2, 3], [4, 5, 6]]) + assert m[index1, index2] == 6 + assert m[1, index2] == 6 + assert m[index1, 2] == 6 + + m[index1, index2] = 4 + assert m[1, 2] == 4 + m[1, index2] = 6 + assert m[1, 2] == 6 + m[index1, 2] = 8 + assert m[1, 2] == 8 + + +def test_evalf(): + a = Matrix([sqrt(5), 6]) + assert all(a.evalf()[i] == a[i].evalf() for i in range(2)) + assert all(a.evalf(2)[i] == a[i].evalf(2) for i in range(2)) + assert all(a.n(2)[i] == a[i].n(2) for i in range(2)) + + +def test_is_symbolic(): + a = Matrix([[x, x], [x, x]]) + assert a.is_symbolic() is True + a = Matrix([[1, 2, 3, 4], [5, 6, 7, 8]]) + assert a.is_symbolic() is False + a = Matrix([[1, 2, 3, 4], [5, 6, x, 8]]) + assert a.is_symbolic() is True + a = Matrix([[1, x, 3]]) + assert a.is_symbolic() is True + a = Matrix([[1, 2, 3]]) + assert a.is_symbolic() is False + a = Matrix([[1], [x], [3]]) + assert a.is_symbolic() is True + a = Matrix([[1], [2], [3]]) + assert a.is_symbolic() is False + + +def test_is_upper(): + a = Matrix([[1, 2, 3]]) + assert a.is_upper is True + a = Matrix([[1], [2], [3]]) + assert a.is_upper is False + a = zeros(4, 2) + assert a.is_upper is True + + +def test_is_lower(): + a = Matrix([[1, 2, 3]]) + assert a.is_lower is False + a = Matrix([[1], [2], [3]]) + assert a.is_lower is True + + +def test_is_nilpotent(): + a = Matrix(4, 4, [0, 2, 1, 6, 0, 0, 1, 2, 0, 0, 0, 3, 0, 0, 0, 0]) + assert a.is_nilpotent() + a = Matrix([[1, 0], [0, 1]]) + assert not a.is_nilpotent() + a = Matrix([]) + assert a.is_nilpotent() + + +def test_zeros_ones_fill(): + n, m = 3, 5 + + a = zeros(n, m) + a.fill( 5 ) + + b = 5 * ones(n, m) + + assert a == b + assert a.rows == b.rows == 3 + assert a.cols == b.cols == 5 + assert a.shape == b.shape == (3, 5) + assert zeros(2) == zeros(2, 2) + assert ones(2) == ones(2, 2) + assert zeros(2, 3) == Matrix(2, 3, [0]*6) + assert ones(2, 3) == Matrix(2, 3, [1]*6) + + a.fill(0) + assert a == zeros(n, m) + + +def test_empty_zeros(): + a = zeros(0) + assert a == Matrix() + a = zeros(0, 2) + assert a.rows == 0 + assert a.cols == 2 + a = zeros(2, 0) + assert a.rows == 2 + assert a.cols == 0 + + +def test_issue_3749(): + a = Matrix([[x**2, x*y], [x*sin(y), x*cos(y)]]) + assert a.diff(x) == Matrix([[2*x, y], [sin(y), cos(y)]]) + assert Matrix([ + [x, -x, x**2], + [exp(x), 1/x - exp(-x), x + 1/x]]).limit(x, oo) == \ + Matrix([[oo, -oo, oo], [oo, 0, oo]]) + assert Matrix([ + [(exp(x) - 1)/x, 2*x + y*x, x**x ], + [1/x, abs(x), abs(sin(x + 1))]]).limit(x, 0) == \ + Matrix([[1, 0, 1], [oo, 0, sin(1)]]) + assert a.integrate(x) == Matrix([ + [Rational(1, 3)*x**3, y*x**2/2], + [x**2*sin(y)/2, x**2*cos(y)/2]]) + + +def test_inv_iszerofunc(): + A = eye(4) + A.col_swap(0, 1) + for method in "GE", "LU": + assert A.inv(method=method, iszerofunc=lambda x: x == 0) == \ + A.inv(method="ADJ") + + +def test_jacobian_metrics(): + rho, phi = symbols("rho,phi") + X = Matrix([rho*cos(phi), rho*sin(phi)]) + Y = Matrix([rho, phi]) + J = X.jacobian(Y) + assert J == X.jacobian(Y.T) + assert J == (X.T).jacobian(Y) + assert J == (X.T).jacobian(Y.T) + g = J.T*eye(J.shape[0])*J + g = g.applyfunc(trigsimp) + assert g == Matrix([[1, 0], [0, rho**2]]) + + +def test_jacobian2(): + rho, phi = symbols("rho,phi") + X = Matrix([rho*cos(phi), rho*sin(phi), rho**2]) + Y = Matrix([rho, phi]) + J = Matrix([ + [cos(phi), -rho*sin(phi)], + [sin(phi), rho*cos(phi)], + [ 2*rho, 0], + ]) + assert X.jacobian(Y) == J + + +def test_issue_4564(): + X = Matrix([exp(x + y + z), exp(x + y + z), exp(x + y + z)]) + Y = Matrix([x, y, z]) + for i in range(1, 3): + for j in range(1, 3): + X_slice = X[:i, :] + Y_slice = Y[:j, :] + J = X_slice.jacobian(Y_slice) + assert J.rows == i + assert J.cols == j + for k in range(j): + assert J[:, k] == X_slice + + +def test_nonvectorJacobian(): + X = Matrix([[exp(x + y + z), exp(x + y + z)], + [exp(x + y + z), exp(x + y + z)]]) + raises(TypeError, lambda: X.jacobian(Matrix([x, y, z]))) + X = X[0, :] + Y = Matrix([[x, y], [x, z]]) + raises(TypeError, lambda: X.jacobian(Y)) + raises(TypeError, lambda: X.jacobian(Matrix([ [x, y], [x, z] ]))) + + +def test_vec(): + m = Matrix([[1, 3], [2, 4]]) + m_vec = m.vec() + assert m_vec.cols == 1 + for i in range(4): + assert m_vec[i] == i + 1 + + +def test_vech(): + m = Matrix([[1, 2], [2, 3]]) + m_vech = m.vech() + assert m_vech.cols == 1 + for i in range(3): + assert m_vech[i] == i + 1 + m_vech = m.vech(diagonal=False) + assert m_vech[0] == 2 + + m = Matrix([[1, x*(x + y)], [y*x + x**2, 1]]) + m_vech = m.vech(diagonal=False) + assert m_vech[0] == y*x + x**2 + + m = Matrix([[1, x*(x + y)], [y*x, 1]]) + m_vech = m.vech(diagonal=False, check_symmetry=False) + assert m_vech[0] == y*x + + raises(ShapeError, lambda: Matrix([[1, 3]]).vech()) + raises(ValueError, lambda: Matrix([[1, 3], [2, 4]]).vech()) + raises(ShapeError, lambda: Matrix([[1, 3]]).vech()) + raises(ValueError, lambda: Matrix([[1, 3], [2, 4]]).vech()) + + +def test_diag(): + # mostly tested in testcommonmatrix.py + assert diag([1, 2, 3]) == Matrix([1, 2, 3]) + m = [1, 2, [3]] + raises(ValueError, lambda: diag(m)) + assert diag(m, strict=False) == Matrix([1, 2, 3]) + + +def test_get_diag_blocks1(): + a = Matrix([[1, 2], [2, 3]]) + b = Matrix([[3, x], [y, 3]]) + c = Matrix([[3, x, 3], [y, 3, z], [x, y, z]]) + assert a.get_diag_blocks() == [a] + assert b.get_diag_blocks() == [b] + assert c.get_diag_blocks() == [c] + + +def test_get_diag_blocks2(): + a = Matrix([[1, 2], [2, 3]]) + b = Matrix([[3, x], [y, 3]]) + c = Matrix([[3, x, 3], [y, 3, z], [x, y, z]]) + assert diag(a, b, b).get_diag_blocks() == [a, b, b] + assert diag(a, b, c).get_diag_blocks() == [a, b, c] + assert diag(a, c, b).get_diag_blocks() == [a, c, b] + assert diag(c, c, b).get_diag_blocks() == [c, c, b] + + +def test_inv_block(): + a = Matrix([[1, 2], [2, 3]]) + b = Matrix([[3, x], [y, 3]]) + c = Matrix([[3, x, 3], [y, 3, z], [x, y, z]]) + A = diag(a, b, b) + assert A.inv(try_block_diag=True) == diag(a.inv(), b.inv(), b.inv()) + A = diag(a, b, c) + assert A.inv(try_block_diag=True) == diag(a.inv(), b.inv(), c.inv()) + A = diag(a, c, b) + assert A.inv(try_block_diag=True) == diag(a.inv(), c.inv(), b.inv()) + A = diag(a, a, b, a, c, a) + assert A.inv(try_block_diag=True) == diag( + a.inv(), a.inv(), b.inv(), a.inv(), c.inv(), a.inv()) + assert A.inv(try_block_diag=True, method="ADJ") == diag( + a.inv(method="ADJ"), a.inv(method="ADJ"), b.inv(method="ADJ"), + a.inv(method="ADJ"), c.inv(method="ADJ"), a.inv(method="ADJ")) + + +def test_creation_args(): + """ + Check that matrix dimensions can be specified using any reasonable type + (see issue 4614). + """ + raises(ValueError, lambda: zeros(3, -1)) + raises(TypeError, lambda: zeros(1, 2, 3, 4)) + assert zeros(int(3)) == zeros(3) + assert zeros(Integer(3)) == zeros(3) + raises(ValueError, lambda: zeros(3.)) + assert eye(int(3)) == eye(3) + assert eye(Integer(3)) == eye(3) + raises(ValueError, lambda: eye(3.)) + assert ones(int(3), Integer(4)) == ones(3, 4) + raises(TypeError, lambda: Matrix(5)) + raises(TypeError, lambda: Matrix(1, 2)) + raises(ValueError, lambda: Matrix([1, [2]])) + + +def test_diagonal_symmetrical(): + m = Matrix(2, 2, [0, 1, 1, 0]) + assert not m.is_diagonal() + assert m.is_symmetric() + assert m.is_symmetric(simplify=False) + + m = Matrix(2, 2, [1, 0, 0, 1]) + assert m.is_diagonal() + + m = diag(1, 2, 3) + assert m.is_diagonal() + assert m.is_symmetric() + + m = Matrix(3, 3, [1, 0, 0, 0, 2, 0, 0, 0, 3]) + assert m == diag(1, 2, 3) + + m = Matrix(2, 3, zeros(2, 3)) + assert not m.is_symmetric() + assert m.is_diagonal() + + m = Matrix(((5, 0), (0, 6), (0, 0))) + assert m.is_diagonal() + + m = Matrix(((5, 0, 0), (0, 6, 0))) + assert m.is_diagonal() + + m = Matrix(3, 3, [1, x**2 + 2*x + 1, y, (x + 1)**2, 2, 0, y, 0, 3]) + assert m.is_symmetric() + assert not m.is_symmetric(simplify=False) + assert m.expand().is_symmetric(simplify=False) + + +def test_diagonalization(): + m = Matrix([[1, 2+I], [2-I, 3]]) + assert m.is_diagonalizable() + + m = Matrix(3, 2, [-3, 1, -3, 20, 3, 10]) + assert not m.is_diagonalizable() + assert not m.is_symmetric() + raises(NonSquareMatrixError, lambda: m.diagonalize()) + + # diagonalizable + m = diag(1, 2, 3) + (P, D) = m.diagonalize() + assert P == eye(3) + assert D == m + + m = Matrix(2, 2, [0, 1, 1, 0]) + assert m.is_symmetric() + assert m.is_diagonalizable() + (P, D) = m.diagonalize() + assert P.inv() * m * P == D + + m = Matrix(2, 2, [1, 0, 0, 3]) + assert m.is_symmetric() + assert m.is_diagonalizable() + (P, D) = m.diagonalize() + assert P.inv() * m * P == D + assert P == eye(2) + assert D == m + + m = Matrix(2, 2, [1, 1, 0, 0]) + assert m.is_diagonalizable() + (P, D) = m.diagonalize() + assert P.inv() * m * P == D + + m = Matrix(3, 3, [1, 2, 0, 0, 3, 0, 2, -4, 2]) + assert m.is_diagonalizable() + (P, D) = m.diagonalize() + assert P.inv() * m * P == D + for i in P: + assert i.as_numer_denom()[1] == 1 + + m = Matrix(2, 2, [1, 0, 0, 0]) + assert m.is_diagonal() + assert m.is_diagonalizable() + (P, D) = m.diagonalize() + assert P.inv() * m * P == D + assert P == Matrix([[0, 1], [1, 0]]) + + # diagonalizable, complex only + m = Matrix(2, 2, [0, 1, -1, 0]) + assert not m.is_diagonalizable(True) + raises(MatrixError, lambda: m.diagonalize(True)) + assert m.is_diagonalizable() + (P, D) = m.diagonalize() + assert P.inv() * m * P == D + + # not diagonalizable + m = Matrix(2, 2, [0, 1, 0, 0]) + assert not m.is_diagonalizable() + raises(MatrixError, lambda: m.diagonalize()) + + m = Matrix(3, 3, [-3, 1, -3, 20, 3, 10, 2, -2, 4]) + assert not m.is_diagonalizable() + raises(MatrixError, lambda: m.diagonalize()) + + # symbolic + a, b, c, d = symbols('a b c d') + m = Matrix(2, 2, [a, c, c, b]) + assert m.is_symmetric() + assert m.is_diagonalizable() + + +def test_issue_15887(): + # Mutable matrix should not use cache + a = MutableDenseMatrix([[0, 1], [1, 0]]) + assert a.is_diagonalizable() is True + a[1, 0] = 0 + assert a.is_diagonalizable() is False + + a = MutableDenseMatrix([[0, 1], [1, 0]]) + a.diagonalize() + a[1, 0] = 0 + raises(MatrixError, lambda: a.diagonalize()) + + +def test_jordan_form(): + + m = Matrix(3, 2, [-3, 1, -3, 20, 3, 10]) + raises(NonSquareMatrixError, lambda: m.jordan_form()) + + # diagonalizable + m = Matrix(3, 3, [7, -12, 6, 10, -19, 10, 12, -24, 13]) + Jmust = Matrix(3, 3, [-1, 0, 0, 0, 1, 0, 0, 0, 1]) + P, J = m.jordan_form() + assert Jmust == J + assert Jmust == m.diagonalize()[1] + + # m = Matrix(3, 3, [0, 6, 3, 1, 3, 1, -2, 2, 1]) + # m.jordan_form() # very long + # m.jordan_form() # + + # diagonalizable, complex only + + # Jordan cells + # complexity: one of eigenvalues is zero + m = Matrix(3, 3, [0, 1, 0, -4, 4, 0, -2, 1, 2]) + # The blocks are ordered according to the value of their eigenvalues, + # in order to make the matrix compatible with .diagonalize() + Jmust = Matrix(3, 3, [2, 1, 0, 0, 2, 0, 0, 0, 2]) + P, J = m.jordan_form() + assert Jmust == J + + # complexity: all of eigenvalues are equal + m = Matrix(3, 3, [2, 6, -15, 1, 1, -5, 1, 2, -6]) + # Jmust = Matrix(3, 3, [-1, 0, 0, 0, -1, 1, 0, 0, -1]) + # same here see 1456ff + Jmust = Matrix(3, 3, [-1, 1, 0, 0, -1, 0, 0, 0, -1]) + P, J = m.jordan_form() + assert Jmust == J + + # complexity: two of eigenvalues are zero + m = Matrix(3, 3, [4, -5, 2, 5, -7, 3, 6, -9, 4]) + Jmust = Matrix(3, 3, [0, 1, 0, 0, 0, 0, 0, 0, 1]) + P, J = m.jordan_form() + assert Jmust == J + + m = Matrix(4, 4, [6, 5, -2, -3, -3, -1, 3, 3, 2, 1, -2, -3, -1, 1, 5, 5]) + Jmust = Matrix(4, 4, [2, 1, 0, 0, + 0, 2, 0, 0, + 0, 0, 2, 1, + 0, 0, 0, 2] + ) + P, J = m.jordan_form() + assert Jmust == J + + m = Matrix(4, 4, [6, 2, -8, -6, -3, 2, 9, 6, 2, -2, -8, -6, -1, 0, 3, 4]) + # Jmust = Matrix(4, 4, [2, 0, 0, 0, 0, 2, 1, 0, 0, 0, 2, 0, 0, 0, 0, -2]) + # same here see 1456ff + Jmust = Matrix(4, 4, [-2, 0, 0, 0, + 0, 2, 1, 0, + 0, 0, 2, 0, + 0, 0, 0, 2]) + P, J = m.jordan_form() + assert Jmust == J + + m = Matrix(4, 4, [5, 4, 2, 1, 0, 1, -1, -1, -1, -1, 3, 0, 1, 1, -1, 2]) + assert not m.is_diagonalizable() + Jmust = Matrix(4, 4, [1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 4, 1, 0, 0, 0, 4]) + P, J = m.jordan_form() + assert Jmust == J + + # checking for maximum precision to remain unchanged + m = Matrix([[Float('1.0', precision=110), Float('2.0', precision=110)], + [Float('3.14159265358979323846264338327', precision=110), Float('4.0', precision=110)]]) + P, J = m.jordan_form() + for term in J.values(): + if isinstance(term, Float): + assert term._prec == 110 + + +def test_jordan_form_complex_issue_9274(): + A = Matrix([[ 2, 4, 1, 0], + [-4, 2, 0, 1], + [ 0, 0, 2, 4], + [ 0, 0, -4, 2]]) + p = 2 - 4*I + q = 2 + 4*I + Jmust1 = Matrix([[p, 1, 0, 0], + [0, p, 0, 0], + [0, 0, q, 1], + [0, 0, 0, q]]) + Jmust2 = Matrix([[q, 1, 0, 0], + [0, q, 0, 0], + [0, 0, p, 1], + [0, 0, 0, p]]) + P, J = A.jordan_form() + assert J == Jmust1 or J == Jmust2 + assert simplify(P*J*P.inv()) == A + +def test_issue_10220(): + # two non-orthogonal Jordan blocks with eigenvalue 1 + M = Matrix([[1, 0, 0, 1], + [0, 1, 1, 0], + [0, 0, 1, 1], + [0, 0, 0, 1]]) + P, J = M.jordan_form() + assert P == Matrix([[0, 1, 0, 1], + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0]]) + assert J == Matrix([ + [1, 1, 0, 0], + [0, 1, 1, 0], + [0, 0, 1, 0], + [0, 0, 0, 1]]) + +def test_jordan_form_issue_15858(): + A = Matrix([ + [1, 1, 1, 0], + [-2, -1, 0, -1], + [0, 0, -1, -1], + [0, 0, 2, 1]]) + (P, J) = A.jordan_form() + assert P.expand() == Matrix([ + [ -I, -I/2, I, I/2], + [-1 + I, 0, -1 - I, 0], + [ 0, -S(1)/2 - I/2, 0, -S(1)/2 + I/2], + [ 0, 1, 0, 1]]) + assert J == Matrix([ + [-I, 1, 0, 0], + [0, -I, 0, 0], + [0, 0, I, 1], + [0, 0, 0, I]]) + +def test_Matrix_berkowitz_charpoly(): + UA, K_i, K_w = symbols('UA K_i K_w') + + A = Matrix([[-K_i - UA + K_i**2/(K_i + K_w), K_i*K_w/(K_i + K_w)], + [ K_i*K_w/(K_i + K_w), -K_w + K_w**2/(K_i + K_w)]]) + + charpoly = A.charpoly(x) + + assert charpoly == \ + Poly(x**2 + (K_i*UA + K_w*UA + 2*K_i*K_w)/(K_i + K_w)*x + + K_i*K_w*UA/(K_i + K_w), x, domain='ZZ(K_i,K_w,UA)') + + assert type(charpoly) is PurePoly + + A = Matrix([[1, 3], [2, 0]]) + assert A.charpoly() == A.charpoly(x) == PurePoly(x**2 - x - 6) + + A = Matrix([[1, 2], [x, 0]]) + p = A.charpoly(x) + assert p.gen != x + assert p.as_expr().subs(p.gen, x) == x**2 - 3*x + + +def test_exp_jordan_block(): + l = Symbol('lamda') + + m = Matrix.jordan_block(1, l) + assert m._eval_matrix_exp_jblock() == Matrix([[exp(l)]]) + + m = Matrix.jordan_block(3, l) + assert m._eval_matrix_exp_jblock() == \ + Matrix([ + [exp(l), exp(l), exp(l)/2], + [0, exp(l), exp(l)], + [0, 0, exp(l)]]) + + +def test_exp(): + m = Matrix([[3, 4], [0, -2]]) + m_exp = Matrix([[exp(3), -4*exp(-2)/5 + 4*exp(3)/5], [0, exp(-2)]]) + assert m.exp() == m_exp + assert exp(m) == m_exp + + m = Matrix([[1, 0], [0, 1]]) + assert m.exp() == Matrix([[E, 0], [0, E]]) + assert exp(m) == Matrix([[E, 0], [0, E]]) + + m = Matrix([[1, -1], [1, 1]]) + assert m.exp() == Matrix([[E*cos(1), -E*sin(1)], [E*sin(1), E*cos(1)]]) + + +def test_log(): + l = Symbol('lamda') + + m = Matrix.jordan_block(1, l) + assert m._eval_matrix_log_jblock() == Matrix([[log(l)]]) + + m = Matrix.jordan_block(4, l) + assert m._eval_matrix_log_jblock() == \ + Matrix( + [ + [log(l), 1/l, -1/(2*l**2), 1/(3*l**3)], + [0, log(l), 1/l, -1/(2*l**2)], + [0, 0, log(l), 1/l], + [0, 0, 0, log(l)] + ] + ) + + m = Matrix( + [[0, 0, 1], + [0, 0, 0], + [-1, 0, 0]] + ) + raises(MatrixError, lambda: m.log()) + + +def test_has(): + A = Matrix(((x, y), (2, 3))) + assert A.has(x) + assert not A.has(z) + assert A.has(Symbol) + + A = A.subs(x, 2) + assert not A.has(x) + + +def test_find_reasonable_pivot_naive_finds_guaranteed_nonzero1(): + # Test if matrices._find_reasonable_pivot_naive() + # finds a guaranteed non-zero pivot when the + # some of the candidate pivots are symbolic expressions. + # Keyword argument: simpfunc=None indicates that no simplifications + # should be performed during the search. + x = Symbol('x') + column = Matrix(3, 1, [x, cos(x)**2 + sin(x)**2, S.Half]) + pivot_offset, pivot_val, pivot_assumed_nonzero, simplified =\ + _find_reasonable_pivot_naive(column) + assert pivot_val == S.Half + +def test_find_reasonable_pivot_naive_finds_guaranteed_nonzero2(): + # Test if matrices._find_reasonable_pivot_naive() + # finds a guaranteed non-zero pivot when the + # some of the candidate pivots are symbolic expressions. + # Keyword argument: simpfunc=_simplify indicates that the search + # should attempt to simplify candidate pivots. + x = Symbol('x') + column = Matrix(3, 1, + [x, + cos(x)**2+sin(x)**2+x**2, + cos(x)**2+sin(x)**2]) + pivot_offset, pivot_val, pivot_assumed_nonzero, simplified =\ + _find_reasonable_pivot_naive(column, simpfunc=_simplify) + assert pivot_val == 1 + +def test_find_reasonable_pivot_naive_simplifies(): + # Test if matrices._find_reasonable_pivot_naive() + # simplifies candidate pivots, and reports + # their offsets correctly. + x = Symbol('x') + column = Matrix(3, 1, + [x, + cos(x)**2+sin(x)**2+x, + cos(x)**2+sin(x)**2]) + pivot_offset, pivot_val, pivot_assumed_nonzero, simplified =\ + _find_reasonable_pivot_naive(column, simpfunc=_simplify) + + assert len(simplified) == 2 + assert simplified[0][0] == 1 + assert simplified[0][1] == 1+x + assert simplified[1][0] == 2 + assert simplified[1][1] == 1 + +def test_errors(): + raises(ValueError, lambda: Matrix([[1, 2], [1]])) + raises(IndexError, lambda: Matrix([[1, 2]])[1.2, 5]) + raises(IndexError, lambda: Matrix([[1, 2]])[1, 5.2]) + raises(ValueError, lambda: randMatrix(3, c=4, symmetric=True)) + raises(ValueError, lambda: Matrix([1, 2]).reshape(4, 6)) + raises(ShapeError, + lambda: Matrix([[1, 2], [3, 4]]).copyin_matrix([1, 0], Matrix([1, 2]))) + raises(TypeError, lambda: Matrix([[1, 2], [3, 4]]).copyin_list([0, + 1], set())) + raises(NonSquareMatrixError, lambda: Matrix([[1, 2, 3], [2, 3, 0]]).inv()) + raises(ShapeError, + lambda: Matrix(1, 2, [1, 2]).row_join(Matrix([[1, 2], [3, 4]]))) + raises( + ShapeError, lambda: Matrix([1, 2]).col_join(Matrix([[1, 2], [3, 4]]))) + raises(ShapeError, lambda: Matrix([1]).row_insert(1, Matrix([[1, + 2], [3, 4]]))) + raises(ShapeError, lambda: Matrix([1]).col_insert(1, Matrix([[1, + 2], [3, 4]]))) + raises(NonSquareMatrixError, lambda: Matrix([1, 2]).trace()) + raises(TypeError, lambda: Matrix([1]).applyfunc(1)) + raises(ValueError, lambda: Matrix([[1, 2], [3, 4]]).minor(4, 5)) + raises(ValueError, lambda: Matrix([[1, 2], [3, 4]]).minor_submatrix(4, 5)) + raises(TypeError, lambda: Matrix([1, 2, 3]).cross(1)) + raises(TypeError, lambda: Matrix([1, 2, 3]).dot(1)) + raises(ShapeError, lambda: Matrix([1, 2, 3]).dot(Matrix([1, 2]))) + raises(ShapeError, lambda: Matrix([1, 2]).dot([])) + raises(TypeError, lambda: Matrix([1, 2]).dot('a')) + raises(ShapeError, lambda: Matrix([1, 2]).dot([1, 2, 3])) + raises(NonSquareMatrixError, lambda: Matrix([1, 2, 3]).exp()) + raises(ShapeError, lambda: Matrix([[1, 2], [3, 4]]).normalized()) + raises(ValueError, lambda: Matrix([1, 2]).inv(method='not a method')) + raises(NonSquareMatrixError, lambda: Matrix([1, 2]).inverse_GE()) + raises(ValueError, lambda: Matrix([[1, 2], [1, 2]]).inverse_GE()) + raises(NonSquareMatrixError, lambda: Matrix([1, 2]).inverse_ADJ()) + raises(ValueError, lambda: Matrix([[1, 2], [1, 2]]).inverse_ADJ()) + raises(NonSquareMatrixError, lambda: Matrix([1, 2]).inverse_LU()) + raises(NonSquareMatrixError, lambda: Matrix([1, 2]).is_nilpotent()) + raises(NonSquareMatrixError, lambda: Matrix([1, 2]).det()) + raises(ValueError, + lambda: Matrix([[1, 2], [3, 4]]).det(method='Not a real method')) + raises(ValueError, + lambda: Matrix([[1, 2, 3, 4], [5, 6, 7, 8], + [9, 10, 11, 12], [13, 14, 15, 16]]).det(iszerofunc="Not function")) + raises(ValueError, + lambda: Matrix([[1, 2, 3, 4], [5, 6, 7, 8], + [9, 10, 11, 12], [13, 14, 15, 16]]).det(iszerofunc=False)) + raises(ValueError, + lambda: hessian(Matrix([[1, 2], [3, 4]]), Matrix([[1, 2], [2, 1]]))) + raises(ValueError, lambda: hessian(Matrix([[1, 2], [3, 4]]), [])) + raises(ValueError, lambda: hessian(Symbol('x')**2, 'a')) + raises(IndexError, lambda: eye(3)[5, 2]) + raises(IndexError, lambda: eye(3)[2, 5]) + M = Matrix(((1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12), (13, 14, 15, 16))) + raises(ValueError, lambda: M.det('method=LU_decomposition()')) + V = Matrix([[10, 10, 10]]) + M = Matrix([[1, 2, 3], [2, 3, 4], [3, 4, 5]]) + raises(ValueError, lambda: M.row_insert(4.7, V)) + M = Matrix([[1, 2, 3], [2, 3, 4], [3, 4, 5]]) + raises(ValueError, lambda: M.col_insert(-4.2, V)) + +def test_len(): + assert len(Matrix()) == 0 + assert len(Matrix([[1, 2]])) == len(Matrix([[1], [2]])) == 2 + assert len(Matrix(0, 2, lambda i, j: 0)) == \ + len(Matrix(2, 0, lambda i, j: 0)) == 0 + assert len(Matrix([[0, 1, 2], [3, 4, 5]])) == 6 + assert Matrix([1]) == Matrix([[1]]) + assert not Matrix() + assert Matrix() == Matrix([]) + + +def test_integrate(): + A = Matrix(((1, 4, x), (y, 2, 4), (10, 5, x**2))) + assert A.integrate(x) == \ + Matrix(((x, 4*x, x**2/2), (x*y, 2*x, 4*x), (10*x, 5*x, x**3/3))) + assert A.integrate(y) == \ + Matrix(((y, 4*y, x*y), (y**2/2, 2*y, 4*y), (10*y, 5*y, y*x**2))) + + +def test_limit(): + A = Matrix(((1, 4, sin(x)/x), (y, 2, 4), (10, 5, x**2 + 1))) + assert A.limit(x, 0) == Matrix(((1, 4, 1), (y, 2, 4), (10, 5, 1))) + + +def test_diff(): + A = MutableDenseMatrix(((1, 4, x), (y, 2, 4), (10, 5, x**2 + 1))) + assert isinstance(A.diff(x), type(A)) + assert A.diff(x) == MutableDenseMatrix(((0, 0, 1), (0, 0, 0), (0, 0, 2*x))) + assert A.diff(y) == MutableDenseMatrix(((0, 0, 0), (1, 0, 0), (0, 0, 0))) + + assert diff(A, x) == MutableDenseMatrix(((0, 0, 1), (0, 0, 0), (0, 0, 2*x))) + assert diff(A, y) == MutableDenseMatrix(((0, 0, 0), (1, 0, 0), (0, 0, 0))) + + A_imm = A.as_immutable() + assert isinstance(A_imm.diff(x), type(A_imm)) + assert A_imm.diff(x) == ImmutableDenseMatrix(((0, 0, 1), (0, 0, 0), (0, 0, 2*x))) + assert A_imm.diff(y) == ImmutableDenseMatrix(((0, 0, 0), (1, 0, 0), (0, 0, 0))) + + assert diff(A_imm, x) == ImmutableDenseMatrix(((0, 0, 1), (0, 0, 0), (0, 0, 2*x))) + assert diff(A_imm, y) == ImmutableDenseMatrix(((0, 0, 0), (1, 0, 0), (0, 0, 0))) + + assert A.diff(x, evaluate=False) == ArrayDerivative(A, x, evaluate=False) + assert diff(A, x, evaluate=False) == ArrayDerivative(A, x, evaluate=False) + + +def test_diff_by_matrix(): + + # Derive matrix by matrix: + + A = MutableDenseMatrix([[x, y], [z, t]]) + assert A.diff(A) == Array([[[[1, 0], [0, 0]], [[0, 1], [0, 0]]], [[[0, 0], [1, 0]], [[0, 0], [0, 1]]]]) + assert diff(A, A) == Array([[[[1, 0], [0, 0]], [[0, 1], [0, 0]]], [[[0, 0], [1, 0]], [[0, 0], [0, 1]]]]) + + A_imm = A.as_immutable() + assert A_imm.diff(A_imm) == Array([[[[1, 0], [0, 0]], [[0, 1], [0, 0]]], [[[0, 0], [1, 0]], [[0, 0], [0, 1]]]]) + assert diff(A_imm, A_imm) == Array([[[[1, 0], [0, 0]], [[0, 1], [0, 0]]], [[[0, 0], [1, 0]], [[0, 0], [0, 1]]]]) + + # Derive a constant matrix: + assert A.diff(a) == MutableDenseMatrix([[0, 0], [0, 0]]) + + B = ImmutableDenseMatrix([a, b]) + assert A.diff(B) == Array.zeros(2, 1, 2, 2) + assert A.diff(A) == Array([[[[1, 0], [0, 0]], [[0, 1], [0, 0]]], [[[0, 0], [1, 0]], [[0, 0], [0, 1]]]]) + + # Test diff with tuples: + + dB = B.diff([[a, b]]) + assert dB.shape == (2, 2, 1) + assert dB == Array([[[1], [0]], [[0], [1]]]) + + f = Function("f") + fxyz = f(x, y, z) + assert fxyz.diff([[x, y, z]]) == Array([fxyz.diff(x), fxyz.diff(y), fxyz.diff(z)]) + assert fxyz.diff(([x, y, z], 2)) == Array([ + [fxyz.diff(x, 2), fxyz.diff(x, y), fxyz.diff(x, z)], + [fxyz.diff(x, y), fxyz.diff(y, 2), fxyz.diff(y, z)], + [fxyz.diff(x, z), fxyz.diff(z, y), fxyz.diff(z, 2)], + ]) + + expr = sin(x)*exp(y) + assert expr.diff([[x, y]]) == Array([cos(x)*exp(y), sin(x)*exp(y)]) + assert expr.diff(y, ((x, y),)) == Array([cos(x)*exp(y), sin(x)*exp(y)]) + assert expr.diff(x, ((x, y),)) == Array([-sin(x)*exp(y), cos(x)*exp(y)]) + assert expr.diff(((y, x),), [[x, y]]) == Array([[cos(x)*exp(y), -sin(x)*exp(y)], [sin(x)*exp(y), cos(x)*exp(y)]]) + + # Test different notations: + + assert fxyz.diff(x).diff(y).diff(x) == fxyz.diff(((x, y, z),), 3)[0, 1, 0] + assert fxyz.diff(z).diff(y).diff(x) == fxyz.diff(((x, y, z),), 3)[2, 1, 0] + assert fxyz.diff([[x, y, z]], ((z, y, x),)) == Array([[fxyz.diff(i).diff(j) for i in (x, y, z)] for j in (z, y, x)]) + + # Test scalar derived by matrix remains matrix: + res = x.diff(Matrix([[x, y]])) + assert isinstance(res, ImmutableDenseMatrix) + assert res == Matrix([[1, 0]]) + res = (x**3).diff(Matrix([[x, y]])) + assert isinstance(res, ImmutableDenseMatrix) + assert res == Matrix([[3*x**2, 0]]) + + +def test_getattr(): + A = Matrix(((1, 4, x), (y, 2, 4), (10, 5, x**2 + 1))) + raises(AttributeError, lambda: A.nonexistantattribute) + assert getattr(A, 'diff')(x) == Matrix(((0, 0, 1), (0, 0, 0), (0, 0, 2*x))) + + +def test_hessenberg(): + A = Matrix([[3, 4, 1], [2, 4, 5], [0, 1, 2]]) + assert A.is_upper_hessenberg + A = A.T + assert A.is_lower_hessenberg + A[0, -1] = 1 + assert A.is_lower_hessenberg is False + + A = Matrix([[3, 4, 1], [2, 4, 5], [3, 1, 2]]) + assert not A.is_upper_hessenberg + + A = zeros(5, 2) + assert A.is_upper_hessenberg + + +def test_cholesky(): + raises(NonSquareMatrixError, lambda: Matrix((1, 2)).cholesky()) + raises(ValueError, lambda: Matrix(((1, 2), (3, 4))).cholesky()) + raises(ValueError, lambda: Matrix(((5 + I, 0), (0, 1))).cholesky()) + raises(ValueError, lambda: Matrix(((1, 5), (5, 1))).cholesky()) + raises(ValueError, lambda: Matrix(((1, 2), (3, 4))).cholesky(hermitian=False)) + assert Matrix(((5 + I, 0), (0, 1))).cholesky(hermitian=False) == Matrix([ + [sqrt(5 + I), 0], [0, 1]]) + A = Matrix(((1, 5), (5, 1))) + L = A.cholesky(hermitian=False) + assert L == Matrix([[1, 0], [5, 2*sqrt(6)*I]]) + assert L*L.T == A + A = Matrix(((25, 15, -5), (15, 18, 0), (-5, 0, 11))) + L = A.cholesky() + assert L * L.T == A + assert L.is_lower + assert L == Matrix([[5, 0, 0], [3, 3, 0], [-1, 1, 3]]) + A = Matrix(((4, -2*I, 2 + 2*I), (2*I, 2, -1 + I), (2 - 2*I, -1 - I, 11))) + assert A.cholesky().expand() == Matrix(((2, 0, 0), (I, 1, 0), (1 - I, 0, 3))) + + raises(NonSquareMatrixError, lambda: SparseMatrix((1, 2)).cholesky()) + raises(ValueError, lambda: SparseMatrix(((1, 2), (3, 4))).cholesky()) + raises(ValueError, lambda: SparseMatrix(((5 + I, 0), (0, 1))).cholesky()) + raises(ValueError, lambda: SparseMatrix(((1, 5), (5, 1))).cholesky()) + raises(ValueError, lambda: SparseMatrix(((1, 2), (3, 4))).cholesky(hermitian=False)) + assert SparseMatrix(((5 + I, 0), (0, 1))).cholesky(hermitian=False) == Matrix([ + [sqrt(5 + I), 0], [0, 1]]) + A = SparseMatrix(((1, 5), (5, 1))) + L = A.cholesky(hermitian=False) + assert L == Matrix([[1, 0], [5, 2*sqrt(6)*I]]) + assert L*L.T == A + A = SparseMatrix(((25, 15, -5), (15, 18, 0), (-5, 0, 11))) + L = A.cholesky() + assert L * L.T == A + assert L.is_lower + assert L == Matrix([[5, 0, 0], [3, 3, 0], [-1, 1, 3]]) + A = SparseMatrix(((4, -2*I, 2 + 2*I), (2*I, 2, -1 + I), (2 - 2*I, -1 - I, 11))) + assert A.cholesky() == Matrix(((2, 0, 0), (I, 1, 0), (1 - I, 0, 3))) + + +def test_matrix_norm(): + # Vector Tests + # Test columns and symbols + x = Symbol('x', real=True) + v = Matrix([cos(x), sin(x)]) + assert trigsimp(v.norm(2)) == 1 + assert v.norm(10) == Pow(cos(x)**10 + sin(x)**10, Rational(1, 10)) + + # Test Rows + A = Matrix([[5, Rational(3, 2)]]) + assert A.norm() == Pow(25 + Rational(9, 4), S.Half) + assert A.norm(oo) == max(A) + assert A.norm(-oo) == min(A) + + # Matrix Tests + # Intuitive test + A = Matrix([[1, 1], [1, 1]]) + assert A.norm(2) == 2 + assert A.norm(-2) == 0 + assert A.norm('frobenius') == 2 + assert eye(10).norm(2) == eye(10).norm(-2) == 1 + assert A.norm(oo) == 2 + + # Test with Symbols and more complex entries + A = Matrix([[3, y, y], [x, S.Half, -pi]]) + assert (A.norm('fro') + == sqrt(Rational(37, 4) + 2*abs(y)**2 + pi**2 + x**2)) + + # Check non-square + A = Matrix([[1, 2, -3], [4, 5, Rational(13, 2)]]) + assert A.norm(2) == sqrt(Rational(389, 8) + sqrt(78665)/8) + assert A.norm(-2) is S.Zero + assert A.norm('frobenius') == sqrt(389)/2 + + # Test properties of matrix norms + # https://en.wikipedia.org/wiki/Matrix_norm#Definition + # Two matrices + A = Matrix([[1, 2], [3, 4]]) + B = Matrix([[5, 5], [-2, 2]]) + C = Matrix([[0, -I], [I, 0]]) + D = Matrix([[1, 0], [0, -1]]) + L = [A, B, C, D] + alpha = Symbol('alpha', real=True) + + for order in ['fro', 2, -2]: + # Zero Check + assert zeros(3).norm(order) is S.Zero + # Check Triangle Inequality for all Pairs of Matrices + for X in L: + for Y in L: + dif = (X.norm(order) + Y.norm(order) - + (X + Y).norm(order)) + assert (dif >= 0) + # Scalar multiplication linearity + for M in [A, B, C, D]: + dif = simplify((alpha*M).norm(order) - + abs(alpha) * M.norm(order)) + assert dif == 0 + + # Test Properties of Vector Norms + # https://en.wikipedia.org/wiki/Vector_norm + # Two column vectors + a = Matrix([1, 1 - 1*I, -3]) + b = Matrix([S.Half, 1*I, 1]) + c = Matrix([-1, -1, -1]) + d = Matrix([3, 2, I]) + e = Matrix([Integer(1e2), Rational(1, 1e2), 1]) + L = [a, b, c, d, e] + alpha = Symbol('alpha', real=True) + + for order in [1, 2, -1, -2, S.Infinity, S.NegativeInfinity, pi]: + # Zero Check + if order > 0: + assert Matrix([0, 0, 0]).norm(order) is S.Zero + # Triangle inequality on all pairs + if order >= 1: # Triangle InEq holds only for these norms + for X in L: + for Y in L: + dif = (X.norm(order) + Y.norm(order) - + (X + Y).norm(order)) + assert simplify(dif >= 0) is S.true + # Linear to scalar multiplication + if order in [1, 2, -1, -2, S.Infinity, S.NegativeInfinity]: + for X in L: + dif = simplify((alpha*X).norm(order) - + (abs(alpha) * X.norm(order))) + assert dif == 0 + + # ord=1 + M = Matrix(3, 3, [1, 3, 0, -2, -1, 0, 3, 9, 6]) + assert M.norm(1) == 13 + + +def test_condition_number(): + x = Symbol('x', real=True) + A = eye(3) + A[0, 0] = 10 + A[2, 2] = Rational(1, 10) + assert A.condition_number() == 100 + + A[1, 1] = x + assert A.condition_number() == Max(10, Abs(x)) / Min(Rational(1, 10), Abs(x)) + + M = Matrix([[cos(x), sin(x)], [-sin(x), cos(x)]]) + Mc = M.condition_number() + assert all(Float(1.).epsilon_eq(Mc.subs(x, val).evalf()) for val in + [Rational(1, 5), S.Half, Rational(1, 10), pi/2, pi, pi*Rational(7, 4) ]) + + #issue 10782 + assert Matrix([]).condition_number() == 0 + + +def test_equality(): + A = Matrix(((1, 2, 3), (4, 5, 6), (7, 8, 9))) + B = Matrix(((9, 8, 7), (6, 5, 4), (3, 2, 1))) + assert A == A[:, :] + assert not A != A[:, :] + assert not A == B + assert A != B + assert A != 10 + assert not A == 10 + + # A SparseMatrix can be equal to a Matrix + C = SparseMatrix(((1, 0, 0), (0, 1, 0), (0, 0, 1))) + D = Matrix(((1, 0, 0), (0, 1, 0), (0, 0, 1))) + assert C == D + assert not C != D + + +def test_col_join(): + assert eye(3).col_join(Matrix([[7, 7, 7]])) == \ + Matrix([[1, 0, 0], + [0, 1, 0], + [0, 0, 1], + [7, 7, 7]]) + + +def test_row_insert(): + r4 = Matrix([[4, 4, 4]]) + for i in range(-4, 5): + l = [1, 0, 0] + l.insert(i, 4) + assert flatten(eye(3).row_insert(i, r4).col(0).tolist()) == l + + +def test_col_insert(): + c4 = Matrix([4, 4, 4]) + for i in range(-4, 5): + l = [0, 0, 0] + l.insert(i, 4) + assert flatten(zeros(3).col_insert(i, c4).row(0).tolist()) == l + + +def test_normalized(): + assert Matrix([3, 4]).normalized() == \ + Matrix([Rational(3, 5), Rational(4, 5)]) + + # Zero vector trivial cases + assert Matrix([0, 0, 0]).normalized() == Matrix([0, 0, 0]) + + # Machine precision error truncation trivial cases + m = Matrix([0,0,1.e-100]) + assert m.normalized( + iszerofunc=lambda x: x.evalf(n=10, chop=True).is_zero + ) == Matrix([0, 0, 0]) + + +def test_print_nonzero(): + assert capture(lambda: eye(3).print_nonzero()) == \ + '[X ]\n[ X ]\n[ X]\n' + assert capture(lambda: eye(3).print_nonzero('.')) == \ + '[. ]\n[ . ]\n[ .]\n' + + +def test_zeros_eye(): + assert Matrix.eye(3) == eye(3) + assert Matrix.zeros(3) == zeros(3) + assert ones(3, 4) == Matrix(3, 4, [1]*12) + + i = Matrix([[1, 0], [0, 1]]) + z = Matrix([[0, 0], [0, 0]]) + for cls in classes: + m = cls.eye(2) + assert i == m # but m == i will fail if m is immutable + assert i == eye(2, cls=cls) + assert type(m) == cls + m = cls.zeros(2) + assert z == m + assert z == zeros(2, cls=cls) + assert type(m) == cls + + +def test_is_zero(): + assert Matrix().is_zero_matrix + assert Matrix([[0, 0], [0, 0]]).is_zero_matrix + assert zeros(3, 4).is_zero_matrix + assert not eye(3).is_zero_matrix + assert Matrix([[x, 0], [0, 0]]).is_zero_matrix == None + assert SparseMatrix([[x, 0], [0, 0]]).is_zero_matrix == None + assert ImmutableMatrix([[x, 0], [0, 0]]).is_zero_matrix == None + assert ImmutableSparseMatrix([[x, 0], [0, 0]]).is_zero_matrix == None + assert Matrix([[x, 1], [0, 0]]).is_zero_matrix == False + a = Symbol('a', nonzero=True) + assert Matrix([[a, 0], [0, 0]]).is_zero_matrix == False + + +def test_rotation_matrices(): + # This tests the rotation matrices by rotating about an axis and back. + theta = pi/3 + r3_plus = rot_axis3(theta) + r3_minus = rot_axis3(-theta) + r2_plus = rot_axis2(theta) + r2_minus = rot_axis2(-theta) + r1_plus = rot_axis1(theta) + r1_minus = rot_axis1(-theta) + assert r3_minus*r3_plus*eye(3) == eye(3) + assert r2_minus*r2_plus*eye(3) == eye(3) + assert r1_minus*r1_plus*eye(3) == eye(3) + + # Check the correctness of the trace of the rotation matrix + assert r1_plus.trace() == 1 + 2*cos(theta) + assert r2_plus.trace() == 1 + 2*cos(theta) + assert r3_plus.trace() == 1 + 2*cos(theta) + + # Check that a rotation with zero angle doesn't change anything. + assert rot_axis1(0) == eye(3) + assert rot_axis2(0) == eye(3) + assert rot_axis3(0) == eye(3) + + # Check left-hand convention + # see Issue #24529 + q1 = Quaternion.from_axis_angle([1, 0, 0], pi / 2) + q2 = Quaternion.from_axis_angle([0, 1, 0], pi / 2) + q3 = Quaternion.from_axis_angle([0, 0, 1], pi / 2) + assert rot_axis1(- pi / 2) == q1.to_rotation_matrix() + assert rot_axis2(- pi / 2) == q2.to_rotation_matrix() + assert rot_axis3(- pi / 2) == q3.to_rotation_matrix() + # Check right-hand convention + assert rot_ccw_axis1(+ pi / 2) == q1.to_rotation_matrix() + assert rot_ccw_axis2(+ pi / 2) == q2.to_rotation_matrix() + assert rot_ccw_axis3(+ pi / 2) == q3.to_rotation_matrix() + + +def test_DeferredVector(): + assert str(DeferredVector("vector")[4]) == "vector[4]" + assert sympify(DeferredVector("d")) == DeferredVector("d") + raises(IndexError, lambda: DeferredVector("d")[-1]) + assert str(DeferredVector("d")) == "d" + assert repr(DeferredVector("test")) == "DeferredVector('test')" + +def test_DeferredVector_not_iterable(): + assert not iterable(DeferredVector('X')) + +def test_DeferredVector_Matrix(): + raises(TypeError, lambda: Matrix(DeferredVector("V"))) + +def test_GramSchmidt(): + R = Rational + m1 = Matrix(1, 2, [1, 2]) + m2 = Matrix(1, 2, [2, 3]) + assert GramSchmidt([m1, m2]) == \ + [Matrix(1, 2, [1, 2]), Matrix(1, 2, [R(2)/5, R(-1)/5])] + assert GramSchmidt([m1.T, m2.T]) == \ + [Matrix(2, 1, [1, 2]), Matrix(2, 1, [R(2)/5, R(-1)/5])] + # from wikipedia + assert GramSchmidt([Matrix([3, 1]), Matrix([2, 2])], True) == [ + Matrix([3*sqrt(10)/10, sqrt(10)/10]), + Matrix([-sqrt(10)/10, 3*sqrt(10)/10])] + # https://github.com/sympy/sympy/issues/9488 + L = FiniteSet(Matrix([1])) + assert GramSchmidt(L) == [Matrix([[1]])] + + +def test_casoratian(): + assert casoratian([1, 2, 3, 4], 1) == 0 + assert casoratian([1, 2, 3, 4], 1, zero=False) == 0 + + +def test_zero_dimension_multiply(): + assert (Matrix()*zeros(0, 3)).shape == (0, 3) + assert zeros(3, 0)*zeros(0, 3) == zeros(3, 3) + assert zeros(0, 3)*zeros(3, 0) == Matrix() + + +def test_slice_issue_2884(): + m = Matrix(2, 2, range(4)) + assert m[1, :] == Matrix([[2, 3]]) + assert m[-1, :] == Matrix([[2, 3]]) + assert m[:, 1] == Matrix([[1, 3]]).T + assert m[:, -1] == Matrix([[1, 3]]).T + raises(IndexError, lambda: m[2, :]) + raises(IndexError, lambda: m[2, 2]) + + +def test_slice_issue_3401(): + assert zeros(0, 3)[:, -1].shape == (0, 1) + assert zeros(3, 0)[0, :] == Matrix(1, 0, []) + + +def test_copyin(): + s = zeros(3, 3) + s[3] = 1 + assert s[:, 0] == Matrix([0, 1, 0]) + assert s[3] == 1 + assert s[3: 4] == [1] + s[1, 1] = 42 + assert s[1, 1] == 42 + assert s[1, 1:] == Matrix([[42, 0]]) + s[1, 1:] = Matrix([[5, 6]]) + assert s[1, :] == Matrix([[1, 5, 6]]) + s[1, 1:] = [[42, 43]] + assert s[1, :] == Matrix([[1, 42, 43]]) + s[0, 0] = 17 + assert s[:, :1] == Matrix([17, 1, 0]) + s[0, 0] = [1, 1, 1] + assert s[:, 0] == Matrix([1, 1, 1]) + s[0, 0] = Matrix([1, 1, 1]) + assert s[:, 0] == Matrix([1, 1, 1]) + s[0, 0] = SparseMatrix([1, 1, 1]) + assert s[:, 0] == Matrix([1, 1, 1]) + + +def test_invertible_check(): + # sometimes a singular matrix will have a pivot vector shorter than + # the number of rows in a matrix... + assert Matrix([[1, 2], [1, 2]]).rref() == (Matrix([[1, 2], [0, 0]]), (0,)) + raises(ValueError, lambda: Matrix([[1, 2], [1, 2]]).inv()) + m = Matrix([ + [-1, -1, 0], + [ x, 1, 1], + [ 1, x, -1], + ]) + assert len(m.rref()[1]) != m.rows + # in addition, unless simplify=True in the call to rref, the identity + # matrix will be returned even though m is not invertible + assert m.rref()[0] != eye(3) + assert m.rref(simplify=signsimp)[0] != eye(3) + raises(ValueError, lambda: m.inv(method="ADJ")) + raises(ValueError, lambda: m.inv(method="GE")) + raises(ValueError, lambda: m.inv(method="LU")) + + +def test_issue_3959(): + x, y = symbols('x, y') + e = x*y + assert e.subs(x, Matrix([3, 5, 3])) == Matrix([3, 5, 3])*y + + +def test_issue_5964(): + assert str(Matrix([[1, 2], [3, 4]])) == 'Matrix([[1, 2], [3, 4]])' + + +def test_issue_7604(): + x, y = symbols("x y") + assert sstr(Matrix([[x, 2*y], [y**2, x + 3]])) == \ + 'Matrix([\n[ x, 2*y],\n[y**2, x + 3]])' + + +def test_is_Identity(): + assert eye(3).is_Identity + assert eye(3).as_immutable().is_Identity + assert not zeros(3).is_Identity + assert not ones(3).is_Identity + # issue 6242 + assert not Matrix([[1, 0, 0]]).is_Identity + # issue 8854 + assert SparseMatrix(3,3, {(0,0):1, (1,1):1, (2,2):1}).is_Identity + assert not SparseMatrix(2,3, range(6)).is_Identity + assert not SparseMatrix(3,3, {(0,0):1, (1,1):1}).is_Identity + assert not SparseMatrix(3,3, {(0,0):1, (1,1):1, (2,2):1, (0,1):2, (0,2):3}).is_Identity + + +def test_dot(): + assert ones(1, 3).dot(ones(3, 1)) == 3 + assert ones(1, 3).dot([1, 1, 1]) == 3 + assert Matrix([1, 2, 3]).dot(Matrix([1, 2, 3])) == 14 + assert Matrix([1, 2, 3*I]).dot(Matrix([I, 2, 3*I])) == -5 + I + assert Matrix([1, 2, 3*I]).dot(Matrix([I, 2, 3*I]), hermitian=False) == -5 + I + assert Matrix([1, 2, 3*I]).dot(Matrix([I, 2, 3*I]), hermitian=True) == 13 + I + assert Matrix([1, 2, 3*I]).dot(Matrix([I, 2, 3*I]), hermitian=True, conjugate_convention="physics") == 13 - I + assert Matrix([1, 2, 3*I]).dot(Matrix([4, 5*I, 6]), hermitian=True, conjugate_convention="right") == 4 + 8*I + assert Matrix([1, 2, 3*I]).dot(Matrix([4, 5*I, 6]), hermitian=True, conjugate_convention="left") == 4 - 8*I + assert Matrix([I, 2*I]).dot(Matrix([I, 2*I]), hermitian=False, conjugate_convention="left") == -5 + assert Matrix([I, 2*I]).dot(Matrix([I, 2*I]), conjugate_convention="left") == 5 + raises(ValueError, lambda: Matrix([1, 2]).dot(Matrix([3, 4]), hermitian=True, conjugate_convention="test")) + + +def test_dual(): + B_x, B_y, B_z, E_x, E_y, E_z = symbols( + 'B_x B_y B_z E_x E_y E_z', real=True) + F = Matrix(( + ( 0, E_x, E_y, E_z), + (-E_x, 0, B_z, -B_y), + (-E_y, -B_z, 0, B_x), + (-E_z, B_y, -B_x, 0) + )) + Fd = Matrix(( + ( 0, -B_x, -B_y, -B_z), + (B_x, 0, E_z, -E_y), + (B_y, -E_z, 0, E_x), + (B_z, E_y, -E_x, 0) + )) + assert F.dual().equals(Fd) + assert eye(3).dual().equals(zeros(3)) + assert F.dual().dual().equals(-F) + + +def test_anti_symmetric(): + assert Matrix([1, 2]).is_anti_symmetric() is False + m = Matrix(3, 3, [0, x**2 + 2*x + 1, y, -(x + 1)**2, 0, x*y, -y, -x*y, 0]) + assert m.is_anti_symmetric() is True + assert m.is_anti_symmetric(simplify=False) is None + assert m.is_anti_symmetric(simplify=lambda x: x) is None + + # tweak to fail + m[2, 1] = -m[2, 1] + assert m.is_anti_symmetric() is None + # untweak + m[2, 1] = -m[2, 1] + + m = m.expand() + assert m.is_anti_symmetric(simplify=False) is True + m[0, 0] = 1 + assert m.is_anti_symmetric() is False + + +def test_normalize_sort_diogonalization(): + A = Matrix(((1, 2), (2, 1))) + P, Q = A.diagonalize(normalize=True) + assert P*P.T == P.T*P == eye(P.cols) + P, Q = A.diagonalize(normalize=True, sort=True) + assert P*P.T == P.T*P == eye(P.cols) + assert P*Q*P.inv() == A + + +def test_issue_5321(): + raises(ValueError, lambda: Matrix([[1, 2, 3], Matrix(0, 1, [])])) + + +def test_issue_5320(): + assert Matrix.hstack(eye(2), 2*eye(2)) == Matrix([ + [1, 0, 2, 0], + [0, 1, 0, 2] + ]) + assert Matrix.vstack(eye(2), 2*eye(2)) == Matrix([ + [1, 0], + [0, 1], + [2, 0], + [0, 2] + ]) + cls = SparseMatrix + assert cls.hstack(cls(eye(2)), cls(2*eye(2))) == Matrix([ + [1, 0, 2, 0], + [0, 1, 0, 2] + ]) + +def test_issue_11944(): + A = Matrix([[1]]) + AIm = sympify(A) + assert Matrix.hstack(AIm, A) == Matrix([[1, 1]]) + assert Matrix.vstack(AIm, A) == Matrix([[1], [1]]) + +def test_cross(): + a = [1, 2, 3] + b = [3, 4, 5] + col = Matrix([-2, 4, -2]) + row = col.T + + def test(M, ans): + assert ans == M + assert type(M) == cls + for cls in classes: + A = cls(a) + B = cls(b) + test(A.cross(B), col) + test(A.cross(B.T), col) + test(A.T.cross(B.T), row) + test(A.T.cross(B), row) + raises(ShapeError, lambda: + Matrix(1, 2, [1, 1]).cross(Matrix(1, 2, [1, 1]))) + +def test_hat_vee(): + v1 = Matrix([x, y, z]) + v2 = Matrix([a, b, c]) + assert v1.hat() * v2 == v1.cross(v2) + assert v1.hat().is_anti_symmetric() + assert v1.hat().vee() == v1 + +def test_hash(): + for cls in classes[-2:]: + s = {cls.eye(1), cls.eye(1)} + assert len(s) == 1 and s.pop() == cls.eye(1) + # issue 3979 + for cls in classes[:2]: + assert not isinstance(cls.eye(1), Hashable) + + +@XFAIL +def test_issue_3979(): + # when this passes, delete this and change the [1:2] + # to [:2] in the test_hash above for issue 3979 + cls = classes[0] + raises(AttributeError, lambda: hash(cls.eye(1))) + + +def test_adjoint(): + dat = [[0, I], [1, 0]] + ans = Matrix([[0, 1], [-I, 0]]) + for cls in classes: + assert ans == cls(dat).adjoint() + + +def test_adjoint_with_operator(): + # Regression test for issue 25130: adjoint() should propagate to operators + import sympy.physics.quantum + a = sympy.physics.quantum.operator.Operator('a') + a_dag = sympy.physics.quantum.Dagger(a) + dat = [[0, I * a], [0, a_dag]] + ans = Matrix([[0, 0], [-I * a_dag, a]]) + for cls in classes: + assert ans == cls(dat).adjoint() + + +def test_simplify_immutable(): + assert simplify(ImmutableMatrix([[sin(x)**2 + cos(x)**2]])) == \ + ImmutableMatrix([[1]]) + +def test_replace(): + F, G = symbols('F, G', cls=Function) + K = Matrix(2, 2, lambda i, j: G(i+j)) + M = Matrix(2, 2, lambda i, j: F(i+j)) + N = M.replace(F, G) + assert N == K + + +def test_atoms(): + m = Matrix([[1, 2], [x, 1 - 1/x]]) + assert m.atoms() == {S.One,S(2),S.NegativeOne, x} + assert m.atoms(Symbol) == {x} + + +def test_pinv(): + # Pseudoinverse of an invertible matrix is the inverse. + A1 = Matrix([[a, b], [c, d]]) + assert simplify(A1.pinv(method="RD")) == simplify(A1.inv()) + + # Test the four properties of the pseudoinverse for various matrices. + As = [Matrix([[13, 104], [2212, 3], [-3, 5]]), + Matrix([[1, 7, 9], [11, 17, 19]]), + Matrix([a, b])] + + for A in As: + A_pinv = A.pinv(method="RD") + AAp = A * A_pinv + ApA = A_pinv * A + assert simplify(AAp * A) == A + assert simplify(ApA * A_pinv) == A_pinv + assert AAp.H == AAp + assert ApA.H == ApA + + # XXX Pinv with diagonalization makes expression too complicated. + for A in As: + A_pinv = simplify(A.pinv(method="ED")) + AAp = A * A_pinv + ApA = A_pinv * A + assert simplify(AAp * A) == A + assert simplify(ApA * A_pinv) == A_pinv + assert AAp.H == AAp + assert ApA.H == ApA + + # XXX Computing pinv using diagonalization makes an expression that + # is too complicated to simplify. + # A1 = Matrix([[a, b], [c, d]]) + # assert simplify(A1.pinv(method="ED")) == simplify(A1.inv()) + # so this is tested numerically at a fixed random point + + from sympy.core.numbers import comp + q = A1.pinv(method="ED") + w = A1.inv() + reps = {a: -73633, b: 11362, c: 55486, d: 62570} + assert all( + comp(i.n(), j.n()) + for i, j in zip(q.subs(reps), w.subs(reps)) + ) + + +@slow +def test_pinv_rank_deficient_when_diagonalization_fails(): + # Test the four properties of the pseudoinverse for matrices when + # diagonalization of A.H*A fails. + As = [ + Matrix([ + [61, 89, 55, 20, 71, 0], + [62, 96, 85, 85, 16, 0], + [69, 56, 17, 4, 54, 0], + [10, 54, 91, 41, 71, 0], + [ 7, 30, 10, 48, 90, 0], + [0, 0, 0, 0, 0, 0]]) + ] + for A in As: + A_pinv = A.pinv(method="ED") + AAp = A * A_pinv + ApA = A_pinv * A + assert AAp.H == AAp + + # Here ApA.H and ApA are equivalent expressions but they are very + # complicated expressions involving RootOfs. Using simplify would be + # too slow and so would evalf so we substitute approximate values for + # the RootOfs and then evalf which is less accurate but good enough to + # confirm that these two matrices are equivalent. + # + # assert ApA.H == ApA # <--- would fail (structural equality) + # assert simplify(ApA.H - ApA).is_zero_matrix # <--- too slow + # (ApA.H - ApA).evalf() # <--- too slow + + def allclose(M1, M2): + rootofs = M1.atoms(RootOf) + rootofs_approx = {r: r.evalf() for r in rootofs} + diff_approx = (M1 - M2).xreplace(rootofs_approx).evalf() + return all(abs(e) < 1e-10 for e in diff_approx) + + assert allclose(ApA.H, ApA) + + +def test_issue_7201(): + assert ones(0, 1) + ones(0, 1) == Matrix(0, 1, []) + assert ones(1, 0) + ones(1, 0) == Matrix(1, 0, []) + +def test_free_symbols(): + for M in ImmutableMatrix, ImmutableSparseMatrix, Matrix, SparseMatrix: + assert M([[x], [0]]).free_symbols == {x} + +def test_from_ndarray(): + """See issue 7465.""" + try: + from numpy import array + except ImportError: + skip('NumPy must be available to test creating matrices from ndarrays') + + assert Matrix(array([1, 2, 3])) == Matrix([1, 2, 3]) + assert Matrix(array([[1, 2, 3]])) == Matrix([[1, 2, 3]]) + assert Matrix(array([[1, 2, 3], [4, 5, 6]])) == \ + Matrix([[1, 2, 3], [4, 5, 6]]) + assert Matrix(array([x, y, z])) == Matrix([x, y, z]) + raises(NotImplementedError, + lambda: Matrix(array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]))) + assert Matrix([array([1, 2]), array([3, 4])]) == Matrix([[1, 2], [3, 4]]) + assert Matrix([array([1, 2]), [3, 4]]) == Matrix([[1, 2], [3, 4]]) + assert Matrix([array([]), array([])]) == Matrix(2, 0, []) != Matrix(0, 0, []) + +def test_17522_numpy(): + from sympy.matrices.common import _matrixify + try: + from numpy import array, matrix + except ImportError: + skip('NumPy must be available to test indexing matrixified NumPy ndarrays and matrices') + + m = _matrixify(array([[1, 2], [3, 4]])) + assert m[3] == 4 + assert list(m) == [1, 2, 3, 4] + + with ignore_warnings(PendingDeprecationWarning): + m = _matrixify(matrix([[1, 2], [3, 4]])) + assert m[3] == 4 + assert list(m) == [1, 2, 3, 4] + +def test_17522_mpmath(): + from sympy.matrices.common import _matrixify + try: + from mpmath import matrix + except ImportError: + skip('mpmath must be available to test indexing matrixified mpmath matrices') + + m = _matrixify(matrix([[1, 2], [3, 4]])) + assert m[3] == 4.0 + assert list(m) == [1.0, 2.0, 3.0, 4.0] + +def test_17522_scipy(): + from sympy.matrices.common import _matrixify + try: + from scipy.sparse import csr_matrix + except ImportError: + skip('SciPy must be available to test indexing matrixified SciPy sparse matrices') + + m = _matrixify(csr_matrix([[1, 2], [3, 4]])) + assert m[3] == 4 + assert list(m) == [1, 2, 3, 4] + +def test_hermitian(): + a = Matrix([[1, I], [-I, 1]]) + assert a.is_hermitian + a[0, 0] = 2*I + assert a.is_hermitian is False + a[0, 0] = x + assert a.is_hermitian is None + a[0, 1] = a[1, 0]*I + assert a.is_hermitian is False + b = HermitianOperator("b") + c = Operator("c") + assert Matrix([[b]]).is_hermitian is True + assert Matrix([[b, c], [Dagger(c), b]]).is_hermitian is True + assert Matrix([[b, c], [c, b]]).is_hermitian is False + assert Matrix([[b, c], [transpose(c), b]]).is_hermitian is False + +def test_doit(): + a = Matrix([[Add(x,x, evaluate=False)]]) + assert a[0] != 2*x + assert a.doit() == Matrix([[2*x]]) + +def test_issue_9457_9467_9876(): + # for row_del(index) + M = Matrix([[1, 2, 3], [2, 3, 4], [3, 4, 5]]) + M.row_del(1) + assert M == Matrix([[1, 2, 3], [3, 4, 5]]) + N = Matrix([[1, 2, 3], [2, 3, 4], [3, 4, 5]]) + N.row_del(-2) + assert N == Matrix([[1, 2, 3], [3, 4, 5]]) + O = Matrix([[1, 2, 3], [5, 6, 7], [9, 10, 11]]) + O.row_del(-1) + assert O == Matrix([[1, 2, 3], [5, 6, 7]]) + P = Matrix([[1, 2, 3], [2, 3, 4], [3, 4, 5]]) + raises(IndexError, lambda: P.row_del(10)) + Q = Matrix([[1, 2, 3], [2, 3, 4], [3, 4, 5]]) + raises(IndexError, lambda: Q.row_del(-10)) + + # for col_del(index) + M = Matrix([[1, 2, 3], [2, 3, 4], [3, 4, 5]]) + M.col_del(1) + assert M == Matrix([[1, 3], [2, 4], [3, 5]]) + N = Matrix([[1, 2, 3], [2, 3, 4], [3, 4, 5]]) + N.col_del(-2) + assert N == Matrix([[1, 3], [2, 4], [3, 5]]) + P = Matrix([[1, 2, 3], [2, 3, 4], [3, 4, 5]]) + raises(IndexError, lambda: P.col_del(10)) + Q = Matrix([[1, 2, 3], [2, 3, 4], [3, 4, 5]]) + raises(IndexError, lambda: Q.col_del(-10)) + +def test_issue_9422(): + x, y = symbols('x y', commutative=False) + a, b = symbols('a b') + M = eye(2) + M1 = Matrix(2, 2, [x, y, y, z]) + assert y*x*M != x*y*M + assert b*a*M == a*b*M + assert x*M1 != M1*x + assert a*M1 == M1*a + assert y*x*M == Matrix([[y*x, 0], [0, y*x]]) + + +def test_issue_10770(): + M = Matrix([]) + a = ['col_insert', 'row_join'], Matrix([9, 6, 3]) + b = ['row_insert', 'col_join'], a[1].T + c = ['row_insert', 'col_insert'], Matrix([[1, 2], [3, 4]]) + for ops, m in (a, b, c): + for op in ops: + f = getattr(M, op) + new = f(m) if 'join' in op else f(42, m) + assert new == m and id(new) != id(m) + + +def test_issue_10658(): + A = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + assert A.extract([0, 1, 2], [True, True, False]) == \ + Matrix([[1, 2], [4, 5], [7, 8]]) + assert A.extract([0, 1, 2], [True, False, False]) == Matrix([[1], [4], [7]]) + assert A.extract([True, False, False], [0, 1, 2]) == Matrix([[1, 2, 3]]) + assert A.extract([True, False, True], [0, 1, 2]) == \ + Matrix([[1, 2, 3], [7, 8, 9]]) + assert A.extract([0, 1, 2], [False, False, False]) == Matrix(3, 0, []) + assert A.extract([False, False, False], [0, 1, 2]) == Matrix(0, 3, []) + assert A.extract([True, False, True], [False, True, False]) == \ + Matrix([[2], [8]]) + +def test_opportunistic_simplification(): + # this test relates to issue #10718, #9480, #11434 + + # issue #9480 + m = Matrix([[-5 + 5*sqrt(2), -5], [-5*sqrt(2)/2 + 5, -5*sqrt(2)/2]]) + assert m.rank() == 1 + + # issue #10781 + m = Matrix([[3+3*sqrt(3)*I, -9],[4,-3+3*sqrt(3)*I]]) + assert simplify(m.rref()[0] - Matrix([[1, -9/(3 + 3*sqrt(3)*I)], [0, 0]])) == zeros(2, 2) + + # issue #11434 + ax,ay,bx,by,cx,cy,dx,dy,ex,ey,t0,t1 = symbols('a_x a_y b_x b_y c_x c_y d_x d_y e_x e_y t_0 t_1') + m = Matrix([[ax,ay,ax*t0,ay*t0,0],[bx,by,bx*t0,by*t0,0],[cx,cy,cx*t0,cy*t0,1],[dx,dy,dx*t0,dy*t0,1],[ex,ey,2*ex*t1-ex*t0,2*ey*t1-ey*t0,0]]) + assert m.rank() == 4 + +def test_partial_pivoting(): + # example from https://en.wikipedia.org/wiki/Pivot_element + # partial pivoting with back substitution gives a perfect result + # naive pivoting give an error ~1e-13, so anything better than + # 1e-15 is good + mm=Matrix([[0.003, 59.14, 59.17], [5.291, -6.13, 46.78]]) + assert (mm.rref()[0] - Matrix([[1.0, 0, 10.0], + [ 0, 1.0, 1.0]])).norm() < 1e-15 + + # issue #11549 + m_mixed = Matrix([[6e-17, 1.0, 4], + [ -1.0, 0, 8], + [ 0, 0, 1]]) + m_float = Matrix([[6e-17, 1.0, 4.], + [ -1.0, 0., 8.], + [ 0., 0., 1.]]) + m_inv = Matrix([[ 0, -1.0, 8.0], + [1.0, 6.0e-17, -4.0], + [ 0, 0, 1]]) + # this example is numerically unstable and involves a matrix with a norm >= 8, + # this comparing the difference of the results with 1e-15 is numerically sound. + assert (m_mixed.inv() - m_inv).norm() < 1e-15 + assert (m_float.inv() - m_inv).norm() < 1e-15 + +def test_iszero_substitution(): + """ When doing numerical computations, all elements that pass + the iszerofunc test should be set to numerically zero if they + aren't already. """ + + # Matrix from issue #9060 + m = Matrix([[0.9, -0.1, -0.2, 0],[-0.8, 0.9, -0.4, 0],[-0.1, -0.8, 0.6, 0]]) + m_rref = m.rref(iszerofunc=lambda x: abs(x)<6e-15)[0] + m_correct = Matrix([[1.0, 0, -0.301369863013699, 0],[ 0, 1.0, -0.712328767123288, 0],[ 0, 0, 0, 0]]) + m_diff = m_rref - m_correct + assert m_diff.norm() < 1e-15 + # if a zero-substitution wasn't made, this entry will be -1.11022302462516e-16 + assert m_rref[2,2] == 0 + +def test_issue_11238(): + from sympy.geometry.point import Point + xx = 8*tan(pi*Rational(13, 45))/(tan(pi*Rational(13, 45)) + sqrt(3)) + yy = (-8*sqrt(3)*tan(pi*Rational(13, 45))**2 + 24*tan(pi*Rational(13, 45)))/(-3 + tan(pi*Rational(13, 45))**2) + p1 = Point(0, 0) + p2 = Point(1, -sqrt(3)) + p0 = Point(xx,yy) + m1 = Matrix([p1 - simplify(p0), p2 - simplify(p0)]) + m2 = Matrix([p1 - p0, p2 - p0]) + m3 = Matrix([simplify(p1 - p0), simplify(p2 - p0)]) + + # This system has expressions which are zero and + # cannot be easily proved to be such, so without + # numerical testing, these assertions will fail. + Z = lambda x: abs(x.n()) < 1e-20 + assert m1.rank(simplify=True, iszerofunc=Z) == 1 + assert m2.rank(simplify=True, iszerofunc=Z) == 1 + assert m3.rank(simplify=True, iszerofunc=Z) == 1 + +def test_as_real_imag(): + m1 = Matrix(2,2,[1,2,3,4]) + m2 = m1*S.ImaginaryUnit + m3 = m1 + m2 + + for kls in classes: + a,b = kls(m3).as_real_imag() + assert list(a) == list(m1) + assert list(b) == list(m1) + +def test_deprecated(): + # Maintain tests for deprecated functions. We must capture + # the deprecation warnings. When the deprecated functionality is + # removed, the corresponding tests should be removed. + + m = Matrix(3, 3, [0, 1, 0, -4, 4, 0, -2, 1, 2]) + P, Jcells = m.jordan_cells() + assert Jcells[1] == Matrix(1, 1, [2]) + assert Jcells[0] == Matrix(2, 2, [2, 1, 0, 2]) + + +def test_issue_14489(): + from sympy.core.mod import Mod + A = Matrix([-1, 1, 2]) + B = Matrix([10, 20, -15]) + + assert Mod(A, 3) == Matrix([2, 1, 2]) + assert Mod(B, 4) == Matrix([2, 0, 1]) + +def test_issue_14943(): + # Test that __array__ accepts the optional dtype argument + try: + from numpy import array + except ImportError: + skip('NumPy must be available to test creating matrices from ndarrays') + + M = Matrix([[1,2], [3,4]]) + assert array(M, dtype=float).dtype.name == 'float64' + +def test_case_6913(): + m = MatrixSymbol('m', 1, 1) + a = Symbol("a") + a = m[0, 0]>0 + assert str(a) == 'm[0, 0] > 0' + +def test_issue_11948(): + A = MatrixSymbol('A', 3, 3) + a = Wild('a') + assert A.match(a) == {a: A} + +def test_gramschmidt_conjugate_dot(): + vecs = [Matrix([1, I]), Matrix([1, -I])] + assert Matrix.orthogonalize(*vecs) == \ + [Matrix([[1], [I]]), Matrix([[1], [-I]])] + + vecs = [Matrix([1, I, 0]), Matrix([I, 0, -I])] + assert Matrix.orthogonalize(*vecs) == \ + [Matrix([[1], [I], [0]]), Matrix([[I/2], [S(1)/2], [-I]])] + + mat = Matrix([[1, I], [1, -I]]) + Q, R = mat.QRdecomposition() + assert Q * Q.H == Matrix.eye(2) + +def test_issue_8207(): + a = Matrix(MatrixSymbol('a', 3, 1)) + b = Matrix(MatrixSymbol('b', 3, 1)) + c = a.dot(b) + d = diff(c, a[0, 0]) + e = diff(d, a[0, 0]) + assert d == b[0, 0] + assert e == 0 + +def test_func(): + from sympy.simplify.simplify import nthroot + + A = Matrix([[1, 2],[0, 3]]) + assert A.analytic_func(sin(x*t), x) == Matrix([[sin(t), sin(3*t) - sin(t)], [0, sin(3*t)]]) + + A = Matrix([[2, 1],[1, 2]]) + assert (pi * A / 6).analytic_func(cos(x), x) == Matrix([[sqrt(3)/4, -sqrt(3)/4], [-sqrt(3)/4, sqrt(3)/4]]) + + + raises(ValueError, lambda : zeros(5).analytic_func(log(x), x)) + raises(ValueError, lambda : (A*x).analytic_func(log(x), x)) + + A = Matrix([[0, -1, -2, 3], [0, -1, -2, 3], [0, 1, 0, -1], [0, 0, -1, 1]]) + assert A.analytic_func(exp(x), x) == A.exp() + raises(ValueError, lambda : A.analytic_func(sqrt(x), x)) + + A = Matrix([[41, 12],[12, 34]]) + assert simplify(A.analytic_func(sqrt(x), x)**2) == A + + A = Matrix([[3, -12, 4], [-1, 0, -2], [-1, 5, -1]]) + assert simplify(A.analytic_func(nthroot(x, 3), x)**3) == A + + A = Matrix([[2, 0, 0, 0], [1, 2, 0, 0], [0, 1, 3, 0], [0, 0, 1, 3]]) + assert A.analytic_func(exp(x), x) == A.exp() + + A = Matrix([[0, 2, 1, 6], [0, 0, 1, 2], [0, 0, 0, 3], [0, 0, 0, 0]]) + assert A.analytic_func(exp(x*t), x) == expand(simplify((A*t).exp())) + + +@skip_under_pyodide("Cannot create threads under pyodide.") +def test_issue_19809(): + + def f(): + assert _dotprodsimp_state.state == None + m = Matrix([[1]]) + m = m * m + return True + + with dotprodsimp(True): + with concurrent.futures.ThreadPoolExecutor() as executor: + future = executor.submit(f) + assert future.result() + + +def test_issue_23276(): + M = Matrix([x, y]) + assert integrate(M, (x, 0, 1), (y, 0, 1)) == Matrix([ + [S.Half], + [S.Half]]) + + +# SubspaceOnlyMatrix tests +def test_columnspace_one(): + m = SubspaceOnlyMatrix([[ 1, 2, 0, 2, 5], + [-2, -5, 1, -1, -8], + [ 0, -3, 3, 4, 1], + [ 3, 6, 0, -7, 2]]) + + basis = m.columnspace() + assert basis[0] == Matrix([1, -2, 0, 3]) + assert basis[1] == Matrix([2, -5, -3, 6]) + assert basis[2] == Matrix([2, -1, 4, -7]) + + assert len(basis) == 3 + assert Matrix.hstack(m, *basis).columnspace() == basis + + +def test_rowspace(): + m = SubspaceOnlyMatrix([[ 1, 2, 0, 2, 5], + [-2, -5, 1, -1, -8], + [ 0, -3, 3, 4, 1], + [ 3, 6, 0, -7, 2]]) + + basis = m.rowspace() + assert basis[0] == Matrix([[1, 2, 0, 2, 5]]) + assert basis[1] == Matrix([[0, -1, 1, 3, 2]]) + assert basis[2] == Matrix([[0, 0, 0, 5, 5]]) + + assert len(basis) == 3 + + +def test_nullspace_one(): + m = SubspaceOnlyMatrix([[ 1, 2, 0, 2, 5], + [-2, -5, 1, -1, -8], + [ 0, -3, 3, 4, 1], + [ 3, 6, 0, -7, 2]]) + + basis = m.nullspace() + assert basis[0] == Matrix([-2, 1, 1, 0, 0]) + assert basis[1] == Matrix([-1, -1, 0, -1, 1]) + # make sure the null space is really gets zeroed + assert all(e.is_zero for e in m*basis[0]) + assert all(e.is_zero for e in m*basis[1]) + + +# ReductionsOnlyMatrix tests +def test_row_op(): + e = eye_Reductions(3) + + raises(ValueError, lambda: e.elementary_row_op("abc")) + raises(ValueError, lambda: e.elementary_row_op()) + raises(ValueError, lambda: e.elementary_row_op('n->kn', row=5, k=5)) + raises(ValueError, lambda: e.elementary_row_op('n->kn', row=-5, k=5)) + raises(ValueError, lambda: e.elementary_row_op('n<->m', row1=1, row2=5)) + raises(ValueError, lambda: e.elementary_row_op('n<->m', row1=5, row2=1)) + raises(ValueError, lambda: e.elementary_row_op('n<->m', row1=-5, row2=1)) + raises(ValueError, lambda: e.elementary_row_op('n<->m', row1=1, row2=-5)) + raises(ValueError, lambda: e.elementary_row_op('n->n+km', row1=1, row2=5, k=5)) + raises(ValueError, lambda: e.elementary_row_op('n->n+km', row1=5, row2=1, k=5)) + raises(ValueError, lambda: e.elementary_row_op('n->n+km', row1=-5, row2=1, k=5)) + raises(ValueError, lambda: e.elementary_row_op('n->n+km', row1=1, row2=-5, k=5)) + raises(ValueError, lambda: e.elementary_row_op('n->n+km', row1=1, row2=1, k=5)) + + # test various ways to set arguments + assert e.elementary_row_op("n->kn", 0, 5) == Matrix([[5, 0, 0], [0, 1, 0], [0, 0, 1]]) + assert e.elementary_row_op("n->kn", 1, 5) == Matrix([[1, 0, 0], [0, 5, 0], [0, 0, 1]]) + assert e.elementary_row_op("n->kn", row=1, k=5) == Matrix([[1, 0, 0], [0, 5, 0], [0, 0, 1]]) + assert e.elementary_row_op("n->kn", row1=1, k=5) == Matrix([[1, 0, 0], [0, 5, 0], [0, 0, 1]]) + assert e.elementary_row_op("n<->m", 0, 1) == Matrix([[0, 1, 0], [1, 0, 0], [0, 0, 1]]) + assert e.elementary_row_op("n<->m", row1=0, row2=1) == Matrix([[0, 1, 0], [1, 0, 0], [0, 0, 1]]) + assert e.elementary_row_op("n<->m", row=0, row2=1) == Matrix([[0, 1, 0], [1, 0, 0], [0, 0, 1]]) + assert e.elementary_row_op("n->n+km", 0, 5, 1) == Matrix([[1, 5, 0], [0, 1, 0], [0, 0, 1]]) + assert e.elementary_row_op("n->n+km", row=0, k=5, row2=1) == Matrix([[1, 5, 0], [0, 1, 0], [0, 0, 1]]) + assert e.elementary_row_op("n->n+km", row1=0, k=5, row2=1) == Matrix([[1, 5, 0], [0, 1, 0], [0, 0, 1]]) + + # make sure the matrix doesn't change size + a = ReductionsOnlyMatrix(2, 3, [0]*6) + assert a.elementary_row_op("n->kn", 1, 5) == Matrix(2, 3, [0]*6) + assert a.elementary_row_op("n<->m", 0, 1) == Matrix(2, 3, [0]*6) + assert a.elementary_row_op("n->n+km", 0, 5, 1) == Matrix(2, 3, [0]*6) + + +def test_col_op(): + e = eye_Reductions(3) + + raises(ValueError, lambda: e.elementary_col_op("abc")) + raises(ValueError, lambda: e.elementary_col_op()) + raises(ValueError, lambda: e.elementary_col_op('n->kn', col=5, k=5)) + raises(ValueError, lambda: e.elementary_col_op('n->kn', col=-5, k=5)) + raises(ValueError, lambda: e.elementary_col_op('n<->m', col1=1, col2=5)) + raises(ValueError, lambda: e.elementary_col_op('n<->m', col1=5, col2=1)) + raises(ValueError, lambda: e.elementary_col_op('n<->m', col1=-5, col2=1)) + raises(ValueError, lambda: e.elementary_col_op('n<->m', col1=1, col2=-5)) + raises(ValueError, lambda: e.elementary_col_op('n->n+km', col1=1, col2=5, k=5)) + raises(ValueError, lambda: e.elementary_col_op('n->n+km', col1=5, col2=1, k=5)) + raises(ValueError, lambda: e.elementary_col_op('n->n+km', col1=-5, col2=1, k=5)) + raises(ValueError, lambda: e.elementary_col_op('n->n+km', col1=1, col2=-5, k=5)) + raises(ValueError, lambda: e.elementary_col_op('n->n+km', col1=1, col2=1, k=5)) + + # test various ways to set arguments + assert e.elementary_col_op("n->kn", 0, 5) == Matrix([[5, 0, 0], [0, 1, 0], [0, 0, 1]]) + assert e.elementary_col_op("n->kn", 1, 5) == Matrix([[1, 0, 0], [0, 5, 0], [0, 0, 1]]) + assert e.elementary_col_op("n->kn", col=1, k=5) == Matrix([[1, 0, 0], [0, 5, 0], [0, 0, 1]]) + assert e.elementary_col_op("n->kn", col1=1, k=5) == Matrix([[1, 0, 0], [0, 5, 0], [0, 0, 1]]) + assert e.elementary_col_op("n<->m", 0, 1) == Matrix([[0, 1, 0], [1, 0, 0], [0, 0, 1]]) + assert e.elementary_col_op("n<->m", col1=0, col2=1) == Matrix([[0, 1, 0], [1, 0, 0], [0, 0, 1]]) + assert e.elementary_col_op("n<->m", col=0, col2=1) == Matrix([[0, 1, 0], [1, 0, 0], [0, 0, 1]]) + assert e.elementary_col_op("n->n+km", 0, 5, 1) == Matrix([[1, 0, 0], [5, 1, 0], [0, 0, 1]]) + assert e.elementary_col_op("n->n+km", col=0, k=5, col2=1) == Matrix([[1, 0, 0], [5, 1, 0], [0, 0, 1]]) + assert e.elementary_col_op("n->n+km", col1=0, k=5, col2=1) == Matrix([[1, 0, 0], [5, 1, 0], [0, 0, 1]]) + + # make sure the matrix doesn't change size + a = ReductionsOnlyMatrix(2, 3, [0]*6) + assert a.elementary_col_op("n->kn", 1, 5) == Matrix(2, 3, [0]*6) + assert a.elementary_col_op("n<->m", 0, 1) == Matrix(2, 3, [0]*6) + assert a.elementary_col_op("n->n+km", 0, 5, 1) == Matrix(2, 3, [0]*6) + + +def test_is_echelon(): + zro = zeros_Reductions(3) + ident = eye_Reductions(3) + + assert zro.is_echelon + assert ident.is_echelon + + a = ReductionsOnlyMatrix(0, 0, []) + assert a.is_echelon + + a = ReductionsOnlyMatrix(2, 3, [3, 2, 1, 0, 0, 6]) + assert a.is_echelon + + a = ReductionsOnlyMatrix(2, 3, [0, 0, 6, 3, 2, 1]) + assert not a.is_echelon + + x = Symbol('x') + a = ReductionsOnlyMatrix(3, 1, [x, 0, 0]) + assert a.is_echelon + + a = ReductionsOnlyMatrix(3, 1, [x, x, 0]) + assert not a.is_echelon + + a = ReductionsOnlyMatrix(3, 3, [0, 0, 0, 1, 2, 3, 0, 0, 0]) + assert not a.is_echelon + + +def test_echelon_form(): + # echelon form is not unique, but the result + # must be row-equivalent to the original matrix + # and it must be in echelon form. + + a = zeros_Reductions(3) + e = eye_Reductions(3) + + # we can assume the zero matrix and the identity matrix shouldn't change + assert a.echelon_form() == a + assert e.echelon_form() == e + + a = ReductionsOnlyMatrix(0, 0, []) + assert a.echelon_form() == a + + a = ReductionsOnlyMatrix(1, 1, [5]) + assert a.echelon_form() == a + + # now we get to the real tests + + def verify_row_null_space(mat, rows, nulls): + for v in nulls: + assert all(t.is_zero for t in a_echelon*v) + for v in rows: + if not all(t.is_zero for t in v): + assert not all(t.is_zero for t in a_echelon*v.transpose()) + + a = ReductionsOnlyMatrix(3, 3, [1, 2, 3, 4, 5, 6, 7, 8, 9]) + nulls = [Matrix([ + [ 1], + [-2], + [ 1]])] + rows = [a[i, :] for i in range(a.rows)] + a_echelon = a.echelon_form() + assert a_echelon.is_echelon + verify_row_null_space(a, rows, nulls) + + + a = ReductionsOnlyMatrix(3, 3, [1, 2, 3, 4, 5, 6, 7, 8, 8]) + nulls = [] + rows = [a[i, :] for i in range(a.rows)] + a_echelon = a.echelon_form() + assert a_echelon.is_echelon + verify_row_null_space(a, rows, nulls) + + a = ReductionsOnlyMatrix(3, 3, [2, 1, 3, 0, 0, 0, 2, 1, 3]) + nulls = [Matrix([ + [Rational(-1, 2)], + [ 1], + [ 0]]), + Matrix([ + [Rational(-3, 2)], + [ 0], + [ 1]])] + rows = [a[i, :] for i in range(a.rows)] + a_echelon = a.echelon_form() + assert a_echelon.is_echelon + verify_row_null_space(a, rows, nulls) + + # this one requires a row swap + a = ReductionsOnlyMatrix(3, 3, [2, 1, 3, 0, 0, 0, 1, 1, 3]) + nulls = [Matrix([ + [ 0], + [ -3], + [ 1]])] + rows = [a[i, :] for i in range(a.rows)] + a_echelon = a.echelon_form() + assert a_echelon.is_echelon + verify_row_null_space(a, rows, nulls) + + a = ReductionsOnlyMatrix(3, 3, [0, 3, 3, 0, 2, 2, 0, 1, 1]) + nulls = [Matrix([ + [1], + [0], + [0]]), + Matrix([ + [ 0], + [-1], + [ 1]])] + rows = [a[i, :] for i in range(a.rows)] + a_echelon = a.echelon_form() + assert a_echelon.is_echelon + verify_row_null_space(a, rows, nulls) + + a = ReductionsOnlyMatrix(2, 3, [2, 2, 3, 3, 3, 0]) + nulls = [Matrix([ + [-1], + [1], + [0]])] + rows = [a[i, :] for i in range(a.rows)] + a_echelon = a.echelon_form() + assert a_echelon.is_echelon + verify_row_null_space(a, rows, nulls) + + +def test_rref(): + e = ReductionsOnlyMatrix(0, 0, []) + assert e.rref(pivots=False) == e + + e = ReductionsOnlyMatrix(1, 1, [1]) + a = ReductionsOnlyMatrix(1, 1, [5]) + assert e.rref(pivots=False) == a.rref(pivots=False) == e + + a = ReductionsOnlyMatrix(3, 1, [1, 2, 3]) + assert a.rref(pivots=False) == Matrix([[1], [0], [0]]) + + a = ReductionsOnlyMatrix(1, 3, [1, 2, 3]) + assert a.rref(pivots=False) == Matrix([[1, 2, 3]]) + + a = ReductionsOnlyMatrix(3, 3, [1, 2, 3, 4, 5, 6, 7, 8, 9]) + assert a.rref(pivots=False) == Matrix([ + [1, 0, -1], + [0, 1, 2], + [0, 0, 0]]) + + a = ReductionsOnlyMatrix(3, 3, [1, 2, 3, 1, 2, 3, 1, 2, 3]) + b = ReductionsOnlyMatrix(3, 3, [1, 2, 3, 0, 0, 0, 0, 0, 0]) + c = ReductionsOnlyMatrix(3, 3, [0, 0, 0, 1, 2, 3, 0, 0, 0]) + d = ReductionsOnlyMatrix(3, 3, [0, 0, 0, 0, 0, 0, 1, 2, 3]) + assert a.rref(pivots=False) == \ + b.rref(pivots=False) == \ + c.rref(pivots=False) == \ + d.rref(pivots=False) == b + + e = eye_Reductions(3) + z = zeros_Reductions(3) + assert e.rref(pivots=False) == e + assert z.rref(pivots=False) == z + + a = ReductionsOnlyMatrix([ + [ 0, 0, 1, 2, 2, -5, 3], + [-1, 5, 2, 2, 1, -7, 5], + [ 0, 0, -2, -3, -3, 8, -5], + [-1, 5, 0, -1, -2, 1, 0]]) + mat, pivot_offsets = a.rref() + assert mat == Matrix([ + [1, -5, 0, 0, 1, 1, -1], + [0, 0, 1, 0, 0, -1, 1], + [0, 0, 0, 1, 1, -2, 1], + [0, 0, 0, 0, 0, 0, 0]]) + assert pivot_offsets == (0, 2, 3) + + a = ReductionsOnlyMatrix([[Rational(1, 19), Rational(1, 5), 2, 3], + [ 4, 5, 6, 7], + [ 8, 9, 10, 11], + [ 12, 13, 14, 15]]) + assert a.rref(pivots=False) == Matrix([ + [1, 0, 0, Rational(-76, 157)], + [0, 1, 0, Rational(-5, 157)], + [0, 0, 1, Rational(238, 157)], + [0, 0, 0, 0]]) + + x = Symbol('x') + a = ReductionsOnlyMatrix(2, 3, [x, 1, 1, sqrt(x), x, 1]) + for i, j in zip(a.rref(pivots=False), + [1, 0, sqrt(x)*(-x + 1)/(-x**Rational(5, 2) + x), + 0, 1, 1/(sqrt(x) + x + 1)]): + assert simplify(i - j).is_zero + + +def test_rref_rhs(): + a, b, c, d = symbols('a b c d') + A = Matrix([[0, 0], [0, 0], [1, 2], [3, 4]]) + B = Matrix([a, b, c, d]) + assert A.rref_rhs(B) == (Matrix([ + [1, 0], + [0, 1], + [0, 0], + [0, 0]]), Matrix([ + [ -2*c + d], + [3*c/2 - d/2], + [ a], + [ b]])) + + +def test_issue_17827(): + C = Matrix([ + [3, 4, -1, 1], + [9, 12, -3, 3], + [0, 2, 1, 3], + [2, 3, 0, -2], + [0, 3, 3, -5], + [8, 15, 0, 6] + ]) + # Tests for row/col within valid range + D = C.elementary_row_op('n<->m', row1=2, row2=5) + E = C.elementary_row_op('n->n+km', row1=5, row2=3, k=-4) + F = C.elementary_row_op('n->kn', row=5, k=2) + assert(D[5, :] == Matrix([[0, 2, 1, 3]])) + assert(E[5, :] == Matrix([[0, 3, 0, 14]])) + assert(F[5, :] == Matrix([[16, 30, 0, 12]])) + # Tests for row/col out of range + raises(ValueError, lambda: C.elementary_row_op('n<->m', row1=2, row2=6)) + raises(ValueError, lambda: C.elementary_row_op('n->kn', row=7, k=2)) + raises(ValueError, lambda: C.elementary_row_op('n->n+km', row1=-1, row2=5, k=2)) + +def test_rank(): + m = Matrix([[1, 2], [x, 1 - 1/x]]) + assert m.rank() == 2 + n = Matrix(3, 3, range(1, 10)) + assert n.rank() == 2 + p = zeros(3) + assert p.rank() == 0 + +def test_issue_11434(): + ax, ay, bx, by, cx, cy, dx, dy, ex, ey, t0, t1 = \ + symbols('a_x a_y b_x b_y c_x c_y d_x d_y e_x e_y t_0 t_1') + M = Matrix([[ax, ay, ax*t0, ay*t0, 0], + [bx, by, bx*t0, by*t0, 0], + [cx, cy, cx*t0, cy*t0, 1], + [dx, dy, dx*t0, dy*t0, 1], + [ex, ey, 2*ex*t1 - ex*t0, 2*ey*t1 - ey*t0, 0]]) + assert M.rank() == 4 + +def test_rank_regression_from_so(): + # see: + # https://stackoverflow.com/questions/19072700/why-does-sympy-give-me-the-wrong-answer-when-i-row-reduce-a-symbolic-matrix + + nu, lamb = symbols('nu, lambda') + A = Matrix([[-3*nu, 1, 0, 0], + [ 3*nu, -2*nu - 1, 2, 0], + [ 0, 2*nu, (-1*nu) - lamb - 2, 3], + [ 0, 0, nu + lamb, -3]]) + expected_reduced = Matrix([[1, 0, 0, 1/(nu**2*(-lamb - nu))], + [0, 1, 0, 3/(nu*(-lamb - nu))], + [0, 0, 1, 3/(-lamb - nu)], + [0, 0, 0, 0]]) + expected_pivots = (0, 1, 2) + + reduced, pivots = A.rref() + + assert simplify(expected_reduced - reduced) == zeros(*A.shape) + assert pivots == expected_pivots + +def test_issue_15872(): + A = Matrix([[1, 1, 1, 0], [-2, -1, 0, -1], [0, 0, -1, -1], [0, 0, 2, 1]]) + B = A - Matrix.eye(4) * I + assert B.rank() == 3 + assert (B**2).rank() == 2 + assert (B**3).rank() == 2 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_matrixbase.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_matrixbase.py new file mode 100644 index 0000000000000000000000000000000000000000..a77f51596c6622dc427feeeb9383214592fab632 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_matrixbase.py @@ -0,0 +1,3795 @@ +import concurrent.futures +import random +from collections.abc import Hashable + +from sympy import ( + Abs, Add, Array, DeferredVector, E, Expr, FiniteSet, Float, Function, + GramSchmidt, I, ImmutableDenseMatrix, ImmutableMatrix, + ImmutableSparseMatrix, Integer, KroneckerDelta, MatPow, Matrix, + MatrixSymbol, Max, Min, MutableDenseMatrix, MutableSparseMatrix, Poly, Pow, + PurePoly, Q, Quaternion, Rational, RootOf, S, SparseMatrix, Symbol, Tuple, + Wild, banded, casoratian, cos, diag, diff, exp, expand, eye, floor, hessian, + integrate, log, matrix_multiply_elementwise, nan, ones, oo, pi, randMatrix, + rot_axis1, rot_axis2, rot_axis3, rot_ccw_axis1, rot_ccw_axis2, + rot_ccw_axis3, signsimp, simplify, sin, sqrt, sstr, symbols, sympify, tan, + trigsimp, wronskian, zeros, cancel) +from sympy.abc import a, b, c, d, t, x, y, z +from sympy.core.kind import NumberKind, UndefinedKind +from sympy.matrices.determinant import _find_reasonable_pivot_naive +from sympy.matrices.exceptions import ( + MatrixError, NonSquareMatrixError, ShapeError) +from sympy.matrices.kind import MatrixKind +from sympy.matrices.utilities import _dotprodsimp_state, _simplify, dotprodsimp +from sympy.tensor.array.array_derivatives import ArrayDerivative +from sympy.testing.pytest import ( + ignore_warnings, raises, skip, skip_under_pyodide, slow, + warns_deprecated_sympy) +from sympy.utilities.iterables import capture, iterable +from importlib.metadata import version + +all_classes = (Matrix, SparseMatrix, ImmutableMatrix, ImmutableSparseMatrix) +mutable_classes = (Matrix, SparseMatrix) +immutable_classes = (ImmutableMatrix, ImmutableSparseMatrix) + + +def test__MinimalMatrix(): + x = Matrix(2, 3, [1, 2, 3, 4, 5, 6]) + assert x.rows == 2 + assert x.cols == 3 + assert x[2] == 3 + assert x[1, 1] == 5 + assert list(x) == [1, 2, 3, 4, 5, 6] + assert list(x[1, :]) == [4, 5, 6] + assert list(x[:, 1]) == [2, 5] + assert list(x[:, :]) == list(x) + assert x[:, :] == x + assert Matrix(x) == x + assert Matrix([[1, 2, 3], [4, 5, 6]]) == x + assert Matrix(([1, 2, 3], [4, 5, 6])) == x + assert Matrix([(1, 2, 3), (4, 5, 6)]) == x + assert Matrix(((1, 2, 3), (4, 5, 6))) == x + assert not (Matrix([[1, 2], [3, 4], [5, 6]]) == x) + + +def test_kind(): + assert Matrix([[1, 2], [3, 4]]).kind == MatrixKind(NumberKind) + assert Matrix([[0, 0], [0, 0]]).kind == MatrixKind(NumberKind) + assert Matrix(0, 0, []).kind == MatrixKind(NumberKind) + assert Matrix([[x]]).kind == MatrixKind(NumberKind) + assert Matrix([[1, Matrix([[1]])]]).kind == MatrixKind(UndefinedKind) + assert SparseMatrix([[1]]).kind == MatrixKind(NumberKind) + assert SparseMatrix([[1, Matrix([[1]])]]).kind == MatrixKind(UndefinedKind) + + +def test_todok(): + a, b, c, d = symbols('a:d') + m1 = MutableDenseMatrix([[a, b], [c, d]]) + m2 = ImmutableDenseMatrix([[a, b], [c, d]]) + m3 = MutableSparseMatrix([[a, b], [c, d]]) + m4 = ImmutableSparseMatrix([[a, b], [c, d]]) + assert m1.todok() == m2.todok() == m3.todok() == m4.todok() == \ + {(0, 0): a, (0, 1): b, (1, 0): c, (1, 1): d} + + +def test_tolist(): + lst = [[S.One, S.Half, x*y, S.Zero], [x, y, z, x**2], [y, -S.One, z*x, 3]] + flat_lst = [S.One, S.Half, x*y, S.Zero, x, y, z, x**2, y, -S.One, z*x, 3] + m = Matrix(3, 4, flat_lst) + assert m.tolist() == lst + + +def test_todod(): + m = Matrix([[S.One, 0], [0, S.Half], [x, 0]]) + dict = {0: {0: S.One}, 1: {1: S.Half}, 2: {0: x}} + assert m.todod() == dict + + +def test_row_col_del(): + e = ImmutableMatrix(3, 3, [1, 2, 3, 4, 5, 6, 7, 8, 9]) + raises(IndexError, lambda: e.row_del(5)) + raises(IndexError, lambda: e.row_del(-5)) + raises(IndexError, lambda: e.col_del(5)) + raises(IndexError, lambda: e.col_del(-5)) + + assert e.row_del(2) == e.row_del(-1) == Matrix([[1, 2, 3], [4, 5, 6]]) + assert e.col_del(2) == e.col_del(-1) == Matrix([[1, 2], [4, 5], [7, 8]]) + + assert e.row_del(1) == e.row_del(-2) == Matrix([[1, 2, 3], [7, 8, 9]]) + assert e.col_del(1) == e.col_del(-2) == Matrix([[1, 3], [4, 6], [7, 9]]) + + +def test_get_diag_blocks1(): + a = Matrix([[1, 2], [2, 3]]) + b = Matrix([[3, x], [y, 3]]) + c = Matrix([[3, x, 3], [y, 3, z], [x, y, z]]) + assert a.get_diag_blocks() == [a] + assert b.get_diag_blocks() == [b] + assert c.get_diag_blocks() == [c] + + +def test_get_diag_blocks2(): + a = Matrix([[1, 2], [2, 3]]) + b = Matrix([[3, x], [y, 3]]) + c = Matrix([[3, x, 3], [y, 3, z], [x, y, z]]) + A, B, C, D = diag(a, b, b), diag(a, b, c), diag(a, c, b), diag(c, c, b) + A = Matrix(A.rows, A.cols, A) + B = Matrix(B.rows, B.cols, B) + C = Matrix(C.rows, C.cols, C) + D = Matrix(D.rows, D.cols, D) + + assert A.get_diag_blocks() == [a, b, b] + assert B.get_diag_blocks() == [a, b, c] + assert C.get_diag_blocks() == [a, c, b] + assert D.get_diag_blocks() == [c, c, b] + + +def test_row_col(): + m = Matrix(3, 3, [1, 2, 3, 4, 5, 6, 7, 8, 9]) + assert m.row(0) == Matrix(1, 3, [1, 2, 3]) + assert m.col(0) == Matrix(3, 1, [1, 4, 7]) + + +def test_row_join(): + assert eye(3).row_join(Matrix([7, 7, 7])) == \ + Matrix([[1, 0, 0, 7], + [0, 1, 0, 7], + [0, 0, 1, 7]]) + + +def test_col_join(): + assert eye(3).col_join(Matrix([[7, 7, 7]])) == \ + Matrix([[1, 0, 0], + [0, 1, 0], + [0, 0, 1], + [7, 7, 7]]) + + +def test_row_insert(): + r4 = Matrix([[4, 4, 4]]) + for i in range(-4, 5): + l = [1, 0, 0] + l.insert(i, 4) + assert eye(3).row_insert(i, r4).col(0).flat() == l + + +def test_col_insert(): + c4 = Matrix([4, 4, 4]) + for i in range(-4, 5): + l = [0, 0, 0] + l.insert(i, 4) + assert zeros(3).col_insert(i, c4).row(0).flat() == l + # issue 13643 + assert eye(6).col_insert(3, Matrix([[2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2]])) == \ + Matrix([[1, 0, 0, 2, 2, 0, 0, 0], + [0, 1, 0, 2, 2, 0, 0, 0], + [0, 0, 1, 2, 2, 0, 0, 0], + [0, 0, 0, 2, 2, 1, 0, 0], + [0, 0, 0, 2, 2, 0, 1, 0], + [0, 0, 0, 2, 2, 0, 0, 1]]) + + +def test_extract(): + m = Matrix(4, 3, lambda i, j: i*3 + j) + assert m.extract([0, 1, 3], [0, 1]) == Matrix(3, 2, [0, 1, 3, 4, 9, 10]) + assert m.extract([0, 3], [0, 0, 2]) == Matrix(2, 3, [0, 0, 2, 9, 9, 11]) + assert m.extract(range(4), range(3)) == m + raises(IndexError, lambda: m.extract([4], [0])) + raises(IndexError, lambda: m.extract([0], [3])) + + +def test_hstack(): + m = Matrix(4, 3, lambda i, j: i*3 + j) + m2 = Matrix(3, 4, lambda i, j: i*3 + j) + assert m == m.hstack(m) + assert m.hstack(m, m, m) == Matrix.hstack(m, m, m) == Matrix([ + [0, 1, 2, 0, 1, 2, 0, 1, 2], + [3, 4, 5, 3, 4, 5, 3, 4, 5], + [6, 7, 8, 6, 7, 8, 6, 7, 8], + [9, 10, 11, 9, 10, 11, 9, 10, 11]]) + raises(ShapeError, lambda: m.hstack(m, m2)) + assert Matrix.hstack() == Matrix() + + # test regression #12938 + M1 = Matrix.zeros(0, 0) + M2 = Matrix.zeros(0, 1) + M3 = Matrix.zeros(0, 2) + M4 = Matrix.zeros(0, 3) + m = Matrix.hstack(M1, M2, M3, M4) + assert m.rows == 0 and m.cols == 6 + + +def test_vstack(): + m = Matrix(4, 3, lambda i, j: i*3 + j) + m2 = Matrix(3, 4, lambda i, j: i*3 + j) + assert m == m.vstack(m) + assert m.vstack(m, m, m) == Matrix.vstack(m, m, m) == Matrix([ + [0, 1, 2], + [3, 4, 5], + [6, 7, 8], + [9, 10, 11], + [0, 1, 2], + [3, 4, 5], + [6, 7, 8], + [9, 10, 11], + [0, 1, 2], + [3, 4, 5], + [6, 7, 8], + [9, 10, 11]]) + raises(ShapeError, lambda: m.vstack(m, m2)) + assert Matrix.vstack() == Matrix() + + +def test_has(): + A = Matrix(((x, y), (2, 3))) + assert A.has(x) + assert not A.has(z) + assert A.has(Symbol) + + A = Matrix(((2, y), (2, 3))) + assert not A.has(x) + + +def test_is_anti_symmetric(): + x = symbols('x') + assert Matrix(2, 1, [1, 2]).is_anti_symmetric() is False + m = Matrix(3, 3, [0, x**2 + 2*x + 1, y, -(x + 1)**2, 0, x*y, -y, -x*y, 0]) + assert m.is_anti_symmetric() is True + assert m.is_anti_symmetric(simplify=False) is None + assert m.is_anti_symmetric(simplify=lambda x: x) is None + + m = Matrix(3, 3, [x.expand() for x in m]) + assert m.is_anti_symmetric(simplify=False) is True + m = Matrix(3, 3, [x.expand() for x in [S.One] + list(m)[1:]]) + assert m.is_anti_symmetric() is False + + +def test_is_hermitian(): + a = Matrix([[1, I], [-I, 1]]) + assert a.is_hermitian + a = Matrix([[2*I, I], [-I, 1]]) + assert a.is_hermitian is False + a = Matrix([[x, I], [-I, 1]]) + assert a.is_hermitian is None + a = Matrix([[x, 1], [-I, 1]]) + assert a.is_hermitian is False + + +def test_is_symbolic(): + a = Matrix([[x, x], [x, x]]) + assert a.is_symbolic() is True + a = Matrix([[1, 2, 3, 4], [5, 6, 7, 8]]) + assert a.is_symbolic() is False + a = Matrix([[1, 2, 3, 4], [5, 6, x, 8]]) + assert a.is_symbolic() is True + a = Matrix([[1, x, 3]]) + assert a.is_symbolic() is True + a = Matrix([[1, 2, 3]]) + assert a.is_symbolic() is False + a = Matrix([[1], [x], [3]]) + assert a.is_symbolic() is True + a = Matrix([[1], [2], [3]]) + assert a.is_symbolic() is False + + +def test_is_square(): + m = Matrix([[1], [1]]) + m2 = Matrix([[2, 2], [2, 2]]) + assert not m.is_square + assert m2.is_square + + +def test_is_symmetric(): + m = Matrix(2, 2, [0, 1, 1, 0]) + assert m.is_symmetric() + m = Matrix(2, 2, [0, 1, 0, 1]) + assert not m.is_symmetric() + + +def test_is_hessenberg(): + A = Matrix([[3, 4, 1], [2, 4, 5], [0, 1, 2]]) + assert A.is_upper_hessenberg + A = Matrix(3, 3, [3, 2, 0, 4, 4, 1, 1, 5, 2]) + assert A.is_lower_hessenberg + A = Matrix(3, 3, [3, 2, -1, 4, 4, 1, 1, 5, 2]) + assert A.is_lower_hessenberg is False + assert A.is_upper_hessenberg is False + + A = Matrix([[3, 4, 1], [2, 4, 5], [3, 1, 2]]) + assert not A.is_upper_hessenberg + + +def test_values(): + assert set(Matrix(2, 2, [0, 1, 2, 3] + ).values()) == {1, 2, 3} + x = Symbol('x', real=True) + assert set(Matrix(2, 2, [x, 0, 0, 1] + ).values()) == {x, 1} + + +def test_conjugate(): + M = Matrix([[0, I, 5], + [1, 2, 0]]) + + assert M.T == Matrix([[0, 1], + [I, 2], + [5, 0]]) + + assert M.C == Matrix([[0, -I, 5], + [1, 2, 0]]) + assert M.C == M.conjugate() + + assert M.H == M.T.C + assert M.H == Matrix([[ 0, 1], + [-I, 2], + [ 5, 0]]) + + +def test_doit(): + a = Matrix([[Add(x, x, evaluate=False)]]) + assert a[0] != 2*x + assert a.doit() == Matrix([[2*x]]) + + +def test_evalf(): + a = Matrix(2, 1, [sqrt(5), 6]) + assert all(a.evalf()[i] == a[i].evalf() for i in range(2)) + assert all(a.evalf(2)[i] == a[i].evalf(2) for i in range(2)) + assert all(a.n(2)[i] == a[i].n(2) for i in range(2)) + + +def test_replace(): + F, G = symbols('F, G', cls=Function) + K = Matrix(2, 2, lambda i, j: G(i+j)) + M = Matrix(2, 2, lambda i, j: F(i+j)) + N = M.replace(F, G) + assert N == K + + +def test_replace_map(): + F, G = symbols('F, G', cls=Function) + M = Matrix(2, 2, lambda i, j: F(i+j)) + N, d = M.replace(F, G, True) + assert N == Matrix(2, 2, lambda i, j: G(i+j)) + assert d == {F(0): G(0), F(1): G(1), F(2): G(2)} + +def test_numpy_conversion(): + try: + from numpy import array, array_equal + except ImportError: + skip('NumPy must be available to test creating matrices from ndarrays') + A = Matrix([[1,2], [3,4]]) + np_array = array([[1,2], [3,4]]) + assert array_equal(array(A), np_array) + assert array_equal(array(A, copy=True), np_array) + if(int(version('numpy').split('.')[0]) >= 2): #run this test only if numpy is new enough that copy variable is passed properly. + raises(TypeError, lambda: array(A, copy=False)) + +def test_rot90(): + A = Matrix([[1, 2], [3, 4]]) + assert A == A.rot90(0) == A.rot90(4) + assert A.rot90(2) == A.rot90(-2) == A.rot90(6) == Matrix(((4, 3), (2, 1))) + assert A.rot90(3) == A.rot90(-1) == A.rot90(7) == Matrix(((2, 4), (1, 3))) + assert A.rot90() == A.rot90(-7) == A.rot90(-3) == Matrix(((3, 1), (4, 2))) + + +def test_subs(): + assert Matrix([[1, x], [x, 4]]).subs(x, 5) == Matrix([[1, 5], [5, 4]]) + assert Matrix([[x, 2], [x + y, 4]]).subs([[x, -1], [y, -2]]) == \ + Matrix([[-1, 2], [-3, 4]]) + assert Matrix([[x, 2], [x + y, 4]]).subs([(x, -1), (y, -2)]) == \ + Matrix([[-1, 2], [-3, 4]]) + assert Matrix([[x, 2], [x + y, 4]]).subs({x: -1, y: -2}) == \ + Matrix([[-1, 2], [-3, 4]]) + assert Matrix([[x*y]]).subs({x: y - 1, y: x - 1}, simultaneous=True) == \ + Matrix([[(x - 1)*(y - 1)]]) + + +def test_permute(): + a = Matrix(3, 4, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]) + + raises(IndexError, lambda: a.permute([[0, 5]])) + raises(ValueError, lambda: a.permute(Symbol('x'))) + b = a.permute_rows([[0, 2], [0, 1]]) + assert a.permute([[0, 2], [0, 1]]) == b == Matrix([ + [5, 6, 7, 8], + [9, 10, 11, 12], + [1, 2, 3, 4]]) + + b = a.permute_cols([[0, 2], [0, 1]]) + assert a.permute([[0, 2], [0, 1]], orientation='cols') == b ==\ + Matrix([ + [ 2, 3, 1, 4], + [ 6, 7, 5, 8], + [10, 11, 9, 12]]) + + b = a.permute_cols([[0, 2], [0, 1]], direction='backward') + assert a.permute([[0, 2], [0, 1]], orientation='cols', direction='backward') == b ==\ + Matrix([ + [ 3, 1, 2, 4], + [ 7, 5, 6, 8], + [11, 9, 10, 12]]) + + assert a.permute([1, 2, 0, 3]) == Matrix([ + [5, 6, 7, 8], + [9, 10, 11, 12], + [1, 2, 3, 4]]) + + from sympy.combinatorics import Permutation + assert a.permute(Permutation([1, 2, 0, 3])) == Matrix([ + [5, 6, 7, 8], + [9, 10, 11, 12], + [1, 2, 3, 4]]) + +def test_upper_triangular(): + + A = Matrix([ + [1, 1, 1, 1], + [1, 1, 1, 1], + [1, 1, 1, 1], + [1, 1, 1, 1] + ]) + + R = A.upper_triangular(2) + assert R == Matrix([ + [0, 0, 1, 1], + [0, 0, 0, 1], + [0, 0, 0, 0], + [0, 0, 0, 0] + ]) + + R = A.upper_triangular(-2) + assert R == Matrix([ + [1, 1, 1, 1], + [1, 1, 1, 1], + [1, 1, 1, 1], + [0, 1, 1, 1] + ]) + + R = A.upper_triangular() + assert R == Matrix([ + [1, 1, 1, 1], + [0, 1, 1, 1], + [0, 0, 1, 1], + [0, 0, 0, 1] + ]) + + +def test_lower_triangular(): + A = Matrix([ + [1, 1, 1, 1], + [1, 1, 1, 1], + [1, 1, 1, 1], + [1, 1, 1, 1] + ]) + + L = A.lower_triangular() + assert L == Matrix([ + [1, 0, 0, 0], + [1, 1, 0, 0], + [1, 1, 1, 0], + [1, 1, 1, 1]]) + + L = A.lower_triangular(2) + assert L == Matrix([ + [1, 1, 1, 0], + [1, 1, 1, 1], + [1, 1, 1, 1], + [1, 1, 1, 1] + ]) + + L = A.lower_triangular(-2) + assert L == Matrix([ + [0, 0, 0, 0], + [0, 0, 0, 0], + [1, 0, 0, 0], + [1, 1, 0, 0] + ]) + + +def test_add(): + m = Matrix([[1, 2, 3], [x, y, x], [2*y, -50, z*x]]) + assert m + m == Matrix([[2, 4, 6], [2*x, 2*y, 2*x], [4*y, -100, 2*z*x]]) + n = Matrix(1, 2, [1, 2]) + raises(ShapeError, lambda: m + n) + + +def test_matmul(): + a = Matrix([[1, 2], [3, 4]]) + + assert a.__matmul__(2) == NotImplemented + + assert a.__rmatmul__(2) == NotImplemented + + #This is done this way because @ is only supported in Python 3.5+ + #To check 2@a case + try: + eval('2 @ a') + except SyntaxError: + pass + except TypeError: #TypeError is raised in case of NotImplemented is returned + pass + + #Check a@2 case + try: + eval('a @ 2') + except SyntaxError: + pass + except TypeError: #TypeError is raised in case of NotImplemented is returned + pass + + +def test_non_matmul(): + """ + Test that if explicitly specified as non-matrix, mul reverts + to scalar multiplication. + """ + class foo(Expr): + is_Matrix=False + is_MatrixLike=False + shape = (1, 1) + + A = Matrix([[1, 2], [3, 4]]) + b = foo() + assert b*A == Matrix([[b, 2*b], [3*b, 4*b]]) + assert A*b == Matrix([[b, 2*b], [3*b, 4*b]]) + + +def test_neg(): + n = Matrix(1, 2, [1, 2]) + assert -n == Matrix(1, 2, [-1, -2]) + + +def test_sub(): + n = Matrix(1, 2, [1, 2]) + assert n - n == Matrix(1, 2, [0, 0]) + + +def test_div(): + n = Matrix(1, 2, [1, 2]) + assert n/2 == Matrix(1, 2, [S.Half, S(2)/2]) + + +def test_eye(): + assert list(Matrix.eye(2, 2)) == [1, 0, 0, 1] + assert list(Matrix.eye(2)) == [1, 0, 0, 1] + assert type(Matrix.eye(2)) == Matrix + assert type(Matrix.eye(2, cls=Matrix)) == Matrix + + +def test_ones(): + assert list(Matrix.ones(2, 2)) == [1, 1, 1, 1] + assert list(Matrix.ones(2)) == [1, 1, 1, 1] + assert Matrix.ones(2, 3) == Matrix([[1, 1, 1], [1, 1, 1]]) + assert type(Matrix.ones(2)) == Matrix + assert type(Matrix.ones(2, cls=Matrix)) == Matrix + + +def test_zeros(): + assert list(Matrix.zeros(2, 2)) == [0, 0, 0, 0] + assert list(Matrix.zeros(2)) == [0, 0, 0, 0] + assert Matrix.zeros(2, 3) == Matrix([[0, 0, 0], [0, 0, 0]]) + assert type(Matrix.zeros(2)) == Matrix + assert type(Matrix.zeros(2, cls=Matrix)) == Matrix + + +def test_diag_make(): + diag = Matrix.diag + a = Matrix([[1, 2], [2, 3]]) + b = Matrix([[3, x], [y, 3]]) + c = Matrix([[3, x, 3], [y, 3, z], [x, y, z]]) + assert diag(a, b, b) == Matrix([ + [1, 2, 0, 0, 0, 0], + [2, 3, 0, 0, 0, 0], + [0, 0, 3, x, 0, 0], + [0, 0, y, 3, 0, 0], + [0, 0, 0, 0, 3, x], + [0, 0, 0, 0, y, 3], + ]) + assert diag(a, b, c) == Matrix([ + [1, 2, 0, 0, 0, 0, 0], + [2, 3, 0, 0, 0, 0, 0], + [0, 0, 3, x, 0, 0, 0], + [0, 0, y, 3, 0, 0, 0], + [0, 0, 0, 0, 3, x, 3], + [0, 0, 0, 0, y, 3, z], + [0, 0, 0, 0, x, y, z], + ]) + assert diag(a, c, b) == Matrix([ + [1, 2, 0, 0, 0, 0, 0], + [2, 3, 0, 0, 0, 0, 0], + [0, 0, 3, x, 3, 0, 0], + [0, 0, y, 3, z, 0, 0], + [0, 0, x, y, z, 0, 0], + [0, 0, 0, 0, 0, 3, x], + [0, 0, 0, 0, 0, y, 3], + ]) + a = Matrix([x, y, z]) + b = Matrix([[1, 2], [3, 4]]) + c = Matrix([[5, 6]]) + # this "wandering diagonal" is what makes this + # a block diagonal where each block is independent + # of the others + assert diag(a, 7, b, c) == Matrix([ + [x, 0, 0, 0, 0, 0], + [y, 0, 0, 0, 0, 0], + [z, 0, 0, 0, 0, 0], + [0, 7, 0, 0, 0, 0], + [0, 0, 1, 2, 0, 0], + [0, 0, 3, 4, 0, 0], + [0, 0, 0, 0, 5, 6]]) + raises(ValueError, lambda: diag(a, 7, b, c, rows=5)) + assert diag(1) == Matrix([[1]]) + assert diag(1, rows=2) == Matrix([[1, 0], [0, 0]]) + assert diag(1, cols=2) == Matrix([[1, 0], [0, 0]]) + assert diag(1, rows=3, cols=2) == Matrix([[1, 0], [0, 0], [0, 0]]) + assert diag(*[2, 3]) == Matrix([ + [2, 0], + [0, 3]]) + assert diag(Matrix([2, 3])) == Matrix([ + [2], + [3]]) + assert diag([1, [2, 3], 4], unpack=False) == \ + diag([[1], [2, 3], [4]], unpack=False) == Matrix([ + [1, 0], + [2, 3], + [4, 0]]) + assert type(diag(1)) == Matrix + assert type(diag(1, cls=Matrix)) == Matrix + assert Matrix.diag([1, 2, 3]) == Matrix.diag(1, 2, 3) + assert Matrix.diag([1, 2, 3], unpack=False).shape == (3, 1) + assert Matrix.diag([[1, 2, 3]]).shape == (3, 1) + assert Matrix.diag([[1, 2, 3]], unpack=False).shape == (1, 3) + assert Matrix.diag([[[1, 2, 3]]]).shape == (1, 3) + # kerning can be used to move the starting point + assert Matrix.diag(ones(0, 2), 1, 2) == Matrix([ + [0, 0, 1, 0], + [0, 0, 0, 2]]) + assert Matrix.diag(ones(2, 0), 1, 2) == Matrix([ + [0, 0], + [0, 0], + [1, 0], + [0, 2]]) + + +def test_diagonal(): + m = Matrix(3, 3, range(9)) + d = m.diagonal() + assert d == m.diagonal(0) + assert tuple(d) == (0, 4, 8) + assert tuple(m.diagonal(1)) == (1, 5) + assert tuple(m.diagonal(-1)) == (3, 7) + assert tuple(m.diagonal(2)) == (2,) + assert type(m.diagonal()) == type(m) + s = SparseMatrix(3, 3, {(1, 1): 1}) + assert type(s.diagonal()) == type(s) + assert type(m) != type(s) + raises(ValueError, lambda: m.diagonal(3)) + raises(ValueError, lambda: m.diagonal(-3)) + raises(ValueError, lambda: m.diagonal(pi)) + M = ones(2, 3) + assert banded({i: list(M.diagonal(i)) + for i in range(1-M.rows, M.cols)}) == M + + +def test_jordan_block(): + assert Matrix.jordan_block(3, 2) == Matrix.jordan_block(3, eigenvalue=2) \ + == Matrix.jordan_block(size=3, eigenvalue=2) \ + == Matrix.jordan_block(3, 2, band='upper') \ + == Matrix.jordan_block( + size=3, eigenval=2, eigenvalue=2) \ + == Matrix([ + [2, 1, 0], + [0, 2, 1], + [0, 0, 2]]) + + assert Matrix.jordan_block(3, 2, band='lower') == Matrix([ + [2, 0, 0], + [1, 2, 0], + [0, 1, 2]]) + # missing eigenvalue + raises(ValueError, lambda: Matrix.jordan_block(2)) + # non-integral size + raises(ValueError, lambda: Matrix.jordan_block(3.5, 2)) + # size not specified + raises(ValueError, lambda: Matrix.jordan_block(eigenvalue=2)) + # inconsistent eigenvalue + raises(ValueError, + lambda: Matrix.jordan_block( + eigenvalue=2, eigenval=4)) + + # Using alias keyword + assert Matrix.jordan_block(size=3, eigenvalue=2) == \ + Matrix.jordan_block(size=3, eigenval=2) + + +def test_orthogonalize(): + m = Matrix([[1, 2], [3, 4]]) + assert m.orthogonalize(Matrix([[2], [1]])) == [Matrix([[2], [1]])] + assert m.orthogonalize(Matrix([[2], [1]]), normalize=True) == \ + [Matrix([[2*sqrt(5)/5], [sqrt(5)/5]])] + assert m.orthogonalize(Matrix([[1], [2]]), Matrix([[-1], [4]])) == \ + [Matrix([[1], [2]]), Matrix([[Rational(-12, 5)], [Rational(6, 5)]])] + assert m.orthogonalize(Matrix([[0], [0]]), Matrix([[-1], [4]])) == \ + [Matrix([[-1], [4]])] + assert m.orthogonalize(Matrix([[0], [0]])) == [] + + n = Matrix([[9, 1, 9], [3, 6, 10], [8, 5, 2]]) + vecs = [Matrix([[-5], [1]]), Matrix([[-5], [2]]), Matrix([[-5], [-2]])] + assert n.orthogonalize(*vecs) == \ + [Matrix([[-5], [1]]), Matrix([[Rational(5, 26)], [Rational(25, 26)]])] + + vecs = [Matrix([0, 0, 0]), Matrix([1, 2, 3]), Matrix([1, 4, 5])] + raises(ValueError, lambda: Matrix.orthogonalize(*vecs, rankcheck=True)) + + vecs = [Matrix([1, 2, 3]), Matrix([4, 5, 6]), Matrix([7, 8, 9])] + raises(ValueError, lambda: Matrix.orthogonalize(*vecs, rankcheck=True)) + +def test_wilkinson(): + + wminus, wplus = Matrix.wilkinson(1) + assert wminus == Matrix([ + [-1, 1, 0], + [1, 0, 1], + [0, 1, 1]]) + assert wplus == Matrix([ + [1, 1, 0], + [1, 0, 1], + [0, 1, 1]]) + + wminus, wplus = Matrix.wilkinson(3) + assert wminus == Matrix([ + [-3, 1, 0, 0, 0, 0, 0], + [1, -2, 1, 0, 0, 0, 0], + [0, 1, -1, 1, 0, 0, 0], + [0, 0, 1, 0, 1, 0, 0], + [0, 0, 0, 1, 1, 1, 0], + [0, 0, 0, 0, 1, 2, 1], + + [0, 0, 0, 0, 0, 1, 3]]) + + assert wplus == Matrix([ + [3, 1, 0, 0, 0, 0, 0], + [1, 2, 1, 0, 0, 0, 0], + [0, 1, 1, 1, 0, 0, 0], + [0, 0, 1, 0, 1, 0, 0], + [0, 0, 0, 1, 1, 1, 0], + [0, 0, 0, 0, 1, 2, 1], + [0, 0, 0, 0, 0, 1, 3]]) + + +def test_limit(): + x, y = symbols('x y') + m = Matrix(2, 1, [1/x, y]) + assert m.limit(x, 5) == Matrix(2, 1, [Rational(1, 5), y]) + A = Matrix(((1, 4, sin(x)/x), (y, 2, 4), (10, 5, x**2 + 1))) + assert A.limit(x, 0) == Matrix(((1, 4, 1), (y, 2, 4), (10, 5, 1))) + + +def test_issue_13774(): + M = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + v = [1, 1, 1] + raises(TypeError, lambda: M*v) + raises(TypeError, lambda: v*M) + + +def test_companion(): + x = Symbol('x') + y = Symbol('y') + raises(ValueError, lambda: Matrix.companion(1)) + raises(ValueError, lambda: Matrix.companion(Poly([1], x))) + raises(ValueError, lambda: Matrix.companion(Poly([2, 1], x))) + raises(ValueError, lambda: Matrix.companion(Poly(x*y, [x, y]))) + + c0, c1, c2 = symbols('c0:3') + assert Matrix.companion(Poly([1, c0], x)) == Matrix([-c0]) + assert Matrix.companion(Poly([1, c1, c0], x)) == \ + Matrix([[0, -c0], [1, -c1]]) + assert Matrix.companion(Poly([1, c2, c1, c0], x)) == \ + Matrix([[0, 0, -c0], [1, 0, -c1], [0, 1, -c2]]) + + +def test_issue_10589(): + x, y, z = symbols("x, y z") + M1 = Matrix([x, y, z]) + M1 = M1.subs(zip([x, y, z], [1, 2, 3])) + assert M1 == Matrix([[1], [2], [3]]) + + M2 = Matrix([[x, x, x, x, x], [x, x, x, x, x], [x, x, x, x, x]]) + M2 = M2.subs(zip([x], [1])) + assert M2 == Matrix([[1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1]]) + + +def test_rmul_pr19860(): + class Foo(ImmutableDenseMatrix): + _op_priority = MutableDenseMatrix._op_priority + 0.01 + + a = Matrix(2, 2, [1, 2, 3, 4]) + b = Foo(2, 2, [1, 2, 3, 4]) + + # This would throw a RecursionError: maximum recursion depth + # since b always has higher priority even after a.as_mutable() + c = a*b + + assert isinstance(c, Foo) + assert c == Matrix([[7, 10], [15, 22]]) + + +def test_issue_18956(): + A = Array([[1, 2], [3, 4]]) + B = Matrix([[1,2],[3,4]]) + raises(TypeError, lambda: B + A) + raises(TypeError, lambda: A + B) + + +def test__eq__(): + class My(object): + def __iter__(self): + yield 1 + yield 2 + return + def __getitem__(self, i): + return list(self)[i] + a = Matrix(2, 1, [1, 2]) + assert a != My() + class My_sympy(My): + def _sympy_(self): + return Matrix(self) + assert a == My_sympy() + + +def test_args(): + for n, cls in enumerate(all_classes): + m = cls.zeros(3, 2) + # all should give back the same type of arguments, e.g. ints for shape + assert m.shape == (3, 2) and all(type(i) is int for i in m.shape) + assert m.rows == 3 and type(m.rows) is int + assert m.cols == 2 and type(m.cols) is int + if not n % 2: + assert type(m.flat()) in (list, tuple, Tuple) + else: + assert type(m.todok()) is dict + + +def test_deprecated_mat_smat(): + for cls in Matrix, ImmutableMatrix: + m = cls.zeros(3, 2) + with warns_deprecated_sympy(): + mat = m._mat + assert mat == m.flat() + for cls in SparseMatrix, ImmutableSparseMatrix: + m = cls.zeros(3, 2) + with warns_deprecated_sympy(): + smat = m._smat + assert smat == m.todok() + + +def test_division(): + v = Matrix(1, 2, [x, y]) + assert v/z == Matrix(1, 2, [x/z, y/z]) + + +def test_sum(): + m = Matrix([[1, 2, 3], [x, y, x], [2*y, -50, z*x]]) + assert m + m == Matrix([[2, 4, 6], [2*x, 2*y, 2*x], [4*y, -100, 2*z*x]]) + n = Matrix(1, 2, [1, 2]) + raises(ShapeError, lambda: m + n) + + +def test_abs(): + m = Matrix([[1, -2], [x, y]]) + assert abs(m) == Matrix([[1, 2], [Abs(x), Abs(y)]]) + m = Matrix(1, 2, [-3, x]) + n = Matrix(1, 2, [3, Abs(x)]) + assert abs(m) == n + + +def test_addition(): + a = Matrix(( + (1, 2), + (3, 1), + )) + + b = Matrix(( + (1, 2), + (3, 0), + )) + + assert a + b == a.add(b) == Matrix([[2, 4], [6, 1]]) + + +def test_fancy_index_matrix(): + for M in (Matrix, SparseMatrix): + a = M(3, 3, range(9)) + assert a == a[:, :] + assert a[1, :] == Matrix(1, 3, [3, 4, 5]) + assert a[:, 1] == Matrix([1, 4, 7]) + assert a[[0, 1], :] == Matrix([[0, 1, 2], [3, 4, 5]]) + assert a[[0, 1], 2] == a[[0, 1], [2]] + assert a[2, [0, 1]] == a[[2], [0, 1]] + assert a[:, [0, 1]] == Matrix([[0, 1], [3, 4], [6, 7]]) + assert a[0, 0] == 0 + assert a[0:2, :] == Matrix([[0, 1, 2], [3, 4, 5]]) + assert a[:, 0:2] == Matrix([[0, 1], [3, 4], [6, 7]]) + assert a[::2, 1] == a[[0, 2], 1] + assert a[1, ::2] == a[1, [0, 2]] + a = M(3, 3, range(9)) + assert a[[0, 2, 1, 2, 1], :] == Matrix([ + [0, 1, 2], + [6, 7, 8], + [3, 4, 5], + [6, 7, 8], + [3, 4, 5]]) + assert a[:, [0,2,1,2,1]] == Matrix([ + [0, 2, 1, 2, 1], + [3, 5, 4, 5, 4], + [6, 8, 7, 8, 7]]) + + a = SparseMatrix.zeros(3) + a[1, 2] = 2 + a[0, 1] = 3 + a[2, 0] = 4 + assert a.extract([1, 1], [2]) == Matrix([ + [2], + [2]]) + assert a.extract([1, 0], [2, 2, 2]) == Matrix([ + [2, 2, 2], + [0, 0, 0]]) + assert a.extract([1, 0, 1, 2], [2, 0, 1, 0]) == Matrix([ + [2, 0, 0, 0], + [0, 0, 3, 0], + [2, 0, 0, 0], + [0, 4, 0, 4]]) + + +def test_multiplication(): + a = Matrix(( + (1, 2), + (3, 1), + (0, 6), + )) + + b = Matrix(( + (1, 2), + (3, 0), + )) + + raises(ShapeError, lambda: b*a) + raises(TypeError, lambda: a*{}) + + c = a*b + assert c[0, 0] == 7 + assert c[0, 1] == 2 + assert c[1, 0] == 6 + assert c[1, 1] == 6 + assert c[2, 0] == 18 + assert c[2, 1] == 0 + + c = a @ b + assert c[0, 0] == 7 + assert c[0, 1] == 2 + assert c[1, 0] == 6 + assert c[1, 1] == 6 + assert c[2, 0] == 18 + assert c[2, 1] == 0 + + h = matrix_multiply_elementwise(a, c) + assert h == a.multiply_elementwise(c) + assert h[0, 0] == 7 + assert h[0, 1] == 4 + assert h[1, 0] == 18 + assert h[1, 1] == 6 + assert h[2, 0] == 0 + assert h[2, 1] == 0 + raises(ShapeError, lambda: matrix_multiply_elementwise(a, b)) + + c = b * Symbol("x") + assert isinstance(c, Matrix) + assert c[0, 0] == x + assert c[0, 1] == 2*x + assert c[1, 0] == 3*x + assert c[1, 1] == 0 + + c2 = x * b + assert c == c2 + + c = 5 * b + assert isinstance(c, Matrix) + assert c[0, 0] == 5 + assert c[0, 1] == 2*5 + assert c[1, 0] == 3*5 + assert c[1, 1] == 0 + + M = Matrix([[oo, 0], [0, oo]]) + assert M ** 2 == M + + M = Matrix([[oo, oo], [0, 0]]) + assert M ** 2 == Matrix([[nan, nan], [nan, nan]]) + + # https://github.com/sympy/sympy/issues/22353 + A = Matrix(ones(3, 1)) + _h = -Rational(1, 2) + B = Matrix([_h, _h, _h]) + assert A.multiply_elementwise(B) == Matrix([ + [_h], + [_h], + [_h]]) + + +def test_power(): + raises(NonSquareMatrixError, lambda: Matrix((1, 2))**2) + + A = Matrix([[2, 3], [4, 5]]) + assert A**5 == Matrix([[6140, 8097], [10796, 14237]]) + A = Matrix([[2, 1, 3], [4, 2, 4], [6, 12, 1]]) + assert A**3 == Matrix([[290, 262, 251], [448, 440, 368], [702, 954, 433]]) + assert A**0 == eye(3) + assert A**1 == A + assert (Matrix([[2]]) ** 100)[0, 0] == 2**100 + assert Matrix([[1, 2], [3, 4]])**Integer(2) == Matrix([[7, 10], [15, 22]]) + A = Matrix([[1,2],[4,5]]) + assert A.pow(20, method='cayley') == A.pow(20, method='multiply') + assert A**Integer(2) == Matrix([[9, 12], [24, 33]]) + assert eye(2)**10000000 == eye(2) + + A = Matrix([[33, 24], [48, 57]]) + assert (A**S.Half)[:] == [5, 2, 4, 7] + A = Matrix([[0, 4], [-1, 5]]) + assert (A**S.Half)**2 == A + + assert Matrix([[1, 0], [1, 1]])**S.Half == Matrix([[1, 0], [S.Half, 1]]) + assert Matrix([[1, 0], [1, 1]])**0.5 == Matrix([[1, 0], [0.5, 1]]) + from sympy.abc import n + assert Matrix([[1, a], [0, 1]])**n == Matrix([[1, a*n], [0, 1]]) + assert Matrix([[b, a], [0, b]])**n == Matrix([[b**n, a*b**(n-1)*n], [0, b**n]]) + assert Matrix([ + [a**n, a**(n - 1)*n, (a**n*n**2 - a**n*n)/(2*a**2)], + [ 0, a**n, a**(n - 1)*n], + [ 0, 0, a**n]]) + assert Matrix([[a, 1, 0], [0, a, 0], [0, 0, b]])**n == Matrix([ + [a**n, a**(n-1)*n, 0], + [0, a**n, 0], + [0, 0, b**n]]) + + A = Matrix([[1, 0], [1, 7]]) + assert A._matrix_pow_by_jordan_blocks(S(3)) == A._eval_pow_by_recursion(3) + A = Matrix([[2]]) + assert A**10 == Matrix([[2**10]]) == A._matrix_pow_by_jordan_blocks(S(10)) == \ + A._eval_pow_by_recursion(10) + + # testing a matrix that cannot be jordan blocked issue 11766 + m = Matrix([[3, 0, 0, 0, -3], [0, -3, -3, 0, 3], [0, 3, 0, 3, 0], [0, 0, 3, 0, 3], [3, 0, 0, 3, 0]]) + raises(MatrixError, lambda: m._matrix_pow_by_jordan_blocks(S(10))) + + # test issue 11964 + raises(MatrixError, lambda: Matrix([[1, 1], [3, 3]])._matrix_pow_by_jordan_blocks(S(-10))) + A = Matrix([[0, 1, 0], [0, 0, 1], [0, 0, 0]]) # Nilpotent jordan block size 3 + assert A**10.0 == Matrix([[0, 0, 0], [0, 0, 0], [0, 0, 0]]) + raises(ValueError, lambda: A**2.1) + raises(ValueError, lambda: A**Rational(3, 2)) + A = Matrix([[8, 1], [3, 2]]) + assert A**10.0 == Matrix([[1760744107, 272388050], [817164150, 126415807]]) + A = Matrix([[0, 0, 1], [0, 0, 1], [0, 0, 1]]) # Nilpotent jordan block size 1 + assert A**10.0 == Matrix([[0, 0, 1], [0, 0, 1], [0, 0, 1]]) + A = Matrix([[0, 1, 0], [0, 0, 1], [0, 0, 1]]) # Nilpotent jordan block size 2 + assert A**10.0 == Matrix([[0, 0, 1], [0, 0, 1], [0, 0, 1]]) + n = Symbol('n', integer=True) + assert isinstance(A**n, MatPow) + n = Symbol('n', integer=True, negative=True) + raises(ValueError, lambda: A**n) + n = Symbol('n', integer=True, nonnegative=True) + assert A**n == Matrix([ + [KroneckerDelta(0, n), KroneckerDelta(1, n), -KroneckerDelta(0, n) - KroneckerDelta(1, n) + 1], + [ 0, KroneckerDelta(0, n), 1 - KroneckerDelta(0, n)], + [ 0, 0, 1]]) + assert A**(n + 2) == Matrix([[0, 0, 1], [0, 0, 1], [0, 0, 1]]) + raises(ValueError, lambda: A**Rational(3, 2)) + A = Matrix([[0, 0, 1], [3, 0, 1], [4, 3, 1]]) + assert A**5.0 == Matrix([[168, 72, 89], [291, 144, 161], [572, 267, 329]]) + assert A**5.0 == A**5 + A = Matrix([[0, 1, 0],[-1, 0, 0],[0, 0, 0]]) + n = Symbol("n") + An = A**n + assert An.subs(n, 2).doit() == A**2 + raises(ValueError, lambda: An.subs(n, -2).doit()) + assert An * An == A**(2*n) + + # concretizing behavior for non-integer and complex powers + A = Matrix([[0,0,0],[0,0,0],[0,0,0]]) + n = Symbol('n', integer=True, positive=True) + assert A**n == A + n = Symbol('n', integer=True, nonnegative=True) + assert A**n == diag(0**n, 0**n, 0**n) + assert (A**n).subs(n, 0) == eye(3) + assert (A**n).subs(n, 1) == zeros(3) + A = Matrix ([[2,0,0],[0,2,0],[0,0,2]]) + assert A**2.1 == diag (2**2.1, 2**2.1, 2**2.1) + assert A**I == diag (2**I, 2**I, 2**I) + A = Matrix([[0, 1, 0], [0, 0, 1], [0, 0, 1]]) + raises(ValueError, lambda: A**2.1) + raises(ValueError, lambda: A**I) + A = Matrix([[S.Half, S.Half], [S.Half, S.Half]]) + assert A**S.Half == A + A = Matrix([[1, 1],[3, 3]]) + assert A**S.Half == Matrix ([[S.Half, S.Half], [3*S.Half, 3*S.Half]]) + + +def test_issue_17247_expression_blowup_1(): + M = Matrix([[1+x, 1-x], [1-x, 1+x]]) + with dotprodsimp(True): + assert M.exp().expand() == Matrix([ + [ (exp(2*x) + exp(2))/2, (-exp(2*x) + exp(2))/2], + [(-exp(2*x) + exp(2))/2, (exp(2*x) + exp(2))/2]]) + + +def test_issue_17247_expression_blowup_2(): + M = Matrix([[1+x, 1-x], [1-x, 1+x]]) + with dotprodsimp(True): + P, J = M.jordan_form () + assert P*J*P.inv() + + +def test_issue_17247_expression_blowup_3(): + M = Matrix([[1+x, 1-x], [1-x, 1+x]]) + with dotprodsimp(True): + assert M**100 == Matrix([ + [633825300114114700748351602688*x**100 + 633825300114114700748351602688, 633825300114114700748351602688 - 633825300114114700748351602688*x**100], + [633825300114114700748351602688 - 633825300114114700748351602688*x**100, 633825300114114700748351602688*x**100 + 633825300114114700748351602688]]) + + +def test_issue_17247_expression_blowup_4(): +# This matrix takes extremely long on current master even with intermediate simplification so an abbreviated version is used. It is left here for test in case of future optimizations. +# M = Matrix(S('''[ +# [ -3/4, 45/32 - 37*I/16, 1/4 + I/2, -129/64 - 9*I/64, 1/4 - 5*I/16, 65/128 + 87*I/64, -9/32 - I/16, 183/256 - 97*I/128, 3/64 + 13*I/64, -23/32 - 59*I/256, 15/128 - 3*I/32, 19/256 + 551*I/1024], +# [-149/64 + 49*I/32, -177/128 - 1369*I/128, 125/64 + 87*I/64, -2063/256 + 541*I/128, 85/256 - 33*I/16, 805/128 + 2415*I/512, -219/128 + 115*I/256, 6301/4096 - 6609*I/1024, 119/128 + 143*I/128, -10879/2048 + 4343*I/4096, 129/256 - 549*I/512, 42533/16384 + 29103*I/8192], +# [ 1/2 - I, 9/4 + 55*I/16, -3/4, 45/32 - 37*I/16, 1/4 + I/2, -129/64 - 9*I/64, 1/4 - 5*I/16, 65/128 + 87*I/64, -9/32 - I/16, 183/256 - 97*I/128, 3/64 + 13*I/64, -23/32 - 59*I/256], +# [ -5/8 - 39*I/16, 2473/256 + 137*I/64, -149/64 + 49*I/32, -177/128 - 1369*I/128, 125/64 + 87*I/64, -2063/256 + 541*I/128, 85/256 - 33*I/16, 805/128 + 2415*I/512, -219/128 + 115*I/256, 6301/4096 - 6609*I/1024, 119/128 + 143*I/128, -10879/2048 + 4343*I/4096], +# [ 1 + I, -19/4 + 5*I/4, 1/2 - I, 9/4 + 55*I/16, -3/4, 45/32 - 37*I/16, 1/4 + I/2, -129/64 - 9*I/64, 1/4 - 5*I/16, 65/128 + 87*I/64, -9/32 - I/16, 183/256 - 97*I/128], +# [ 21/8 + I, -537/64 + 143*I/16, -5/8 - 39*I/16, 2473/256 + 137*I/64, -149/64 + 49*I/32, -177/128 - 1369*I/128, 125/64 + 87*I/64, -2063/256 + 541*I/128, 85/256 - 33*I/16, 805/128 + 2415*I/512, -219/128 + 115*I/256, 6301/4096 - 6609*I/1024], +# [ -2, 17/4 - 13*I/2, 1 + I, -19/4 + 5*I/4, 1/2 - I, 9/4 + 55*I/16, -3/4, 45/32 - 37*I/16, 1/4 + I/2, -129/64 - 9*I/64, 1/4 - 5*I/16, 65/128 + 87*I/64], +# [ 1/4 + 13*I/4, -825/64 - 147*I/32, 21/8 + I, -537/64 + 143*I/16, -5/8 - 39*I/16, 2473/256 + 137*I/64, -149/64 + 49*I/32, -177/128 - 1369*I/128, 125/64 + 87*I/64, -2063/256 + 541*I/128, 85/256 - 33*I/16, 805/128 + 2415*I/512], +# [ -4*I, 27/2 + 6*I, -2, 17/4 - 13*I/2, 1 + I, -19/4 + 5*I/4, 1/2 - I, 9/4 + 55*I/16, -3/4, 45/32 - 37*I/16, 1/4 + I/2, -129/64 - 9*I/64], +# [ 1/4 + 5*I/2, -23/8 - 57*I/16, 1/4 + 13*I/4, -825/64 - 147*I/32, 21/8 + I, -537/64 + 143*I/16, -5/8 - 39*I/16, 2473/256 + 137*I/64, -149/64 + 49*I/32, -177/128 - 1369*I/128, 125/64 + 87*I/64, -2063/256 + 541*I/128], +# [ -4, 9 - 5*I, -4*I, 27/2 + 6*I, -2, 17/4 - 13*I/2, 1 + I, -19/4 + 5*I/4, 1/2 - I, 9/4 + 55*I/16, -3/4, 45/32 - 37*I/16], +# [ -2*I, 119/8 + 29*I/4, 1/4 + 5*I/2, -23/8 - 57*I/16, 1/4 + 13*I/4, -825/64 - 147*I/32, 21/8 + I, -537/64 + 143*I/16, -5/8 - 39*I/16, 2473/256 + 137*I/64, -149/64 + 49*I/32, -177/128 - 1369*I/128]]''')) +# assert M**10 == Matrix([ +# [ 7*(-221393644768594642173548179825793834595 - 1861633166167425978847110897013541127952*I)/9671406556917033397649408, 15*(31670992489131684885307005100073928751695 + 10329090958303458811115024718207404523808*I)/77371252455336267181195264, 7*(-3710978679372178839237291049477017392703 + 1377706064483132637295566581525806894169*I)/19342813113834066795298816, (9727707023582419994616144751727760051598 - 59261571067013123836477348473611225724433*I)/9671406556917033397649408, (31896723509506857062605551443641668183707 + 54643444538699269118869436271152084599580*I)/38685626227668133590597632, (-2024044860947539028275487595741003997397402 + 130959428791783397562960461903698670485863*I)/309485009821345068724781056, 3*(26190251453797590396533756519358368860907 - 27221191754180839338002754608545400941638*I)/77371252455336267181195264, (1154643595139959842768960128434994698330461 + 3385496216250226964322872072260446072295634*I)/618970019642690137449562112, 3*(-31849347263064464698310044805285774295286 - 11877437776464148281991240541742691164309*I)/77371252455336267181195264, (4661330392283532534549306589669150228040221 - 4171259766019818631067810706563064103956871*I)/1237940039285380274899124224, (9598353794289061833850770474812760144506 + 358027153990999990968244906482319780943983*I)/309485009821345068724781056, (-9755135335127734571547571921702373498554177 - 4837981372692695195747379349593041939686540*I)/2475880078570760549798248448], +# [(-379516731607474268954110071392894274962069 - 422272153179747548473724096872271700878296*I)/77371252455336267181195264, (41324748029613152354787280677832014263339501 - 12715121258662668420833935373453570749288074*I)/1237940039285380274899124224, (-339216903907423793947110742819264306542397 + 494174755147303922029979279454787373566517*I)/77371252455336267181195264, (-18121350839962855576667529908850640619878381 - 37413012454129786092962531597292531089199003*I)/1237940039285380274899124224, (2489661087330511608618880408199633556675926 + 1137821536550153872137379935240732287260863*I)/309485009821345068724781056, (-136644109701594123227587016790354220062972119 + 110130123468183660555391413889600443583585272*I)/4951760157141521099596496896, (1488043981274920070468141664150073426459593 - 9691968079933445130866371609614474474327650*I)/1237940039285380274899124224, 27*(4636797403026872518131756991410164760195942 + 3369103221138229204457272860484005850416533*I)/4951760157141521099596496896, (-8534279107365915284081669381642269800472363 + 2241118846262661434336333368511372725482742*I)/1237940039285380274899124224, (60923350128174260992536531692058086830950875 - 263673488093551053385865699805250505661590126*I)/9903520314283042199192993792, (18520943561240714459282253753348921824172569 + 24846649186468656345966986622110971925703604*I)/4951760157141521099596496896, (-232781130692604829085973604213529649638644431 + 35981505277760667933017117949103953338570617*I)/9903520314283042199192993792], +# [ (8742968295129404279528270438201520488950 + 3061473358639249112126847237482570858327*I)/4835703278458516698824704, (-245657313712011778432792959787098074935273 + 253113767861878869678042729088355086740856*I)/38685626227668133590597632, (1947031161734702327107371192008011621193 - 19462330079296259148177542369999791122762*I)/9671406556917033397649408, (552856485625209001527688949522750288619217 + 392928441196156725372494335248099016686580*I)/77371252455336267181195264, (-44542866621905323121630214897126343414629 + 3265340021421335059323962377647649632959*I)/19342813113834066795298816, (136272594005759723105646069956434264218730 - 330975364731707309489523680957584684763587*I)/38685626227668133590597632, (27392593965554149283318732469825168894401 + 75157071243800133880129376047131061115278*I)/38685626227668133590597632, 7*(-357821652913266734749960136017214096276154 - 45509144466378076475315751988405961498243*I)/309485009821345068724781056, (104485001373574280824835174390219397141149 - 99041000529599568255829489765415726168162*I)/77371252455336267181195264, (1198066993119982409323525798509037696321291 + 4249784165667887866939369628840569844519936*I)/618970019642690137449562112, (-114985392587849953209115599084503853611014 - 52510376847189529234864487459476242883449*I)/77371252455336267181195264, (6094620517051332877965959223269600650951573 - 4683469779240530439185019982269137976201163*I)/1237940039285380274899124224], +# [ (611292255597977285752123848828590587708323 - 216821743518546668382662964473055912169502*I)/77371252455336267181195264, (-1144023204575811464652692396337616594307487 + 12295317806312398617498029126807758490062855*I)/309485009821345068724781056, (-374093027769390002505693378578475235158281 - 573533923565898290299607461660384634333639*I)/77371252455336267181195264, (47405570632186659000138546955372796986832987 - 2837476058950808941605000274055970055096534*I)/1237940039285380274899124224, (-571573207393621076306216726219753090535121 + 533381457185823100878764749236639320783831*I)/77371252455336267181195264, (-7096548151856165056213543560958582513797519 - 24035731898756040059329175131592138642195366*I)/618970019642690137449562112, (2396762128833271142000266170154694033849225 + 1448501087375679588770230529017516492953051*I)/309485009821345068724781056, (-150609293845161968447166237242456473262037053 + 92581148080922977153207018003184520294188436*I)/4951760157141521099596496896, 5*(270278244730804315149356082977618054486347 - 1997830155222496880429743815321662710091562*I)/1237940039285380274899124224, (62978424789588828258068912690172109324360330 + 44803641177219298311493356929537007630129097*I)/2475880078570760549798248448, 19*(-451431106327656743945775812536216598712236 + 114924966793632084379437683991151177407937*I)/1237940039285380274899124224, (63417747628891221594106738815256002143915995 - 261508229397507037136324178612212080871150958*I)/9903520314283042199192993792], +# [ (-2144231934021288786200752920446633703357 + 2305614436009705803670842248131563850246*I)/1208925819614629174706176, (-90720949337459896266067589013987007078153 - 221951119475096403601562347412753844534569*I)/19342813113834066795298816, (11590973613116630788176337262688659880376 + 6514520676308992726483494976339330626159*I)/4835703278458516698824704, 3*(-131776217149000326618649542018343107657237 + 79095042939612668486212006406818285287004*I)/38685626227668133590597632, (10100577916793945997239221374025741184951 - 28631383488085522003281589065994018550748*I)/9671406556917033397649408, 67*(10090295594251078955008130473573667572549 + 10449901522697161049513326446427839676762*I)/77371252455336267181195264, (-54270981296988368730689531355811033930513 - 3413683117592637309471893510944045467443*I)/19342813113834066795298816, (440372322928679910536575560069973699181278 - 736603803202303189048085196176918214409081*I)/77371252455336267181195264, (33220374714789391132887731139763250155295 + 92055083048787219934030779066298919603554*I)/38685626227668133590597632, 5*(-594638554579967244348856981610805281527116 - 82309245323128933521987392165716076704057*I)/309485009821345068724781056, (128056368815300084550013708313312073721955 - 114619107488668120303579745393765245911404*I)/77371252455336267181195264, 21*(59839959255173222962789517794121843393573 + 241507883613676387255359616163487405826334*I)/618970019642690137449562112], +# [ (-13454485022325376674626653802541391955147 + 184471402121905621396582628515905949793486*I)/19342813113834066795298816, (-6158730123400322562149780662133074862437105 - 3416173052604643794120262081623703514107476*I)/154742504910672534362390528, (770558003844914708453618983120686116100419 - 127758381209767638635199674005029818518766*I)/77371252455336267181195264, (-4693005771813492267479835161596671660631703 + 12703585094750991389845384539501921531449948*I)/309485009821345068724781056, (-295028157441149027913545676461260860036601 - 841544569970643160358138082317324743450770*I)/77371252455336267181195264, (56716442796929448856312202561538574275502893 + 7216818824772560379753073185990186711454778*I)/1237940039285380274899124224, 15*(-87061038932753366532685677510172566368387 + 61306141156647596310941396434445461895538*I)/154742504910672534362390528, (-3455315109680781412178133042301025723909347 - 24969329563196972466388460746447646686670670*I)/618970019642690137449562112, (2453418854160886481106557323699250865361849 + 1497886802326243014471854112161398141242514*I)/309485009821345068724781056, (-151343224544252091980004429001205664193082173 + 90471883264187337053549090899816228846836628*I)/4951760157141521099596496896, (1652018205533026103358164026239417416432989 - 9959733619236515024261775397109724431400162*I)/1237940039285380274899124224, 3*(40676374242956907656984876692623172736522006 + 31023357083037817469535762230872667581366205*I)/4951760157141521099596496896], +# [ (-1226990509403328460274658603410696548387 - 4131739423109992672186585941938392788458*I)/1208925819614629174706176, (162392818524418973411975140074368079662703 + 23706194236915374831230612374344230400704*I)/9671406556917033397649408, (-3935678233089814180000602553655565621193 + 2283744757287145199688061892165659502483*I)/1208925819614629174706176, (-2400210250844254483454290806930306285131 - 315571356806370996069052930302295432758205*I)/19342813113834066795298816, (13365917938215281056563183751673390817910 + 15911483133819801118348625831132324863881*I)/4835703278458516698824704, 3*(-215950551370668982657516660700301003897855 + 51684341999223632631602864028309400489378*I)/38685626227668133590597632, (20886089946811765149439844691320027184765 - 30806277083146786592790625980769214361844*I)/9671406556917033397649408, (562180634592713285745940856221105667874855 + 1031543963988260765153550559766662245114916*I)/77371252455336267181195264, (-65820625814810177122941758625652476012867 - 12429918324787060890804395323920477537595*I)/19342813113834066795298816, (319147848192012911298771180196635859221089 - 402403304933906769233365689834404519960394*I)/38685626227668133590597632, (23035615120921026080284733394359587955057 + 115351677687031786114651452775242461310624*I)/38685626227668133590597632, (-3426830634881892756966440108592579264936130 - 1022954961164128745603407283836365128598559*I)/309485009821345068724781056], +# [ (-192574788060137531023716449082856117537757 - 69222967328876859586831013062387845780692*I)/19342813113834066795298816, (2736383768828013152914815341491629299773262 - 2773252698016291897599353862072533475408743*I)/77371252455336267181195264, (-23280005281223837717773057436155921656805 + 214784953368021840006305033048142888879224*I)/19342813113834066795298816, (-3035247484028969580570400133318947903462326 - 2195168903335435855621328554626336958674325*I)/77371252455336267181195264, (984552428291526892214541708637840971548653 - 64006622534521425620714598573494988589378*I)/77371252455336267181195264, (-3070650452470333005276715136041262898509903 + 7286424705750810474140953092161794621989080*I)/154742504910672534362390528, (-147848877109756404594659513386972921139270 - 416306113044186424749331418059456047650861*I)/38685626227668133590597632, (55272118474097814260289392337160619494260781 + 7494019668394781211907115583302403519488058*I)/1237940039285380274899124224, (-581537886583682322424771088996959213068864 + 542191617758465339135308203815256798407429*I)/77371252455336267181195264, (-6422548983676355789975736799494791970390991 - 23524183982209004826464749309156698827737702*I)/618970019642690137449562112, 7*(180747195387024536886923192475064903482083 + 84352527693562434817771649853047924991804*I)/154742504910672534362390528, (-135485179036717001055310712747643466592387031 + 102346575226653028836678855697782273460527608*I)/4951760157141521099596496896], +# [ (3384238362616083147067025892852431152105 + 156724444932584900214919898954874618256*I)/604462909807314587353088, (-59558300950677430189587207338385764871866 + 114427143574375271097298201388331237478857*I)/4835703278458516698824704, (-1356835789870635633517710130971800616227 - 7023484098542340388800213478357340875410*I)/1208925819614629174706176, (234884918567993750975181728413524549575881 + 79757294640629983786895695752733890213506*I)/9671406556917033397649408, (-7632732774935120473359202657160313866419 + 2905452608512927560554702228553291839465*I)/1208925819614629174706176, (52291747908702842344842889809762246649489 - 520996778817151392090736149644507525892649*I)/19342813113834066795298816, (17472406829219127839967951180375981717322 + 23464704213841582137898905375041819568669*I)/4835703278458516698824704, (-911026971811893092350229536132730760943307 + 150799318130900944080399439626714846752360*I)/38685626227668133590597632, (26234457233977042811089020440646443590687 - 45650293039576452023692126463683727692890*I)/9671406556917033397649408, 3*(288348388717468992528382586652654351121357 + 454526517721403048270274049572136109264668*I)/77371252455336267181195264, (-91583492367747094223295011999405657956347 - 12704691128268298435362255538069612411331*I)/19342813113834066795298816, (411208730251327843849027957710164064354221 - 569898526380691606955496789378230959965898*I)/38685626227668133590597632], +# [ (27127513117071487872628354831658811211795 - 37765296987901990355760582016892124833857*I)/4835703278458516698824704, (1741779916057680444272938534338833170625435 + 3083041729779495966997526404685535449810378*I)/77371252455336267181195264, 3*(-60642236251815783728374561836962709533401 - 24630301165439580049891518846174101510744*I)/19342813113834066795298816, 3*(445885207364591681637745678755008757483408 - 350948497734812895032502179455610024541643*I)/38685626227668133590597632, (-47373295621391195484367368282471381775684 + 219122969294089357477027867028071400054973*I)/19342813113834066795298816, (-2801565819673198722993348253876353741520438 - 2250142129822658548391697042460298703335701*I)/77371252455336267181195264, (801448252275607253266997552356128790317119 - 50890367688077858227059515894356594900558*I)/77371252455336267181195264, (-5082187758525931944557763799137987573501207 + 11610432359082071866576699236013484487676124*I)/309485009821345068724781056, (-328925127096560623794883760398247685166830 - 643447969697471610060622160899409680422019*I)/77371252455336267181195264, 15*(2954944669454003684028194956846659916299765 + 33434406416888505837444969347824812608566*I)/1237940039285380274899124224, (-415749104352001509942256567958449835766827 + 479330966144175743357171151440020955412219*I)/77371252455336267181195264, 3*(-4639987285852134369449873547637372282914255 - 11994411888966030153196659207284951579243273*I)/1237940039285380274899124224], +# [ (-478846096206269117345024348666145495601 + 1249092488629201351470551186322814883283*I)/302231454903657293676544, (-17749319421930878799354766626365926894989 - 18264580106418628161818752318217357231971*I)/1208925819614629174706176, (2801110795431528876849623279389579072819 + 363258850073786330770713557775566973248*I)/604462909807314587353088, (-59053496693129013745775512127095650616252 + 78143588734197260279248498898321500167517*I)/4835703278458516698824704, (-283186724922498212468162690097101115349 - 6443437753863179883794497936345437398276*I)/1208925819614629174706176, (188799118826748909206887165661384998787543 + 84274736720556630026311383931055307398820*I)/9671406556917033397649408, (-5482217151670072904078758141270295025989 + 1818284338672191024475557065444481298568*I)/1208925819614629174706176, (56564463395350195513805521309731217952281 - 360208541416798112109946262159695452898431*I)/19342813113834066795298816, 11*(1259539805728870739006416869463689438068 + 1409136581547898074455004171305324917387*I)/4835703278458516698824704, 5*(-123701190701414554945251071190688818343325 + 30997157322590424677294553832111902279712*I)/38685626227668133590597632, (16130917381301373033736295883982414239781 - 32752041297570919727145380131926943374516*I)/9671406556917033397649408, (650301385108223834347093740500375498354925 + 899526407681131828596801223402866051809258*I)/77371252455336267181195264], +# [ (9011388245256140876590294262420614839483 + 8167917972423946282513000869327525382672*I)/1208925819614629174706176, (-426393174084720190126376382194036323028924 + 180692224825757525982858693158209545430621*I)/9671406556917033397649408, (24588556702197802674765733448108154175535 - 45091766022876486566421953254051868331066*I)/4835703278458516698824704, (1872113939365285277373877183750416985089691 + 3030392393733212574744122057679633775773130*I)/77371252455336267181195264, (-222173405538046189185754954524429864167549 - 75193157893478637039381059488387511299116*I)/19342813113834066795298816, (2670821320766222522963689317316937579844558 - 2645837121493554383087981511645435472169191*I)/77371252455336267181195264, 5*(-2100110309556476773796963197283876204940 + 41957457246479840487980315496957337371937*I)/19342813113834066795298816, (-5733743755499084165382383818991531258980593 - 3328949988392698205198574824396695027195732*I)/154742504910672534362390528, (707827994365259025461378911159398206329247 - 265730616623227695108042528694302299777294*I)/77371252455336267181195264, (-1442501604682933002895864804409322823788319 + 11504137805563265043376405214378288793343879*I)/309485009821345068724781056, (-56130472299445561499538726459719629522285 - 61117552419727805035810982426639329818864*I)/9671406556917033397649408, (39053692321126079849054272431599539429908717 - 10209127700342570953247177602860848130710666*I)/1237940039285380274899124224]]) + M = Matrix(S('''[ + [ -3/4, 45/32 - 37*I/16, 1/4 + I/2, -129/64 - 9*I/64, 1/4 - 5*I/16, 65/128 + 87*I/64], + [-149/64 + 49*I/32, -177/128 - 1369*I/128, 125/64 + 87*I/64, -2063/256 + 541*I/128, 85/256 - 33*I/16, 805/128 + 2415*I/512], + [ 1/2 - I, 9/4 + 55*I/16, -3/4, 45/32 - 37*I/16, 1/4 + I/2, -129/64 - 9*I/64], + [ -5/8 - 39*I/16, 2473/256 + 137*I/64, -149/64 + 49*I/32, -177/128 - 1369*I/128, 125/64 + 87*I/64, -2063/256 + 541*I/128], + [ 1 + I, -19/4 + 5*I/4, 1/2 - I, 9/4 + 55*I/16, -3/4, 45/32 - 37*I/16], + [ 21/8 + I, -537/64 + 143*I/16, -5/8 - 39*I/16, 2473/256 + 137*I/64, -149/64 + 49*I/32, -177/128 - 1369*I/128]]''')) + with dotprodsimp(True): + assert M**10 == Matrix(S('''[ + [ 7369525394972778926719607798014571861/604462909807314587353088 - 229284202061790301477392339912557559*I/151115727451828646838272, -19704281515163975949388435612632058035/1208925819614629174706176 + 14319858347987648723768698170712102887*I/302231454903657293676544, -3623281909451783042932142262164941211/604462909807314587353088 - 6039240602494288615094338643452320495*I/604462909807314587353088, 109260497799140408739847239685705357695/2417851639229258349412352 - 7427566006564572463236368211555511431*I/2417851639229258349412352, -16095803767674394244695716092817006641/2417851639229258349412352 + 10336681897356760057393429626719177583*I/1208925819614629174706176, -42207883340488041844332828574359769743/2417851639229258349412352 - 182332262671671273188016400290188468499*I/4835703278458516698824704], + [50566491050825573392726324995779608259/1208925819614629174706176 - 90047007594468146222002432884052362145*I/2417851639229258349412352, 74273703462900000967697427843983822011/1208925819614629174706176 + 265947522682943571171988741842776095421*I/1208925819614629174706176, -116900341394390200556829767923360888429/2417851639229258349412352 - 53153263356679268823910621474478756845*I/2417851639229258349412352, 195407378023867871243426523048612490249/1208925819614629174706176 - 1242417915995360200584837585002906728929*I/9671406556917033397649408, -863597594389821970177319682495878193/302231454903657293676544 + 476936100741548328800725360758734300481*I/9671406556917033397649408, -3154451590535653853562472176601754835575/19342813113834066795298816 - 232909875490506237386836489998407329215*I/2417851639229258349412352], + [ -1715444997702484578716037230949868543/302231454903657293676544 + 5009695651321306866158517287924120777*I/302231454903657293676544, -30551582497996879620371947949342101301/604462909807314587353088 - 7632518367986526187139161303331519629*I/151115727451828646838272, 312680739924495153190604170938220575/18889465931478580854784 - 108664334509328818765959789219208459*I/75557863725914323419136, -14693696966703036206178521686918865509/604462909807314587353088 + 72345386220900843930147151999899692401*I/1208925819614629174706176, -8218872496728882299722894680635296519/1208925819614629174706176 - 16776782833358893712645864791807664983*I/1208925819614629174706176, 143237839169380078671242929143670635137/2417851639229258349412352 + 2883817094806115974748882735218469447*I/2417851639229258349412352], + [ 3087979417831061365023111800749855987/151115727451828646838272 + 34441942370802869368851419102423997089*I/604462909807314587353088, -148309181940158040917731426845476175667/604462909807314587353088 - 263987151804109387844966835369350904919*I/9671406556917033397649408, 50259518594816377378747711930008883165/1208925819614629174706176 - 95713974916869240305450001443767979653*I/2417851639229258349412352, 153466447023875527996457943521467271119/2417851639229258349412352 + 517285524891117105834922278517084871349*I/2417851639229258349412352, -29184653615412989036678939366291205575/604462909807314587353088 - 27551322282526322041080173287022121083*I/1208925819614629174706176, 196404220110085511863671393922447671649/1208925819614629174706176 - 1204712019400186021982272049902206202145*I/9671406556917033397649408], + [ -2632581805949645784625606590600098779/151115727451828646838272 - 589957435912868015140272627522612771*I/37778931862957161709568, 26727850893953715274702844733506310247/302231454903657293676544 - 10825791956782128799168209600694020481*I/302231454903657293676544, -1036348763702366164044671908440791295/151115727451828646838272 + 3188624571414467767868303105288107375*I/151115727451828646838272, -36814959939970644875593411585393242449/604462909807314587353088 - 18457555789119782404850043842902832647*I/302231454903657293676544, 12454491297984637815063964572803058647/604462909807314587353088 - 340489532842249733975074349495329171*I/302231454903657293676544, -19547211751145597258386735573258916681/604462909807314587353088 + 87299583775782199663414539883938008933*I/1208925819614629174706176], + [ -40281994229560039213253423262678393183/604462909807314587353088 - 2939986850065527327299273003299736641*I/604462909807314587353088, 331940684638052085845743020267462794181/2417851639229258349412352 - 284574901963624403933361315517248458969*I/1208925819614629174706176, 6453843623051745485064693628073010961/302231454903657293676544 + 36062454107479732681350914931391590957*I/604462909807314587353088, -147665869053634695632880753646441962067/604462909807314587353088 - 305987938660447291246597544085345123927*I/9671406556917033397649408, 107821369195275772166593879711259469423/2417851639229258349412352 - 11645185518211204108659001435013326687*I/302231454903657293676544, 64121228424717666402009446088588091619/1208925819614629174706176 + 265557133337095047883844369272389762133*I/1208925819614629174706176]]''')) + + +def test_issue_17247_expression_blowup_5(): + M = Matrix(6, 6, lambda i, j: 1 + (-1)**(i+j)*I) + with dotprodsimp(True): + assert M.charpoly('x') == PurePoly(x**6 + (-6 - 6*I)*x**5 + 36*I*x**4, x, domain='EX') + + +def test_issue_17247_expression_blowup_6(): + M = Matrix(8, 8, [x+i for i in range (64)]) + with dotprodsimp(True): + assert M.det('bareiss') == 0 + + +def test_issue_17247_expression_blowup_7(): + M = Matrix(6, 6, lambda i, j: 1 + (-1)**(i+j)*I) + with dotprodsimp(True): + assert M.det('berkowitz') == 0 + + +def test_issue_17247_expression_blowup_8(): + M = Matrix(8, 8, [x+i for i in range (64)]) + with dotprodsimp(True): + assert M.det('lu') == 0 + + +def test_issue_17247_expression_blowup_9(): + M = Matrix(8, 8, [x+i for i in range (64)]) + with dotprodsimp(True): + assert M.rref() == (Matrix([ + [1, 0, -1, -2, -3, -4, -5, -6], + [0, 1, 2, 3, 4, 5, 6, 7], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0]]), (0, 1)) + + +def test_issue_17247_expression_blowup_10(): + M = Matrix(6, 6, lambda i, j: 1 + (-1)**(i+j)*I) + with dotprodsimp(True): + assert M.cofactor(0, 0) == 0 + + +def test_issue_17247_expression_blowup_11(): + M = Matrix(6, 6, lambda i, j: 1 + (-1)**(i+j)*I) + with dotprodsimp(True): + assert M.cofactor_matrix() == Matrix(6, 6, [0]*36) + + +def test_issue_17247_expression_blowup_12(): + M = Matrix(6, 6, lambda i, j: 1 + (-1)**(i+j)*I) + with dotprodsimp(True): + assert M.eigenvals() == {6: 1, 6*I: 1, 0: 4} + + +def test_issue_17247_expression_blowup_13(): + M = Matrix([ + [ 0, 1 - x, x + 1, 1 - x], + [1 - x, x + 1, 0, x + 1], + [ 0, 1 - x, x + 1, 1 - x], + [ 0, 0, 1 - x, 0]]) + + ev = M.eigenvects() + assert ev[0] == (0, 2, [Matrix([0, -1, 0, 1])]) + assert ev[1][0] == x - sqrt(2)*(x - 1) + 1 + assert ev[1][1] == 1 + assert ev[1][2][0].expand(deep=False, numer=True) == Matrix([ + [(-x + sqrt(2)*(x - 1) - 1)/(x - 1)], + [-4*x/(x**2 - 2*x + 1) + (x + 1)*(x - sqrt(2)*(x - 1) + 1)/(x**2 - 2*x + 1)], + [(-x + sqrt(2)*(x - 1) - 1)/(x - 1)], + [1] + ]) + + assert ev[2][0] == x + sqrt(2)*(x - 1) + 1 + assert ev[2][1] == 1 + assert ev[2][2][0].expand(deep=False, numer=True) == Matrix([ + [(-x - sqrt(2)*(x - 1) - 1)/(x - 1)], + [-4*x/(x**2 - 2*x + 1) + (x + 1)*(x + sqrt(2)*(x - 1) + 1)/(x**2 - 2*x + 1)], + [(-x - sqrt(2)*(x - 1) - 1)/(x - 1)], + [1] + ]) + + +def test_issue_17247_expression_blowup_14(): + M = Matrix(8, 8, ([1+x, 1-x]*4 + [1-x, 1+x]*4)*4) + with dotprodsimp(True): + assert M.echelon_form() == Matrix([ + [x + 1, 1 - x, x + 1, 1 - x, x + 1, 1 - x, x + 1, 1 - x], + [ 0, 4*x, 0, 4*x, 0, 4*x, 0, 4*x], + [ 0, 0, 0, 0, 0, 0, 0, 0], + [ 0, 0, 0, 0, 0, 0, 0, 0], + [ 0, 0, 0, 0, 0, 0, 0, 0], + [ 0, 0, 0, 0, 0, 0, 0, 0], + [ 0, 0, 0, 0, 0, 0, 0, 0], + [ 0, 0, 0, 0, 0, 0, 0, 0]]) + + +def test_issue_17247_expression_blowup_15(): + M = Matrix(8, 8, ([1+x, 1-x]*4 + [1-x, 1+x]*4)*4) + with dotprodsimp(True): + assert M.rowspace() == [Matrix([[x + 1, 1 - x, x + 1, 1 - x, x + 1, 1 - x, x + 1, 1 - x]]), Matrix([[0, 4*x, 0, 4*x, 0, 4*x, 0, 4*x]])] + + +def test_issue_17247_expression_blowup_16(): + M = Matrix(8, 8, ([1+x, 1-x]*4 + [1-x, 1+x]*4)*4) + with dotprodsimp(True): + assert M.columnspace() == [Matrix([[x + 1],[1 - x],[x + 1],[1 - x],[x + 1],[1 - x],[x + 1],[1 - x]]), Matrix([[1 - x],[x + 1],[1 - x],[x + 1],[1 - x],[x + 1],[1 - x],[x + 1]])] + + +def test_issue_17247_expression_blowup_17(): + M = Matrix(8, 8, [x+i for i in range (64)]) + with dotprodsimp(True): + assert M.nullspace() == [ + Matrix([[1],[-2],[1],[0],[0],[0],[0],[0]]), + Matrix([[2],[-3],[0],[1],[0],[0],[0],[0]]), + Matrix([[3],[-4],[0],[0],[1],[0],[0],[0]]), + Matrix([[4],[-5],[0],[0],[0],[1],[0],[0]]), + Matrix([[5],[-6],[0],[0],[0],[0],[1],[0]]), + Matrix([[6],[-7],[0],[0],[0],[0],[0],[1]])] + + +def test_issue_17247_expression_blowup_18(): + M = Matrix(6, 6, ([1+x, 1-x]*3 + [1-x, 1+x]*3)*3) + with dotprodsimp(True): + assert not M.is_nilpotent() + + +def test_issue_17247_expression_blowup_19(): + M = Matrix(S('''[ + [ -3/4, 0, 1/4 + I/2, 0], + [ 0, -177/128 - 1369*I/128, 0, -2063/256 + 541*I/128], + [ 1/2 - I, 0, 0, 0], + [ 0, 0, 0, -177/128 - 1369*I/128]]''')) + with dotprodsimp(True): + assert not M.is_diagonalizable() + + +def test_issue_17247_expression_blowup_20(): + M = Matrix([ + [x + 1, 1 - x, 0, 0], + [1 - x, x + 1, 0, x + 1], + [ 0, 1 - x, x + 1, 0], + [ 0, 0, 0, x + 1]]) + with dotprodsimp(True): + assert M.diagonalize() == (Matrix([ + [1, 1, 0, (x + 1)/(x - 1)], + [1, -1, 0, 0], + [1, 1, 1, 0], + [0, 0, 0, 1]]), + Matrix([ + [2, 0, 0, 0], + [0, 2*x, 0, 0], + [0, 0, x + 1, 0], + [0, 0, 0, x + 1]])) + + +def test_issue_17247_expression_blowup_21(): + M = Matrix(S('''[ + [ -3/4, 45/32 - 37*I/16, 0, 0], + [-149/64 + 49*I/32, -177/128 - 1369*I/128, 0, -2063/256 + 541*I/128], + [ 0, 9/4 + 55*I/16, 2473/256 + 137*I/64, 0], + [ 0, 0, 0, -177/128 - 1369*I/128]]''')) + with dotprodsimp(True): + assert M.inv(method='GE') == Matrix(S('''[ + [-26194832/3470993 - 31733264*I/3470993, 156352/3470993 + 10325632*I/3470993, 0, -7741283181072/3306971225785 + 2999007604624*I/3306971225785], + [4408224/3470993 - 9675328*I/3470993, -2422272/3470993 + 1523712*I/3470993, 0, -1824666489984/3306971225785 - 1401091949952*I/3306971225785], + [-26406945676288/22270005630769 + 10245925485056*I/22270005630769, 7453523312640/22270005630769 + 1601616519168*I/22270005630769, 633088/6416033 - 140288*I/6416033, 872209227109521408/21217636514687010905 + 6066405081802389504*I/21217636514687010905], + [0, 0, 0, -11328/952745 + 87616*I/952745]]''')) + + +def test_issue_17247_expression_blowup_22(): + M = Matrix(S('''[ + [ -3/4, 45/32 - 37*I/16, 0, 0], + [-149/64 + 49*I/32, -177/128 - 1369*I/128, 0, -2063/256 + 541*I/128], + [ 0, 9/4 + 55*I/16, 2473/256 + 137*I/64, 0], + [ 0, 0, 0, -177/128 - 1369*I/128]]''')) + with dotprodsimp(True): + assert M.inv(method='LU') == Matrix(S('''[ + [-26194832/3470993 - 31733264*I/3470993, 156352/3470993 + 10325632*I/3470993, 0, -7741283181072/3306971225785 + 2999007604624*I/3306971225785], + [4408224/3470993 - 9675328*I/3470993, -2422272/3470993 + 1523712*I/3470993, 0, -1824666489984/3306971225785 - 1401091949952*I/3306971225785], + [-26406945676288/22270005630769 + 10245925485056*I/22270005630769, 7453523312640/22270005630769 + 1601616519168*I/22270005630769, 633088/6416033 - 140288*I/6416033, 872209227109521408/21217636514687010905 + 6066405081802389504*I/21217636514687010905], + [0, 0, 0, -11328/952745 + 87616*I/952745]]''')) + + +def test_issue_17247_expression_blowup_23(): + M = Matrix(S('''[ + [ -3/4, 45/32 - 37*I/16, 0, 0], + [-149/64 + 49*I/32, -177/128 - 1369*I/128, 0, -2063/256 + 541*I/128], + [ 0, 9/4 + 55*I/16, 2473/256 + 137*I/64, 0], + [ 0, 0, 0, -177/128 - 1369*I/128]]''')) + with dotprodsimp(True): + assert M.inv(method='ADJ').expand() == Matrix(S('''[ + [-26194832/3470993 - 31733264*I/3470993, 156352/3470993 + 10325632*I/3470993, 0, -7741283181072/3306971225785 + 2999007604624*I/3306971225785], + [4408224/3470993 - 9675328*I/3470993, -2422272/3470993 + 1523712*I/3470993, 0, -1824666489984/3306971225785 - 1401091949952*I/3306971225785], + [-26406945676288/22270005630769 + 10245925485056*I/22270005630769, 7453523312640/22270005630769 + 1601616519168*I/22270005630769, 633088/6416033 - 140288*I/6416033, 872209227109521408/21217636514687010905 + 6066405081802389504*I/21217636514687010905], + [0, 0, 0, -11328/952745 + 87616*I/952745]]''')) + + +def test_issue_17247_expression_blowup_24(): + M = SparseMatrix(S('''[ + [ -3/4, 45/32 - 37*I/16, 0, 0], + [-149/64 + 49*I/32, -177/128 - 1369*I/128, 0, -2063/256 + 541*I/128], + [ 0, 9/4 + 55*I/16, 2473/256 + 137*I/64, 0], + [ 0, 0, 0, -177/128 - 1369*I/128]]''')) + with dotprodsimp(True): + assert M.inv(method='CH') == Matrix(S('''[ + [-26194832/3470993 - 31733264*I/3470993, 156352/3470993 + 10325632*I/3470993, 0, -7741283181072/3306971225785 + 2999007604624*I/3306971225785], + [4408224/3470993 - 9675328*I/3470993, -2422272/3470993 + 1523712*I/3470993, 0, -1824666489984/3306971225785 - 1401091949952*I/3306971225785], + [-26406945676288/22270005630769 + 10245925485056*I/22270005630769, 7453523312640/22270005630769 + 1601616519168*I/22270005630769, 633088/6416033 - 140288*I/6416033, 872209227109521408/21217636514687010905 + 6066405081802389504*I/21217636514687010905], + [0, 0, 0, -11328/952745 + 87616*I/952745]]''')) + + +def test_issue_17247_expression_blowup_25(): + M = SparseMatrix(S('''[ + [ -3/4, 45/32 - 37*I/16, 0, 0], + [-149/64 + 49*I/32, -177/128 - 1369*I/128, 0, -2063/256 + 541*I/128], + [ 0, 9/4 + 55*I/16, 2473/256 + 137*I/64, 0], + [ 0, 0, 0, -177/128 - 1369*I/128]]''')) + with dotprodsimp(True): + assert M.inv(method='LDL') == Matrix(S('''[ + [-26194832/3470993 - 31733264*I/3470993, 156352/3470993 + 10325632*I/3470993, 0, -7741283181072/3306971225785 + 2999007604624*I/3306971225785], + [4408224/3470993 - 9675328*I/3470993, -2422272/3470993 + 1523712*I/3470993, 0, -1824666489984/3306971225785 - 1401091949952*I/3306971225785], + [-26406945676288/22270005630769 + 10245925485056*I/22270005630769, 7453523312640/22270005630769 + 1601616519168*I/22270005630769, 633088/6416033 - 140288*I/6416033, 872209227109521408/21217636514687010905 + 6066405081802389504*I/21217636514687010905], + [0, 0, 0, -11328/952745 + 87616*I/952745]]''')) + + +def test_issue_17247_expression_blowup_26(): + M = Matrix(S('''[ + [ -3/4, 45/32 - 37*I/16, 1/4 + I/2, -129/64 - 9*I/64, 1/4 - 5*I/16, 65/128 + 87*I/64, -9/32 - I/16, 183/256 - 97*I/128], + [-149/64 + 49*I/32, -177/128 - 1369*I/128, 125/64 + 87*I/64, -2063/256 + 541*I/128, 85/256 - 33*I/16, 805/128 + 2415*I/512, -219/128 + 115*I/256, 6301/4096 - 6609*I/1024], + [ 1/2 - I, 9/4 + 55*I/16, -3/4, 45/32 - 37*I/16, 1/4 + I/2, -129/64 - 9*I/64, 1/4 - 5*I/16, 65/128 + 87*I/64], + [ -5/8 - 39*I/16, 2473/256 + 137*I/64, -149/64 + 49*I/32, -177/128 - 1369*I/128, 125/64 + 87*I/64, -2063/256 + 541*I/128, 85/256 - 33*I/16, 805/128 + 2415*I/512], + [ 1 + I, -19/4 + 5*I/4, 1/2 - I, 9/4 + 55*I/16, -3/4, 45/32 - 37*I/16, 1/4 + I/2, -129/64 - 9*I/64], + [ 21/8 + I, -537/64 + 143*I/16, -5/8 - 39*I/16, 2473/256 + 137*I/64, -149/64 + 49*I/32, -177/128 - 1369*I/128, 125/64 + 87*I/64, -2063/256 + 541*I/128], + [ -2, 17/4 - 13*I/2, 1 + I, -19/4 + 5*I/4, 1/2 - I, 9/4 + 55*I/16, -3/4, 45/32 - 37*I/16], + [ 1/4 + 13*I/4, -825/64 - 147*I/32, 21/8 + I, -537/64 + 143*I/16, -5/8 - 39*I/16, 2473/256 + 137*I/64, -149/64 + 49*I/32, -177/128 - 1369*I/128]]''')) + with dotprodsimp(True): + assert M.rank() == 4 + + +def test_issue_17247_expression_blowup_27(): + M = Matrix([ + [ 0, 1 - x, x + 1, 1 - x], + [1 - x, x + 1, 0, x + 1], + [ 0, 1 - x, x + 1, 1 - x], + [ 0, 0, 1 - x, 0]]) + with dotprodsimp(True): + P, J = M.jordan_form() + assert P.expand() == Matrix(S('''[ + [ 0, 4*x/(x**2 - 2*x + 1), -(-17*x**4 + 12*sqrt(2)*x**4 - 4*sqrt(2)*x**3 + 6*x**3 - 6*x - 4*sqrt(2)*x + 12*sqrt(2) + 17)/(-7*x**4 + 5*sqrt(2)*x**4 - 6*sqrt(2)*x**3 + 8*x**3 - 2*x**2 + 8*x + 6*sqrt(2)*x - 5*sqrt(2) - 7), -(12*sqrt(2)*x**4 + 17*x**4 - 6*x**3 - 4*sqrt(2)*x**3 - 4*sqrt(2)*x + 6*x - 17 + 12*sqrt(2))/(7*x**4 + 5*sqrt(2)*x**4 - 6*sqrt(2)*x**3 - 8*x**3 + 2*x**2 - 8*x + 6*sqrt(2)*x - 5*sqrt(2) + 7)], + [x - 1, x/(x - 1) + 1/(x - 1), (-7*x**3 + 5*sqrt(2)*x**3 - x**2 + sqrt(2)*x**2 - sqrt(2)*x - x - 5*sqrt(2) - 7)/(-3*x**3 + 2*sqrt(2)*x**3 - 2*sqrt(2)*x**2 + 3*x**2 + 2*sqrt(2)*x + 3*x - 3 - 2*sqrt(2)), (7*x**3 + 5*sqrt(2)*x**3 + x**2 + sqrt(2)*x**2 - sqrt(2)*x + x - 5*sqrt(2) + 7)/(2*sqrt(2)*x**3 + 3*x**3 - 3*x**2 - 2*sqrt(2)*x**2 - 3*x + 2*sqrt(2)*x - 2*sqrt(2) + 3)], + [ 0, 1, -(-3*x**2 + 2*sqrt(2)*x**2 + 2*x - 3 - 2*sqrt(2))/(-x**2 + sqrt(2)*x**2 - 2*sqrt(2)*x + 1 + sqrt(2)), -(2*sqrt(2)*x**2 + 3*x**2 - 2*x - 2*sqrt(2) + 3)/(x**2 + sqrt(2)*x**2 - 2*sqrt(2)*x - 1 + sqrt(2))], + [1 - x, 0, 1, 1]]''')).expand() + assert J == Matrix(S('''[ + [0, 1, 0, 0], + [0, 0, 0, 0], + [0, 0, x - sqrt(2)*(x - 1) + 1, 0], + [0, 0, 0, x + sqrt(2)*(x - 1) + 1]]''')) + + +def test_issue_17247_expression_blowup_28(): + M = Matrix(S('''[ + [ -3/4, 45/32 - 37*I/16, 0, 0], + [-149/64 + 49*I/32, -177/128 - 1369*I/128, 0, -2063/256 + 541*I/128], + [ 0, 9/4 + 55*I/16, 2473/256 + 137*I/64, 0], + [ 0, 0, 0, -177/128 - 1369*I/128]]''')) + with dotprodsimp(True): + assert M.singular_values() == S('''[ + sqrt(14609315/131072 + sqrt(64789115132571/2147483648 - 2*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3) + 76627253330829751075/(35184372088832*sqrt(64789115132571/4294967296 + 3546944054712886603889144627/(110680464442257309696*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3)) + 2*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3))) - 3546944054712886603889144627/(110680464442257309696*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3)))/2 + sqrt(64789115132571/4294967296 + 3546944054712886603889144627/(110680464442257309696*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3)) + 2*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3))/2), + sqrt(14609315/131072 - sqrt(64789115132571/2147483648 - 2*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3) + 76627253330829751075/(35184372088832*sqrt(64789115132571/4294967296 + 3546944054712886603889144627/(110680464442257309696*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3)) + 2*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3))) - 3546944054712886603889144627/(110680464442257309696*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3)))/2 + sqrt(64789115132571/4294967296 + 3546944054712886603889144627/(110680464442257309696*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3)) + 2*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3))/2), + sqrt(14609315/131072 - sqrt(64789115132571/4294967296 + 3546944054712886603889144627/(110680464442257309696*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3)) + 2*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3))/2 + sqrt(64789115132571/2147483648 - 2*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3) - 76627253330829751075/(35184372088832*sqrt(64789115132571/4294967296 + 3546944054712886603889144627/(110680464442257309696*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3)) + 2*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3))) - 3546944054712886603889144627/(110680464442257309696*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3)))/2), + sqrt(14609315/131072 - sqrt(64789115132571/4294967296 + 3546944054712886603889144627/(110680464442257309696*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3)) + 2*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3))/2 - sqrt(64789115132571/2147483648 - 2*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3) - 76627253330829751075/(35184372088832*sqrt(64789115132571/4294967296 + 3546944054712886603889144627/(110680464442257309696*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3)) + 2*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3))) - 3546944054712886603889144627/(110680464442257309696*(25895222463957462655758224991455280215303/633825300114114700748351602688 + sqrt(1213909058710955930446995195883114969038524625997915131236390724543989220134670)*I/22282920707136844948184236032)**(1/3)))/2)]''') + + +def test_issue_16823(): + # This still needs to be fixed if not using dotprodsimp. + M = Matrix(S('''[ + [1+I,-19/4+5/4*I,1/2-I,9/4+55/16*I,-3/4,45/32-37/16*I,1/4+1/2*I,-129/64-9/64*I,1/4-5/16*I,65/128+87/64*I,-9/32-1/16*I,183/256-97/128*I,3/64+13/64*I,-23/32-59/256*I,15/128-3/32*I,19/256+551/1024*I], + [21/8+I,-537/64+143/16*I,-5/8-39/16*I,2473/256+137/64*I,-149/64+49/32*I,-177/128-1369/128*I,125/64+87/64*I,-2063/256+541/128*I,85/256-33/16*I,805/128+2415/512*I,-219/128+115/256*I,6301/4096-6609/1024*I,119/128+143/128*I,-10879/2048+4343/4096*I,129/256-549/512*I,42533/16384+29103/8192*I], + [-2,17/4-13/2*I,1+I,-19/4+5/4*I,1/2-I,9/4+55/16*I,-3/4,45/32-37/16*I,1/4+1/2*I,-129/64-9/64*I,1/4-5/16*I,65/128+87/64*I,-9/32-1/16*I,183/256-97/128*I,3/64+13/64*I,-23/32-59/256*I], + [1/4+13/4*I,-825/64-147/32*I,21/8+I,-537/64+143/16*I,-5/8-39/16*I,2473/256+137/64*I,-149/64+49/32*I,-177/128-1369/128*I,125/64+87/64*I,-2063/256+541/128*I,85/256-33/16*I,805/128+2415/512*I,-219/128+115/256*I,6301/4096-6609/1024*I,119/128+143/128*I,-10879/2048+4343/4096*I], + [-4*I,27/2+6*I,-2,17/4-13/2*I,1+I,-19/4+5/4*I,1/2-I,9/4+55/16*I,-3/4,45/32-37/16*I,1/4+1/2*I,-129/64-9/64*I,1/4-5/16*I,65/128+87/64*I,-9/32-1/16*I,183/256-97/128*I], + [1/4+5/2*I,-23/8-57/16*I,1/4+13/4*I,-825/64-147/32*I,21/8+I,-537/64+143/16*I,-5/8-39/16*I,2473/256+137/64*I,-149/64+49/32*I,-177/128-1369/128*I,125/64+87/64*I,-2063/256+541/128*I,85/256-33/16*I,805/128+2415/512*I,-219/128+115/256*I,6301/4096-6609/1024*I], + [-4,9-5*I,-4*I,27/2+6*I,-2,17/4-13/2*I,1+I,-19/4+5/4*I,1/2-I,9/4+55/16*I,-3/4,45/32-37/16*I,1/4+1/2*I,-129/64-9/64*I,1/4-5/16*I,65/128+87/64*I], + [-2*I,119/8+29/4*I,1/4+5/2*I,-23/8-57/16*I,1/4+13/4*I,-825/64-147/32*I,21/8+I,-537/64+143/16*I,-5/8-39/16*I,2473/256+137/64*I,-149/64+49/32*I,-177/128-1369/128*I,125/64+87/64*I,-2063/256+541/128*I,85/256-33/16*I,805/128+2415/512*I], + [0,-6,-4,9-5*I,-4*I,27/2+6*I,-2,17/4-13/2*I,1+I,-19/4+5/4*I,1/2-I,9/4+55/16*I,-3/4,45/32-37/16*I,1/4+1/2*I,-129/64-9/64*I], + [1,-9/4+3*I,-2*I,119/8+29/4*I,1/4+5/2*I,-23/8-57/16*I,1/4+13/4*I,-825/64-147/32*I,21/8+I,-537/64+143/16*I,-5/8-39/16*I,2473/256+137/64*I,-149/64+49/32*I,-177/128-1369/128*I,125/64+87/64*I,-2063/256+541/128*I], + [0,-4*I,0,-6,-4,9-5*I,-4*I,27/2+6*I,-2,17/4-13/2*I,1+I,-19/4+5/4*I,1/2-I,9/4+55/16*I,-3/4,45/32-37/16*I], + [0,1/4+1/2*I,1,-9/4+3*I,-2*I,119/8+29/4*I,1/4+5/2*I,-23/8-57/16*I,1/4+13/4*I,-825/64-147/32*I,21/8+I,-537/64+143/16*I,-5/8-39/16*I,2473/256+137/64*I,-149/64+49/32*I,-177/128-1369/128*I]]''')) + with dotprodsimp(True): + assert M.rank() == 8 + + +def test_issue_18531(): + # solve_linear_system still needs fixing but the rref works. + M = Matrix([ + [1, 1, 1, 1, 1, 0, 1, 0, 0], + [1 + sqrt(2), -1 + sqrt(2), 1 - sqrt(2), -sqrt(2) - 1, 1, 1, -1, 1, 1], + [-5 + 2*sqrt(2), -5 - 2*sqrt(2), -5 - 2*sqrt(2), -5 + 2*sqrt(2), -7, 2, -7, -2, 0], + [-3*sqrt(2) - 1, 1 - 3*sqrt(2), -1 + 3*sqrt(2), 1 + 3*sqrt(2), -7, -5, 7, -5, 3], + [7 - 4*sqrt(2), 4*sqrt(2) + 7, 4*sqrt(2) + 7, 7 - 4*sqrt(2), 7, -12, 7, 12, 0], + [-1 + 3*sqrt(2), 1 + 3*sqrt(2), -3*sqrt(2) - 1, 1 - 3*sqrt(2), 7, -5, -7, -5, 3], + [-3 + 2*sqrt(2), -3 - 2*sqrt(2), -3 - 2*sqrt(2), -3 + 2*sqrt(2), -1, 2, -1, -2, 0], + [1 - sqrt(2), -sqrt(2) - 1, 1 + sqrt(2), -1 + sqrt(2), -1, 1, 1, 1, 1] + ]) + with dotprodsimp(True): + assert M.rref() == (Matrix([ + [1, 0, 0, 0, 0, 0, 0, 0, S(1)/2], + [0, 1, 0, 0, 0, 0, 0, 0, -S(1)/2], + [0, 0, 1, 0, 0, 0, 0, 0, S(1)/2], + [0, 0, 0, 1, 0, 0, 0, 0, -S(1)/2], + [0, 0, 0, 0, 1, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 1, 0, 0, -S(1)/2], + [0, 0, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 1, -S(1)/2]]), (0, 1, 2, 3, 4, 5, 6, 7)) + + +def test_creation(): + raises(ValueError, lambda: Matrix(5, 5, range(20))) + raises(ValueError, lambda: Matrix(5, -1, [])) + raises(IndexError, lambda: Matrix((1, 2))[2]) + with raises(IndexError): + Matrix((1, 2))[3] = 5 + + assert Matrix() == Matrix([]) == Matrix(0, 0, []) + assert Matrix([[]]) == Matrix(1, 0, []) + assert Matrix([[], []]) == Matrix(2, 0, []) + + # anything used to be allowed in a matrix + with warns_deprecated_sympy(): + assert Matrix([[[1], (2,)]]).tolist() == [[[1], (2,)]] + with warns_deprecated_sympy(): + assert Matrix([[[1], (2,)]]).T.tolist() == [[[1]], [(2,)]] + M = Matrix([[0]]) + with warns_deprecated_sympy(): + M[0, 0] = S.EmptySet + + a = Matrix([[x, 0], [0, 0]]) + m = a + assert m.cols == m.rows + assert m.cols == 2 + assert m[:] == [x, 0, 0, 0] + + b = Matrix(2, 2, [x, 0, 0, 0]) + m = b + assert m.cols == m.rows + assert m.cols == 2 + assert m[:] == [x, 0, 0, 0] + + assert a == b + + assert Matrix(b) == b + + c23 = Matrix(2, 3, range(1, 7)) + c13 = Matrix(1, 3, range(7, 10)) + c = Matrix([c23, c13]) + assert c.cols == 3 + assert c.rows == 3 + assert c[:] == [1, 2, 3, 4, 5, 6, 7, 8, 9] + + assert Matrix(eye(2)) == eye(2) + assert ImmutableMatrix(ImmutableMatrix(eye(2))) == ImmutableMatrix(eye(2)) + assert ImmutableMatrix(c) == c.as_immutable() + assert Matrix(ImmutableMatrix(c)) == ImmutableMatrix(c).as_mutable() + + assert c is not Matrix(c) + + dat = [[ones(3,2), ones(3,3)*2], [ones(2,3)*3, ones(2,2)*4]] + M = Matrix(dat) + assert M == Matrix([ + [1, 1, 2, 2, 2], + [1, 1, 2, 2, 2], + [1, 1, 2, 2, 2], + [3, 3, 3, 4, 4], + [3, 3, 3, 4, 4]]) + assert M.tolist() != dat + # keep block form if evaluate=False + assert Matrix(dat, evaluate=False).tolist() == dat + A = MatrixSymbol("A", 2, 2) + dat = [ones(2), A] + assert Matrix(dat) == Matrix([ + [ 1, 1], + [ 1, 1], + [A[0, 0], A[0, 1]], + [A[1, 0], A[1, 1]]]) + with warns_deprecated_sympy(): + assert Matrix(dat, evaluate=False).tolist() == [[i] for i in dat] + + # 0-dim tolerance + assert Matrix([ones(2), ones(0)]) == Matrix([ones(2)]) + raises(ValueError, lambda: Matrix([ones(2), ones(0, 3)])) + raises(ValueError, lambda: Matrix([ones(2), ones(3, 0)])) + + # mix of Matrix and iterable + M = Matrix([[1, 2], [3, 4]]) + M2 = Matrix([M, (5, 6)]) + assert M2 == Matrix([[1, 2], [3, 4], [5, 6]]) + + +def test_irregular_block(): + assert Matrix.irregular(3, ones(2,1), ones(3,3)*2, ones(2,2)*3, + ones(1,1)*4, ones(2,2)*5, ones(1,2)*6, ones(1,2)*7) == Matrix([ + [1, 2, 2, 2, 3, 3], + [1, 2, 2, 2, 3, 3], + [4, 2, 2, 2, 5, 5], + [6, 6, 7, 7, 5, 5]]) + + +def test_slicing(): + m0 = eye(4) + assert m0[:3, :3] == eye(3) + assert m0[2:4, 0:2] == zeros(2) + + m1 = Matrix(3, 3, lambda i, j: i + j) + assert m1[0, :] == Matrix(1, 3, (0, 1, 2)) + assert m1[1:3, 1] == Matrix(2, 1, (2, 3)) + + m2 = Matrix([[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]]) + assert m2[:, -1] == Matrix(4, 1, [3, 7, 11, 15]) + assert m2[-2:, :] == Matrix([[8, 9, 10, 11], [12, 13, 14, 15]]) + + +def test_submatrix_assignment(): + m = zeros(4) + m[2:4, 2:4] = eye(2) + assert m == Matrix(((0, 0, 0, 0), + (0, 0, 0, 0), + (0, 0, 1, 0), + (0, 0, 0, 1))) + m[:2, :2] = eye(2) + assert m == eye(4) + m[:, 0] = Matrix(4, 1, (1, 2, 3, 4)) + assert m == Matrix(((1, 0, 0, 0), + (2, 1, 0, 0), + (3, 0, 1, 0), + (4, 0, 0, 1))) + m[:, :] = zeros(4) + assert m == zeros(4) + m[:, :] = [(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12), (13, 14, 15, 16)] + assert m == Matrix(((1, 2, 3, 4), + (5, 6, 7, 8), + (9, 10, 11, 12), + (13, 14, 15, 16))) + m[:2, 0] = [0, 0] + assert m == Matrix(((0, 2, 3, 4), + (0, 6, 7, 8), + (9, 10, 11, 12), + (13, 14, 15, 16))) + + +def test_reshape(): + m0 = eye(3) + assert m0.reshape(1, 9) == Matrix(1, 9, (1, 0, 0, 0, 1, 0, 0, 0, 1)) + m1 = Matrix(3, 4, lambda i, j: i + j) + assert m1.reshape( + 4, 3) == Matrix(((0, 1, 2), (3, 1, 2), (3, 4, 2), (3, 4, 5))) + assert m1.reshape(2, 6) == Matrix(((0, 1, 2, 3, 1, 2), (3, 4, 2, 3, 4, 5))) + + +def test_applyfunc(): + m0 = eye(3) + assert m0.applyfunc(lambda x: 2*x) == eye(3)*2 + assert m0.applyfunc(lambda x: 0) == zeros(3) + + +def test_expand(): + m0 = Matrix([[x*(x + y), 2], [((x + y)*y)*x, x*(y + x*(x + y))]]) + # Test if expand() returns a matrix + m1 = m0.expand() + assert m1 == Matrix( + [[x*y + x**2, 2], [x*y**2 + y*x**2, x*y + y*x**2 + x**3]]) + + a = Symbol('a', real=True) + + assert Matrix([exp(I*a)]).expand(complex=True) == \ + Matrix([cos(a) + I*sin(a)]) + + assert Matrix([[0, 1, 2], [0, 0, -1], [0, 0, 0]]).exp() == Matrix([ + [1, 1, Rational(3, 2)], + [0, 1, -1], + [0, 0, 1]] + ) + + +def test_refine(): + m0 = Matrix([[Abs(x)**2, sqrt(x**2)], + [sqrt(x**2)*Abs(y)**2, sqrt(y**2)*Abs(x)**2]]) + m1 = m0.refine(Q.real(x) & Q.real(y)) + assert m1 == Matrix([[x**2, Abs(x)], [y**2*Abs(x), x**2*Abs(y)]]) + + m1 = m0.refine(Q.positive(x) & Q.positive(y)) + assert m1 == Matrix([[x**2, x], [x*y**2, x**2*y]]) + + m1 = m0.refine(Q.negative(x) & Q.negative(y)) + assert m1 == Matrix([[x**2, -x], [-x*y**2, -x**2*y]]) + + +def test_random(): + M = randMatrix(3, 3) + M = randMatrix(3, 3, seed=3) + assert M == randMatrix(3, 3, seed=3) + + M = randMatrix(3, 4, 0, 150) + M = randMatrix(3, seed=4, symmetric=True) + assert M == randMatrix(3, seed=4, symmetric=True) + + S = M.copy() + S.simplify() + assert S == M # doesn't fail when elements are Numbers, not int + + rng = random.Random(4) + assert M == randMatrix(3, symmetric=True, prng=rng) + + # Ensure symmetry + for size in (10, 11): # Test odd and even + for percent in (100, 70, 30): + M = randMatrix(size, symmetric=True, percent=percent, prng=rng) + assert M == M.T + + M = randMatrix(10, min=1, percent=70) + zero_count = 0 + for i in range(M.shape[0]): + for j in range(M.shape[1]): + if M[i, j] == 0: + zero_count += 1 + assert zero_count == 30 + + +def test_inverse(): + A = eye(4) + assert A.inv() == eye(4) + assert A.inv(method="LU") == eye(4) + assert A.inv(method="ADJ") == eye(4) + assert A.inv(method="CH") == eye(4) + assert A.inv(method="LDL") == eye(4) + assert A.inv(method="QR") == eye(4) + A = Matrix([[2, 3, 5], + [3, 6, 2], + [8, 3, 6]]) + Ainv = A.inv() + assert A*Ainv == eye(3) + assert A.inv(method="LU") == Ainv + assert A.inv(method="ADJ") == Ainv + assert A.inv(method="CH") == Ainv + assert A.inv(method="LDL") == Ainv + assert A.inv(method="QR") == Ainv + + AA = Matrix([[0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0], + [1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0], + [1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1], + [1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0], + [1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0], + [1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1], + [0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0], + [1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1], + [0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1], + [1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0], + [0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0], + [1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0], + [0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1], + [1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0], + [0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0], + [1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0], + [0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1], + [0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1], + [1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1], + [0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1], + [0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1], + [0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0], + [0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0], + [0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0]]) + assert AA.inv(method="BLOCK") * AA == eye(AA.shape[0]) + # test that immutability is not a problem + cls = ImmutableMatrix + m = cls([[48, 49, 31], + [ 9, 71, 94], + [59, 28, 65]]) + assert all(type(m.inv(s)) is cls for s in 'GE ADJ LU CH LDL QR'.split()) + cls = ImmutableSparseMatrix + m = cls([[48, 49, 31], + [ 9, 71, 94], + [59, 28, 65]]) + assert all(type(m.inv(s)) is cls for s in 'GE ADJ LU CH LDL QR'.split()) + + +def test_inverse_symbolic_float_issue_26821(): + Tau, Tau_syn_in, Tau_syn_ex, C_m, Tau_syn_gap = symbols("Tau Tau_syn_in Tau_syn_ex C_m Tau_syn_gap") + __h = symbols("__h") + + M = Matrix([ + [0,0,0,0,0,(1.0*Tau*__h-1.0*Tau_syn_in*__h)/(2.0*Tau-1.0*Tau_syn_in),-1.0*Tau*Tau_syn_in/(2.0*Tau-1.0*Tau_syn_in)], + [0,0,0,0,0,(-1.0*Tau*__h+1.0*Tau_syn_in*__h)/(2.0*Tau*Tau_syn_in-1.0*Tau_syn_in**2),1.0], + [0,(1.0*Tau*__h-1.0*Tau_syn_ex*__h)/(2.0*Tau-1.0*Tau_syn_ex),-1.0*Tau*Tau_syn_ex/(2.0*Tau-1.0*Tau_syn_ex),0,0,0,0], + [0,(-1.0*Tau*__h+1.0*Tau_syn_ex*__h)/(2.0*Tau*Tau_syn_ex-1.0*Tau_syn_ex**2),1.0,0,0,0,0], + [0,0,0,(1.0*Tau*__h-1.0*Tau_syn_gap*__h)/(2.0*Tau-1.0*Tau_syn_gap),-1.0*Tau*Tau_syn_gap/(2.0*Tau-1.0*Tau_syn_gap),0,0], + [0,0,0,(-1.0*Tau*__h+1.0*Tau_syn_gap*__h)/(2.0*Tau*Tau_syn_gap-1.0*Tau_syn_gap**2),1.0,0,0], + [1.0,-1.0*Tau*Tau_syn_ex*__h/(2.0*C_m*Tau-1.0*C_m*Tau_syn_ex),0,-1.0*Tau*Tau_syn_gap*__h/(2.0*C_m*Tau-1.0*C_m*Tau_syn_gap),0,-1.0*Tau*Tau_syn_in*__h/(2.0*C_m*Tau-1.0*C_m*Tau_syn_in),0] + ]) + + Mi = M.inv() + + assert (M*Mi - eye(7)).applyfunc(cancel) == zeros(7) + + # https://github.com/sympy/sympy/issues/26821 + # Previously very large floats were in the result. + assert max(abs(f) for f in Mi.atoms(Float)) < 1e3 + + +@slow +def test_matrix_exponential_issue_26821(): + # The symbol names matter in the original bug... + a, b, c, d, e = symbols("Tau, Tau_syn_in, Tau_syn_ex, C_m, Tau_syn_gap") + t = symbols("__h") + M = Matrix([ + [ 0, 1.0, 0, 0, 0, 0, 0], + [-1/b**2, -2/b, 0, 0, 0, 0, 0], + [ 0, 0, 0, 1.0, 0, 0, 0], + [ 0, 0, -1/c**2, -2/c, 0, 0, 0], + [ 0, 0, 0, 0, 0, 1, 0], + [ 0, 0, 0, 0, -1/e**2, -2/e, 0], + [ 1/d, 0, 1/d, 0, 1/d, 0, -1/a] + ]) + + Me = (t*M).exp() + assert (Me.diff(t) - M*Me).applyfunc(cancel) == zeros(7) + # https://github.com/sympy/sympy/issues/26821 + # Previously very large floats were in the result. + assert max(abs(f) for f in Me.atoms(Float)) < 1e3 + + +def test_jacobian_hessian(): + L = Matrix(1, 2, [x**2*y, 2*y**2 + x*y]) + syms = [x, y] + assert L.jacobian(syms) == Matrix([[2*x*y, x**2], [y, 4*y + x]]) + + L = Matrix(1, 2, [x, x**2*y**3]) + assert L.jacobian(syms) == Matrix([[1, 0], [2*x*y**3, x**2*3*y**2]]) + + f = x**2*y + syms = [x, y] + assert hessian(f, syms) == Matrix([[2*y, 2*x], [2*x, 0]]) + + f = x**2*y**3 + assert hessian(f, syms) == \ + Matrix([[2*y**3, 6*x*y**2], [6*x*y**2, 6*x**2*y]]) + + f = z + x*y**2 + g = x**2 + 2*y**3 + ans = Matrix([[0, 2*y], + [2*y, 2*x]]) + assert ans == hessian(f, Matrix([x, y])) + assert ans == hessian(f, Matrix([x, y]).T) + assert hessian(f, (y, x), [g]) == Matrix([ + [ 0, 6*y**2, 2*x], + [6*y**2, 2*x, 2*y], + [ 2*x, 2*y, 0]]) + + +def test_wronskian(): + assert wronskian([cos(x), sin(x)], x) == cos(x)**2 + sin(x)**2 + assert wronskian([exp(x), exp(2*x)], x) == exp(3*x) + assert wronskian([exp(x), x], x) == exp(x) - x*exp(x) + assert wronskian([1, x, x**2], x) == 2 + w1 = -6*exp(x)*sin(x)*x + 6*cos(x)*exp(x)*x**2 - 6*exp(x)*cos(x)*x - \ + exp(x)*cos(x)*x**3 + exp(x)*sin(x)*x**3 + assert wronskian([exp(x), cos(x), x**3], x).expand() == w1 + assert wronskian([exp(x), cos(x), x**3], x, method='berkowitz').expand() \ + == w1 + w2 = -x**3*cos(x)**2 - x**3*sin(x)**2 - 6*x*cos(x)**2 - 6*x*sin(x)**2 + assert wronskian([sin(x), cos(x), x**3], x).expand() == w2 + assert wronskian([sin(x), cos(x), x**3], x, method='berkowitz').expand() \ + == w2 + assert wronskian([], x) == 1 + + +def test_xreplace(): + assert Matrix([[1, x], [x, 4]]).xreplace({x: 5}) == \ + Matrix([[1, 5], [5, 4]]) + assert Matrix([[x, 2], [x + y, 4]]).xreplace({x: -1, y: -2}) == \ + Matrix([[-1, 2], [-3, 4]]) + for cls in all_classes: + assert Matrix([[2, 0], [0, 2]]) == cls.eye(2).xreplace({1: 2}) + + +def test_simplify(): + n = Symbol('n') + f = Function('f') + + M = Matrix([[ 1/x + 1/y, (x + x*y) / x ], + [ (f(x) + y*f(x))/f(x), 2 * (1/n - cos(n * pi)/n) / pi ]]) + M.simplify() + assert M == Matrix([[ (x + y)/(x * y), 1 + y ], + [ 1 + y, 2*((1 - 1*cos(pi*n))/(pi*n)) ]]) + eq = (1 + x)**2 + M = Matrix([[eq]]) + M.simplify() + assert M == Matrix([[eq]]) + M.simplify(ratio=oo) + assert M == Matrix([[eq.simplify(ratio=oo)]]) + + n = Symbol('n') + f = Function('f') + + M = ImmutableMatrix([ + [ 1/x + 1/y, (x + x*y) / x ], + [ (f(x) + y*f(x))/f(x), 2 * (1/n - cos(n * pi)/n) / pi ] + ]) + assert M.simplify() == Matrix([ + [ (x + y)/(x * y), 1 + y ], + [ 1 + y, 2*((1 - 1*cos(pi*n))/(pi*n)) ] + ]) + + eq = (1 + x)**2 + M = ImmutableMatrix([[eq]]) + assert M.simplify() == Matrix([[eq]]) + assert M.simplify(ratio=oo) == Matrix([[eq.simplify(ratio=oo)]]) + + assert simplify(ImmutableMatrix([[sin(x)**2 + cos(x)**2]])) == \ + ImmutableMatrix([[1]]) + + # https://github.com/sympy/sympy/issues/19353 + m = Matrix([[30, 2], [3, 4]]) + assert (1/(m.trace())).simplify() == Rational(1, 34) + +def test_transpose(): + M = Matrix([[1, 2, 3, 4, 5, 6, 7, 8, 9, 0], + [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]]) + assert M.T == Matrix( [ [1, 1], + [2, 2], + [3, 3], + [4, 4], + [5, 5], + [6, 6], + [7, 7], + [8, 8], + [9, 9], + [0, 0] ]) + assert M.T.T == M + assert M.T == M.transpose() + + +def test_conj_dirac(): + raises(AttributeError, lambda: eye(3).D) + + M = Matrix([[1, I, I, I], + [0, 1, I, I], + [0, 0, 1, I], + [0, 0, 0, 1]]) + + assert M.D == Matrix([[ 1, 0, 0, 0], + [-I, 1, 0, 0], + [-I, -I, -1, 0], + [-I, -I, I, -1]]) + + +def test_trace(): + M = Matrix([[1, 0, 0], + [0, 5, 0], + [0, 0, 8]]) + assert M.trace() == 14 + + +def test_shape(): + m = Matrix(1, 2, [0, 0]) + assert m.shape == (1, 2) + M = Matrix([[x, 0, 0], + [0, y, 0]]) + assert M.shape == (2, 3) + + +def test_col_row_op(): + M = Matrix([[x, 0, 0], + [0, y, 0]]) + M.row_op(1, lambda r, j: r + j + 1) + assert M == Matrix([[x, 0, 0], + [1, y + 2, 3]]) + + M.col_op(0, lambda c, j: c + y**j) + assert M == Matrix([[x + 1, 0, 0], + [1 + y, y + 2, 3]]) + + # neither row nor slice give copies that allow the original matrix to + # be changed + assert M.row(0) == Matrix([[x + 1, 0, 0]]) + r1 = M.row(0) + r1[0] = 42 + assert M[0, 0] == x + 1 + r1 = M[0, :-1] # also testing negative slice + r1[0] = 42 + assert M[0, 0] == x + 1 + c1 = M.col(0) + assert c1 == Matrix([x + 1, 1 + y]) + c1[0] = 0 + assert M[0, 0] == x + 1 + c1 = M[:, 0] + c1[0] = 42 + assert M[0, 0] == x + 1 + + +def test_row_mult(): + M = Matrix([[1,2,3], + [4,5,6]]) + M.row_mult(1,3) + assert M[1,0] == 12 + assert M[0,0] == 1 + assert M[1,2] == 18 + + +def test_row_add(): + M = Matrix([[1,2,3], + [4,5,6], + [1,1,1]]) + M.row_add(2,0,5) + assert M[0,0] == 6 + assert M[1,0] == 4 + assert M[0,2] == 8 + + +def test_zip_row_op(): + for cls in mutable_classes: # XXX: immutable matrices don't support row ops + M = cls.eye(3) + M.zip_row_op(1, 0, lambda v, u: v + 2*u) + assert M == cls([[1, 0, 0], + [2, 1, 0], + [0, 0, 1]]) + + M = cls.eye(3)*2 + M[0, 1] = -1 + M.zip_row_op(1, 0, lambda v, u: v + 2*u); M + assert M == cls([[2, -1, 0], + [4, 0, 0], + [0, 0, 2]]) + + +def test_issue_3950(): + m = Matrix([1, 2, 3]) + a = Matrix([1, 2, 3]) + b = Matrix([2, 2, 3]) + assert not (m in []) + assert not (m in [1]) + assert m != 1 + assert m == a + assert m != b + + +def test_issue_3981(): + class Index1: + def __index__(self): + return 1 + + class Index2: + def __index__(self): + return 2 + index1 = Index1() + index2 = Index2() + + m = Matrix([1, 2, 3]) + + assert m[index2] == 3 + + m[index2] = 5 + assert m[2] == 5 + + m = Matrix([[1, 2, 3], [4, 5, 6]]) + assert m[index1, index2] == 6 + assert m[1, index2] == 6 + assert m[index1, 2] == 6 + + m[index1, index2] = 4 + assert m[1, 2] == 4 + m[1, index2] = 6 + assert m[1, 2] == 6 + m[index1, 2] = 8 + assert m[1, 2] == 8 + + +def test_is_upper(): + a = Matrix([[1, 2, 3]]) + assert a.is_upper is True + a = Matrix([[1], [2], [3]]) + assert a.is_upper is False + a = zeros(4, 2) + assert a.is_upper is True + + +def test_is_lower(): + a = Matrix([[1, 2, 3]]) + assert a.is_lower is False + a = Matrix([[1], [2], [3]]) + assert a.is_lower is True + + +def test_is_nilpotent(): + a = Matrix(4, 4, [0, 2, 1, 6, 0, 0, 1, 2, 0, 0, 0, 3, 0, 0, 0, 0]) + assert a.is_nilpotent() + a = Matrix([[1, 0], [0, 1]]) + assert not a.is_nilpotent() + a = Matrix([]) + assert a.is_nilpotent() + + +def test_zeros_ones_fill(): + n, m = 3, 5 + + a = zeros(n, m) + a.fill( 5 ) + + b = 5 * ones(n, m) + + assert a == b + assert a.rows == b.rows == 3 + assert a.cols == b.cols == 5 + assert a.shape == b.shape == (3, 5) + assert zeros(2) == zeros(2, 2) + assert ones(2) == ones(2, 2) + assert zeros(2, 3) == Matrix(2, 3, [0]*6) + assert ones(2, 3) == Matrix(2, 3, [1]*6) + + a.fill(0) + assert a == zeros(n, m) + + +def test_empty_zeros(): + a = zeros(0) + assert a == Matrix() + a = zeros(0, 2) + assert a.rows == 0 + assert a.cols == 2 + a = zeros(2, 0) + assert a.rows == 2 + assert a.cols == 0 + + +def test_issue_3749(): + a = Matrix([[x**2, x*y], [x*sin(y), x*cos(y)]]) + assert a.diff(x) == Matrix([[2*x, y], [sin(y), cos(y)]]) + assert Matrix([ + [x, -x, x**2], + [exp(x), 1/x - exp(-x), x + 1/x]]).limit(x, oo) == \ + Matrix([[oo, -oo, oo], [oo, 0, oo]]) + assert Matrix([ + [(exp(x) - 1)/x, 2*x + y*x, x**x ], + [1/x, abs(x), abs(sin(x + 1))]]).limit(x, 0) == \ + Matrix([[1, 0, 1], [oo, 0, sin(1)]]) + assert a.integrate(x) == Matrix([ + [Rational(1, 3)*x**3, y*x**2/2], + [x**2*sin(y)/2, x**2*cos(y)/2]]) + + +def test_inv_iszerofunc(): + A = eye(4) + A.col_swap(0, 1) + for method in "GE", "LU": + assert A.inv(method=method, iszerofunc=lambda x: x == 0) == \ + A.inv(method="ADJ") + + +def test_jacobian_metrics(): + rho, phi = symbols("rho,phi") + X = Matrix([rho*cos(phi), rho*sin(phi)]) + Y = Matrix([rho, phi]) + J = X.jacobian(Y) + assert J == X.jacobian(Y.T) + assert J == (X.T).jacobian(Y) + assert J == (X.T).jacobian(Y.T) + g = J.T*eye(J.shape[0])*J + g = g.applyfunc(trigsimp) + assert g == Matrix([[1, 0], [0, rho**2]]) + + +def test_jacobian2(): + rho, phi = symbols("rho,phi") + X = Matrix([rho*cos(phi), rho*sin(phi), rho**2]) + Y = Matrix([rho, phi]) + J = Matrix([ + [cos(phi), -rho*sin(phi)], + [sin(phi), rho*cos(phi)], + [ 2*rho, 0], + ]) + assert X.jacobian(Y) == J + + +def test_issue_4564(): + X = Matrix([exp(x + y + z), exp(x + y + z), exp(x + y + z)]) + Y = Matrix([x, y, z]) + for i in range(1, 3): + for j in range(1, 3): + X_slice = X[:i, :] + Y_slice = Y[:j, :] + J = X_slice.jacobian(Y_slice) + assert J.rows == i + assert J.cols == j + for k in range(j): + assert J[:, k] == X_slice + + +def test_nonvectorJacobian(): + X = Matrix([[exp(x + y + z), exp(x + y + z)], + [exp(x + y + z), exp(x + y + z)]]) + raises(TypeError, lambda: X.jacobian(Matrix([x, y, z]))) + X = X[0, :] + Y = Matrix([[x, y], [x, z]]) + raises(TypeError, lambda: X.jacobian(Y)) + raises(TypeError, lambda: X.jacobian(Matrix([ [x, y], [x, z] ]))) + + +def test_vec(): + m = Matrix([[1, 3], [2, 4]]) + m_vec = m.vec() + assert m_vec.cols == 1 + for i in range(4): + assert m_vec[i] == i + 1 + + +def test_vech(): + m = Matrix([[1, 2], [2, 3]]) + m_vech = m.vech() + assert m_vech.cols == 1 + for i in range(3): + assert m_vech[i] == i + 1 + m_vech = m.vech(diagonal=False) + assert m_vech[0] == 2 + + m = Matrix([[1, x*(x + y)], [y*x + x**2, 1]]) + m_vech = m.vech(diagonal=False) + assert m_vech[0] == y*x + x**2 + + m = Matrix([[1, x*(x + y)], [y*x, 1]]) + m_vech = m.vech(diagonal=False, check_symmetry=False) + assert m_vech[0] == y*x + + raises(ShapeError, lambda: Matrix([[1, 3]]).vech()) + raises(ValueError, lambda: Matrix([[1, 3], [2, 4]]).vech()) + raises(ShapeError, lambda: Matrix([[1, 3]]).vech()) + raises(ValueError, lambda: Matrix([[1, 3], [2, 4]]).vech()) + + +def test_diag(): + # mostly tested in testcommonmatrix.py + assert diag([1, 2, 3]) == Matrix([1, 2, 3]) + m = [1, 2, [3]] + raises(ValueError, lambda: diag(m)) + assert diag(m, strict=False) == Matrix([1, 2, 3]) + + +def test_inv_block(): + a = Matrix([[1, 2], [2, 3]]) + b = Matrix([[3, x], [y, 3]]) + c = Matrix([[3, x, 3], [y, 3, z], [x, y, z]]) + A = diag(a, b, b) + assert A.inv(try_block_diag=True) == diag(a.inv(), b.inv(), b.inv()) + A = diag(a, b, c) + assert A.inv(try_block_diag=True) == diag(a.inv(), b.inv(), c.inv()) + A = diag(a, c, b) + assert A.inv(try_block_diag=True) == diag(a.inv(), c.inv(), b.inv()) + A = diag(a, a, b, a, c, a) + assert A.inv(try_block_diag=True) == diag( + a.inv(), a.inv(), b.inv(), a.inv(), c.inv(), a.inv()) + assert A.inv(try_block_diag=True, method="ADJ") == diag( + a.inv(method="ADJ"), a.inv(method="ADJ"), b.inv(method="ADJ"), + a.inv(method="ADJ"), c.inv(method="ADJ"), a.inv(method="ADJ")) + + +def test_creation_args(): + """ + Check that matrix dimensions can be specified using any reasonable type + (see issue 4614). + """ + raises(ValueError, lambda: zeros(3, -1)) + raises(TypeError, lambda: zeros(1, 2, 3, 4)) + assert zeros(int(3)) == zeros(3) + assert zeros(Integer(3)) == zeros(3) + raises(ValueError, lambda: zeros(3.)) + assert eye(int(3)) == eye(3) + assert eye(Integer(3)) == eye(3) + raises(ValueError, lambda: eye(3.)) + assert ones(int(3), Integer(4)) == ones(3, 4) + raises(TypeError, lambda: Matrix(5)) + raises(TypeError, lambda: Matrix(1, 2)) + raises(ValueError, lambda: Matrix([1, [2]])) + + +def test_diagonal_symmetrical(): + m = Matrix(2, 2, [0, 1, 1, 0]) + assert not m.is_diagonal() + assert m.is_symmetric() + assert m.is_symmetric(simplify=False) + + m = Matrix(2, 2, [1, 0, 0, 1]) + assert m.is_diagonal() + + m = diag(1, 2, 3) + assert m.is_diagonal() + assert m.is_symmetric() + + m = Matrix(3, 3, [1, 0, 0, 0, 2, 0, 0, 0, 3]) + assert m == diag(1, 2, 3) + + m = Matrix(2, 3, zeros(2, 3)) + assert not m.is_symmetric() + assert m.is_diagonal() + + m = Matrix(((5, 0), (0, 6), (0, 0))) + assert m.is_diagonal() + + m = Matrix(((5, 0, 0), (0, 6, 0))) + assert m.is_diagonal() + + m = Matrix(3, 3, [1, x**2 + 2*x + 1, y, (x + 1)**2, 2, 0, y, 0, 3]) + assert m.is_symmetric() + assert not m.is_symmetric(simplify=False) + assert m.expand().is_symmetric(simplify=False) + + +def test_diagonalization(): + m = Matrix([[1, 2+I], [2-I, 3]]) + assert m.is_diagonalizable() + + m = Matrix(3, 2, [-3, 1, -3, 20, 3, 10]) + assert not m.is_diagonalizable() + assert not m.is_symmetric() + raises(NonSquareMatrixError, lambda: m.diagonalize()) + + # diagonalizable + m = diag(1, 2, 3) + (P, D) = m.diagonalize() + assert P == eye(3) + assert D == m + + m = Matrix(2, 2, [0, 1, 1, 0]) + assert m.is_symmetric() + assert m.is_diagonalizable() + (P, D) = m.diagonalize() + assert P.inv() * m * P == D + + m = Matrix(2, 2, [1, 0, 0, 3]) + assert m.is_symmetric() + assert m.is_diagonalizable() + (P, D) = m.diagonalize() + assert P.inv() * m * P == D + assert P == eye(2) + assert D == m + + m = Matrix(2, 2, [1, 1, 0, 0]) + assert m.is_diagonalizable() + (P, D) = m.diagonalize() + assert P.inv() * m * P == D + + m = Matrix(3, 3, [1, 2, 0, 0, 3, 0, 2, -4, 2]) + assert m.is_diagonalizable() + (P, D) = m.diagonalize() + assert P.inv() * m * P == D + for i in P: + assert i.as_numer_denom()[1] == 1 + + m = Matrix(2, 2, [1, 0, 0, 0]) + assert m.is_diagonal() + assert m.is_diagonalizable() + (P, D) = m.diagonalize() + assert P.inv() * m * P == D + assert P == Matrix([[0, 1], [1, 0]]) + + # diagonalizable, complex only + m = Matrix(2, 2, [0, 1, -1, 0]) + assert not m.is_diagonalizable(True) + raises(MatrixError, lambda: m.diagonalize(True)) + assert m.is_diagonalizable() + (P, D) = m.diagonalize() + assert P.inv() * m * P == D + + # not diagonalizable + m = Matrix(2, 2, [0, 1, 0, 0]) + assert not m.is_diagonalizable() + raises(MatrixError, lambda: m.diagonalize()) + + m = Matrix(3, 3, [-3, 1, -3, 20, 3, 10, 2, -2, 4]) + assert not m.is_diagonalizable() + raises(MatrixError, lambda: m.diagonalize()) + + # symbolic + a, b, c, d = symbols('a b c d') + m = Matrix(2, 2, [a, c, c, b]) + assert m.is_symmetric() + assert m.is_diagonalizable() + + +def test_issue_15887(): + # Mutable matrix should not use cache + a = MutableDenseMatrix([[0, 1], [1, 0]]) + assert a.is_diagonalizable() is True + a[1, 0] = 0 + assert a.is_diagonalizable() is False + + a = MutableDenseMatrix([[0, 1], [1, 0]]) + a.diagonalize() + a[1, 0] = 0 + raises(MatrixError, lambda: a.diagonalize()) + + +def test_jordan_form(): + + m = Matrix(3, 2, [-3, 1, -3, 20, 3, 10]) + raises(NonSquareMatrixError, lambda: m.jordan_form()) + + # diagonalizable + m = Matrix(3, 3, [7, -12, 6, 10, -19, 10, 12, -24, 13]) + Jmust = Matrix(3, 3, [-1, 0, 0, 0, 1, 0, 0, 0, 1]) + P, J = m.jordan_form() + assert Jmust == J + assert Jmust == m.diagonalize()[1] + + # m = Matrix(3, 3, [0, 6, 3, 1, 3, 1, -2, 2, 1]) + # m.jordan_form() # very long + # m.jordan_form() # + + # diagonalizable, complex only + + # Jordan cells + # complexity: one of eigenvalues is zero + m = Matrix(3, 3, [0, 1, 0, -4, 4, 0, -2, 1, 2]) + # The blocks are ordered according to the value of their eigenvalues, + # in order to make the matrix compatible with .diagonalize() + Jmust = Matrix(3, 3, [2, 1, 0, 0, 2, 0, 0, 0, 2]) + P, J = m.jordan_form() + assert Jmust == J + + # complexity: all of eigenvalues are equal + m = Matrix(3, 3, [2, 6, -15, 1, 1, -5, 1, 2, -6]) + # Jmust = Matrix(3, 3, [-1, 0, 0, 0, -1, 1, 0, 0, -1]) + # same here see 1456ff + Jmust = Matrix(3, 3, [-1, 1, 0, 0, -1, 0, 0, 0, -1]) + P, J = m.jordan_form() + assert Jmust == J + + # complexity: two of eigenvalues are zero + m = Matrix(3, 3, [4, -5, 2, 5, -7, 3, 6, -9, 4]) + Jmust = Matrix(3, 3, [0, 1, 0, 0, 0, 0, 0, 0, 1]) + P, J = m.jordan_form() + assert Jmust == J + + m = Matrix(4, 4, [6, 5, -2, -3, -3, -1, 3, 3, 2, 1, -2, -3, -1, 1, 5, 5]) + Jmust = Matrix(4, 4, [2, 1, 0, 0, + 0, 2, 0, 0, + 0, 0, 2, 1, + 0, 0, 0, 2] + ) + P, J = m.jordan_form() + assert Jmust == J + + m = Matrix(4, 4, [6, 2, -8, -6, -3, 2, 9, 6, 2, -2, -8, -6, -1, 0, 3, 4]) + # Jmust = Matrix(4, 4, [2, 0, 0, 0, 0, 2, 1, 0, 0, 0, 2, 0, 0, 0, 0, -2]) + # same here see 1456ff + Jmust = Matrix(4, 4, [-2, 0, 0, 0, + 0, 2, 1, 0, + 0, 0, 2, 0, + 0, 0, 0, 2]) + P, J = m.jordan_form() + assert Jmust == J + + m = Matrix(4, 4, [5, 4, 2, 1, 0, 1, -1, -1, -1, -1, 3, 0, 1, 1, -1, 2]) + assert not m.is_diagonalizable() + Jmust = Matrix(4, 4, [1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 4, 1, 0, 0, 0, 4]) + P, J = m.jordan_form() + assert Jmust == J + + # checking for maximum precision to remain unchanged + m = Matrix([[Float('1.0', precision=110), Float('2.0', precision=110)], + [Float('3.14159265358979323846264338327', precision=110), Float('4.0', precision=110)]]) + P, J = m.jordan_form() + for term in J.values(): + if isinstance(term, Float): + assert term._prec == 110 + + +def test_jordan_form_complex_issue_9274(): + A = Matrix([[ 2, 4, 1, 0], + [-4, 2, 0, 1], + [ 0, 0, 2, 4], + [ 0, 0, -4, 2]]) + p = 2 - 4*I + q = 2 + 4*I + Jmust1 = Matrix([[p, 1, 0, 0], + [0, p, 0, 0], + [0, 0, q, 1], + [0, 0, 0, q]]) + Jmust2 = Matrix([[q, 1, 0, 0], + [0, q, 0, 0], + [0, 0, p, 1], + [0, 0, 0, p]]) + P, J = A.jordan_form() + assert J == Jmust1 or J == Jmust2 + assert simplify(P*J*P.inv()) == A + + +def test_issue_10220(): + # two non-orthogonal Jordan blocks with eigenvalue 1 + M = Matrix([[1, 0, 0, 1], + [0, 1, 1, 0], + [0, 0, 1, 1], + [0, 0, 0, 1]]) + P, J = M.jordan_form() + assert P == Matrix([[0, 1, 0, 1], + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0]]) + assert J == Matrix([ + [1, 1, 0, 0], + [0, 1, 1, 0], + [0, 0, 1, 0], + [0, 0, 0, 1]]) + + +def test_jordan_form_issue_15858(): + A = Matrix([ + [1, 1, 1, 0], + [-2, -1, 0, -1], + [0, 0, -1, -1], + [0, 0, 2, 1]]) + (P, J) = A.jordan_form() + assert P.expand() == Matrix([ + [ -I, -I/2, I, I/2], + [-1 + I, 0, -1 - I, 0], + [ 0, -S(1)/2 - I/2, 0, -S(1)/2 + I/2], + [ 0, 1, 0, 1]]) + assert J == Matrix([ + [-I, 1, 0, 0], + [0, -I, 0, 0], + [0, 0, I, 1], + [0, 0, 0, I]]) + + +def test_Matrix_berkowitz_charpoly(): + UA, K_i, K_w = symbols('UA K_i K_w') + + A = Matrix([[-K_i - UA + K_i**2/(K_i + K_w), K_i*K_w/(K_i + K_w)], + [ K_i*K_w/(K_i + K_w), -K_w + K_w**2/(K_i + K_w)]]) + + charpoly = A.charpoly(x) + + assert charpoly == \ + Poly(x**2 + (K_i*UA + K_w*UA + 2*K_i*K_w)/(K_i + K_w)*x + + K_i*K_w*UA/(K_i + K_w), x, domain='ZZ(K_i,K_w,UA)') + + assert type(charpoly) is PurePoly + + A = Matrix([[1, 3], [2, 0]]) + assert A.charpoly() == A.charpoly(x) == PurePoly(x**2 - x - 6) + + A = Matrix([[1, 2], [x, 0]]) + p = A.charpoly(x) + assert p.gen != x + assert p.as_expr().subs(p.gen, x) == x**2 - 3*x + + +def test_exp_jordan_block(): + l = Symbol('lamda') + + m = Matrix.jordan_block(1, l) + assert m._eval_matrix_exp_jblock() == Matrix([[exp(l)]]) + + m = Matrix.jordan_block(3, l) + assert m._eval_matrix_exp_jblock() == \ + Matrix([ + [exp(l), exp(l), exp(l)/2], + [0, exp(l), exp(l)], + [0, 0, exp(l)]]) + + +def test_exp(): + m = Matrix([[3, 4], [0, -2]]) + m_exp = Matrix([[exp(3), -4*exp(-2)/5 + 4*exp(3)/5], [0, exp(-2)]]) + assert m.exp() == m_exp + assert exp(m) == m_exp + + m = Matrix([[1, 0], [0, 1]]) + assert m.exp() == Matrix([[E, 0], [0, E]]) + assert exp(m) == Matrix([[E, 0], [0, E]]) + + m = Matrix([[1, -1], [1, 1]]) + assert m.exp() == Matrix([[E*cos(1), -E*sin(1)], [E*sin(1), E*cos(1)]]) + + +def test_log(): + l = Symbol('lamda') + + m = Matrix.jordan_block(1, l) + assert m._eval_matrix_log_jblock() == Matrix([[log(l)]]) + + m = Matrix.jordan_block(4, l) + assert m._eval_matrix_log_jblock() == \ + Matrix( + [ + [log(l), 1/l, -1/(2*l**2), 1/(3*l**3)], + [0, log(l), 1/l, -1/(2*l**2)], + [0, 0, log(l), 1/l], + [0, 0, 0, log(l)] + ] + ) + + m = Matrix( + [[0, 0, 1], + [0, 0, 0], + [-1, 0, 0]] + ) + raises(MatrixError, lambda: m.log()) + + +def test_find_reasonable_pivot_naive_finds_guaranteed_nonzero1(): + # Test if matrices._find_reasonable_pivot_naive() + # finds a guaranteed non-zero pivot when the + # some of the candidate pivots are symbolic expressions. + # Keyword argument: simpfunc=None indicates that no simplifications + # should be performed during the search. + x = Symbol('x') + column = Matrix(3, 1, [x, cos(x)**2 + sin(x)**2, S.Half]) + pivot_offset, pivot_val, pivot_assumed_nonzero, simplified =\ + _find_reasonable_pivot_naive(column) + assert pivot_val == S.Half + + +def test_find_reasonable_pivot_naive_finds_guaranteed_nonzero2(): + # Test if matrices._find_reasonable_pivot_naive() + # finds a guaranteed non-zero pivot when the + # some of the candidate pivots are symbolic expressions. + # Keyword argument: simpfunc=_simplify indicates that the search + # should attempt to simplify candidate pivots. + x = Symbol('x') + column = Matrix(3, 1, + [x, + cos(x)**2+sin(x)**2+x**2, + cos(x)**2+sin(x)**2]) + pivot_offset, pivot_val, pivot_assumed_nonzero, simplified =\ + _find_reasonable_pivot_naive(column, simpfunc=_simplify) + assert pivot_val == 1 + + +def test_find_reasonable_pivot_naive_simplifies(): + # Test if matrices._find_reasonable_pivot_naive() + # simplifies candidate pivots, and reports + # their offsets correctly. + x = Symbol('x') + column = Matrix(3, 1, + [x, + cos(x)**2+sin(x)**2+x, + cos(x)**2+sin(x)**2]) + pivot_offset, pivot_val, pivot_assumed_nonzero, simplified =\ + _find_reasonable_pivot_naive(column, simpfunc=_simplify) + + assert len(simplified) == 2 + assert simplified[0][0] == 1 + assert simplified[0][1] == 1+x + assert simplified[1][0] == 2 + assert simplified[1][1] == 1 + + +def test_errors(): + raises(ValueError, lambda: Matrix([[1, 2], [1]])) + raises(IndexError, lambda: Matrix([[1, 2]])[1.2, 5]) + raises(IndexError, lambda: Matrix([[1, 2]])[1, 5.2]) + raises(ValueError, lambda: randMatrix(3, c=4, symmetric=True)) + raises(ValueError, lambda: Matrix([1, 2]).reshape(4, 6)) + raises(ShapeError, + lambda: Matrix([[1, 2], [3, 4]]).copyin_matrix([1, 0], Matrix([1, 2]))) + raises(TypeError, lambda: Matrix([[1, 2], [3, 4]]).copyin_list([0, + 1], set())) + raises(NonSquareMatrixError, lambda: Matrix([[1, 2, 3], [2, 3, 0]]).inv()) + raises(ShapeError, + lambda: Matrix(1, 2, [1, 2]).row_join(Matrix([[1, 2], [3, 4]]))) + raises( + ShapeError, lambda: Matrix([1, 2]).col_join(Matrix([[1, 2], [3, 4]]))) + raises(ShapeError, lambda: Matrix([1]).row_insert(1, Matrix([[1, + 2], [3, 4]]))) + raises(ShapeError, lambda: Matrix([1]).col_insert(1, Matrix([[1, + 2], [3, 4]]))) + raises(NonSquareMatrixError, lambda: Matrix([1, 2]).trace()) + raises(TypeError, lambda: Matrix([1]).applyfunc(1)) + raises(ValueError, lambda: Matrix([[1, 2], [3, 4]]).minor(4, 5)) + raises(ValueError, lambda: Matrix([[1, 2], [3, 4]]).minor_submatrix(4, 5)) + raises(TypeError, lambda: Matrix([1, 2, 3]).cross(1)) + raises(TypeError, lambda: Matrix([1, 2, 3]).dot(1)) + raises(ShapeError, lambda: Matrix([1, 2, 3]).dot(Matrix([1, 2]))) + raises(ShapeError, lambda: Matrix([1, 2]).dot([])) + raises(TypeError, lambda: Matrix([1, 2]).dot('a')) + raises(ShapeError, lambda: Matrix([1, 2]).dot([1, 2, 3])) + raises(NonSquareMatrixError, lambda: Matrix([1, 2, 3]).exp()) + raises(ShapeError, lambda: Matrix([[1, 2], [3, 4]]).normalized()) + raises(ValueError, lambda: Matrix([1, 2]).inv(method='not a method')) + raises(NonSquareMatrixError, lambda: Matrix([1, 2]).inverse_GE()) + raises(ValueError, lambda: Matrix([[1, 2], [1, 2]]).inverse_GE()) + raises(NonSquareMatrixError, lambda: Matrix([1, 2]).inverse_ADJ()) + raises(ValueError, lambda: Matrix([[1, 2], [1, 2]]).inverse_ADJ()) + raises(NonSquareMatrixError, lambda: Matrix([1, 2]).inverse_LU()) + raises(NonSquareMatrixError, lambda: Matrix([1, 2]).is_nilpotent()) + raises(NonSquareMatrixError, lambda: Matrix([1, 2]).det()) + raises(ValueError, + lambda: Matrix([[1, 2], [3, 4]]).det(method='Not a real method')) + raises(ValueError, + lambda: Matrix([[1, 2, 3, 4], [5, 6, 7, 8], + [9, 10, 11, 12], [13, 14, 15, 16]]).det(iszerofunc="Not function")) + raises(ValueError, + lambda: Matrix([[1, 2, 3, 4], [5, 6, 7, 8], + [9, 10, 11, 12], [13, 14, 15, 16]]).det(iszerofunc=False)) + raises(ValueError, + lambda: hessian(Matrix([[1, 2], [3, 4]]), Matrix([[1, 2], [2, 1]]))) + raises(ValueError, lambda: hessian(Matrix([[1, 2], [3, 4]]), [])) + raises(ValueError, lambda: hessian(Symbol('x')**2, 'a')) + raises(IndexError, lambda: eye(3)[5, 2]) + raises(IndexError, lambda: eye(3)[2, 5]) + M = Matrix(((1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12), (13, 14, 15, 16))) + raises(ValueError, lambda: M.det('method=LU_decomposition()')) + V = Matrix([[10, 10, 10]]) + M = Matrix([[1, 2, 3], [2, 3, 4], [3, 4, 5]]) + raises(ValueError, lambda: M.row_insert(4.7, V)) + M = Matrix([[1, 2, 3], [2, 3, 4], [3, 4, 5]]) + raises(ValueError, lambda: M.col_insert(-4.2, V)) + + +def test_len(): + assert len(Matrix()) == 0 + assert len(Matrix([[1, 2]])) == len(Matrix([[1], [2]])) == 2 + assert len(Matrix(0, 2, lambda i, j: 0)) == \ + len(Matrix(2, 0, lambda i, j: 0)) == 0 + assert len(Matrix([[0, 1, 2], [3, 4, 5]])) == 6 + assert Matrix([1]) == Matrix([[1]]) + assert not Matrix() + assert Matrix() == Matrix([]) + + +def test_integrate(): + A = Matrix(((1, 4, x), (y, 2, 4), (10, 5, x**2))) + assert A.integrate(x) == \ + Matrix(((x, 4*x, x**2/2), (x*y, 2*x, 4*x), (10*x, 5*x, x**3/3))) + assert A.integrate(y) == \ + Matrix(((y, 4*y, x*y), (y**2/2, 2*y, 4*y), (10*y, 5*y, y*x**2))) + m = Matrix(2, 1, [x, y]) + assert m.integrate(x) == Matrix(2, 1, [x**2/2, y*x]) + + +def test_diff(): + A = MutableDenseMatrix(((1, 4, x), (y, 2, 4), (10, 5, x**2 + 1))) + assert isinstance(A.diff(x), type(A)) + assert A.diff(x) == MutableDenseMatrix(((0, 0, 1), (0, 0, 0), (0, 0, 2*x))) + assert A.diff(y) == MutableDenseMatrix(((0, 0, 0), (1, 0, 0), (0, 0, 0))) + + assert diff(A, x) == MutableDenseMatrix(((0, 0, 1), (0, 0, 0), (0, 0, 2*x))) + assert diff(A, y) == MutableDenseMatrix(((0, 0, 0), (1, 0, 0), (0, 0, 0))) + + A_imm = A.as_immutable() + assert isinstance(A_imm.diff(x), type(A_imm)) + assert A_imm.diff(x) == ImmutableDenseMatrix(((0, 0, 1), (0, 0, 0), (0, 0, 2*x))) + assert A_imm.diff(y) == ImmutableDenseMatrix(((0, 0, 0), (1, 0, 0), (0, 0, 0))) + + assert diff(A_imm, x) == ImmutableDenseMatrix(((0, 0, 1), (0, 0, 0), (0, 0, 2*x))) + assert diff(A_imm, y) == ImmutableDenseMatrix(((0, 0, 0), (1, 0, 0), (0, 0, 0))) + + assert A.diff(x, evaluate=False) == ArrayDerivative(A, x, evaluate=False) + assert diff(A, x, evaluate=False) == ArrayDerivative(A, x, evaluate=False) + + +def test_diff_by_matrix(): + + # Derive matrix by matrix: + + A = MutableDenseMatrix([[x, y], [z, t]]) + assert A.diff(A) == Array([[[[1, 0], [0, 0]], [[0, 1], [0, 0]]], [[[0, 0], [1, 0]], [[0, 0], [0, 1]]]]) + assert diff(A, A) == Array([[[[1, 0], [0, 0]], [[0, 1], [0, 0]]], [[[0, 0], [1, 0]], [[0, 0], [0, 1]]]]) + + A_imm = A.as_immutable() + assert A_imm.diff(A_imm) == Array([[[[1, 0], [0, 0]], [[0, 1], [0, 0]]], [[[0, 0], [1, 0]], [[0, 0], [0, 1]]]]) + assert diff(A_imm, A_imm) == Array([[[[1, 0], [0, 0]], [[0, 1], [0, 0]]], [[[0, 0], [1, 0]], [[0, 0], [0, 1]]]]) + + # Derive a constant matrix: + assert A.diff(a) == MutableDenseMatrix([[0, 0], [0, 0]]) + + B = ImmutableDenseMatrix([a, b]) + assert A.diff(B) == Array.zeros(2, 1, 2, 2) + assert A.diff(A) == Array([[[[1, 0], [0, 0]], [[0, 1], [0, 0]]], [[[0, 0], [1, 0]], [[0, 0], [0, 1]]]]) + + # Test diff with tuples: + + dB = B.diff([[a, b]]) + assert dB.shape == (2, 2, 1) + assert dB == Array([[[1], [0]], [[0], [1]]]) + + f = Function("f") + fxyz = f(x, y, z) + assert fxyz.diff([[x, y, z]]) == Array([fxyz.diff(x), fxyz.diff(y), fxyz.diff(z)]) + assert fxyz.diff(([x, y, z], 2)) == Array([ + [fxyz.diff(x, 2), fxyz.diff(x, y), fxyz.diff(x, z)], + [fxyz.diff(x, y), fxyz.diff(y, 2), fxyz.diff(y, z)], + [fxyz.diff(x, z), fxyz.diff(z, y), fxyz.diff(z, 2)], + ]) + + expr = sin(x)*exp(y) + assert expr.diff([[x, y]]) == Array([cos(x)*exp(y), sin(x)*exp(y)]) + assert expr.diff(y, ((x, y),)) == Array([cos(x)*exp(y), sin(x)*exp(y)]) + assert expr.diff(x, ((x, y),)) == Array([-sin(x)*exp(y), cos(x)*exp(y)]) + assert expr.diff(((y, x),), [[x, y]]) == Array([[cos(x)*exp(y), -sin(x)*exp(y)], [sin(x)*exp(y), cos(x)*exp(y)]]) + + # Test different notations: + + assert fxyz.diff(x).diff(y).diff(x) == fxyz.diff(((x, y, z),), 3)[0, 1, 0] + assert fxyz.diff(z).diff(y).diff(x) == fxyz.diff(((x, y, z),), 3)[2, 1, 0] + assert fxyz.diff([[x, y, z]], ((z, y, x),)) == Array([[fxyz.diff(i).diff(j) for i in (x, y, z)] for j in (z, y, x)]) + + # Test scalar derived by matrix remains matrix: + res = x.diff(Matrix([[x, y]])) + assert isinstance(res, ImmutableDenseMatrix) + assert res == Matrix([[1, 0]]) + res = (x**3).diff(Matrix([[x, y]])) + assert isinstance(res, ImmutableDenseMatrix) + assert res == Matrix([[3*x**2, 0]]) + + +def test_getattr(): + A = Matrix(((1, 4, x), (y, 2, 4), (10, 5, x**2 + 1))) + raises(AttributeError, lambda: A.nonexistantattribute) + assert getattr(A, 'diff')(x) == Matrix(((0, 0, 1), (0, 0, 0), (0, 0, 2*x))) + + +def test_hessenberg(): + A = Matrix([[3, 4, 1], [2, 4, 5], [0, 1, 2]]) + assert A.is_upper_hessenberg + A = A.T + assert A.is_lower_hessenberg + A[0, -1] = 1 + assert A.is_lower_hessenberg is False + + A = Matrix([[3, 4, 1], [2, 4, 5], [3, 1, 2]]) + assert not A.is_upper_hessenberg + + A = zeros(5, 2) + assert A.is_upper_hessenberg + + +def test_cholesky(): + raises(NonSquareMatrixError, lambda: Matrix((1, 2)).cholesky()) + raises(ValueError, lambda: Matrix(((1, 2), (3, 4))).cholesky()) + raises(ValueError, lambda: Matrix(((5 + I, 0), (0, 1))).cholesky()) + raises(ValueError, lambda: Matrix(((1, 5), (5, 1))).cholesky()) + raises(ValueError, lambda: Matrix(((1, 2), (3, 4))).cholesky(hermitian=False)) + assert Matrix(((5 + I, 0), (0, 1))).cholesky(hermitian=False) == Matrix([ + [sqrt(5 + I), 0], [0, 1]]) + A = Matrix(((1, 5), (5, 1))) + L = A.cholesky(hermitian=False) + assert L == Matrix([[1, 0], [5, 2*sqrt(6)*I]]) + assert L*L.T == A + A = Matrix(((25, 15, -5), (15, 18, 0), (-5, 0, 11))) + L = A.cholesky() + assert L * L.T == A + assert L.is_lower + assert L == Matrix([[5, 0, 0], [3, 3, 0], [-1, 1, 3]]) + A = Matrix(((4, -2*I, 2 + 2*I), (2*I, 2, -1 + I), (2 - 2*I, -1 - I, 11))) + assert A.cholesky().expand() == Matrix(((2, 0, 0), (I, 1, 0), (1 - I, 0, 3))) + + raises(NonSquareMatrixError, lambda: SparseMatrix((1, 2)).cholesky()) + raises(ValueError, lambda: SparseMatrix(((1, 2), (3, 4))).cholesky()) + raises(ValueError, lambda: SparseMatrix(((5 + I, 0), (0, 1))).cholesky()) + raises(ValueError, lambda: SparseMatrix(((1, 5), (5, 1))).cholesky()) + raises(ValueError, lambda: SparseMatrix(((1, 2), (3, 4))).cholesky(hermitian=False)) + assert SparseMatrix(((5 + I, 0), (0, 1))).cholesky(hermitian=False) == Matrix([ + [sqrt(5 + I), 0], [0, 1]]) + A = SparseMatrix(((1, 5), (5, 1))) + L = A.cholesky(hermitian=False) + assert L == Matrix([[1, 0], [5, 2*sqrt(6)*I]]) + assert L*L.T == A + A = SparseMatrix(((25, 15, -5), (15, 18, 0), (-5, 0, 11))) + L = A.cholesky() + assert L * L.T == A + assert L.is_lower + assert L == Matrix([[5, 0, 0], [3, 3, 0], [-1, 1, 3]]) + A = SparseMatrix(((4, -2*I, 2 + 2*I), (2*I, 2, -1 + I), (2 - 2*I, -1 - I, 11))) + assert A.cholesky() == Matrix(((2, 0, 0), (I, 1, 0), (1 - I, 0, 3))) + + +def test_matrix_norm(): + # Vector Tests + # Test columns and symbols + x = Symbol('x', real=True) + v = Matrix([cos(x), sin(x)]) + assert trigsimp(v.norm(2)) == 1 + assert v.norm(10) == Pow(cos(x)**10 + sin(x)**10, Rational(1, 10)) + + # Test Rows + A = Matrix([[5, Rational(3, 2)]]) + assert A.norm() == Pow(25 + Rational(9, 4), S.Half) + assert A.norm(oo) == max(A) + assert A.norm(-oo) == min(A) + + # Matrix Tests + # Intuitive test + A = Matrix([[1, 1], [1, 1]]) + assert A.norm(2) == 2 + assert A.norm(-2) == 0 + assert A.norm('frobenius') == 2 + assert eye(10).norm(2) == eye(10).norm(-2) == 1 + assert A.norm(oo) == 2 + + # Test with Symbols and more complex entries + A = Matrix([[3, y, y], [x, S.Half, -pi]]) + assert (A.norm('fro') + == sqrt(Rational(37, 4) + 2*abs(y)**2 + pi**2 + x**2)) + + # Check non-square + A = Matrix([[1, 2, -3], [4, 5, Rational(13, 2)]]) + assert A.norm(2) == sqrt(Rational(389, 8) + sqrt(78665)/8) + assert A.norm(-2) is S.Zero + assert A.norm('frobenius') == sqrt(389)/2 + + # Test properties of matrix norms + # https://en.wikipedia.org/wiki/Matrix_norm#Definition + # Two matrices + A = Matrix([[1, 2], [3, 4]]) + B = Matrix([[5, 5], [-2, 2]]) + C = Matrix([[0, -I], [I, 0]]) + D = Matrix([[1, 0], [0, -1]]) + L = [A, B, C, D] + alpha = Symbol('alpha', real=True) + + for order in ['fro', 2, -2]: + # Zero Check + assert zeros(3).norm(order) is S.Zero + # Check Triangle Inequality for all Pairs of Matrices + for X in L: + for Y in L: + dif = (X.norm(order) + Y.norm(order) - + (X + Y).norm(order)) + assert (dif >= 0) + # Scalar multiplication linearity + for M in [A, B, C, D]: + dif = simplify((alpha*M).norm(order) - + abs(alpha) * M.norm(order)) + assert dif == 0 + + # Test Properties of Vector Norms + # https://en.wikipedia.org/wiki/Vector_norm + # Two column vectors + a = Matrix([1, 1 - 1*I, -3]) + b = Matrix([S.Half, 1*I, 1]) + c = Matrix([-1, -1, -1]) + d = Matrix([3, 2, I]) + e = Matrix([Integer(1e2), Rational(1, 1e2), 1]) + L = [a, b, c, d, e] + alpha = Symbol('alpha', real=True) + + for order in [1, 2, -1, -2, S.Infinity, S.NegativeInfinity, pi]: + # Zero Check + if order > 0: + assert Matrix([0, 0, 0]).norm(order) is S.Zero + # Triangle inequality on all pairs + if order >= 1: # Triangle InEq holds only for these norms + for X in L: + for Y in L: + dif = (X.norm(order) + Y.norm(order) - + (X + Y).norm(order)) + assert simplify(dif >= 0) is S.true + # Linear to scalar multiplication + if order in [1, 2, -1, -2, S.Infinity, S.NegativeInfinity]: + for X in L: + dif = simplify((alpha*X).norm(order) - + (abs(alpha) * X.norm(order))) + assert dif == 0 + + # ord=1 + M = Matrix(3, 3, [1, 3, 0, -2, -1, 0, 3, 9, 6]) + assert M.norm(1) == 13 + + +def test_condition_number(): + x = Symbol('x', real=True) + A = eye(3) + A[0, 0] = 10 + A[2, 2] = Rational(1, 10) + assert A.condition_number() == 100 + + A[1, 1] = x + assert A.condition_number() == Max(10, Abs(x)) / Min(Rational(1, 10), Abs(x)) + + M = Matrix([[cos(x), sin(x)], [-sin(x), cos(x)]]) + Mc = M.condition_number() + assert all(Float(1.).epsilon_eq(Mc.subs(x, val).evalf()) for val in + [Rational(1, 5), S.Half, Rational(1, 10), pi/2, pi, pi*Rational(7, 4) ]) + + #issue 10782 + assert Matrix([]).condition_number() == 0 + + +def test_equality(): + A = Matrix(((1, 2, 3), (4, 5, 6), (7, 8, 9))) + B = Matrix(((9, 8, 7), (6, 5, 4), (3, 2, 1))) + assert A == A[:, :] + assert not A != A[:, :] + assert not A == B + assert A != B + assert A != 10 + assert not A == 10 + + # A SparseMatrix can be equal to a Matrix + C = SparseMatrix(((1, 0, 0), (0, 1, 0), (0, 0, 1))) + D = Matrix(((1, 0, 0), (0, 1, 0), (0, 0, 1))) + assert C == D + assert not C != D + + +def test_normalized(): + assert Matrix([3, 4]).normalized() == \ + Matrix([Rational(3, 5), Rational(4, 5)]) + + # Zero vector trivial cases + assert Matrix([0, 0, 0]).normalized() == Matrix([0, 0, 0]) + + # Machine precision error truncation trivial cases + m = Matrix([0,0,1.e-100]) + assert m.normalized( + iszerofunc=lambda x: x.evalf(n=10, chop=True).is_zero + ) == Matrix([0, 0, 0]) + + +def test_print_nonzero(): + assert capture(lambda: eye(3).print_nonzero()) == \ + '[X ]\n[ X ]\n[ X]\n' + assert capture(lambda: eye(3).print_nonzero('.')) == \ + '[. ]\n[ . ]\n[ .]\n' + + +def test_zeros_eye(): + assert Matrix.eye(3) == eye(3) + assert Matrix.zeros(3) == zeros(3) + assert ones(3, 4) == Matrix(3, 4, [1]*12) + + i = Matrix([[1, 0], [0, 1]]) + z = Matrix([[0, 0], [0, 0]]) + for cls in all_classes: + m = cls.eye(2) + assert i == m # but m == i will fail if m is immutable + assert i == eye(2, cls=cls) + assert type(m) == cls + m = cls.zeros(2) + assert z == m + assert z == zeros(2, cls=cls) + assert type(m) == cls + + +def test_is_zero(): + assert Matrix().is_zero_matrix + assert Matrix([[0, 0], [0, 0]]).is_zero_matrix + assert zeros(3, 4).is_zero_matrix + assert not eye(3).is_zero_matrix + assert Matrix([[x, 0], [0, 0]]).is_zero_matrix == None + assert SparseMatrix([[x, 0], [0, 0]]).is_zero_matrix == None + assert ImmutableMatrix([[x, 0], [0, 0]]).is_zero_matrix == None + assert ImmutableSparseMatrix([[x, 0], [0, 0]]).is_zero_matrix == None + assert Matrix([[x, 1], [0, 0]]).is_zero_matrix == False + a = Symbol('a', nonzero=True) + assert Matrix([[a, 0], [0, 0]]).is_zero_matrix == False + + +def test_rotation_matrices(): + # This tests the rotation matrices by rotating about an axis and back. + theta = pi/3 + r3_plus = rot_axis3(theta) + r3_minus = rot_axis3(-theta) + r2_plus = rot_axis2(theta) + r2_minus = rot_axis2(-theta) + r1_plus = rot_axis1(theta) + r1_minus = rot_axis1(-theta) + assert r3_minus*r3_plus*eye(3) == eye(3) + assert r2_minus*r2_plus*eye(3) == eye(3) + assert r1_minus*r1_plus*eye(3) == eye(3) + + # Check the correctness of the trace of the rotation matrix + assert r1_plus.trace() == 1 + 2*cos(theta) + assert r2_plus.trace() == 1 + 2*cos(theta) + assert r3_plus.trace() == 1 + 2*cos(theta) + + # Check that a rotation with zero angle doesn't change anything. + assert rot_axis1(0) == eye(3) + assert rot_axis2(0) == eye(3) + assert rot_axis3(0) == eye(3) + + # Check left-hand convention + # see Issue #24529 + q1 = Quaternion.from_axis_angle([1, 0, 0], pi / 2) + q2 = Quaternion.from_axis_angle([0, 1, 0], pi / 2) + q3 = Quaternion.from_axis_angle([0, 0, 1], pi / 2) + assert rot_axis1(- pi / 2) == q1.to_rotation_matrix() + assert rot_axis2(- pi / 2) == q2.to_rotation_matrix() + assert rot_axis3(- pi / 2) == q3.to_rotation_matrix() + # Check right-hand convention + assert rot_ccw_axis1(+ pi / 2) == q1.to_rotation_matrix() + assert rot_ccw_axis2(+ pi / 2) == q2.to_rotation_matrix() + assert rot_ccw_axis3(+ pi / 2) == q3.to_rotation_matrix() + + +def test_DeferredVector(): + assert str(DeferredVector("vector")[4]) == "vector[4]" + assert sympify(DeferredVector("d")) == DeferredVector("d") + raises(IndexError, lambda: DeferredVector("d")[-1]) + assert str(DeferredVector("d")) == "d" + assert repr(DeferredVector("test")) == "DeferredVector('test')" + + +def test_DeferredVector_not_iterable(): + assert not iterable(DeferredVector('X')) + + +def test_DeferredVector_Matrix(): + raises(TypeError, lambda: Matrix(DeferredVector("V"))) + + +def test_GramSchmidt(): + R = Rational + m1 = Matrix(1, 2, [1, 2]) + m2 = Matrix(1, 2, [2, 3]) + assert GramSchmidt([m1, m2]) == \ + [Matrix(1, 2, [1, 2]), Matrix(1, 2, [R(2)/5, R(-1)/5])] + assert GramSchmidt([m1.T, m2.T]) == \ + [Matrix(2, 1, [1, 2]), Matrix(2, 1, [R(2)/5, R(-1)/5])] + # from wikipedia + assert GramSchmidt([Matrix([3, 1]), Matrix([2, 2])], True) == [ + Matrix([3*sqrt(10)/10, sqrt(10)/10]), + Matrix([-sqrt(10)/10, 3*sqrt(10)/10])] + # https://github.com/sympy/sympy/issues/9488 + L = FiniteSet(Matrix([1])) + assert GramSchmidt(L) == [Matrix([[1]])] + + +def test_casoratian(): + assert casoratian([1, 2, 3, 4], 1) == 0 + assert casoratian([1, 2, 3, 4], 1, zero=False) == 0 + + +def test_zero_dimension_multiply(): + assert (Matrix()*zeros(0, 3)).shape == (0, 3) + assert zeros(3, 0)*zeros(0, 3) == zeros(3, 3) + assert zeros(0, 3)*zeros(3, 0) == Matrix() + + +def test_slice_issue_2884(): + m = Matrix(2, 2, range(4)) + assert m[1, :] == Matrix([[2, 3]]) + assert m[-1, :] == Matrix([[2, 3]]) + assert m[:, 1] == Matrix([[1, 3]]).T + assert m[:, -1] == Matrix([[1, 3]]).T + raises(IndexError, lambda: m[2, :]) + raises(IndexError, lambda: m[2, 2]) + + +def test_slice_issue_3401(): + assert zeros(0, 3)[:, -1].shape == (0, 1) + assert zeros(3, 0)[0, :] == Matrix(1, 0, []) + + +def test_copyin(): + s = zeros(3, 3) + s[3] = 1 + assert s[:, 0] == Matrix([0, 1, 0]) + assert s[3] == 1 + assert s[3: 4] == [1] + s[1, 1] = 42 + assert s[1, 1] == 42 + assert s[1, 1:] == Matrix([[42, 0]]) + s[1, 1:] = Matrix([[5, 6]]) + assert s[1, :] == Matrix([[1, 5, 6]]) + s[1, 1:] = [[42, 43]] + assert s[1, :] == Matrix([[1, 42, 43]]) + s[0, 0] = 17 + assert s[:, :1] == Matrix([17, 1, 0]) + s[0, 0] = [1, 1, 1] + assert s[:, 0] == Matrix([1, 1, 1]) + s[0, 0] = Matrix([1, 1, 1]) + assert s[:, 0] == Matrix([1, 1, 1]) + s[0, 0] = SparseMatrix([1, 1, 1]) + assert s[:, 0] == Matrix([1, 1, 1]) + + +def test_invertible_check(): + # sometimes a singular matrix will have a pivot vector shorter than + # the number of rows in a matrix... + assert Matrix([[1, 2], [1, 2]]).rref() == (Matrix([[1, 2], [0, 0]]), (0,)) + raises(ValueError, lambda: Matrix([[1, 2], [1, 2]]).inv()) + m = Matrix([ + [-1, -1, 0], + [ x, 1, 1], + [ 1, x, -1], + ]) + assert len(m.rref()[1]) != m.rows + # in addition, unless simplify=True in the call to rref, the identity + # matrix will be returned even though m is not invertible + assert m.rref()[0] != eye(3) + assert m.rref(simplify=signsimp)[0] != eye(3) + raises(ValueError, lambda: m.inv(method="ADJ")) + raises(ValueError, lambda: m.inv(method="GE")) + raises(ValueError, lambda: m.inv(method="LU")) + + +def test_issue_3959(): + x, y = symbols('x, y') + e = x*y + assert e.subs(x, Matrix([3, 5, 3])) == Matrix([3, 5, 3])*y + + +def test_issue_5964(): + assert str(Matrix([[1, 2], [3, 4]])) == 'Matrix([[1, 2], [3, 4]])' + + +def test_issue_7604(): + x, y = symbols("x y") + assert sstr(Matrix([[x, 2*y], [y**2, x + 3]])) == \ + 'Matrix([\n[ x, 2*y],\n[y**2, x + 3]])' + + +def test_is_Identity(): + assert eye(3).is_Identity + assert eye(3).as_immutable().is_Identity + assert not zeros(3).is_Identity + assert not ones(3).is_Identity + # issue 6242 + assert not Matrix([[1, 0, 0]]).is_Identity + # issue 8854 + assert SparseMatrix(3,3, {(0,0):1, (1,1):1, (2,2):1}).is_Identity + assert not SparseMatrix(2,3, range(6)).is_Identity + assert not SparseMatrix(3,3, {(0,0):1, (1,1):1}).is_Identity + assert not SparseMatrix(3,3, {(0,0):1, (1,1):1, (2,2):1, (0,1):2, (0,2):3}).is_Identity + + +def test_dot(): + assert ones(1, 3).dot(ones(3, 1)) == 3 + assert ones(1, 3).dot([1, 1, 1]) == 3 + assert Matrix([1, 2, 3]).dot(Matrix([1, 2, 3])) == 14 + assert Matrix([1, 2, 3*I]).dot(Matrix([I, 2, 3*I])) == -5 + I + assert Matrix([1, 2, 3*I]).dot(Matrix([I, 2, 3*I]), hermitian=False) == -5 + I + assert Matrix([1, 2, 3*I]).dot(Matrix([I, 2, 3*I]), hermitian=True) == 13 + I + assert Matrix([1, 2, 3*I]).dot(Matrix([I, 2, 3*I]), hermitian=True, conjugate_convention="physics") == 13 - I + assert Matrix([1, 2, 3*I]).dot(Matrix([4, 5*I, 6]), hermitian=True, conjugate_convention="right") == 4 + 8*I + assert Matrix([1, 2, 3*I]).dot(Matrix([4, 5*I, 6]), hermitian=True, conjugate_convention="left") == 4 - 8*I + assert Matrix([I, 2*I]).dot(Matrix([I, 2*I]), hermitian=False, conjugate_convention="left") == -5 + assert Matrix([I, 2*I]).dot(Matrix([I, 2*I]), conjugate_convention="left") == 5 + raises(ValueError, lambda: Matrix([1, 2]).dot(Matrix([3, 4]), hermitian=True, conjugate_convention="test")) + + +def test_dual(): + B_x, B_y, B_z, E_x, E_y, E_z = symbols( + 'B_x B_y B_z E_x E_y E_z', real=True) + F = Matrix(( + ( 0, E_x, E_y, E_z), + (-E_x, 0, B_z, -B_y), + (-E_y, -B_z, 0, B_x), + (-E_z, B_y, -B_x, 0) + )) + Fd = Matrix(( + ( 0, -B_x, -B_y, -B_z), + (B_x, 0, E_z, -E_y), + (B_y, -E_z, 0, E_x), + (B_z, E_y, -E_x, 0) + )) + assert F.dual().equals(Fd) + assert eye(3).dual().equals(zeros(3)) + assert F.dual().dual().equals(-F) + + +def test_anti_symmetric(): + assert Matrix([1, 2]).is_anti_symmetric() is False + m = Matrix(3, 3, [0, x**2 + 2*x + 1, y, -(x + 1)**2, 0, x*y, -y, -x*y, 0]) + assert m.is_anti_symmetric() is True + assert m.is_anti_symmetric(simplify=False) is None + assert m.is_anti_symmetric(simplify=lambda x: x) is None + + # tweak to fail + m[2, 1] = -m[2, 1] + assert m.is_anti_symmetric() is None + # untweak + m[2, 1] = -m[2, 1] + + m = m.expand() + assert m.is_anti_symmetric(simplify=False) is True + m[0, 0] = 1 + assert m.is_anti_symmetric() is False + + +def test_normalize_sort_diogonalization(): + A = Matrix(((1, 2), (2, 1))) + P, Q = A.diagonalize(normalize=True) + assert P*P.T == P.T*P == eye(P.cols) + P, Q = A.diagonalize(normalize=True, sort=True) + assert P*P.T == P.T*P == eye(P.cols) + assert P*Q*P.inv() == A + + +def test_issue_5321(): + raises(ValueError, lambda: Matrix([[1, 2, 3], Matrix(0, 1, [])])) + + +def test_issue_5320(): + assert Matrix.hstack(eye(2), 2*eye(2)) == Matrix([ + [1, 0, 2, 0], + [0, 1, 0, 2] + ]) + assert Matrix.vstack(eye(2), 2*eye(2)) == Matrix([ + [1, 0], + [0, 1], + [2, 0], + [0, 2] + ]) + cls = SparseMatrix + assert cls.hstack(cls(eye(2)), cls(2*eye(2))) == Matrix([ + [1, 0, 2, 0], + [0, 1, 0, 2] + ]) + + +def test_issue_11944(): + A = Matrix([[1]]) + AIm = sympify(A) + assert Matrix.hstack(AIm, A) == Matrix([[1, 1]]) + assert Matrix.vstack(AIm, A) == Matrix([[1], [1]]) + + +def test_cross(): + a = [1, 2, 3] + b = [3, 4, 5] + col = Matrix([-2, 4, -2]) + row = col.T + + def test(M, ans): + assert ans == M + assert type(M) == cls + for cls in all_classes: + A = cls(a) + B = cls(b) + test(A.cross(B), col) + test(A.cross(B.T), col) + test(A.T.cross(B.T), row) + test(A.T.cross(B), row) + raises(ShapeError, lambda: + Matrix(1, 2, [1, 1]).cross(Matrix(1, 2, [1, 1]))) + + +def test_hat_vee(): + v1 = Matrix([x, y, z]) + v2 = Matrix([a, b, c]) + assert v1.hat() * v2 == v1.cross(v2) + assert v1.hat().is_anti_symmetric() + assert v1.hat().vee() == v1 + + +def test_hash(): + for cls in immutable_classes: + s = {cls.eye(1), cls.eye(1)} + assert len(s) == 1 and s.pop() == cls.eye(1) + # issue 3979 + for cls in mutable_classes: + assert not isinstance(cls.eye(1), Hashable) + + +def test_adjoint(): + dat = [[0, I], [1, 0]] + ans = Matrix([[0, 1], [-I, 0]]) + for cls in all_classes: + assert ans == cls(dat).adjoint() + + +def test_atoms(): + m = Matrix([[1, 2], [x, 1 - 1/x]]) + assert m.atoms() == {S.One,S(2),S.NegativeOne, x} + assert m.atoms(Symbol) == {x} + + +def test_pinv(): + # Pseudoinverse of an invertible matrix is the inverse. + A1 = Matrix([[a, b], [c, d]]) + assert simplify(A1.pinv(method="RD")) == simplify(A1.inv()) + + # Test the four properties of the pseudoinverse for various matrices. + As = [Matrix([[13, 104], [2212, 3], [-3, 5]]), + Matrix([[1, 7, 9], [11, 17, 19]]), + Matrix([a, b])] + + for A in As: + A_pinv = A.pinv(method="RD") + AAp = A * A_pinv + ApA = A_pinv * A + assert simplify(AAp * A) == A + assert simplify(ApA * A_pinv) == A_pinv + assert AAp.H == AAp + assert ApA.H == ApA + + # XXX Pinv with diagonalization makes expression too complicated. + for A in As: + A_pinv = simplify(A.pinv(method="ED")) + AAp = A * A_pinv + ApA = A_pinv * A + assert simplify(AAp * A) == A + assert simplify(ApA * A_pinv) == A_pinv + assert AAp.H == AAp + assert ApA.H == ApA + + # XXX Computing pinv using diagonalization makes an expression that + # is too complicated to simplify. + # A1 = Matrix([[a, b], [c, d]]) + # assert simplify(A1.pinv(method="ED")) == simplify(A1.inv()) + # so this is tested numerically at a fixed random point + + from sympy.core.numbers import comp + q = A1.pinv(method="ED") + w = A1.inv() + reps = {a: -73633, b: 11362, c: 55486, d: 62570} + assert all( + comp(i.n(), j.n()) + for i, j in zip(q.subs(reps), w.subs(reps)) + ) + + +@slow +def test_pinv_rank_deficient_when_diagonalization_fails(): + # Test the four properties of the pseudoinverse for matrices when + # diagonalization of A.H*A fails. + As = [ + Matrix([ + [61, 89, 55, 20, 71, 0], + [62, 96, 85, 85, 16, 0], + [69, 56, 17, 4, 54, 0], + [10, 54, 91, 41, 71, 0], + [ 7, 30, 10, 48, 90, 0], + [0, 0, 0, 0, 0, 0]]) + ] + for A in As: + A_pinv = A.pinv(method="ED") + AAp = A * A_pinv + ApA = A_pinv * A + assert AAp.H == AAp + + # Here ApA.H and ApA are equivalent expressions but they are very + # complicated expressions involving RootOfs. Using simplify would be + # too slow and so would evalf so we substitute approximate values for + # the RootOfs and then evalf which is less accurate but good enough to + # confirm that these two matrices are equivalent. + # + # assert ApA.H == ApA # <--- would fail (structural equality) + # assert simplify(ApA.H - ApA).is_zero_matrix # <--- too slow + # (ApA.H - ApA).evalf() # <--- too slow + + def allclose(M1, M2): + rootofs = M1.atoms(RootOf) + rootofs_approx = {r: r.evalf() for r in rootofs} + diff_approx = (M1 - M2).xreplace(rootofs_approx).evalf() + return all(abs(e) < 1e-10 for e in diff_approx) + + assert allclose(ApA.H, ApA) + + +def test_issue_7201(): + assert ones(0, 1) + ones(0, 1) == Matrix(0, 1, []) + assert ones(1, 0) + ones(1, 0) == Matrix(1, 0, []) + + +def test_free_symbols(): + for M in ImmutableMatrix, ImmutableSparseMatrix, Matrix, SparseMatrix: + assert M([[x], [0]]).free_symbols == {x} + + +def test_from_ndarray(): + """See issue 7465.""" + try: + from numpy import array + except ImportError: + skip('NumPy must be available to test creating matrices from ndarrays') + + assert Matrix(array([1, 2, 3])) == Matrix([1, 2, 3]) + assert Matrix(array([[1, 2, 3]])) == Matrix([[1, 2, 3]]) + assert Matrix(array([[1, 2, 3], [4, 5, 6]])) == \ + Matrix([[1, 2, 3], [4, 5, 6]]) + assert Matrix(array([x, y, z])) == Matrix([x, y, z]) + raises(NotImplementedError, + lambda: Matrix(array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]))) + assert Matrix([array([1, 2]), array([3, 4])]) == Matrix([[1, 2], [3, 4]]) + assert Matrix([array([1, 2]), [3, 4]]) == Matrix([[1, 2], [3, 4]]) + assert Matrix([array([]), array([])]) == Matrix(2, 0, []) != Matrix([]) + + +def test_17522_numpy(): + from sympy.matrices.common import _matrixify + try: + from numpy import array, matrix + except ImportError: + skip('NumPy must be available to test indexing matrixified NumPy ndarrays and matrices') + + m = _matrixify(array([[1, 2], [3, 4]])) + assert m[3] == 4 + assert list(m) == [1, 2, 3, 4] + + with ignore_warnings(PendingDeprecationWarning): + m = _matrixify(matrix([[1, 2], [3, 4]])) + assert m[3] == 4 + assert list(m) == [1, 2, 3, 4] + + +def test_17522_mpmath(): + from sympy.matrices.common import _matrixify + try: + from mpmath import matrix + except ImportError: + skip('mpmath must be available to test indexing matrixified mpmath matrices') + + m = _matrixify(matrix([[1, 2], [3, 4]])) + assert m[3] == 4.0 + assert list(m) == [1.0, 2.0, 3.0, 4.0] + + +def test_17522_scipy(): + from sympy.matrices.common import _matrixify + try: + from scipy.sparse import csr_matrix + except ImportError: + skip('SciPy must be available to test indexing matrixified SciPy sparse matrices') + + m = _matrixify(csr_matrix([[1, 2], [3, 4]])) + assert m[3] == 4 + assert list(m) == [1, 2, 3, 4] + + +def test_hermitian(): + a = Matrix([[1, I], [-I, 1]]) + assert a.is_hermitian + a[0, 0] = 2*I + assert a.is_hermitian is False + a[0, 0] = x + assert a.is_hermitian is None + a[0, 1] = a[1, 0]*I + assert a.is_hermitian is False + + +def test_issue_9457_9467_9876(): + # for row_del(index) + M = Matrix([[1, 2, 3], [2, 3, 4], [3, 4, 5]]) + M.row_del(1) + assert M == Matrix([[1, 2, 3], [3, 4, 5]]) + N = Matrix([[1, 2, 3], [2, 3, 4], [3, 4, 5]]) + N.row_del(-2) + assert N == Matrix([[1, 2, 3], [3, 4, 5]]) + O = Matrix([[1, 2, 3], [5, 6, 7], [9, 10, 11]]) + O.row_del(-1) + assert O == Matrix([[1, 2, 3], [5, 6, 7]]) + P = Matrix([[1, 2, 3], [2, 3, 4], [3, 4, 5]]) + raises(IndexError, lambda: P.row_del(10)) + Q = Matrix([[1, 2, 3], [2, 3, 4], [3, 4, 5]]) + raises(IndexError, lambda: Q.row_del(-10)) + + # for col_del(index) + M = Matrix([[1, 2, 3], [2, 3, 4], [3, 4, 5]]) + M.col_del(1) + assert M == Matrix([[1, 3], [2, 4], [3, 5]]) + N = Matrix([[1, 2, 3], [2, 3, 4], [3, 4, 5]]) + N.col_del(-2) + assert N == Matrix([[1, 3], [2, 4], [3, 5]]) + P = Matrix([[1, 2, 3], [2, 3, 4], [3, 4, 5]]) + raises(IndexError, lambda: P.col_del(10)) + Q = Matrix([[1, 2, 3], [2, 3, 4], [3, 4, 5]]) + raises(IndexError, lambda: Q.col_del(-10)) + + +def test_issue_9422(): + x, y = symbols('x y', commutative=False) + a, b = symbols('a b') + M = eye(2) + M1 = Matrix(2, 2, [x, y, y, z]) + assert y*x*M != x*y*M + assert b*a*M == a*b*M + assert x*M1 != M1*x + assert a*M1 == M1*a + assert y*x*M == Matrix([[y*x, 0], [0, y*x]]) + + +def test_issue_10770(): + M = Matrix([]) + a = ['col_insert', 'row_join'], Matrix([9, 6, 3]) + b = ['row_insert', 'col_join'], a[1].T + c = ['row_insert', 'col_insert'], Matrix([[1, 2], [3, 4]]) + for ops, m in (a, b, c): + for op in ops: + f = getattr(M, op) + new = f(m) if 'join' in op else f(42, m) + assert new == m and id(new) != id(m) + + +def test_issue_10658(): + A = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + assert A.extract([0, 1, 2], [True, True, False]) == \ + Matrix([[1, 2], [4, 5], [7, 8]]) + assert A.extract([0, 1, 2], [True, False, False]) == Matrix([[1], [4], [7]]) + assert A.extract([True, False, False], [0, 1, 2]) == Matrix([[1, 2, 3]]) + assert A.extract([True, False, True], [0, 1, 2]) == \ + Matrix([[1, 2, 3], [7, 8, 9]]) + assert A.extract([0, 1, 2], [False, False, False]) == Matrix(3, 0, []) + assert A.extract([False, False, False], [0, 1, 2]) == Matrix(0, 3, []) + assert A.extract([True, False, True], [False, True, False]) == \ + Matrix([[2], [8]]) + + +def test_opportunistic_simplification(): + # this test relates to issue #10718, #9480, #11434 + + # issue #9480 + m = Matrix([[-5 + 5*sqrt(2), -5], [-5*sqrt(2)/2 + 5, -5*sqrt(2)/2]]) + assert m.rank() == 1 + + # issue #10781 + m = Matrix([[3+3*sqrt(3)*I, -9],[4,-3+3*sqrt(3)*I]]) + assert simplify(m.rref()[0] - Matrix([[1, -9/(3 + 3*sqrt(3)*I)], [0, 0]])) == zeros(2, 2) + + # issue #11434 + ax,ay,bx,by,cx,cy,dx,dy,ex,ey,t0,t1 = symbols('a_x a_y b_x b_y c_x c_y d_x d_y e_x e_y t_0 t_1') + m = Matrix([[ax,ay,ax*t0,ay*t0,0],[bx,by,bx*t0,by*t0,0],[cx,cy,cx*t0,cy*t0,1],[dx,dy,dx*t0,dy*t0,1],[ex,ey,2*ex*t1-ex*t0,2*ey*t1-ey*t0,0]]) + assert m.rank() == 4 + + +def test_partial_pivoting(): + # example from https://en.wikipedia.org/wiki/Pivot_element + # partial pivoting with back substitution gives a perfect result + # naive pivoting give an error ~1e-13, so anything better than + # 1e-15 is good + mm=Matrix([[0.003, 59.14, 59.17], [5.291, -6.13, 46.78]]) + assert (mm.rref()[0] - Matrix([[1.0, 0, 10.0], + [ 0, 1.0, 1.0]])).norm() < 1e-15 + + # issue #11549 + m_mixed = Matrix([[6e-17, 1.0, 4], + [ -1.0, 0, 8], + [ 0, 0, 1]]) + m_float = Matrix([[6e-17, 1.0, 4.], + [ -1.0, 0., 8.], + [ 0., 0., 1.]]) + m_inv = Matrix([[ 0, -1.0, 8.0], + [1.0, 6.0e-17, -4.0], + [ 0, 0, 1]]) + # this example is numerically unstable and involves a matrix with a norm >= 8, + # this comparing the difference of the results with 1e-15 is numerically sound. + assert (m_mixed.inv() - m_inv).norm() < 1e-15 + assert (m_float.inv() - m_inv).norm() < 1e-15 + + +def test_iszero_substitution(): + """ When doing numerical computations, all elements that pass + the iszerofunc test should be set to numerically zero if they + aren't already. """ + + # Matrix from issue #9060 + m = Matrix([[0.9, -0.1, -0.2, 0],[-0.8, 0.9, -0.4, 0],[-0.1, -0.8, 0.6, 0]]) + m_rref = m.rref(iszerofunc=lambda x: abs(x)<6e-15)[0] + m_correct = Matrix([[1.0, 0, -0.301369863013699, 0],[ 0, 1.0, -0.712328767123288, 0],[ 0, 0, 0, 0]]) + m_diff = m_rref - m_correct + assert m_diff.norm() < 1e-15 + # if a zero-substitution wasn't made, this entry will be -1.11022302462516e-16 + assert m_rref[2,2] == 0 + + +def test_issue_11238(): + from sympy.geometry.point import Point + xx = 8*tan(pi*Rational(13, 45))/(tan(pi*Rational(13, 45)) + sqrt(3)) + yy = (-8*sqrt(3)*tan(pi*Rational(13, 45))**2 + 24*tan(pi*Rational(13, 45)))/(-3 + tan(pi*Rational(13, 45))**2) + p1 = Point(0, 0) + p2 = Point(1, -sqrt(3)) + p0 = Point(xx,yy) + m1 = Matrix([p1 - simplify(p0), p2 - simplify(p0)]) + m2 = Matrix([p1 - p0, p2 - p0]) + m3 = Matrix([simplify(p1 - p0), simplify(p2 - p0)]) + + # This system has expressions which are zero and + # cannot be easily proved to be such, so without + # numerical testing, these assertions will fail. + Z = lambda x: abs(x.n()) < 1e-20 + assert m1.rank(simplify=True, iszerofunc=Z) == 1 + assert m2.rank(simplify=True, iszerofunc=Z) == 1 + assert m3.rank(simplify=True, iszerofunc=Z) == 1 + + +def test_as_real_imag(): + m1 = Matrix(2,2,[1,2,3,4]) + m2 = m1*S.ImaginaryUnit + m3 = m1 + m2 + + for kls in all_classes: + a,b = kls(m3).as_real_imag() + assert list(a) == list(m1) + assert list(b) == list(m1) + + +def test_deprecated(): + # Maintain tests for deprecated functions. We must capture + # the deprecation warnings. When the deprecated functionality is + # removed, the corresponding tests should be removed. + + m = Matrix(3, 3, [0, 1, 0, -4, 4, 0, -2, 1, 2]) + P, Jcells = m.jordan_cells() + assert Jcells[1] == Matrix(1, 1, [2]) + assert Jcells[0] == Matrix(2, 2, [2, 1, 0, 2]) + + +def test_issue_14489(): + from sympy.core.mod import Mod + A = Matrix([-1, 1, 2]) + B = Matrix([10, 20, -15]) + + assert Mod(A, 3) == Matrix([2, 1, 2]) + assert Mod(B, 4) == Matrix([2, 0, 1]) + + +def test_issue_14943(): + # Test that __array__ accepts the optional dtype argument + try: + from numpy import array + except ImportError: + skip('NumPy must be available to test creating matrices from ndarrays') + + M = Matrix([[1,2], [3,4]]) + assert array(M, dtype=float).dtype.name == 'float64' + + +def test_case_6913(): + m = MatrixSymbol('m', 1, 1) + a = Symbol("a") + a = m[0, 0]>0 + assert str(a) == 'm[0, 0] > 0' + + +def test_issue_11948(): + A = MatrixSymbol('A', 3, 3) + a = Wild('a') + assert A.match(a) == {a: A} + + +def test_gramschmidt_conjugate_dot(): + vecs = [Matrix([1, I]), Matrix([1, -I])] + assert Matrix.orthogonalize(*vecs) == \ + [Matrix([[1], [I]]), Matrix([[1], [-I]])] + + vecs = [Matrix([1, I, 0]), Matrix([I, 0, -I])] + assert Matrix.orthogonalize(*vecs) == \ + [Matrix([[1], [I], [0]]), Matrix([[I/2], [S(1)/2], [-I]])] + + mat = Matrix([[1, I], [1, -I]]) + Q, R = mat.QRdecomposition() + assert Q * Q.H == Matrix.eye(2) + + +def test_issue_8207(): + a = Matrix(MatrixSymbol('a', 3, 1)) + b = Matrix(MatrixSymbol('b', 3, 1)) + c = a.dot(b) + d = diff(c, a[0, 0]) + e = diff(d, a[0, 0]) + assert d == b[0, 0] + assert e == 0 + + +def test_func(): + from sympy.simplify.simplify import nthroot + + A = Matrix([[1, 2],[0, 3]]) + assert A.analytic_func(sin(x*t), x) == Matrix([[sin(t), sin(3*t) - sin(t)], [0, sin(3*t)]]) + + A = Matrix([[2, 1],[1, 2]]) + assert (pi * A / 6).analytic_func(cos(x), x) == Matrix([[sqrt(3)/4, -sqrt(3)/4], [-sqrt(3)/4, sqrt(3)/4]]) + + + raises(ValueError, lambda : zeros(5).analytic_func(log(x), x)) + raises(ValueError, lambda : (A*x).analytic_func(log(x), x)) + + A = Matrix([[0, -1, -2, 3], [0, -1, -2, 3], [0, 1, 0, -1], [0, 0, -1, 1]]) + assert A.analytic_func(exp(x), x) == A.exp() + raises(ValueError, lambda : A.analytic_func(sqrt(x), x)) + + A = Matrix([[41, 12],[12, 34]]) + assert simplify(A.analytic_func(sqrt(x), x)**2) == A + + A = Matrix([[3, -12, 4], [-1, 0, -2], [-1, 5, -1]]) + assert simplify(A.analytic_func(nthroot(x, 3), x)**3) == A + + A = Matrix([[2, 0, 0, 0], [1, 2, 0, 0], [0, 1, 3, 0], [0, 0, 1, 3]]) + assert A.analytic_func(exp(x), x) == A.exp() + + A = Matrix([[0, 2, 1, 6], [0, 0, 1, 2], [0, 0, 0, 3], [0, 0, 0, 0]]) + assert A.analytic_func(exp(x*t), x) == expand(simplify((A*t).exp())) + + +@skip_under_pyodide("Cannot create threads under pyodide.") +def test_issue_19809(): + + def f(): + assert _dotprodsimp_state.state == None + m = Matrix([[1]]) + m = m * m + return True + + with dotprodsimp(True): + with concurrent.futures.ThreadPoolExecutor() as executor: + future = executor.submit(f) + assert future.result() + + +def test_issue_23276(): + M = Matrix([x, y]) + assert integrate(M, (x, 0, 1), (y, 0, 1)) == Matrix([ + [S.Half], + [S.Half]]) + + +def test_issue_27225(): + # https://github.com/sympy/sympy/issues/27225 + raises(TypeError, lambda : floor(Matrix([1, 1, 0]))) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_normalforms.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_normalforms.py new file mode 100644 index 0000000000000000000000000000000000000000..47ee52d73539f7fb79295443e1cf7e0a49e30a5e --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_normalforms.py @@ -0,0 +1,111 @@ +from sympy.testing.pytest import warns_deprecated_sympy + +from sympy.core.symbol import Symbol +from sympy.polys.polytools import Poly +from sympy.matrices import Matrix, randMatrix +from sympy.matrices.normalforms import ( + invariant_factors, + smith_normal_form, + smith_normal_decomp, + hermite_normal_form, + is_smith_normal_form, +) +from sympy.polys.domains import ZZ, QQ +from sympy.core.numbers import Integer + +import random + + +def test_smith_normal(): + m = Matrix([[12,6,4,8],[3,9,6,12],[2,16,14,28],[20,10,10,20]]) + smf = Matrix([[1, 0, 0, 0], [0, 10, 0, 0], [0, 0, 30, 0], [0, 0, 0, 0]]) + assert smith_normal_form(m) == smf + + a, s, t = smith_normal_decomp(m) + assert a == s * m * t + + x = Symbol('x') + with warns_deprecated_sympy(): + m = Matrix([[Poly(x-1), Poly(1, x),Poly(-1,x)], + [0, Poly(x), Poly(-1,x)], + [Poly(0,x),Poly(-1,x),Poly(x)]]) + invs = 1, x - 1, x**2 - 1 + assert invariant_factors(m, domain=QQ[x]) == invs + + m = Matrix([[2, 4]]) + smf = Matrix([[2, 0]]) + assert smith_normal_form(m) == smf + + prng = random.Random(0) + for i in range(6): + for j in range(6): + for _ in range(10 if i*j else 1): + m = randMatrix(i, j, max=5, percent=50, prng=prng) + a, s, t = smith_normal_decomp(m) + assert a == s * m * t + assert is_smith_normal_form(a) + s.inv().to_DM(ZZ) + t.inv().to_DM(ZZ) + + a, s, t = smith_normal_decomp(m, QQ) + assert a == s * m * t + assert is_smith_normal_form(a) + s.inv() + t.inv() + + +def test_smith_normal_deprecated(): + from sympy.polys.solvers import RawMatrix as Matrix + + with warns_deprecated_sympy(): + m = Matrix([[12, 6, 4,8],[3,9,6,12],[2,16,14,28],[20,10,10,20]]) + setattr(m, 'ring', ZZ) + with warns_deprecated_sympy(): + smf = Matrix([[1, 0, 0, 0], [0, 10, 0, 0], [0, 0, 30, 0], [0, 0, 0, 0]]) + assert smith_normal_form(m) == smf + + x = Symbol('x') + with warns_deprecated_sympy(): + m = Matrix([[Poly(x-1), Poly(1, x),Poly(-1,x)], + [0, Poly(x), Poly(-1,x)], + [Poly(0,x),Poly(-1,x),Poly(x)]]) + setattr(m, 'ring', QQ[x]) + invs = (Poly(1, x, domain='QQ'), Poly(x - 1, domain='QQ'), Poly(x**2 - 1, domain='QQ')) + assert invariant_factors(m) == invs + + with warns_deprecated_sympy(): + m = Matrix([[2, 4]]) + setattr(m, 'ring', ZZ) + with warns_deprecated_sympy(): + smf = Matrix([[2, 0]]) + assert smith_normal_form(m) == smf + + +def test_hermite_normal(): + m = Matrix([[2, 7, 17, 29, 41], [3, 11, 19, 31, 43], [5, 13, 23, 37, 47]]) + hnf = Matrix([[1, 0, 0], [0, 2, 1], [0, 0, 1]]) + assert hermite_normal_form(m) == hnf + + tr_hnf = Matrix([[37, 0, 19], [222, -6, 113], [48, 0, 25], [0, 2, 1], [0, 0, 1]]) + assert hermite_normal_form(m.transpose()) == tr_hnf + + m = Matrix([[8, 28, 68, 116, 164], [3, 11, 19, 31, 43], [5, 13, 23, 37, 47]]) + hnf = Matrix([[4, 0, 0], [0, 2, 1], [0, 0, 1]]) + assert hermite_normal_form(m) == hnf + assert hermite_normal_form(m, D=8) == hnf + assert hermite_normal_form(m, D=ZZ(8)) == hnf + assert hermite_normal_form(m, D=Integer(8)) == hnf + + m = Matrix([[10, 8, 6, 30, 2], [45, 36, 27, 18, 9], [5, 4, 3, 2, 1]]) + hnf = Matrix([[26, 2], [0, 9], [0, 1]]) + assert hermite_normal_form(m) == hnf + + m = Matrix([[2, 7], [0, 0], [0, 0]]) + hnf = Matrix([[1], [0], [0]]) + assert hermite_normal_form(m) == hnf + + +def test_issue_23410(): + A = Matrix([[1, 12], [0, 8], [0, 5]]) + H = Matrix([[1, 0], [0, 8], [0, 5]]) + assert hermite_normal_form(A) == H diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_reductions.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_reductions.py new file mode 100644 index 0000000000000000000000000000000000000000..32c98c6f249b1afafc8193f4248dc9493bb803e0 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_reductions.py @@ -0,0 +1,351 @@ +from sympy.core.numbers import I +from sympy.core.symbol import symbols +from sympy.testing.pytest import raises +from sympy.matrices import Matrix, zeros, eye +from sympy.core.symbol import Symbol +from sympy.core.numbers import Rational +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.simplify.simplify import simplify +from sympy.abc import x + + +# Matrix tests +def test_row_op(): + e = eye(3) + + raises(ValueError, lambda: e.elementary_row_op("abc")) + raises(ValueError, lambda: e.elementary_row_op()) + raises(ValueError, lambda: e.elementary_row_op('n->kn', row=5, k=5)) + raises(ValueError, lambda: e.elementary_row_op('n->kn', row=-5, k=5)) + raises(ValueError, lambda: e.elementary_row_op('n<->m', row1=1, row2=5)) + raises(ValueError, lambda: e.elementary_row_op('n<->m', row1=5, row2=1)) + raises(ValueError, lambda: e.elementary_row_op('n<->m', row1=-5, row2=1)) + raises(ValueError, lambda: e.elementary_row_op('n<->m', row1=1, row2=-5)) + raises(ValueError, lambda: e.elementary_row_op('n->n+km', row1=1, row2=5, k=5)) + raises(ValueError, lambda: e.elementary_row_op('n->n+km', row1=5, row2=1, k=5)) + raises(ValueError, lambda: e.elementary_row_op('n->n+km', row1=-5, row2=1, k=5)) + raises(ValueError, lambda: e.elementary_row_op('n->n+km', row1=1, row2=-5, k=5)) + raises(ValueError, lambda: e.elementary_row_op('n->n+km', row1=1, row2=1, k=5)) + + # test various ways to set arguments + assert e.elementary_row_op("n->kn", 0, 5) == Matrix([[5, 0, 0], [0, 1, 0], [0, 0, 1]]) + assert e.elementary_row_op("n->kn", 1, 5) == Matrix([[1, 0, 0], [0, 5, 0], [0, 0, 1]]) + assert e.elementary_row_op("n->kn", row=1, k=5) == Matrix([[1, 0, 0], [0, 5, 0], [0, 0, 1]]) + assert e.elementary_row_op("n->kn", row1=1, k=5) == Matrix([[1, 0, 0], [0, 5, 0], [0, 0, 1]]) + assert e.elementary_row_op("n<->m", 0, 1) == Matrix([[0, 1, 0], [1, 0, 0], [0, 0, 1]]) + assert e.elementary_row_op("n<->m", row1=0, row2=1) == Matrix([[0, 1, 0], [1, 0, 0], [0, 0, 1]]) + assert e.elementary_row_op("n<->m", row=0, row2=1) == Matrix([[0, 1, 0], [1, 0, 0], [0, 0, 1]]) + assert e.elementary_row_op("n->n+km", 0, 5, 1) == Matrix([[1, 5, 0], [0, 1, 0], [0, 0, 1]]) + assert e.elementary_row_op("n->n+km", row=0, k=5, row2=1) == Matrix([[1, 5, 0], [0, 1, 0], [0, 0, 1]]) + assert e.elementary_row_op("n->n+km", row1=0, k=5, row2=1) == Matrix([[1, 5, 0], [0, 1, 0], [0, 0, 1]]) + + # make sure the matrix doesn't change size + a = Matrix(2, 3, [0]*6) + assert a.elementary_row_op("n->kn", 1, 5) == Matrix(2, 3, [0]*6) + assert a.elementary_row_op("n<->m", 0, 1) == Matrix(2, 3, [0]*6) + assert a.elementary_row_op("n->n+km", 0, 5, 1) == Matrix(2, 3, [0]*6) + + +def test_col_op(): + e = eye(3) + + raises(ValueError, lambda: e.elementary_col_op("abc")) + raises(ValueError, lambda: e.elementary_col_op()) + raises(ValueError, lambda: e.elementary_col_op('n->kn', col=5, k=5)) + raises(ValueError, lambda: e.elementary_col_op('n->kn', col=-5, k=5)) + raises(ValueError, lambda: e.elementary_col_op('n<->m', col1=1, col2=5)) + raises(ValueError, lambda: e.elementary_col_op('n<->m', col1=5, col2=1)) + raises(ValueError, lambda: e.elementary_col_op('n<->m', col1=-5, col2=1)) + raises(ValueError, lambda: e.elementary_col_op('n<->m', col1=1, col2=-5)) + raises(ValueError, lambda: e.elementary_col_op('n->n+km', col1=1, col2=5, k=5)) + raises(ValueError, lambda: e.elementary_col_op('n->n+km', col1=5, col2=1, k=5)) + raises(ValueError, lambda: e.elementary_col_op('n->n+km', col1=-5, col2=1, k=5)) + raises(ValueError, lambda: e.elementary_col_op('n->n+km', col1=1, col2=-5, k=5)) + raises(ValueError, lambda: e.elementary_col_op('n->n+km', col1=1, col2=1, k=5)) + + # test various ways to set arguments + assert e.elementary_col_op("n->kn", 0, 5) == Matrix([[5, 0, 0], [0, 1, 0], [0, 0, 1]]) + assert e.elementary_col_op("n->kn", 1, 5) == Matrix([[1, 0, 0], [0, 5, 0], [0, 0, 1]]) + assert e.elementary_col_op("n->kn", col=1, k=5) == Matrix([[1, 0, 0], [0, 5, 0], [0, 0, 1]]) + assert e.elementary_col_op("n->kn", col1=1, k=5) == Matrix([[1, 0, 0], [0, 5, 0], [0, 0, 1]]) + assert e.elementary_col_op("n<->m", 0, 1) == Matrix([[0, 1, 0], [1, 0, 0], [0, 0, 1]]) + assert e.elementary_col_op("n<->m", col1=0, col2=1) == Matrix([[0, 1, 0], [1, 0, 0], [0, 0, 1]]) + assert e.elementary_col_op("n<->m", col=0, col2=1) == Matrix([[0, 1, 0], [1, 0, 0], [0, 0, 1]]) + assert e.elementary_col_op("n->n+km", 0, 5, 1) == Matrix([[1, 0, 0], [5, 1, 0], [0, 0, 1]]) + assert e.elementary_col_op("n->n+km", col=0, k=5, col2=1) == Matrix([[1, 0, 0], [5, 1, 0], [0, 0, 1]]) + assert e.elementary_col_op("n->n+km", col1=0, k=5, col2=1) == Matrix([[1, 0, 0], [5, 1, 0], [0, 0, 1]]) + + # make sure the matrix doesn't change size + a = Matrix(2, 3, [0]*6) + assert a.elementary_col_op("n->kn", 1, 5) == Matrix(2, 3, [0]*6) + assert a.elementary_col_op("n<->m", 0, 1) == Matrix(2, 3, [0]*6) + assert a.elementary_col_op("n->n+km", 0, 5, 1) == Matrix(2, 3, [0]*6) + + +def test_is_echelon(): + zro = zeros(3) + ident = eye(3) + + assert zro.is_echelon + assert ident.is_echelon + + a = Matrix(0, 0, []) + assert a.is_echelon + + a = Matrix(2, 3, [3, 2, 1, 0, 0, 6]) + assert a.is_echelon + + a = Matrix(2, 3, [0, 0, 6, 3, 2, 1]) + assert not a.is_echelon + + x = Symbol('x') + a = Matrix(3, 1, [x, 0, 0]) + assert a.is_echelon + + a = Matrix(3, 1, [x, x, 0]) + assert not a.is_echelon + + a = Matrix(3, 3, [0, 0, 0, 1, 2, 3, 0, 0, 0]) + assert not a.is_echelon + + +def test_echelon_form(): + # echelon form is not unique, but the result + # must be row-equivalent to the original matrix + # and it must be in echelon form. + + a = zeros(3) + e = eye(3) + + # we can assume the zero matrix and the identity matrix shouldn't change + assert a.echelon_form() == a + assert e.echelon_form() == e + + a = Matrix(0, 0, []) + assert a.echelon_form() == a + + a = Matrix(1, 1, [5]) + assert a.echelon_form() == a + + # now we get to the real tests + + def verify_row_null_space(mat, rows, nulls): + for v in nulls: + assert all(t.is_zero for t in a_echelon*v) + for v in rows: + if not all(t.is_zero for t in v): + assert not all(t.is_zero for t in a_echelon*v.transpose()) + + a = Matrix(3, 3, [1, 2, 3, 4, 5, 6, 7, 8, 9]) + nulls = [Matrix([ + [ 1], + [-2], + [ 1]])] + rows = [a[i, :] for i in range(a.rows)] + a_echelon = a.echelon_form() + assert a_echelon.is_echelon + verify_row_null_space(a, rows, nulls) + + + a = Matrix(3, 3, [1, 2, 3, 4, 5, 6, 7, 8, 8]) + nulls = [] + rows = [a[i, :] for i in range(a.rows)] + a_echelon = a.echelon_form() + assert a_echelon.is_echelon + verify_row_null_space(a, rows, nulls) + + a = Matrix(3, 3, [2, 1, 3, 0, 0, 0, 2, 1, 3]) + nulls = [Matrix([ + [Rational(-1, 2)], + [ 1], + [ 0]]), + Matrix([ + [Rational(-3, 2)], + [ 0], + [ 1]])] + rows = [a[i, :] for i in range(a.rows)] + a_echelon = a.echelon_form() + assert a_echelon.is_echelon + verify_row_null_space(a, rows, nulls) + + # this one requires a row swap + a = Matrix(3, 3, [2, 1, 3, 0, 0, 0, 1, 1, 3]) + nulls = [Matrix([ + [ 0], + [ -3], + [ 1]])] + rows = [a[i, :] for i in range(a.rows)] + a_echelon = a.echelon_form() + assert a_echelon.is_echelon + verify_row_null_space(a, rows, nulls) + + a = Matrix(3, 3, [0, 3, 3, 0, 2, 2, 0, 1, 1]) + nulls = [Matrix([ + [1], + [0], + [0]]), + Matrix([ + [ 0], + [-1], + [ 1]])] + rows = [a[i, :] for i in range(a.rows)] + a_echelon = a.echelon_form() + assert a_echelon.is_echelon + verify_row_null_space(a, rows, nulls) + + a = Matrix(2, 3, [2, 2, 3, 3, 3, 0]) + nulls = [Matrix([ + [-1], + [1], + [0]])] + rows = [a[i, :] for i in range(a.rows)] + a_echelon = a.echelon_form() + assert a_echelon.is_echelon + verify_row_null_space(a, rows, nulls) + + +def test_rref(): + e = Matrix(0, 0, []) + assert e.rref(pivots=False) == e + + e = Matrix(1, 1, [1]) + a = Matrix(1, 1, [5]) + assert e.rref(pivots=False) == a.rref(pivots=False) == e + + a = Matrix(3, 1, [1, 2, 3]) + assert a.rref(pivots=False) == Matrix([[1], [0], [0]]) + + a = Matrix(1, 3, [1, 2, 3]) + assert a.rref(pivots=False) == Matrix([[1, 2, 3]]) + + a = Matrix(3, 3, [1, 2, 3, 4, 5, 6, 7, 8, 9]) + assert a.rref(pivots=False) == Matrix([ + [1, 0, -1], + [0, 1, 2], + [0, 0, 0]]) + + a = Matrix(3, 3, [1, 2, 3, 1, 2, 3, 1, 2, 3]) + b = Matrix(3, 3, [1, 2, 3, 0, 0, 0, 0, 0, 0]) + c = Matrix(3, 3, [0, 0, 0, 1, 2, 3, 0, 0, 0]) + d = Matrix(3, 3, [0, 0, 0, 0, 0, 0, 1, 2, 3]) + assert a.rref(pivots=False) == \ + b.rref(pivots=False) == \ + c.rref(pivots=False) == \ + d.rref(pivots=False) == b + + e = eye(3) + z = zeros(3) + assert e.rref(pivots=False) == e + assert z.rref(pivots=False) == z + + a = Matrix([ + [ 0, 0, 1, 2, 2, -5, 3], + [-1, 5, 2, 2, 1, -7, 5], + [ 0, 0, -2, -3, -3, 8, -5], + [-1, 5, 0, -1, -2, 1, 0]]) + mat, pivot_offsets = a.rref() + assert mat == Matrix([ + [1, -5, 0, 0, 1, 1, -1], + [0, 0, 1, 0, 0, -1, 1], + [0, 0, 0, 1, 1, -2, 1], + [0, 0, 0, 0, 0, 0, 0]]) + assert pivot_offsets == (0, 2, 3) + + a = Matrix([[Rational(1, 19), Rational(1, 5), 2, 3], + [ 4, 5, 6, 7], + [ 8, 9, 10, 11], + [ 12, 13, 14, 15]]) + assert a.rref(pivots=False) == Matrix([ + [1, 0, 0, Rational(-76, 157)], + [0, 1, 0, Rational(-5, 157)], + [0, 0, 1, Rational(238, 157)], + [0, 0, 0, 0]]) + + x = Symbol('x') + a = Matrix(2, 3, [x, 1, 1, sqrt(x), x, 1]) + for i, j in zip(a.rref(pivots=False), + [1, 0, sqrt(x)*(-x + 1)/(-x**Rational(5, 2) + x), + 0, 1, 1/(sqrt(x) + x + 1)]): + assert simplify(i - j).is_zero + + +def test_rref_rhs(): + a, b, c, d = symbols('a b c d') + A = Matrix([[0, 0], [0, 0], [1, 2], [3, 4]]) + B = Matrix([a, b, c, d]) + assert A.rref_rhs(B) == (Matrix([ + [1, 0], + [0, 1], + [0, 0], + [0, 0]]), Matrix([ + [ -2*c + d], + [3*c/2 - d/2], + [ a], + [ b]])) + + +def test_issue_17827(): + C = Matrix([ + [3, 4, -1, 1], + [9, 12, -3, 3], + [0, 2, 1, 3], + [2, 3, 0, -2], + [0, 3, 3, -5], + [8, 15, 0, 6] + ]) + # Tests for row/col within valid range + D = C.elementary_row_op('n<->m', row1=2, row2=5) + E = C.elementary_row_op('n->n+km', row1=5, row2=3, k=-4) + F = C.elementary_row_op('n->kn', row=5, k=2) + assert(D[5, :] == Matrix([[0, 2, 1, 3]])) + assert(E[5, :] == Matrix([[0, 3, 0, 14]])) + assert(F[5, :] == Matrix([[16, 30, 0, 12]])) + # Tests for row/col out of range + raises(ValueError, lambda: C.elementary_row_op('n<->m', row1=2, row2=6)) + raises(ValueError, lambda: C.elementary_row_op('n->kn', row=7, k=2)) + raises(ValueError, lambda: C.elementary_row_op('n->n+km', row1=-1, row2=5, k=2)) + +def test_rank(): + m = Matrix([[1, 2], [x, 1 - 1/x]]) + assert m.rank() == 2 + n = Matrix(3, 3, range(1, 10)) + assert n.rank() == 2 + p = zeros(3) + assert p.rank() == 0 + +def test_issue_11434(): + ax, ay, bx, by, cx, cy, dx, dy, ex, ey, t0, t1 = \ + symbols('a_x a_y b_x b_y c_x c_y d_x d_y e_x e_y t_0 t_1') + M = Matrix([[ax, ay, ax*t0, ay*t0, 0], + [bx, by, bx*t0, by*t0, 0], + [cx, cy, cx*t0, cy*t0, 1], + [dx, dy, dx*t0, dy*t0, 1], + [ex, ey, 2*ex*t1 - ex*t0, 2*ey*t1 - ey*t0, 0]]) + assert M.rank() == 4 + +def test_rank_regression_from_so(): + # see: + # https://stackoverflow.com/questions/19072700/why-does-sympy-give-me-the-wrong-answer-when-i-row-reduce-a-symbolic-matrix + + nu, lamb = symbols('nu, lambda') + A = Matrix([[-3*nu, 1, 0, 0], + [ 3*nu, -2*nu - 1, 2, 0], + [ 0, 2*nu, (-1*nu) - lamb - 2, 3], + [ 0, 0, nu + lamb, -3]]) + expected_reduced = Matrix([[1, 0, 0, 1/(nu**2*(-lamb - nu))], + [0, 1, 0, 3/(nu*(-lamb - nu))], + [0, 0, 1, 3/(-lamb - nu)], + [0, 0, 0, 0]]) + expected_pivots = (0, 1, 2) + + reduced, pivots = A.rref() + + assert simplify(expected_reduced - reduced) == zeros(*A.shape) + assert pivots == expected_pivots + +def test_issue_15872(): + A = Matrix([[1, 1, 1, 0], [-2, -1, 0, -1], [0, 0, -1, -1], [0, 0, 2, 1]]) + B = A - Matrix.eye(4) * I + assert B.rank() == 3 + assert (B**2).rank() == 2 + assert (B**3).rank() == 2 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_repmatrix.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_repmatrix.py new file mode 100644 index 0000000000000000000000000000000000000000..ee36de004705f29eaa49ea8e06fd65a8a2baa718 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_repmatrix.py @@ -0,0 +1,62 @@ +from sympy.testing.pytest import raises +from sympy.matrices.exceptions import NonSquareMatrixError, NonInvertibleMatrixError + +from sympy import Matrix, Rational + + +def test_lll(): + A = Matrix([[1, 0, 0, 0, -20160], + [0, 1, 0, 0, 33768], + [0, 0, 1, 0, 39578], + [0, 0, 0, 1, 47757]]) + L = Matrix([[ 10, -3, -2, 8, -4], + [ 3, -9, 8, 1, -11], + [ -3, 13, -9, -3, -9], + [-12, -7, -11, 9, -1]]) + T = Matrix([[ 10, -3, -2, 8], + [ 3, -9, 8, 1], + [ -3, 13, -9, -3], + [-12, -7, -11, 9]]) + assert A.lll() == L + assert A.lll_transform() == (L, T) + assert T * A == L + + +def test_matrix_inv_mod(): + A = Matrix(2, 1, [1, 0]) + raises(NonSquareMatrixError, lambda: A.inv_mod(2)) + A = Matrix(2, 2, [1, 0, 0, 0]) + raises(NonInvertibleMatrixError, lambda: A.inv_mod(2)) + A = Matrix(2, 2, [1, 2, 3, 4]) + Ai = Matrix(2, 2, [1, 1, 0, 1]) + assert A.inv_mod(3) == Ai + A = Matrix(2, 2, [1, 0, 0, 1]) + assert A.inv_mod(2) == A + A = Matrix(3, 3, [1, 2, 3, 4, 5, 6, 7, 8, 9]) + raises(NonInvertibleMatrixError, lambda: A.inv_mod(5)) + A = Matrix(3, 3, [5, 1, 3, 2, 6, 0, 2, 1, 1]) + Ai = Matrix(3, 3, [6, 8, 0, 1, 5, 6, 5, 6, 4]) + assert A.inv_mod(9) == Ai + A = Matrix(3, 3, [1, 6, -3, 4, 1, -5, 3, -5, 5]) + Ai = Matrix(3, 3, [4, 3, 3, 1, 2, 5, 1, 5, 1]) + assert A.inv_mod(6) == Ai + A = Matrix(3, 3, [1, 6, 1, 4, 1, 5, 3, 2, 5]) + Ai = Matrix(3, 3, [6, 0, 3, 6, 6, 4, 1, 6, 1]) + assert A.inv_mod(7) == Ai + A = Matrix([[1, 2], [3, Rational(3,4)]]) + raises(ValueError, lambda: A.inv_mod(2)) + A = Matrix([[1, 2], [3, 4]]) + raises(TypeError, lambda: A.inv_mod(Rational(1, 2))) + # https://github.com/sympy/sympy/issues/27663 + M = Matrix([ + [2, 3, 1, 4], + [1, 5, 3, 2], + [3, 2, 4, 1], + [4, 1, 2, 5], + ]) + assert M.inv_mod(26) == Matrix([ + [7, 21, 10, 10], + [1, 7, 19, 3], + [14, 1, 15, 1], + [25, 23, 3, 12], + ]) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_solvers.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_solvers.py new file mode 100644 index 0000000000000000000000000000000000000000..c1347062c0482336affbeb4bb9a95aedfcc0ae53 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_solvers.py @@ -0,0 +1,615 @@ +import pytest +from sympy.core.function import expand_mul +from sympy.core.numbers import (I, Rational) +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.core.sympify import sympify +from sympy.simplify.simplify import simplify +from sympy.matrices.exceptions import (ShapeError, NonSquareMatrixError) +from sympy.matrices import ( + ImmutableMatrix, Matrix, eye, ones, ImmutableDenseMatrix, dotprodsimp) +from sympy.matrices.determinant import _det_laplace +from sympy.testing.pytest import raises +from sympy.matrices.exceptions import NonInvertibleMatrixError +from sympy.polys.matrices.exceptions import DMShapeError +from sympy.solvers.solveset import linsolve +from sympy.abc import x, y + +def test_issue_17247_expression_blowup_29(): + M = Matrix(S('''[ + [ -3/4, 45/32 - 37*I/16, 0, 0], + [-149/64 + 49*I/32, -177/128 - 1369*I/128, 0, -2063/256 + 541*I/128], + [ 0, 9/4 + 55*I/16, 2473/256 + 137*I/64, 0], + [ 0, 0, 0, -177/128 - 1369*I/128]]''')) + with dotprodsimp(True): + assert M.gauss_jordan_solve(ones(4, 1)) == (Matrix(S('''[ + [ -32549314808672/3306971225785 - 17397006745216*I/3306971225785], + [ 67439348256/3306971225785 - 9167503335872*I/3306971225785], + [-15091965363354518272/21217636514687010905 + 16890163109293858304*I/21217636514687010905], + [ -11328/952745 + 87616*I/952745]]''')), Matrix(0, 1, [])) + +def test_issue_17247_expression_blowup_30(): + M = Matrix(S('''[ + [ -3/4, 45/32 - 37*I/16, 0, 0], + [-149/64 + 49*I/32, -177/128 - 1369*I/128, 0, -2063/256 + 541*I/128], + [ 0, 9/4 + 55*I/16, 2473/256 + 137*I/64, 0], + [ 0, 0, 0, -177/128 - 1369*I/128]]''')) + with dotprodsimp(True): + assert M.cholesky_solve(ones(4, 1)) == Matrix(S('''[ + [ -32549314808672/3306971225785 - 17397006745216*I/3306971225785], + [ 67439348256/3306971225785 - 9167503335872*I/3306971225785], + [-15091965363354518272/21217636514687010905 + 16890163109293858304*I/21217636514687010905], + [ -11328/952745 + 87616*I/952745]]''')) + +# @XFAIL # This calculation hangs with dotprodsimp. +# def test_issue_17247_expression_blowup_31(): +# M = Matrix([ +# [x + 1, 1 - x, 0, 0], +# [1 - x, x + 1, 0, x + 1], +# [ 0, 1 - x, x + 1, 0], +# [ 0, 0, 0, x + 1]]) +# with dotprodsimp(True): +# assert M.LDLsolve(ones(4, 1)) == Matrix([ +# [(x + 1)/(4*x)], +# [(x - 1)/(4*x)], +# [(x + 1)/(4*x)], +# [ 1/(x + 1)]]) + + +def test_LUsolve_iszerofunc(): + # taken from https://github.com/sympy/sympy/issues/24679 + + M = Matrix([[(x + 1)**2 - (x**2 + 2*x + 1), x], [x, 0]]) + b = Matrix([1, 1]) + is_zero_func = lambda e: False if e._random() else True + + x_exp = Matrix([1/x, (1-(-x**2 - 2*x + (x+1)**2 - 1)/x)/x]) + + assert (x_exp - M.LUsolve(b, iszerofunc=is_zero_func)) == Matrix([0, 0]) + + +def test_issue_17247_expression_blowup_32(): + M = Matrix([ + [x + 1, 1 - x, 0, 0], + [1 - x, x + 1, 0, x + 1], + [ 0, 1 - x, x + 1, 0], + [ 0, 0, 0, x + 1]]) + with dotprodsimp(True): + assert M.LUsolve(ones(4, 1)) == Matrix([ + [(x + 1)/(4*x)], + [(x - 1)/(4*x)], + [(x + 1)/(4*x)], + [ 1/(x + 1)]]) + +def test_LUsolve(): + A = Matrix([[2, 3, 5], + [3, 6, 2], + [8, 3, 6]]) + x = Matrix(3, 1, [3, 7, 5]) + b = A*x + soln = A.LUsolve(b) + assert soln == x + A = Matrix([[0, -1, 2], + [5, 10, 7], + [8, 3, 4]]) + x = Matrix(3, 1, [-1, 2, 5]) + b = A*x + soln = A.LUsolve(b) + assert soln == x + A = Matrix([[2, 1], [1, 0], [1, 0]]) # issue 14548 + b = Matrix([3, 1, 1]) + assert A.LUsolve(b) == Matrix([1, 1]) + b = Matrix([3, 1, 2]) # inconsistent + raises(ValueError, lambda: A.LUsolve(b)) + A = Matrix([[0, -1, 2], + [5, 10, 7], + [8, 3, 4], + [2, 3, 5], + [3, 6, 2], + [8, 3, 6]]) + x = Matrix([2, 1, -4]) + b = A*x + soln = A.LUsolve(b) + assert soln == x + A = Matrix([[0, -1, 2], [5, 10, 7]]) # underdetermined + x = Matrix([-1, 2, 0]) + b = A*x + raises(NotImplementedError, lambda: A.LUsolve(b)) + + A = Matrix(4, 4, lambda i, j: 1/(i+j+1) if i != 3 else 0) + b = Matrix.zeros(4, 1) + raises(NonInvertibleMatrixError, lambda: A.LUsolve(b)) + + +def test_LUsolve_noncommutative(): + a0, a1, a2, a3 = symbols("a:4", commutative=False) + b0, b1 = symbols("b:2", commutative=False) + A = Matrix([[a0, a1], [a2, a3]]) + check = A * A.LUsolve(Matrix([b0, b1])) + assert check[0, 0].expand() == b0 + # Because sympy simplification is very limited with noncommutative expressions, + # perform an explicit check with the second element + assert check[1, 0] == ( + a2*a0**(-1)*(-a1*(-a2*a0**(-1)*a1 + a3)**(-1)*(-a2*a0**(-1)*b0 + b1) + b0) + + a3*(-a2*a0**(-1)*a1 + a3)**(-1)*(-a2*a0**(-1)*b0 + b1) + ) + + +def test_QRsolve(): + A = Matrix([[2, 3, 5], + [3, 6, 2], + [8, 3, 6]]) + x = Matrix(3, 1, [3, 7, 5]) + b = A*x + soln = A.QRsolve(b) + assert soln == x + x = Matrix([[1, 2], [3, 4], [5, 6]]) + b = A*x + soln = A.QRsolve(b) + assert soln == x + + A = Matrix([[0, -1, 2], + [5, 10, 7], + [8, 3, 4]]) + x = Matrix(3, 1, [-1, 2, 5]) + b = A*x + soln = A.QRsolve(b) + assert soln == x + x = Matrix([[7, 8], [9, 10], [11, 12]]) + b = A*x + soln = A.QRsolve(b) + assert soln == x + +def test_errors(): + raises(ShapeError, lambda: Matrix([1]).LUsolve(Matrix([[1, 2], [3, 4]]))) + +def test_cholesky_solve(): + A = Matrix([[2, 3, 5], + [3, 6, 2], + [8, 3, 6]]) + x = Matrix(3, 1, [3, 7, 5]) + b = A*x + soln = A.cholesky_solve(b) + assert soln == x + A = Matrix([[0, -1, 2], + [5, 10, 7], + [8, 3, 4]]) + x = Matrix(3, 1, [-1, 2, 5]) + b = A*x + soln = A.cholesky_solve(b) + assert soln == x + A = Matrix(((1, 5), (5, 1))) + x = Matrix((4, -3)) + b = A*x + soln = A.cholesky_solve(b) + assert soln == x + A = Matrix(((9, 3*I), (-3*I, 5))) + x = Matrix((-2, 1)) + b = A*x + soln = A.cholesky_solve(b) + assert expand_mul(soln) == x + A = Matrix(((9*I, 3), (-3 + I, 5))) + x = Matrix((2 + 3*I, -1)) + b = A*x + soln = A.cholesky_solve(b) + assert expand_mul(soln) == x + a00, a01, a11, b0, b1 = symbols('a00, a01, a11, b0, b1') + A = Matrix(((a00, a01), (a01, a11))) + b = Matrix((b0, b1)) + x = A.cholesky_solve(b) + assert simplify(A*x) == b + + +def test_LDLsolve(): + A = Matrix([[2, 3, 5], + [3, 6, 2], + [8, 3, 6]]) + x = Matrix(3, 1, [3, 7, 5]) + b = A*x + soln = A.LDLsolve(b) + assert soln == x + + A = Matrix([[0, -1, 2], + [5, 10, 7], + [8, 3, 4]]) + x = Matrix(3, 1, [-1, 2, 5]) + b = A*x + soln = A.LDLsolve(b) + assert soln == x + + A = Matrix(((9, 3*I), (-3*I, 5))) + x = Matrix((-2, 1)) + b = A*x + soln = A.LDLsolve(b) + assert expand_mul(soln) == x + + A = Matrix(((9*I, 3), (-3 + I, 5))) + x = Matrix((2 + 3*I, -1)) + b = A*x + soln = A.LDLsolve(b) + assert expand_mul(soln) == x + + A = Matrix(((9, 3), (3, 9))) + x = Matrix((1, 1)) + b = A * x + soln = A.LDLsolve(b) + assert expand_mul(soln) == x + + A = Matrix([[-5, -3, -4], [-3, -7, 7]]) + x = Matrix([[8], [7], [-2]]) + b = A * x + raises(NotImplementedError, lambda: A.LDLsolve(b)) + + +def test_lower_triangular_solve(): + + raises(NonSquareMatrixError, + lambda: Matrix([1, 0]).lower_triangular_solve(Matrix([0, 1]))) + raises(ShapeError, + lambda: Matrix([[1, 0], [0, 1]]).lower_triangular_solve(Matrix([1]))) + raises(ValueError, + lambda: Matrix([[2, 1], [1, 2]]).lower_triangular_solve( + Matrix([[1, 0], [0, 1]]))) + + A = Matrix([[1, 0], [0, 1]]) + B = Matrix([[x, y], [y, x]]) + C = Matrix([[4, 8], [2, 9]]) + + assert A.lower_triangular_solve(B) == B + assert A.lower_triangular_solve(C) == C + + +def test_upper_triangular_solve(): + + raises(NonSquareMatrixError, + lambda: Matrix([1, 0]).upper_triangular_solve(Matrix([0, 1]))) + raises(ShapeError, + lambda: Matrix([[1, 0], [0, 1]]).upper_triangular_solve(Matrix([1]))) + raises(TypeError, + lambda: Matrix([[2, 1], [1, 2]]).upper_triangular_solve( + Matrix([[1, 0], [0, 1]]))) + + A = Matrix([[1, 0], [0, 1]]) + B = Matrix([[x, y], [y, x]]) + C = Matrix([[2, 4], [3, 8]]) + + assert A.upper_triangular_solve(B) == B + assert A.upper_triangular_solve(C) == C + + +def test_diagonal_solve(): + raises(TypeError, lambda: Matrix([1, 1]).diagonal_solve(Matrix([1]))) + A = Matrix([[1, 0], [0, 1]])*2 + B = Matrix([[x, y], [y, x]]) + assert A.diagonal_solve(B) == B/2 + + A = Matrix([[1, 0], [1, 2]]) + raises(TypeError, lambda: A.diagonal_solve(B)) + +def test_pinv_solve(): + # Fully determined system (unique result, identical to other solvers). + A = Matrix([[1, 5], [7, 9]]) + B = Matrix([12, 13]) + assert A.pinv_solve(B) == A.cholesky_solve(B) + assert A.pinv_solve(B) == A.LDLsolve(B) + assert A.pinv_solve(B) == Matrix([sympify('-43/26'), sympify('71/26')]) + assert A * A.pinv() * B == B + # Fully determined, with two-dimensional B matrix. + B = Matrix([[12, 13, 14], [15, 16, 17]]) + assert A.pinv_solve(B) == A.cholesky_solve(B) + assert A.pinv_solve(B) == A.LDLsolve(B) + assert A.pinv_solve(B) == Matrix([[-33, -37, -41], [69, 75, 81]]) / 26 + assert A * A.pinv() * B == B + # Underdetermined system (infinite results). + A = Matrix([[1, 0, 1], [0, 1, 1]]) + B = Matrix([5, 7]) + solution = A.pinv_solve(B) + w = {} + for s in solution.atoms(Symbol): + # Extract dummy symbols used in the solution. + w[s.name] = s + assert solution == Matrix([[w['w0_0']/3 + w['w1_0']/3 - w['w2_0']/3 + 1], + [w['w0_0']/3 + w['w1_0']/3 - w['w2_0']/3 + 3], + [-w['w0_0']/3 - w['w1_0']/3 + w['w2_0']/3 + 4]]) + assert A * A.pinv() * B == B + # Overdetermined system (least squares results). + A = Matrix([[1, 0], [0, 0], [0, 1]]) + B = Matrix([3, 2, 1]) + assert A.pinv_solve(B) == Matrix([3, 1]) + # Proof the solution is not exact. + assert A * A.pinv() * B != B + +def test_pinv_rank_deficient(): + # Test the four properties of the pseudoinverse for various matrices. + As = [Matrix([[1, 1, 1], [2, 2, 2]]), + Matrix([[1, 0], [0, 0]]), + Matrix([[1, 2], [2, 4], [3, 6]])] + + for A in As: + A_pinv = A.pinv(method="RD") + AAp = A * A_pinv + ApA = A_pinv * A + assert simplify(AAp * A) == A + assert simplify(ApA * A_pinv) == A_pinv + assert AAp.H == AAp + assert ApA.H == ApA + + for A in As: + A_pinv = A.pinv(method="ED") + AAp = A * A_pinv + ApA = A_pinv * A + assert simplify(AAp * A) == A + assert simplify(ApA * A_pinv) == A_pinv + assert AAp.H == AAp + assert ApA.H == ApA + + # Test solving with rank-deficient matrices. + A = Matrix([[1, 0], [0, 0]]) + # Exact, non-unique solution. + B = Matrix([3, 0]) + solution = A.pinv_solve(B) + w1 = solution.atoms(Symbol).pop() + assert w1.name == 'w1_0' + assert solution == Matrix([3, w1]) + assert A * A.pinv() * B == B + # Least squares, non-unique solution. + B = Matrix([3, 1]) + solution = A.pinv_solve(B) + w1 = solution.atoms(Symbol).pop() + assert w1.name == 'w1_0' + assert solution == Matrix([3, w1]) + assert A * A.pinv() * B != B + +def test_gauss_jordan_solve(): + + # Square, full rank, unique solution + A = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 10]]) + b = Matrix([3, 6, 9]) + sol, params = A.gauss_jordan_solve(b) + assert sol == Matrix([[-1], [2], [0]]) + assert params == Matrix(0, 1, []) + + # Square, full rank, unique solution, B has more columns than rows + A = eye(3) + B = Matrix([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]) + sol, params = A.gauss_jordan_solve(B) + assert sol == B + assert params == Matrix(0, 4, []) + + # Square, reduced rank, parametrized solution + A = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + b = Matrix([3, 6, 9]) + sol, params, freevar = A.gauss_jordan_solve(b, freevar=True) + w = {} + for s in sol.atoms(Symbol): + # Extract dummy symbols used in the solution. + w[s.name] = s + assert sol == Matrix([[w['tau0'] - 1], [-2*w['tau0'] + 2], [w['tau0']]]) + assert params == Matrix([[w['tau0']]]) + assert freevar == [2] + + # Square, reduced rank, parametrized solution, B has two columns + A = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + B = Matrix([[3, 4], [6, 8], [9, 12]]) + sol, params, freevar = A.gauss_jordan_solve(B, freevar=True) + w = {} + for s in sol.atoms(Symbol): + # Extract dummy symbols used in the solution. + w[s.name] = s + assert sol == Matrix([[w['tau0'] - 1, w['tau1'] - Rational(4, 3)], + [-2*w['tau0'] + 2, -2*w['tau1'] + Rational(8, 3)], + [w['tau0'], w['tau1']],]) + assert params == Matrix([[w['tau0'], w['tau1']]]) + assert freevar == [2] + + # Square, reduced rank, parametrized solution + A = Matrix([[1, 2, 3], [2, 4, 6], [3, 6, 9]]) + b = Matrix([0, 0, 0]) + sol, params = A.gauss_jordan_solve(b) + w = {} + for s in sol.atoms(Symbol): + w[s.name] = s + assert sol == Matrix([[-2*w['tau0'] - 3*w['tau1']], + [w['tau0']], [w['tau1']]]) + assert params == Matrix([[w['tau0']], [w['tau1']]]) + + # Square, reduced rank, parametrized solution + A = Matrix([[0, 0, 0], [0, 0, 0], [0, 0, 0]]) + b = Matrix([0, 0, 0]) + sol, params = A.gauss_jordan_solve(b) + w = {} + for s in sol.atoms(Symbol): + w[s.name] = s + assert sol == Matrix([[w['tau0']], [w['tau1']], [w['tau2']]]) + assert params == Matrix([[w['tau0']], [w['tau1']], [w['tau2']]]) + + # Square, reduced rank, no solution + A = Matrix([[1, 2, 3], [2, 4, 6], [3, 6, 9]]) + b = Matrix([0, 0, 1]) + raises(ValueError, lambda: A.gauss_jordan_solve(b)) + + # Rectangular, tall, full rank, unique solution + A = Matrix([[1, 5, 3], [2, 1, 6], [1, 7, 9], [1, 4, 3]]) + b = Matrix([0, 0, 1, 0]) + sol, params = A.gauss_jordan_solve(b) + assert sol == Matrix([[Rational(-1, 2)], [0], [Rational(1, 6)]]) + assert params == Matrix(0, 1, []) + + # Rectangular, tall, full rank, unique solution, B has less columns than rows + A = Matrix([[1, 5, 3], [2, 1, 6], [1, 7, 9], [1, 4, 3]]) + B = Matrix([[0,0], [0, 0], [1, 2], [0, 0]]) + sol, params = A.gauss_jordan_solve(B) + assert sol == Matrix([[Rational(-1, 2), Rational(-2, 2)], [0, 0], [Rational(1, 6), Rational(2, 6)]]) + assert params == Matrix(0, 2, []) + + # Rectangular, tall, full rank, no solution + A = Matrix([[1, 5, 3], [2, 1, 6], [1, 7, 9], [1, 4, 3]]) + b = Matrix([0, 0, 0, 1]) + raises(ValueError, lambda: A.gauss_jordan_solve(b)) + + # Rectangular, tall, full rank, no solution, B has two columns (2nd has no solution) + A = Matrix([[1, 5, 3], [2, 1, 6], [1, 7, 9], [1, 4, 3]]) + B = Matrix([[0,0], [0, 0], [1, 0], [0, 1]]) + raises(ValueError, lambda: A.gauss_jordan_solve(B)) + + # Rectangular, tall, full rank, no solution, B has two columns (1st has no solution) + A = Matrix([[1, 5, 3], [2, 1, 6], [1, 7, 9], [1, 4, 3]]) + B = Matrix([[0,0], [0, 0], [0, 1], [1, 0]]) + raises(ValueError, lambda: A.gauss_jordan_solve(B)) + + # Rectangular, tall, reduced rank, parametrized solution + A = Matrix([[1, 5, 3], [2, 10, 6], [3, 15, 9], [1, 4, 3]]) + b = Matrix([0, 0, 0, 1]) + sol, params = A.gauss_jordan_solve(b) + w = {} + for s in sol.atoms(Symbol): + w[s.name] = s + assert sol == Matrix([[-3*w['tau0'] + 5], [-1], [w['tau0']]]) + assert params == Matrix([[w['tau0']]]) + + # Rectangular, tall, reduced rank, no solution + A = Matrix([[1, 5, 3], [2, 10, 6], [3, 15, 9], [1, 4, 3]]) + b = Matrix([0, 0, 1, 1]) + raises(ValueError, lambda: A.gauss_jordan_solve(b)) + + # Rectangular, wide, full rank, parametrized solution + A = Matrix([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 1, 12]]) + b = Matrix([1, 1, 1]) + sol, params = A.gauss_jordan_solve(b) + w = {} + for s in sol.atoms(Symbol): + w[s.name] = s + assert sol == Matrix([[2*w['tau0'] - 1], [-3*w['tau0'] + 1], [0], + [w['tau0']]]) + assert params == Matrix([[w['tau0']]]) + + # Rectangular, wide, reduced rank, parametrized solution + A = Matrix([[1, 2, 3, 4], [5, 6, 7, 8], [2, 4, 6, 8]]) + b = Matrix([0, 1, 0]) + sol, params = A.gauss_jordan_solve(b) + w = {} + for s in sol.atoms(Symbol): + w[s.name] = s + assert sol == Matrix([[w['tau0'] + 2*w['tau1'] + S.Half], + [-2*w['tau0'] - 3*w['tau1'] - Rational(1, 4)], + [w['tau0']], [w['tau1']]]) + assert params == Matrix([[w['tau0']], [w['tau1']]]) + # watch out for clashing symbols + x0, x1, x2, _x0 = symbols('_tau0 _tau1 _tau2 tau1') + M = Matrix([[0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, _x0]]) + A = M[:, :-1] + b = M[:, -1:] + sol, params = A.gauss_jordan_solve(b) + assert params == Matrix(3, 1, [x0, x1, x2]) + assert sol == Matrix(5, 1, [x0, 0, x1, _x0, x2]) + + # Rectangular, wide, reduced rank, no solution + A = Matrix([[1, 2, 3, 4], [5, 6, 7, 8], [2, 4, 6, 8]]) + b = Matrix([1, 1, 1]) + raises(ValueError, lambda: A.gauss_jordan_solve(b)) + + # Test for immutable matrix + A = ImmutableMatrix([[1, 0], [0, 1]]) + B = ImmutableMatrix([1, 2]) + sol, params = A.gauss_jordan_solve(B) + assert sol == ImmutableMatrix([1, 2]) + assert params == ImmutableMatrix(0, 1, []) + assert sol.__class__ == ImmutableDenseMatrix + assert params.__class__ == ImmutableDenseMatrix + + # Test placement of free variables + A = Matrix([[1, 0, 0, 0], [0, 0, 0, 1]]) + b = Matrix([1, 1]) + sol, params = A.gauss_jordan_solve(b) + w = {} + for s in sol.atoms(Symbol): + w[s.name] = s + assert sol == Matrix([[1], [w['tau0']], [w['tau1']], [1]]) + assert params == Matrix([[w['tau0']], [w['tau1']]]) + + +def test_linsolve_underdetermined_AND_gauss_jordan_solve(): + #Test placement of free variables as per issue 19815 + A = Matrix([[1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], + [0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1]]) + B = Matrix([1, 2, 1, 1, 1, 1, 1, 2]) + sol, params = A.gauss_jordan_solve(B) + w = {} + for s in sol.atoms(Symbol): + w[s.name] = s + assert params == Matrix([[w['tau0']], [w['tau1']], [w['tau2']], + [w['tau3']], [w['tau4']], [w['tau5']]]) + assert sol == Matrix([[1 - 1*w['tau2']], + [w['tau2']], + [1 - 1*w['tau0'] + w['tau1']], + [w['tau0']], + [w['tau3'] + w['tau4']], + [-1*w['tau3'] - 1*w['tau4'] - 1*w['tau1']], + [1 - 1*w['tau2']], + [w['tau1']], + [w['tau2']], + [w['tau3']], + [w['tau4']], + [1 - 1*w['tau5']], + [w['tau5']], + [1]]) + + from sympy.abc import j,f + # https://github.com/sympy/sympy/issues/20046 + A = Matrix([ + [1, 1, 1, 1, 1, 1, 1, 1, 1], + [0, -1, 0, -1, 0, -1, 0, -1, -j], + [0, 0, 0, 0, 1, 1, 1, 1, f] + ]) + + sol_1=Matrix(list(linsolve(A))[0]) + + tau0, tau1, tau2, tau3, tau4 = symbols('tau:5') + + assert sol_1 == Matrix([[-f - j - tau0 + tau2 + tau4 + 1], + [j - tau1 - tau2 - tau4], + [tau0], + [tau1], + [f - tau2 - tau3 - tau4], + [tau2], + [tau3], + [tau4]]) + + # https://github.com/sympy/sympy/issues/19815 + sol_2 = A[:, : -1 ] * sol_1 - A[:, -1 ] + assert sol_2 == Matrix([[0], [0], [0]]) + + +@pytest.mark.parametrize("det_method", ["bird", "laplace"]) +@pytest.mark.parametrize("M, rhs", [ + (Matrix([[2, 3, 5], [3, 6, 2], [8, 3, 6]]), Matrix(3, 1, [3, 7, 5])), + (Matrix([[2, 3, 5], [3, 6, 2], [8, 3, 6]]), + Matrix([[1, 2], [3, 4], [5, 6]])), + (Matrix(2, 2, symbols("a:4")), Matrix(2, 1, symbols("b:2"))), +]) +def test_cramer_solve(det_method, M, rhs): + assert simplify(M.cramer_solve(rhs, det_method=det_method) - M.LUsolve(rhs) + ) == Matrix.zeros(M.rows, rhs.cols) + + +@pytest.mark.parametrize("det_method, error", [ + ("bird", DMShapeError), (_det_laplace, NonSquareMatrixError)]) +def test_cramer_solve_errors(det_method, error): + # Non-square matrix + A = Matrix([[0, -1, 2], [5, 10, 7]]) + b = Matrix([-2, 15]) + raises(error, lambda: A.cramer_solve(b, det_method=det_method)) + + +def test_solve(): + A = Matrix([[1,2], [2,4]]) + b = Matrix([[3], [4]]) + raises(ValueError, lambda: A.solve(b)) #no solution + b = Matrix([[ 4], [8]]) + raises(ValueError, lambda: A.solve(b)) #infinite solution diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_sparse.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_sparse.py new file mode 100644 index 0000000000000000000000000000000000000000..4d257c8062f220cc06bc0dabdc7ac40ce9dc4adc --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_sparse.py @@ -0,0 +1,745 @@ +from sympy.core.numbers import (Float, I, Rational) +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.elementary.complexes import Abs +from sympy.polys.polytools import PurePoly +from sympy.matrices import \ + Matrix, MutableSparseMatrix, ImmutableSparseMatrix, SparseMatrix, eye, \ + ones, zeros, ShapeError, NonSquareMatrixError +from sympy.testing.pytest import raises + + +def test_sparse_creation(): + a = SparseMatrix(2, 2, {(0, 0): [[1, 2], [3, 4]]}) + assert a == SparseMatrix([[1, 2], [3, 4]]) + a = SparseMatrix(2, 2, {(0, 0): [[1, 2]]}) + assert a == SparseMatrix([[1, 2], [0, 0]]) + a = SparseMatrix(2, 2, {(0, 0): [1, 2]}) + assert a == SparseMatrix([[1, 0], [2, 0]]) + + +def test_sparse_matrix(): + def sparse_eye(n): + return SparseMatrix.eye(n) + + def sparse_zeros(n): + return SparseMatrix.zeros(n) + + # creation args + raises(TypeError, lambda: SparseMatrix(1, 2)) + + a = SparseMatrix(( + (1, 0), + (0, 1) + )) + assert SparseMatrix(a) == a + + from sympy.matrices import MutableDenseMatrix + a = MutableSparseMatrix([]) + b = MutableDenseMatrix([1, 2]) + assert a.row_join(b) == b + assert a.col_join(b) == b + assert type(a.row_join(b)) == type(a) + assert type(a.col_join(b)) == type(a) + + # make sure 0 x n matrices get stacked correctly + sparse_matrices = [SparseMatrix.zeros(0, n) for n in range(4)] + assert SparseMatrix.hstack(*sparse_matrices) == Matrix(0, 6, []) + sparse_matrices = [SparseMatrix.zeros(n, 0) for n in range(4)] + assert SparseMatrix.vstack(*sparse_matrices) == Matrix(6, 0, []) + + # test element assignment + a = SparseMatrix(( + (1, 0), + (0, 1) + )) + + a[3] = 4 + assert a[1, 1] == 4 + a[3] = 1 + + a[0, 0] = 2 + assert a == SparseMatrix(( + (2, 0), + (0, 1) + )) + a[1, 0] = 5 + assert a == SparseMatrix(( + (2, 0), + (5, 1) + )) + a[1, 1] = 0 + assert a == SparseMatrix(( + (2, 0), + (5, 0) + )) + assert a.todok() == {(0, 0): 2, (1, 0): 5} + + # test_multiplication + a = SparseMatrix(( + (1, 2), + (3, 1), + (0, 6), + )) + + b = SparseMatrix(( + (1, 2), + (3, 0), + )) + + c = a*b + assert c[0, 0] == 7 + assert c[0, 1] == 2 + assert c[1, 0] == 6 + assert c[1, 1] == 6 + assert c[2, 0] == 18 + assert c[2, 1] == 0 + + try: + eval('c = a @ b') + except SyntaxError: + pass + else: + assert c[0, 0] == 7 + assert c[0, 1] == 2 + assert c[1, 0] == 6 + assert c[1, 1] == 6 + assert c[2, 0] == 18 + assert c[2, 1] == 0 + + x = Symbol("x") + + c = b * Symbol("x") + assert isinstance(c, SparseMatrix) + assert c[0, 0] == x + assert c[0, 1] == 2*x + assert c[1, 0] == 3*x + assert c[1, 1] == 0 + + c = 5 * b + assert isinstance(c, SparseMatrix) + assert c[0, 0] == 5 + assert c[0, 1] == 2*5 + assert c[1, 0] == 3*5 + assert c[1, 1] == 0 + + #test_power + A = SparseMatrix([[2, 3], [4, 5]]) + assert (A**5)[:] == [6140, 8097, 10796, 14237] + A = SparseMatrix([[2, 1, 3], [4, 2, 4], [6, 12, 1]]) + assert (A**3)[:] == [290, 262, 251, 448, 440, 368, 702, 954, 433] + + # test_creation + x = Symbol("x") + a = SparseMatrix([[x, 0], [0, 0]]) + m = a + assert m.cols == m.rows + assert m.cols == 2 + assert m[:] == [x, 0, 0, 0] + b = SparseMatrix(2, 2, [x, 0, 0, 0]) + m = b + assert m.cols == m.rows + assert m.cols == 2 + assert m[:] == [x, 0, 0, 0] + + assert a == b + S = sparse_eye(3) + S.row_del(1) + assert S == SparseMatrix([ + [1, 0, 0], + [0, 0, 1]]) + S = sparse_eye(3) + S.col_del(1) + assert S == SparseMatrix([ + [1, 0], + [0, 0], + [0, 1]]) + S = SparseMatrix.eye(3) + S[2, 1] = 2 + S.col_swap(1, 0) + assert S == SparseMatrix([ + [0, 1, 0], + [1, 0, 0], + [2, 0, 1]]) + S.row_swap(0, 1) + assert S == SparseMatrix([ + [1, 0, 0], + [0, 1, 0], + [2, 0, 1]]) + + a = SparseMatrix(1, 2, [1, 2]) + b = a.copy() + c = a.copy() + assert a[0] == 1 + a.row_del(0) + assert a == SparseMatrix(0, 2, []) + b.col_del(1) + assert b == SparseMatrix(1, 1, [1]) + + assert SparseMatrix([[1, 2, 3], [1, 2], [1]]) == Matrix([ + [1, 2, 3], + [1, 2, 0], + [1, 0, 0]]) + assert SparseMatrix(4, 4, {(1, 1): sparse_eye(2)}) == Matrix([ + [0, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 0, 0]]) + raises(ValueError, lambda: SparseMatrix(1, 1, {(1, 1): 1})) + assert SparseMatrix(1, 2, [1, 2]).tolist() == [[1, 2]] + assert SparseMatrix(2, 2, [1, [2, 3]]).tolist() == [[1, 0], [2, 3]] + raises(ValueError, lambda: SparseMatrix(2, 2, [1])) + raises(ValueError, lambda: SparseMatrix(1, 1, [[1, 2]])) + assert SparseMatrix([.1]).has(Float) + # autosizing + assert SparseMatrix(None, {(0, 1): 0}).shape == (0, 0) + assert SparseMatrix(None, {(0, 1): 1}).shape == (1, 2) + assert SparseMatrix(None, None, {(0, 1): 1}).shape == (1, 2) + raises(ValueError, lambda: SparseMatrix(None, 1, [[1, 2]])) + raises(ValueError, lambda: SparseMatrix(1, None, [[1, 2]])) + raises(ValueError, lambda: SparseMatrix(3, 3, {(0, 0): ones(2), (1, 1): 2})) + + # test_determinant + x, y = Symbol('x'), Symbol('y') + + assert SparseMatrix(1, 1, [0]).det() == 0 + + assert SparseMatrix([[1]]).det() == 1 + + assert SparseMatrix(((-3, 2), (8, -5))).det() == -1 + + assert SparseMatrix(((x, 1), (y, 2*y))).det() == 2*x*y - y + + assert SparseMatrix(( (1, 1, 1), + (1, 2, 3), + (1, 3, 6) )).det() == 1 + + assert SparseMatrix(( ( 3, -2, 0, 5), + (-2, 1, -2, 2), + ( 0, -2, 5, 0), + ( 5, 0, 3, 4) )).det() == -289 + + assert SparseMatrix(( ( 1, 2, 3, 4), + ( 5, 6, 7, 8), + ( 9, 10, 11, 12), + (13, 14, 15, 16) )).det() == 0 + + assert SparseMatrix(( (3, 2, 0, 0, 0), + (0, 3, 2, 0, 0), + (0, 0, 3, 2, 0), + (0, 0, 0, 3, 2), + (2, 0, 0, 0, 3) )).det() == 275 + + assert SparseMatrix(( (1, 0, 1, 2, 12), + (2, 0, 1, 1, 4), + (2, 1, 1, -1, 3), + (3, 2, -1, 1, 8), + (1, 1, 1, 0, 6) )).det() == -55 + + assert SparseMatrix(( (-5, 2, 3, 4, 5), + ( 1, -4, 3, 4, 5), + ( 1, 2, -3, 4, 5), + ( 1, 2, 3, -2, 5), + ( 1, 2, 3, 4, -1) )).det() == 11664 + + assert SparseMatrix(( ( 3, 0, 0, 0), + (-2, 1, 0, 0), + ( 0, -2, 5, 0), + ( 5, 0, 3, 4) )).det() == 60 + + assert SparseMatrix(( ( 1, 0, 0, 0), + ( 5, 0, 0, 0), + ( 9, 10, 11, 0), + (13, 14, 15, 16) )).det() == 0 + + assert SparseMatrix(( (3, 2, 0, 0, 0), + (0, 3, 2, 0, 0), + (0, 0, 3, 2, 0), + (0, 0, 0, 3, 2), + (0, 0, 0, 0, 3) )).det() == 243 + + assert SparseMatrix(( ( 2, 7, -1, 3, 2), + ( 0, 0, 1, 0, 1), + (-2, 0, 7, 0, 2), + (-3, -2, 4, 5, 3), + ( 1, 0, 0, 0, 1) )).det() == 123 + + # test_slicing + m0 = sparse_eye(4) + assert m0[:3, :3] == sparse_eye(3) + assert m0[2:4, 0:2] == sparse_zeros(2) + + m1 = SparseMatrix(3, 3, lambda i, j: i + j) + assert m1[0, :] == SparseMatrix(1, 3, (0, 1, 2)) + assert m1[1:3, 1] == SparseMatrix(2, 1, (2, 3)) + + m2 = SparseMatrix( + [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]]) + assert m2[:, -1] == SparseMatrix(4, 1, [3, 7, 11, 15]) + assert m2[-2:, :] == SparseMatrix([[8, 9, 10, 11], [12, 13, 14, 15]]) + + assert SparseMatrix([[1, 2], [3, 4]])[[1], [1]] == Matrix([[4]]) + + # test_submatrix_assignment + m = sparse_zeros(4) + m[2:4, 2:4] = sparse_eye(2) + assert m == SparseMatrix([(0, 0, 0, 0), + (0, 0, 0, 0), + (0, 0, 1, 0), + (0, 0, 0, 1)]) + assert len(m.todok()) == 2 + m[:2, :2] = sparse_eye(2) + assert m == sparse_eye(4) + m[:, 0] = SparseMatrix(4, 1, (1, 2, 3, 4)) + assert m == SparseMatrix([(1, 0, 0, 0), + (2, 1, 0, 0), + (3, 0, 1, 0), + (4, 0, 0, 1)]) + m[:, :] = sparse_zeros(4) + assert m == sparse_zeros(4) + m[:, :] = ((1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12), (13, 14, 15, 16)) + assert m == SparseMatrix((( 1, 2, 3, 4), + ( 5, 6, 7, 8), + ( 9, 10, 11, 12), + (13, 14, 15, 16))) + m[:2, 0] = [0, 0] + assert m == SparseMatrix((( 0, 2, 3, 4), + ( 0, 6, 7, 8), + ( 9, 10, 11, 12), + (13, 14, 15, 16))) + + # test_reshape + m0 = sparse_eye(3) + assert m0.reshape(1, 9) == SparseMatrix(1, 9, (1, 0, 0, 0, 1, 0, 0, 0, 1)) + m1 = SparseMatrix(3, 4, lambda i, j: i + j) + assert m1.reshape(4, 3) == \ + SparseMatrix([(0, 1, 2), (3, 1, 2), (3, 4, 2), (3, 4, 5)]) + assert m1.reshape(2, 6) == \ + SparseMatrix([(0, 1, 2, 3, 1, 2), (3, 4, 2, 3, 4, 5)]) + + # test_applyfunc + m0 = sparse_eye(3) + assert m0.applyfunc(lambda x: 2*x) == sparse_eye(3)*2 + assert m0.applyfunc(lambda x: 0 ) == sparse_zeros(3) + + # test__eval_Abs + assert abs(SparseMatrix(((x, 1), (y, 2*y)))) == SparseMatrix(((Abs(x), 1), (Abs(y), 2*Abs(y)))) + + # test_LUdecomp + testmat = SparseMatrix([[ 0, 2, 5, 3], + [ 3, 3, 7, 4], + [ 8, 4, 0, 2], + [-2, 6, 3, 4]]) + L, U, p = testmat.LUdecomposition() + assert L.is_lower + assert U.is_upper + assert (L*U).permute_rows(p, 'backward') - testmat == sparse_zeros(4) + + testmat = SparseMatrix([[ 6, -2, 7, 4], + [ 0, 3, 6, 7], + [ 1, -2, 7, 4], + [-9, 2, 6, 3]]) + L, U, p = testmat.LUdecomposition() + assert L.is_lower + assert U.is_upper + assert (L*U).permute_rows(p, 'backward') - testmat == sparse_zeros(4) + + x, y, z = Symbol('x'), Symbol('y'), Symbol('z') + M = Matrix(((1, x, 1), (2, y, 0), (y, 0, z))) + L, U, p = M.LUdecomposition() + assert L.is_lower + assert U.is_upper + assert (L*U).permute_rows(p, 'backward') - M == sparse_zeros(3) + + # test_LUsolve + A = SparseMatrix([[2, 3, 5], + [3, 6, 2], + [8, 3, 6]]) + x = SparseMatrix(3, 1, [3, 7, 5]) + b = A*x + soln = A.LUsolve(b) + assert soln == x + A = SparseMatrix([[0, -1, 2], + [5, 10, 7], + [8, 3, 4]]) + x = SparseMatrix(3, 1, [-1, 2, 5]) + b = A*x + soln = A.LUsolve(b) + assert soln == x + + # test_inverse + A = sparse_eye(4) + assert A.inv() == sparse_eye(4) + assert A.inv(method="CH") == sparse_eye(4) + assert A.inv(method="LDL") == sparse_eye(4) + + A = SparseMatrix([[2, 3, 5], + [3, 6, 2], + [7, 2, 6]]) + Ainv = SparseMatrix(Matrix(A).inv()) + assert A*Ainv == sparse_eye(3) + assert A.inv(method="CH") == Ainv + assert A.inv(method="LDL") == Ainv + + A = SparseMatrix([[2, 3, 5], + [3, 6, 2], + [5, 2, 6]]) + Ainv = SparseMatrix(Matrix(A).inv()) + assert A*Ainv == sparse_eye(3) + assert A.inv(method="CH") == Ainv + assert A.inv(method="LDL") == Ainv + + # test_cross + v1 = Matrix(1, 3, [1, 2, 3]) + v2 = Matrix(1, 3, [3, 4, 5]) + assert v1.cross(v2) == Matrix(1, 3, [-2, 4, -2]) + assert v1.norm(2)**2 == 14 + + # conjugate + a = SparseMatrix(((1, 2 + I), (3, 4))) + assert a.C == SparseMatrix([ + [1, 2 - I], + [3, 4] + ]) + + # mul + assert a*Matrix(2, 2, [1, 0, 0, 1]) == a + assert a + Matrix(2, 2, [1, 1, 1, 1]) == SparseMatrix([ + [2, 3 + I], + [4, 5] + ]) + + # col join + assert a.col_join(sparse_eye(2)) == SparseMatrix([ + [1, 2 + I], + [3, 4], + [1, 0], + [0, 1] + ]) + + # row insert + assert a.row_insert(2, sparse_eye(2)) == SparseMatrix([ + [1, 2 + I], + [3, 4], + [1, 0], + [0, 1] + ]) + + # col insert + assert a.col_insert(2, SparseMatrix.zeros(2, 1)) == SparseMatrix([ + [1, 2 + I, 0], + [3, 4, 0], + ]) + + # symmetric + assert not a.is_symmetric(simplify=False) + + # col op + M = SparseMatrix.eye(3)*2 + M[1, 0] = -1 + M.col_op(1, lambda v, i: v + 2*M[i, 0]) + assert M == SparseMatrix([ + [ 2, 4, 0], + [-1, 0, 0], + [ 0, 0, 2] + ]) + + # fill + M = SparseMatrix.eye(3) + M.fill(2) + assert M == SparseMatrix([ + [2, 2, 2], + [2, 2, 2], + [2, 2, 2], + ]) + + # test_cofactor + assert sparse_eye(3) == sparse_eye(3).cofactor_matrix() + test = SparseMatrix([[1, 3, 2], [2, 6, 3], [2, 3, 6]]) + assert test.cofactor_matrix() == \ + SparseMatrix([[27, -6, -6], [-12, 2, 3], [-3, 1, 0]]) + test = SparseMatrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + assert test.cofactor_matrix() == \ + SparseMatrix([[-3, 6, -3], [6, -12, 6], [-3, 6, -3]]) + + # test_jacobian + x = Symbol('x') + y = Symbol('y') + L = SparseMatrix(1, 2, [x**2*y, 2*y**2 + x*y]) + syms = [x, y] + assert L.jacobian(syms) == Matrix([[2*x*y, x**2], [y, 4*y + x]]) + + L = SparseMatrix(1, 2, [x, x**2*y**3]) + assert L.jacobian(syms) == SparseMatrix([[1, 0], [2*x*y**3, x**2*3*y**2]]) + + # test_QR + A = Matrix([[1, 2], [2, 3]]) + Q, S = A.QRdecomposition() + R = Rational + assert Q == Matrix([ + [ 5**R(-1, 2), (R(2)/5)*(R(1)/5)**R(-1, 2)], + [2*5**R(-1, 2), (-R(1)/5)*(R(1)/5)**R(-1, 2)]]) + assert S == Matrix([ + [5**R(1, 2), 8*5**R(-1, 2)], + [ 0, (R(1)/5)**R(1, 2)]]) + assert Q*S == A + assert Q.T * Q == sparse_eye(2) + + R = Rational + # test nullspace + # first test reduced row-ech form + + M = SparseMatrix([[5, 7, 2, 1], + [1, 6, 2, -1]]) + out, tmp = M.rref() + assert out == Matrix([[1, 0, -R(2)/23, R(13)/23], + [0, 1, R(8)/23, R(-6)/23]]) + + M = SparseMatrix([[ 1, 3, 0, 2, 6, 3, 1], + [-2, -6, 0, -2, -8, 3, 1], + [ 3, 9, 0, 0, 6, 6, 2], + [-1, -3, 0, 1, 0, 9, 3]]) + + out, tmp = M.rref() + assert out == Matrix([[1, 3, 0, 0, 2, 0, 0], + [0, 0, 0, 1, 2, 0, 0], + [0, 0, 0, 0, 0, 1, R(1)/3], + [0, 0, 0, 0, 0, 0, 0]]) + # now check the vectors + basis = M.nullspace() + assert basis[0] == Matrix([-3, 1, 0, 0, 0, 0, 0]) + assert basis[1] == Matrix([0, 0, 1, 0, 0, 0, 0]) + assert basis[2] == Matrix([-2, 0, 0, -2, 1, 0, 0]) + assert basis[3] == Matrix([0, 0, 0, 0, 0, R(-1)/3, 1]) + + # test eigen + x = Symbol('x') + y = Symbol('y') + sparse_eye3 = sparse_eye(3) + assert sparse_eye3.charpoly(x) == PurePoly((x - 1)**3) + assert sparse_eye3.charpoly(y) == PurePoly((y - 1)**3) + + # test values + M = Matrix([( 0, 1, -1), + ( 1, 1, 0), + (-1, 0, 1)]) + vals = M.eigenvals() + assert sorted(vals.keys()) == [-1, 1, 2] + + R = Rational + M = Matrix([[1, 0, 0], + [0, 1, 0], + [0, 0, 1]]) + assert M.eigenvects() == [(1, 3, [ + Matrix([1, 0, 0]), + Matrix([0, 1, 0]), + Matrix([0, 0, 1])])] + M = Matrix([[5, 0, 2], + [3, 2, 0], + [0, 0, 1]]) + assert M.eigenvects() == [(1, 1, [Matrix([R(-1)/2, R(3)/2, 1])]), + (2, 1, [Matrix([0, 1, 0])]), + (5, 1, [Matrix([1, 1, 0])])] + + assert M.zeros(3, 5) == SparseMatrix(3, 5, {}) + A = SparseMatrix(10, 10, {(0, 0): 18, (0, 9): 12, (1, 4): 18, (2, 7): 16, (3, 9): 12, (4, 2): 19, (5, 7): 16, (6, 2): 12, (9, 7): 18}) + assert A.row_list() == [(0, 0, 18), (0, 9, 12), (1, 4, 18), (2, 7, 16), (3, 9, 12), (4, 2, 19), (5, 7, 16), (6, 2, 12), (9, 7, 18)] + assert A.col_list() == [(0, 0, 18), (4, 2, 19), (6, 2, 12), (1, 4, 18), (2, 7, 16), (5, 7, 16), (9, 7, 18), (0, 9, 12), (3, 9, 12)] + assert SparseMatrix.eye(2).nnz() == 2 + + +def test_scalar_multiply(): + assert SparseMatrix([[1, 2]]).scalar_multiply(3) == SparseMatrix([[3, 6]]) + + +def test_transpose(): + assert SparseMatrix(((1, 2), (3, 4))).transpose() == \ + SparseMatrix(((1, 3), (2, 4))) + + +def test_trace(): + assert SparseMatrix(((1, 2), (3, 4))).trace() == 5 + assert SparseMatrix(((0, 0), (0, 4))).trace() == 4 + + +def test_CL_RL(): + assert SparseMatrix(((1, 2), (3, 4))).row_list() == \ + [(0, 0, 1), (0, 1, 2), (1, 0, 3), (1, 1, 4)] + assert SparseMatrix(((1, 2), (3, 4))).col_list() == \ + [(0, 0, 1), (1, 0, 3), (0, 1, 2), (1, 1, 4)] + + +def test_add(): + assert SparseMatrix(((1, 0), (0, 1))) + SparseMatrix(((0, 1), (1, 0))) == \ + SparseMatrix(((1, 1), (1, 1))) + a = SparseMatrix(100, 100, lambda i, j: int(j != 0 and i % j == 0)) + b = SparseMatrix(100, 100, lambda i, j: int(i != 0 and j % i == 0)) + assert (len(a.todok()) + len(b.todok()) - len((a + b).todok()) > 0) + + +def test_errors(): + raises(ValueError, lambda: SparseMatrix(1.4, 2, lambda i, j: 0)) + raises(TypeError, lambda: SparseMatrix([1, 2, 3], [1, 2])) + raises(ValueError, lambda: SparseMatrix([[1, 2], [3, 4]])[(1, 2, 3)]) + raises(IndexError, lambda: SparseMatrix([[1, 2], [3, 4]])[5]) + raises(ValueError, lambda: SparseMatrix([[1, 2], [3, 4]])[1, 2, 3]) + raises(TypeError, + lambda: SparseMatrix([[1, 2], [3, 4]]).copyin_list([0, 1], set())) + raises( + IndexError, lambda: SparseMatrix([[1, 2], [3, 4]])[1, 2]) + raises(TypeError, lambda: SparseMatrix([1, 2, 3]).cross(1)) + raises(IndexError, lambda: SparseMatrix(1, 2, [1, 2])[3]) + raises(ShapeError, + lambda: SparseMatrix(1, 2, [1, 2]) + SparseMatrix(2, 1, [2, 1])) + + +def test_len(): + assert not SparseMatrix() + assert SparseMatrix() == SparseMatrix([]) + assert SparseMatrix() == SparseMatrix([[]]) + + +def test_sparse_zeros_sparse_eye(): + assert SparseMatrix.eye(3) == eye(3, cls=SparseMatrix) + assert len(SparseMatrix.eye(3).todok()) == 3 + assert SparseMatrix.zeros(3) == zeros(3, cls=SparseMatrix) + assert len(SparseMatrix.zeros(3).todok()) == 0 + + +def test_copyin(): + s = SparseMatrix(3, 3, {}) + s[1, 0] = 1 + assert s[:, 0] == SparseMatrix(Matrix([0, 1, 0])) + assert s[3] == 1 + assert s[3: 4] == [1] + s[1, 1] = 42 + assert s[1, 1] == 42 + assert s[1, 1:] == SparseMatrix([[42, 0]]) + s[1, 1:] = Matrix([[5, 6]]) + assert s[1, :] == SparseMatrix([[1, 5, 6]]) + s[1, 1:] = [[42, 43]] + assert s[1, :] == SparseMatrix([[1, 42, 43]]) + s[0, 0] = 17 + assert s[:, :1] == SparseMatrix([17, 1, 0]) + s[0, 0] = [1, 1, 1] + assert s[:, 0] == SparseMatrix([1, 1, 1]) + s[0, 0] = Matrix([1, 1, 1]) + assert s[:, 0] == SparseMatrix([1, 1, 1]) + s[0, 0] = SparseMatrix([1, 1, 1]) + assert s[:, 0] == SparseMatrix([1, 1, 1]) + + +def test_sparse_solve(): + A = SparseMatrix(((25, 15, -5), (15, 18, 0), (-5, 0, 11))) + assert A.cholesky() == Matrix([ + [ 5, 0, 0], + [ 3, 3, 0], + [-1, 1, 3]]) + assert A.cholesky() * A.cholesky().T == Matrix([ + [25, 15, -5], + [15, 18, 0], + [-5, 0, 11]]) + + A = SparseMatrix(((25, 15, -5), (15, 18, 0), (-5, 0, 11))) + L, D = A.LDLdecomposition() + assert 15*L == Matrix([ + [15, 0, 0], + [ 9, 15, 0], + [-3, 5, 15]]) + assert D == Matrix([ + [25, 0, 0], + [ 0, 9, 0], + [ 0, 0, 9]]) + assert L * D * L.T == A + + A = SparseMatrix(((3, 0, 2), (0, 0, 1), (1, 2, 0))) + assert A.inv() * A == SparseMatrix(eye(3)) + + A = SparseMatrix([ + [ 2, -1, 0], + [-1, 2, -1], + [ 0, 0, 2]]) + ans = SparseMatrix([ + [Rational(2, 3), Rational(1, 3), Rational(1, 6)], + [Rational(1, 3), Rational(2, 3), Rational(1, 3)], + [ 0, 0, S.Half]]) + assert A.inv(method='CH') == ans + assert A.inv(method='LDL') == ans + assert A * ans == SparseMatrix(eye(3)) + + s = A.solve(A[:, 0], 'LDL') + assert A*s == A[:, 0] + s = A.solve(A[:, 0], 'CH') + assert A*s == A[:, 0] + A = A.col_join(A) + s = A.solve_least_squares(A[:, 0], 'CH') + assert A*s == A[:, 0] + s = A.solve_least_squares(A[:, 0], 'LDL') + assert A*s == A[:, 0] + + +def test_lower_triangular_solve(): + raises(NonSquareMatrixError, lambda: + SparseMatrix([[1, 2]]).lower_triangular_solve(Matrix([[1, 2]]))) + raises(ShapeError, lambda: + SparseMatrix([[1, 2], [0, 4]]).lower_triangular_solve(Matrix([1]))) + raises(ValueError, lambda: + SparseMatrix([[1, 2], [3, 4]]).lower_triangular_solve(Matrix([[1, 2], [3, 4]]))) + + a, b, c, d = symbols('a:d') + u, v, w, x = symbols('u:x') + + A = SparseMatrix([[a, 0], [c, d]]) + B = MutableSparseMatrix([[u, v], [w, x]]) + C = ImmutableSparseMatrix([[u, v], [w, x]]) + + sol = Matrix([[u/a, v/a], [(w - c*u/a)/d, (x - c*v/a)/d]]) + assert A.lower_triangular_solve(B) == sol + assert A.lower_triangular_solve(C) == sol + + +def test_upper_triangular_solve(): + raises(NonSquareMatrixError, lambda: + SparseMatrix([[1, 2]]).upper_triangular_solve(Matrix([[1, 2]]))) + raises(ShapeError, lambda: + SparseMatrix([[1, 2], [0, 4]]).upper_triangular_solve(Matrix([1]))) + raises(TypeError, lambda: + SparseMatrix([[1, 2], [3, 4]]).upper_triangular_solve(Matrix([[1, 2], [3, 4]]))) + + a, b, c, d = symbols('a:d') + u, v, w, x = symbols('u:x') + + A = SparseMatrix([[a, b], [0, d]]) + B = MutableSparseMatrix([[u, v], [w, x]]) + C = ImmutableSparseMatrix([[u, v], [w, x]]) + + sol = Matrix([[(u - b*w/d)/a, (v - b*x/d)/a], [w/d, x/d]]) + assert A.upper_triangular_solve(B) == sol + assert A.upper_triangular_solve(C) == sol + + +def test_diagonal_solve(): + a, d = symbols('a d') + u, v, w, x = symbols('u:x') + + A = SparseMatrix([[a, 0], [0, d]]) + B = MutableSparseMatrix([[u, v], [w, x]]) + C = ImmutableSparseMatrix([[u, v], [w, x]]) + + sol = Matrix([[u/a, v/a], [w/d, x/d]]) + assert A.diagonal_solve(B) == sol + assert A.diagonal_solve(C) == sol + + +def test_hermitian(): + x = Symbol('x') + a = SparseMatrix([[0, I], [-I, 0]]) + assert a.is_hermitian + a = SparseMatrix([[1, I], [-I, 1]]) + assert a.is_hermitian + a[0, 0] = 2*I + assert a.is_hermitian is False + a[0, 0] = x + assert a.is_hermitian is None + a[0, 1] = a[1, 0]*I + assert a.is_hermitian is False diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_sparsetools.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_sparsetools.py new file mode 100644 index 0000000000000000000000000000000000000000..244944c31da06460d4bc7beff8bce0f91fea9f14 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_sparsetools.py @@ -0,0 +1,132 @@ +from sympy.matrices.sparsetools import _doktocsr, _csrtodok, banded +from sympy.matrices.dense import (Matrix, eye, ones, zeros) +from sympy.matrices import SparseMatrix +from sympy.testing.pytest import raises + + +def test_doktocsr(): + a = SparseMatrix([[1, 2, 0, 0], [0, 3, 9, 0], [0, 1, 4, 0]]) + b = SparseMatrix(4, 6, [10, 20, 0, 0, 0, 0, 0, 30, 0, 40, 0, 0, 0, 0, 50, + 60, 70, 0, 0, 0, 0, 0, 0, 80]) + c = SparseMatrix(4, 4, [0, 0, 0, 0, 0, 12, 0, 2, 15, 0, 12, 0, 0, 0, 0, 4]) + d = SparseMatrix(10, 10, {(1, 1): 12, (3, 5): 7, (7, 8): 12}) + e = SparseMatrix([[0, 0, 0], [1, 0, 2], [3, 0, 0]]) + f = SparseMatrix(7, 8, {(2, 3): 5, (4, 5):12}) + assert _doktocsr(a) == [[1, 2, 3, 9, 1, 4], [0, 1, 1, 2, 1, 2], + [0, 2, 4, 6], [3, 4]] + assert _doktocsr(b) == [[10, 20, 30, 40, 50, 60, 70, 80], + [0, 1, 1, 3, 2, 3, 4, 5], [0, 2, 4, 7, 8], [4, 6]] + assert _doktocsr(c) == [[12, 2, 15, 12, 4], [1, 3, 0, 2, 3], + [0, 0, 2, 4, 5], [4, 4]] + assert _doktocsr(d) == [[12, 7, 12], [1, 5, 8], + [0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3], [10, 10]] + assert _doktocsr(e) == [[1, 2, 3], [0, 2, 0], [0, 0, 2, 3], [3, 3]] + assert _doktocsr(f) == [[5, 12], [3, 5], [0, 0, 0, 1, 1, 2, 2, 2], [7, 8]] + + +def test_csrtodok(): + h = [[5, 7, 5], [2, 1, 3], [0, 1, 1, 3], [3, 4]] + g = [[12, 5, 4], [2, 4, 2], [0, 1, 2, 3], [3, 7]] + i = [[1, 3, 12], [0, 2, 4], [0, 2, 3], [2, 5]] + j = [[11, 15, 12, 15], [2, 4, 1, 2], [0, 1, 1, 2, 3, 4], [5, 8]] + k = [[1, 3], [2, 1], [0, 1, 1, 2], [3, 3]] + m = _csrtodok(h) + assert isinstance(m, SparseMatrix) + assert m == SparseMatrix(3, 4, + {(0, 2): 5, (2, 1): 7, (2, 3): 5}) + assert _csrtodok(g) == SparseMatrix(3, 7, + {(0, 2): 12, (1, 4): 5, (2, 2): 4}) + assert _csrtodok(i) == SparseMatrix([[1, 0, 3, 0, 0], [0, 0, 0, 0, 12]]) + assert _csrtodok(j) == SparseMatrix(5, 8, + {(0, 2): 11, (2, 4): 15, (3, 1): 12, (4, 2): 15}) + assert _csrtodok(k) == SparseMatrix(3, 3, {(0, 2): 1, (2, 1): 3}) + + +def test_banded(): + raises(TypeError, lambda: banded()) + raises(TypeError, lambda: banded(1)) + raises(TypeError, lambda: banded(1, 2)) + raises(TypeError, lambda: banded(1, 2, 3)) + raises(TypeError, lambda: banded(1, 2, 3, 4)) + raises(ValueError, lambda: banded({0: (1, 2)}, rows=1)) + raises(ValueError, lambda: banded({0: (1, 2)}, cols=1)) + raises(ValueError, lambda: banded(1, {0: (1, 2)})) + raises(ValueError, lambda: banded(2, 1, {0: (1, 2)})) + raises(ValueError, lambda: banded(1, 2, {0: (1, 2)})) + + assert isinstance(banded(2, 4, {}), SparseMatrix) + assert banded(2, 4, {}) == zeros(2, 4) + assert banded({0: 0, 1: 0}) == zeros(0) + assert banded({0: Matrix([1, 2])}) == Matrix([1, 2]) + assert banded({1: [1, 2, 3, 0], -1: [4, 5, 6]}) == \ + banded({1: (1, 2, 3), -1: (4, 5, 6)}) == \ + Matrix([ + [0, 1, 0, 0], + [4, 0, 2, 0], + [0, 5, 0, 3], + [0, 0, 6, 0]]) + assert banded(3, 4, {-1: 1, 0: 2, 1: 3}) == \ + Matrix([ + [2, 3, 0, 0], + [1, 2, 3, 0], + [0, 1, 2, 3]]) + s = lambda d: (1 + d)**2 + assert banded(5, {0: s, 2: s}) == \ + Matrix([ + [1, 0, 1, 0, 0], + [0, 4, 0, 4, 0], + [0, 0, 9, 0, 9], + [0, 0, 0, 16, 0], + [0, 0, 0, 0, 25]]) + assert banded(2, {0: 1}) == \ + Matrix([ + [1, 0], + [0, 1]]) + assert banded(2, 3, {0: 1}) == \ + Matrix([ + [1, 0, 0], + [0, 1, 0]]) + vert = Matrix([1, 2, 3]) + assert banded({0: vert}, cols=3) == \ + Matrix([ + [1, 0, 0], + [2, 1, 0], + [3, 2, 1], + [0, 3, 2], + [0, 0, 3]]) + assert banded(4, {0: ones(2)}) == \ + Matrix([ + [1, 1, 0, 0], + [1, 1, 0, 0], + [0, 0, 1, 1], + [0, 0, 1, 1]]) + raises(ValueError, lambda: banded({0: 2, 1: ones(2)}, rows=5)) + assert banded({0: 2, 2: (ones(2),)*3}) == \ + Matrix([ + [2, 0, 1, 1, 0, 0, 0, 0], + [0, 2, 1, 1, 0, 0, 0, 0], + [0, 0, 2, 0, 1, 1, 0, 0], + [0, 0, 0, 2, 1, 1, 0, 0], + [0, 0, 0, 0, 2, 0, 1, 1], + [0, 0, 0, 0, 0, 2, 1, 1]]) + raises(ValueError, lambda: banded({0: (2,)*5, 1: (ones(2),)*3})) + u2 = Matrix([[1, 1], [0, 1]]) + assert banded({0: (2,)*5, 1: (u2,)*3}) == \ + Matrix([ + [2, 1, 1, 0, 0, 0, 0], + [0, 2, 1, 0, 0, 0, 0], + [0, 0, 2, 1, 1, 0, 0], + [0, 0, 0, 2, 1, 0, 0], + [0, 0, 0, 0, 2, 1, 1], + [0, 0, 0, 0, 0, 0, 1]]) + assert banded({0:(0, ones(2)), 2: 2}) == \ + Matrix([ + [0, 0, 2], + [0, 1, 1], + [0, 1, 1]]) + raises(ValueError, lambda: banded({0: (0, ones(2)), 1: 2})) + assert banded({0: 1}, cols=3) == banded({0: 1}, rows=3) == eye(3) + assert banded({1: 1}, rows=3) == Matrix([ + [0, 1, 0], + [0, 0, 1], + [0, 0, 0]]) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_subspaces.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_subspaces.py new file mode 100644 index 0000000000000000000000000000000000000000..0bd853e321eb06f754c17e7bd0c11deb870506f5 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/matrices/tests/test_subspaces.py @@ -0,0 +1,109 @@ +from sympy.matrices import Matrix +from sympy.core.numbers import Rational +from sympy.core.symbol import symbols +from sympy.solvers import solve + + +def test_columnspace_one(): + m = Matrix([[ 1, 2, 0, 2, 5], + [-2, -5, 1, -1, -8], + [ 0, -3, 3, 4, 1], + [ 3, 6, 0, -7, 2]]) + + basis = m.columnspace() + assert basis[0] == Matrix([1, -2, 0, 3]) + assert basis[1] == Matrix([2, -5, -3, 6]) + assert basis[2] == Matrix([2, -1, 4, -7]) + + assert len(basis) == 3 + assert Matrix.hstack(m, *basis).columnspace() == basis + + +def test_rowspace(): + m = Matrix([[ 1, 2, 0, 2, 5], + [-2, -5, 1, -1, -8], + [ 0, -3, 3, 4, 1], + [ 3, 6, 0, -7, 2]]) + + basis = m.rowspace() + assert basis[0] == Matrix([[1, 2, 0, 2, 5]]) + assert basis[1] == Matrix([[0, -1, 1, 3, 2]]) + assert basis[2] == Matrix([[0, 0, 0, 5, 5]]) + + assert len(basis) == 3 + + +def test_nullspace_one(): + m = Matrix([[ 1, 2, 0, 2, 5], + [-2, -5, 1, -1, -8], + [ 0, -3, 3, 4, 1], + [ 3, 6, 0, -7, 2]]) + + basis = m.nullspace() + assert basis[0] == Matrix([-2, 1, 1, 0, 0]) + assert basis[1] == Matrix([-1, -1, 0, -1, 1]) + # make sure the null space is really gets zeroed + assert all(e.is_zero for e in m*basis[0]) + assert all(e.is_zero for e in m*basis[1]) + +def test_nullspace_second(): + # first test reduced row-ech form + R = Rational + + M = Matrix([[5, 7, 2, 1], + [1, 6, 2, -1]]) + out, tmp = M.rref() + assert out == Matrix([[1, 0, -R(2)/23, R(13)/23], + [0, 1, R(8)/23, R(-6)/23]]) + + M = Matrix([[-5, -1, 4, -3, -1], + [ 1, -1, -1, 1, 0], + [-1, 0, 0, 0, 0], + [ 4, 1, -4, 3, 1], + [-2, 0, 2, -2, -1]]) + assert M*M.nullspace()[0] == Matrix(5, 1, [0]*5) + + M = Matrix([[ 1, 3, 0, 2, 6, 3, 1], + [-2, -6, 0, -2, -8, 3, 1], + [ 3, 9, 0, 0, 6, 6, 2], + [-1, -3, 0, 1, 0, 9, 3]]) + out, tmp = M.rref() + assert out == Matrix([[1, 3, 0, 0, 2, 0, 0], + [0, 0, 0, 1, 2, 0, 0], + [0, 0, 0, 0, 0, 1, R(1)/3], + [0, 0, 0, 0, 0, 0, 0]]) + + # now check the vectors + basis = M.nullspace() + assert basis[0] == Matrix([-3, 1, 0, 0, 0, 0, 0]) + assert basis[1] == Matrix([0, 0, 1, 0, 0, 0, 0]) + assert basis[2] == Matrix([-2, 0, 0, -2, 1, 0, 0]) + assert basis[3] == Matrix([0, 0, 0, 0, 0, R(-1)/3, 1]) + + # issue 4797; just see that we can do it when rows > cols + M = Matrix([[1, 2], [2, 4], [3, 6]]) + assert M.nullspace() + + +def test_columnspace_second(): + M = Matrix([[ 1, 2, 0, 2, 5], + [-2, -5, 1, -1, -8], + [ 0, -3, 3, 4, 1], + [ 3, 6, 0, -7, 2]]) + + # now check the vectors + basis = M.columnspace() + assert basis[0] == Matrix([1, -2, 0, 3]) + assert basis[1] == Matrix([2, -5, -3, 6]) + assert basis[2] == Matrix([2, -1, 4, -7]) + + #check by columnspace definition + a, b, c, d, e = symbols('a b c d e') + X = Matrix([a, b, c, d, e]) + for i in range(len(basis)): + eq=M*X-basis[i] + assert len(solve(eq, X)) != 0 + + #check if rank-nullity theorem holds + assert M.rank() == len(basis) + assert len(M.nullspace()) + len(M.columnspace()) == M.cols diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b59e688eab15251a6a08496c532bb66af117c766 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/__pycache__/conflict.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/__pycache__/conflict.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..42d78ef80eee2b71d6e44871d3d62b40c6193fa1 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/__pycache__/conflict.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/__pycache__/core.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/__pycache__/core.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..011800ecc3bb9973bf25acc19b06b2b40a24ec34 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/__pycache__/core.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/__pycache__/dispatcher.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/__pycache__/dispatcher.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8695569b0dbfa2f0b9092b69019c2cd7957a8d5b Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/__pycache__/dispatcher.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/__pycache__/utils.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/__pycache__/utils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3fcb72b0a0cb7a6d5d876e5707473e331a5aa8d8 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/__pycache__/utils.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eecccae81f9b1caba0c91b5d9507bc5e022bd3a2 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/tests/__pycache__/test_conflict.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/tests/__pycache__/test_conflict.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..89f7440593ee839fc73becd9decd4b96b42ac0c5 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/tests/__pycache__/test_conflict.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/tests/__pycache__/test_core.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/tests/__pycache__/test_core.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a3b2e1d72684dc4731c9cca131fe071821f76af5 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/tests/__pycache__/test_core.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/tests/__pycache__/test_dispatcher.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/tests/__pycache__/test_dispatcher.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..32c3c6d2f3302263fa61f7eacdf6c7549363db4b Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/tests/__pycache__/test_dispatcher.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/tests/test_conflict.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/tests/test_conflict.py new file mode 100644 index 0000000000000000000000000000000000000000..5d2292c460585ae2a65a01795b38499e67706ff0 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/tests/test_conflict.py @@ -0,0 +1,62 @@ +from sympy.multipledispatch.conflict import (supercedes, ordering, ambiguities, + ambiguous, super_signature, consistent) + + +class A: pass +class B(A): pass +class C: pass + + +def test_supercedes(): + assert supercedes([B], [A]) + assert supercedes([B, A], [A, A]) + assert not supercedes([B, A], [A, B]) + assert not supercedes([A], [B]) + + +def test_consistent(): + assert consistent([A], [A]) + assert consistent([B], [B]) + assert not consistent([A], [C]) + assert consistent([A, B], [A, B]) + assert consistent([B, A], [A, B]) + assert not consistent([B, A], [B]) + assert not consistent([B, A], [B, C]) + + +def test_super_signature(): + assert super_signature([[A]]) == [A] + assert super_signature([[A], [B]]) == [B] + assert super_signature([[A, B], [B, A]]) == [B, B] + assert super_signature([[A, A, B], [A, B, A], [B, A, A]]) == [B, B, B] + + +def test_ambiguous(): + assert not ambiguous([A], [A]) + assert not ambiguous([A], [B]) + assert not ambiguous([B], [B]) + assert not ambiguous([A, B], [B, B]) + assert ambiguous([A, B], [B, A]) + + +def test_ambiguities(): + signatures = [[A], [B], [A, B], [B, A], [A, C]] + expected = {((A, B), (B, A))} + result = ambiguities(signatures) + assert set(map(frozenset, expected)) == set(map(frozenset, result)) + + signatures = [[A], [B], [A, B], [B, A], [A, C], [B, B]] + expected = set() + result = ambiguities(signatures) + assert set(map(frozenset, expected)) == set(map(frozenset, result)) + + +def test_ordering(): + signatures = [[A, A], [A, B], [B, A], [B, B], [A, C]] + ord = ordering(signatures) + assert ord[0] == (B, B) or ord[0] == (A, C) + assert ord[-1] == (A, A) or ord[-1] == (A, C) + + +def test_type_mro(): + assert super_signature([[object], [type]]) == [type] diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/tests/test_core.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/tests/test_core.py new file mode 100644 index 0000000000000000000000000000000000000000..016270fecc8cda644fc71b5c310b1430b50361f6 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/tests/test_core.py @@ -0,0 +1,213 @@ +from __future__ import annotations +from typing import Any + +from sympy.multipledispatch import dispatch +from sympy.multipledispatch.conflict import AmbiguityWarning +from sympy.testing.pytest import raises, warns +from functools import partial + +test_namespace: dict[str, Any] = {} + +orig_dispatch = dispatch +dispatch = partial(dispatch, namespace=test_namespace) + + +def test_singledispatch(): + @dispatch(int) + def f(x): # noqa:F811 + return x + 1 + + @dispatch(int) + def g(x): # noqa:F811 + return x + 2 + + @dispatch(float) # noqa:F811 + def f(x): # noqa:F811 + return x - 1 + + assert f(1) == 2 + assert g(1) == 3 + assert f(1.0) == 0 + + assert raises(NotImplementedError, lambda: f('hello')) + + +def test_multipledispatch(): + @dispatch(int, int) + def f(x, y): # noqa:F811 + return x + y + + @dispatch(float, float) # noqa:F811 + def f(x, y): # noqa:F811 + return x - y + + assert f(1, 2) == 3 + assert f(1.0, 2.0) == -1.0 + + +class A: pass +class B: pass +class C(A): pass +class D(C): pass +class E(C): pass + + +def test_inheritance(): + @dispatch(A) + def f(x): # noqa:F811 + return 'a' + + @dispatch(B) # noqa:F811 + def f(x): # noqa:F811 + return 'b' + + assert f(A()) == 'a' + assert f(B()) == 'b' + assert f(C()) == 'a' + + +def test_inheritance_and_multiple_dispatch(): + @dispatch(A, A) + def f(x, y): # noqa:F811 + return type(x), type(y) + + @dispatch(A, B) # noqa:F811 + def f(x, y): # noqa:F811 + return 0 + + assert f(A(), A()) == (A, A) + assert f(A(), C()) == (A, C) + assert f(A(), B()) == 0 + assert f(C(), B()) == 0 + assert raises(NotImplementedError, lambda: f(B(), B())) + + +def test_competing_solutions(): + @dispatch(A) + def h(x): # noqa:F811 + return 1 + + @dispatch(C) # noqa:F811 + def h(x): # noqa:F811 + return 2 + + assert h(D()) == 2 + + +def test_competing_multiple(): + @dispatch(A, B) + def h(x, y): # noqa:F811 + return 1 + + @dispatch(C, B) # noqa:F811 + def h(x, y): # noqa:F811 + return 2 + + assert h(D(), B()) == 2 + + +def test_competing_ambiguous(): + test_namespace = {} + dispatch = partial(orig_dispatch, namespace=test_namespace) + + @dispatch(A, C) + def f(x, y): # noqa:F811 + return 2 + + with warns(AmbiguityWarning, test_stacklevel=False): + @dispatch(C, A) # noqa:F811 + def f(x, y): # noqa:F811 + return 2 + + assert f(A(), C()) == f(C(), A()) == 2 + # assert raises(Warning, lambda : f(C(), C())) + + +def test_caching_correct_behavior(): + @dispatch(A) + def f(x): # noqa:F811 + return 1 + + assert f(C()) == 1 + + @dispatch(C) + def f(x): # noqa:F811 + return 2 + + assert f(C()) == 2 + + +def test_union_types(): + @dispatch((A, C)) + def f(x): # noqa:F811 + return 1 + + assert f(A()) == 1 + assert f(C()) == 1 + + +def test_namespaces(): + ns1 = {} + ns2 = {} + + def foo(x): + return 1 + foo1 = orig_dispatch(int, namespace=ns1)(foo) + + def foo(x): + return 2 + foo2 = orig_dispatch(int, namespace=ns2)(foo) + + assert foo1(0) == 1 + assert foo2(0) == 2 + + +""" +Fails +def test_dispatch_on_dispatch(): + @dispatch(A) + @dispatch(C) + def q(x): # noqa:F811 + return 1 + + assert q(A()) == 1 + assert q(C()) == 1 +""" + + +def test_methods(): + class Foo: + @dispatch(float) + def f(self, x): # noqa:F811 + return x - 1 + + @dispatch(int) # noqa:F811 + def f(self, x): # noqa:F811 + return x + 1 + + @dispatch(int) + def g(self, x): # noqa:F811 + return x + 3 + + + foo = Foo() + assert foo.f(1) == 2 + assert foo.f(1.0) == 0.0 + assert foo.g(1) == 4 + + +def test_methods_multiple_dispatch(): + class Foo: + @dispatch(A, A) + def f(x, y): # noqa:F811 + return 1 + + @dispatch(A, C) # noqa:F811 + def f(x, y): # noqa:F811 + return 2 + + + foo = Foo() + assert foo.f(A(), A()) == 1 + assert foo.f(A(), C()) == 2 + assert foo.f(C(), C()) == 2 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/tests/test_dispatcher.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/tests/test_dispatcher.py new file mode 100644 index 0000000000000000000000000000000000000000..e31ca8a5486b87eb43fc5e6f887caf50d6bfbe20 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/multipledispatch/tests/test_dispatcher.py @@ -0,0 +1,284 @@ +from sympy.multipledispatch.dispatcher import (Dispatcher, MDNotImplementedError, + MethodDispatcher, halt_ordering, + restart_ordering, + ambiguity_register_error_ignore_dup) +from sympy.testing.pytest import raises, warns + + +def identity(x): + return x + + +def inc(x): + return x + 1 + + +def dec(x): + return x - 1 + + +def test_dispatcher(): + f = Dispatcher('f') + f.add((int,), inc) + f.add((float,), dec) + + with warns(DeprecationWarning, test_stacklevel=False): + assert f.resolve((int,)) == inc + assert f.dispatch(int) is inc + + assert f(1) == 2 + assert f(1.0) == 0.0 + + +def test_union_types(): + f = Dispatcher('f') + f.register((int, float))(inc) + + assert f(1) == 2 + assert f(1.0) == 2.0 + + +def test_dispatcher_as_decorator(): + f = Dispatcher('f') + + @f.register(int) + def inc(x): # noqa:F811 + return x + 1 + + @f.register(float) # noqa:F811 + def inc(x): # noqa:F811 + return x - 1 + + assert f(1) == 2 + assert f(1.0) == 0.0 + + +def test_register_instance_method(): + + class Test: + __init__ = MethodDispatcher('f') + + @__init__.register(list) + def _init_list(self, data): + self.data = data + + @__init__.register(object) + def _init_obj(self, datum): + self.data = [datum] + + a = Test(3) + b = Test([3]) + assert a.data == b.data + + +def test_on_ambiguity(): + f = Dispatcher('f') + + def identity(x): return x + + ambiguities = [False] + + def on_ambiguity(dispatcher, amb): + ambiguities[0] = True + + f.add((object, object), identity, on_ambiguity=on_ambiguity) + assert not ambiguities[0] + f.add((object, float), identity, on_ambiguity=on_ambiguity) + assert not ambiguities[0] + f.add((float, object), identity, on_ambiguity=on_ambiguity) + assert ambiguities[0] + + +def test_raise_error_on_non_class(): + f = Dispatcher('f') + assert raises(TypeError, lambda: f.add((1,), inc)) + + +def test_docstring(): + + def one(x, y): + """ Docstring number one """ + return x + y + + def two(x, y): + """ Docstring number two """ + return x + y + + def three(x, y): + return x + y + + master_doc = 'Doc of the multimethod itself' + + f = Dispatcher('f', doc=master_doc) + f.add((object, object), one) + f.add((int, int), two) + f.add((float, float), three) + + assert one.__doc__.strip() in f.__doc__ + assert two.__doc__.strip() in f.__doc__ + assert f.__doc__.find(one.__doc__.strip()) < \ + f.__doc__.find(two.__doc__.strip()) + assert 'object, object' in f.__doc__ + assert master_doc in f.__doc__ + + +def test_help(): + def one(x, y): + """ Docstring number one """ + return x + y + + def two(x, y): + """ Docstring number two """ + return x + y + + def three(x, y): + """ Docstring number three """ + return x + y + + master_doc = 'Doc of the multimethod itself' + + f = Dispatcher('f', doc=master_doc) + f.add((object, object), one) + f.add((int, int), two) + f.add((float, float), three) + + assert f._help(1, 1) == two.__doc__ + assert f._help(1.0, 2.0) == three.__doc__ + + +def test_source(): + def one(x, y): + """ Docstring number one """ + return x + y + + def two(x, y): + """ Docstring number two """ + return x - y + + master_doc = 'Doc of the multimethod itself' + + f = Dispatcher('f', doc=master_doc) + f.add((int, int), one) + f.add((float, float), two) + + assert 'x + y' in f._source(1, 1) + assert 'x - y' in f._source(1.0, 1.0) + + +def test_source_raises_on_missing_function(): + f = Dispatcher('f') + + assert raises(TypeError, lambda: f.source(1)) + + +def test_halt_method_resolution(): + g = [0] + + def on_ambiguity(a, b): + g[0] += 1 + + f = Dispatcher('f') + + halt_ordering() + + def func(*args): + pass + + f.add((int, object), func) + f.add((object, int), func) + + assert g == [0] + + restart_ordering(on_ambiguity=on_ambiguity) + + assert g == [1] + + assert set(f.ordering) == {(int, object), (object, int)} + + +def test_no_implementations(): + f = Dispatcher('f') + assert raises(NotImplementedError, lambda: f('hello')) + + +def test_register_stacking(): + f = Dispatcher('f') + + @f.register(list) + @f.register(tuple) + def rev(x): + return x[::-1] + + assert f((1, 2, 3)) == (3, 2, 1) + assert f([1, 2, 3]) == [3, 2, 1] + + assert raises(NotImplementedError, lambda: f('hello')) + assert rev('hello') == 'olleh' + + +def test_dispatch_method(): + f = Dispatcher('f') + + @f.register(list) + def rev(x): + return x[::-1] + + @f.register(int, int) + def add(x, y): + return x + y + + class MyList(list): + pass + + assert f.dispatch(list) is rev + assert f.dispatch(MyList) is rev + assert f.dispatch(int, int) is add + + +def test_not_implemented(): + f = Dispatcher('f') + + @f.register(object) + def _(x): + return 'default' + + @f.register(int) + def _(x): + if x % 2 == 0: + return 'even' + else: + raise MDNotImplementedError() + + assert f('hello') == 'default' # default behavior + assert f(2) == 'even' # specialized behavior + assert f(3) == 'default' # fall bac to default behavior + assert raises(NotImplementedError, lambda: f(1, 2)) + + +def test_not_implemented_error(): + f = Dispatcher('f') + + @f.register(float) + def _(a): + raise MDNotImplementedError() + + assert raises(NotImplementedError, lambda: f(1.0)) + +def test_ambiguity_register_error_ignore_dup(): + f = Dispatcher('f') + + class A: + pass + class B(A): + pass + class C(A): + pass + + # suppress warning for registering ambiguous signal + f.add((A, B), lambda x,y: None, ambiguity_register_error_ignore_dup) + f.add((B, A), lambda x,y: None, ambiguity_register_error_ignore_dup) + f.add((A, C), lambda x,y: None, ambiguity_register_error_ignore_dup) + f.add((C, A), lambda x,y: None, ambiguity_register_error_ignore_dup) + + # raises error if ambiguous signal is passed + assert raises(NotImplementedError, lambda: f(B(), C())) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..34a52c432a21041d4b5448314b02fb014f031663 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/__pycache__/experimental_lambdify.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/__pycache__/experimental_lambdify.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..89211d86bf25a4510c8a493d51720bf2e7599af0 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/__pycache__/experimental_lambdify.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/__pycache__/plot.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/__pycache__/plot.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2b107bfd13a5835da790a8e759467a04dc5eba72 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/__pycache__/plot.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/__pycache__/plot_implicit.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/__pycache__/plot_implicit.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8f9641a11b3a4de4653c18316cc1ac641a966dc7 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/__pycache__/plot_implicit.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/__pycache__/plotgrid.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/__pycache__/plotgrid.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..682d725604e8c636e6121a6267e816f0c96065d2 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/__pycache__/plotgrid.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/__pycache__/textplot.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/__pycache__/textplot.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..69b5456ece3ae1e133dc070ff1dd3997dfdf1dc4 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/__pycache__/textplot.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/__pycache__/utils.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/__pycache__/utils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..84af686a8dd690a569c22a40c13fb0ffea756a93 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/__pycache__/utils.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..97451a69321c6227724df879b7d22b7c4fdc0532 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/__pycache__/base_backend.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/__pycache__/base_backend.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eff450d4bb3f53ed960ceb43a5023b0e89275b66 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/__pycache__/base_backend.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/base_backend.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/base_backend.py new file mode 100644 index 0000000000000000000000000000000000000000..a43cfa18eb7aff90ddacd6cdb60dfb0dadcb0abf --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/base_backend.py @@ -0,0 +1,419 @@ +from sympy.plotting.series import BaseSeries, GenericDataSeries +from sympy.utilities.exceptions import sympy_deprecation_warning +from sympy.utilities.iterables import is_sequence + + +__doctest_requires__ = { + ('Plot.append', 'Plot.extend'): ['matplotlib'], +} + + +# Global variable +# Set to False when running tests / doctests so that the plots don't show. +_show = True + +def unset_show(): + """ + Disable show(). For use in the tests. + """ + global _show + _show = False + + +def _deprecation_msg_m_a_r_f(attr): + sympy_deprecation_warning( + f"The `{attr}` property is deprecated. The `{attr}` keyword " + "argument should be passed to a plotting function, which generates " + "the appropriate data series. If needed, index the plot object to " + "retrieve a specific data series.", + deprecated_since_version="1.13", + active_deprecations_target="deprecated-markers-annotations-fill-rectangles", + stacklevel=4) + + +def _create_generic_data_series(**kwargs): + keywords = ["annotations", "markers", "fill", "rectangles"] + series = [] + for kw in keywords: + dictionaries = kwargs.pop(kw, []) + if dictionaries is None: + dictionaries = [] + if isinstance(dictionaries, dict): + dictionaries = [dictionaries] + for d in dictionaries: + args = d.pop("args", []) + series.append(GenericDataSeries(kw, *args, **d)) + return series + + +class Plot: + """Base class for all backends. A backend represents the plotting library, + which implements the necessary functionalities in order to use SymPy + plotting functions. + + For interactive work the function :func:`plot` is better suited. + + This class permits the plotting of SymPy expressions using numerous + backends (:external:mod:`matplotlib`, textplot, the old pyglet module for SymPy, Google + charts api, etc). + + The figure can contain an arbitrary number of plots of SymPy expressions, + lists of coordinates of points, etc. Plot has a private attribute _series that + contains all data series to be plotted (expressions for lines or surfaces, + lists of points, etc (all subclasses of BaseSeries)). Those data series are + instances of classes not imported by ``from sympy import *``. + + The customization of the figure is on two levels. Global options that + concern the figure as a whole (e.g. title, xlabel, scale, etc) and + per-data series options (e.g. name) and aesthetics (e.g. color, point shape, + line type, etc.). + + The difference between options and aesthetics is that an aesthetic can be + a function of the coordinates (or parameters in a parametric plot). The + supported values for an aesthetic are: + + - None (the backend uses default values) + - a constant + - a function of one variable (the first coordinate or parameter) + - a function of two variables (the first and second coordinate or parameters) + - a function of three variables (only in nonparametric 3D plots) + + Their implementation depends on the backend so they may not work in some + backends. + + If the plot is parametric and the arity of the aesthetic function permits + it the aesthetic is calculated over parameters and not over coordinates. + If the arity does not permit calculation over parameters the calculation is + done over coordinates. + + Only cartesian coordinates are supported for the moment, but you can use + the parametric plots to plot in polar, spherical and cylindrical + coordinates. + + The arguments for the constructor Plot must be subclasses of BaseSeries. + + Any global option can be specified as a keyword argument. + + The global options for a figure are: + + - title : str + - xlabel : str or Symbol + - ylabel : str or Symbol + - zlabel : str or Symbol + - legend : bool + - xscale : {'linear', 'log'} + - yscale : {'linear', 'log'} + - axis : bool + - axis_center : tuple of two floats or {'center', 'auto'} + - xlim : tuple of two floats + - ylim : tuple of two floats + - aspect_ratio : tuple of two floats or {'auto'} + - autoscale : bool + - margin : float in [0, 1] + - backend : {'default', 'matplotlib', 'text'} or a subclass of BaseBackend + - size : optional tuple of two floats, (width, height); default: None + + The per data series options and aesthetics are: + There are none in the base series. See below for options for subclasses. + + Some data series support additional aesthetics or options: + + :class:`~.LineOver1DRangeSeries`, :class:`~.Parametric2DLineSeries`, and + :class:`~.Parametric3DLineSeries` support the following: + + Aesthetics: + + - line_color : string, or float, or function, optional + Specifies the color for the plot, which depends on the backend being + used. + + For example, if ``MatplotlibBackend`` is being used, then + Matplotlib string colors are acceptable (``"red"``, ``"r"``, + ``"cyan"``, ``"c"``, ...). + Alternatively, we can use a float number, 0 < color < 1, wrapped in a + string (for example, ``line_color="0.5"``) to specify grayscale colors. + Alternatively, We can specify a function returning a single + float value: this will be used to apply a color-loop (for example, + ``line_color=lambda x: math.cos(x)``). + + Note that by setting line_color, it would be applied simultaneously + to all the series. + + Options: + + - label : str + - steps : bool + - integers_only : bool + + :class:`~.SurfaceOver2DRangeSeries` and :class:`~.ParametricSurfaceSeries` + support the following: + + Aesthetics: + + - surface_color : function which returns a float. + + Notes + ===== + + How the plotting module works: + + 1. Whenever a plotting function is called, the provided expressions are + processed and a list of instances of the + :class:`~sympy.plotting.series.BaseSeries` class is created, containing + the necessary information to plot the expressions + (e.g. the expression, ranges, series name, ...). Eventually, these + objects will generate the numerical data to be plotted. + 2. A subclass of :class:`~.Plot` class is instantiaed (referred to as + backend, from now on), which stores the list of series and the main + attributes of the plot (e.g. axis labels, title, ...). + The backend implements the logic to generate the actual figure with + some plotting library. + 3. When the ``show`` command is executed, series are processed one by one + to generate numerical data and add it to the figure. The backend is also + going to set the axis labels, title, ..., according to the values stored + in the Plot instance. + + The backend should check if it supports the data series that it is given + (e.g. :class:`TextBackend` supports only + :class:`~sympy.plotting.series.LineOver1DRangeSeries`). + + It is the backend responsibility to know how to use the class of data series + that it's given. Note that the current implementation of the ``*Series`` + classes is "matplotlib-centric": the numerical data returned by the + ``get_points`` and ``get_meshes`` methods is meant to be used directly by + Matplotlib. Therefore, the new backend will have to pre-process the + numerical data to make it compatible with the chosen plotting library. + Keep in mind that future SymPy versions may improve the ``*Series`` classes + in order to return numerical data "non-matplotlib-centric", hence if you code + a new backend you have the responsibility to check if its working on each + SymPy release. + + Please explore the :class:`MatplotlibBackend` source code to understand + how a backend should be coded. + + In order to be used by SymPy plotting functions, a backend must implement + the following methods: + + * show(self): used to loop over the data series, generate the numerical + data, plot it and set the axis labels, title, ... + * save(self, path): used to save the current plot to the specified file + path. + * close(self): used to close the current plot backend (note: some plotting + library does not support this functionality. In that case, just raise a + warning). + """ + + def __init__(self, *args, + title=None, xlabel=None, ylabel=None, zlabel=None, aspect_ratio='auto', + xlim=None, ylim=None, axis_center='auto', axis=True, + xscale='linear', yscale='linear', legend=False, autoscale=True, + margin=0, annotations=None, markers=None, rectangles=None, + fill=None, backend='default', size=None, **kwargs): + + # Options for the graph as a whole. + # The possible values for each option are described in the docstring of + # Plot. They are based purely on convention, no checking is done. + self.title = title + self.xlabel = xlabel + self.ylabel = ylabel + self.zlabel = zlabel + self.aspect_ratio = aspect_ratio + self.axis_center = axis_center + self.axis = axis + self.xscale = xscale + self.yscale = yscale + self.legend = legend + self.autoscale = autoscale + self.margin = margin + self._annotations = annotations + self._markers = markers + self._rectangles = rectangles + self._fill = fill + + # Contains the data objects to be plotted. The backend should be smart + # enough to iterate over this list. + self._series = [] + self._series.extend(args) + self._series.extend(_create_generic_data_series( + annotations=annotations, markers=markers, rectangles=rectangles, + fill=fill)) + + is_real = \ + lambda lim: all(getattr(i, 'is_real', True) for i in lim) + is_finite = \ + lambda lim: all(getattr(i, 'is_finite', True) for i in lim) + + # reduce code repetition + def check_and_set(t_name, t): + if t: + if not is_real(t): + raise ValueError( + "All numbers from {}={} must be real".format(t_name, t)) + if not is_finite(t): + raise ValueError( + "All numbers from {}={} must be finite".format(t_name, t)) + setattr(self, t_name, (float(t[0]), float(t[1]))) + + self.xlim = None + check_and_set("xlim", xlim) + self.ylim = None + check_and_set("ylim", ylim) + self.size = None + check_and_set("size", size) + + @property + def _backend(self): + return self + + @property + def backend(self): + return type(self) + + def __str__(self): + series_strs = [('[%d]: ' % i) + str(s) + for i, s in enumerate(self._series)] + return 'Plot object containing:\n' + '\n'.join(series_strs) + + def __getitem__(self, index): + return self._series[index] + + def __setitem__(self, index, *args): + if len(args) == 1 and isinstance(args[0], BaseSeries): + self._series[index] = args + + def __delitem__(self, index): + del self._series[index] + + def append(self, arg): + """Adds an element from a plot's series to an existing plot. + + Examples + ======== + + Consider two ``Plot`` objects, ``p1`` and ``p2``. To add the + second plot's first series object to the first, use the + ``append`` method, like so: + + .. plot:: + :format: doctest + :include-source: True + + >>> from sympy import symbols + >>> from sympy.plotting import plot + >>> x = symbols('x') + >>> p1 = plot(x*x, show=False) + >>> p2 = plot(x, show=False) + >>> p1.append(p2[0]) + >>> p1 + Plot object containing: + [0]: cartesian line: x**2 for x over (-10.0, 10.0) + [1]: cartesian line: x for x over (-10.0, 10.0) + >>> p1.show() + + See Also + ======== + + extend + + """ + if isinstance(arg, BaseSeries): + self._series.append(arg) + else: + raise TypeError('Must specify element of plot to append.') + + def extend(self, arg): + """Adds all series from another plot. + + Examples + ======== + + Consider two ``Plot`` objects, ``p1`` and ``p2``. To add the + second plot to the first, use the ``extend`` method, like so: + + .. plot:: + :format: doctest + :include-source: True + + >>> from sympy import symbols + >>> from sympy.plotting import plot + >>> x = symbols('x') + >>> p1 = plot(x**2, show=False) + >>> p2 = plot(x, -x, show=False) + >>> p1.extend(p2) + >>> p1 + Plot object containing: + [0]: cartesian line: x**2 for x over (-10.0, 10.0) + [1]: cartesian line: x for x over (-10.0, 10.0) + [2]: cartesian line: -x for x over (-10.0, 10.0) + >>> p1.show() + + """ + if isinstance(arg, Plot): + self._series.extend(arg._series) + elif is_sequence(arg): + self._series.extend(arg) + else: + raise TypeError('Expecting Plot or sequence of BaseSeries') + + def show(self): + raise NotImplementedError + + def save(self, path): + raise NotImplementedError + + def close(self): + raise NotImplementedError + + # deprecations + + @property + def markers(self): + """.. deprecated:: 1.13""" + _deprecation_msg_m_a_r_f("markers") + return self._markers + + @markers.setter + def markers(self, v): + """.. deprecated:: 1.13""" + _deprecation_msg_m_a_r_f("markers") + self._series.extend(_create_generic_data_series(markers=v)) + self._markers = v + + @property + def annotations(self): + """.. deprecated:: 1.13""" + _deprecation_msg_m_a_r_f("annotations") + return self._annotations + + @annotations.setter + def annotations(self, v): + """.. deprecated:: 1.13""" + _deprecation_msg_m_a_r_f("annotations") + self._series.extend(_create_generic_data_series(annotations=v)) + self._annotations = v + + @property + def rectangles(self): + """.. deprecated:: 1.13""" + _deprecation_msg_m_a_r_f("rectangles") + return self._rectangles + + @rectangles.setter + def rectangles(self, v): + """.. deprecated:: 1.13""" + _deprecation_msg_m_a_r_f("rectangles") + self._series.extend(_create_generic_data_series(rectangles=v)) + self._rectangles = v + + @property + def fill(self): + """.. deprecated:: 1.13""" + _deprecation_msg_m_a_r_f("fill") + return self._fill + + @fill.setter + def fill(self, v): + """.. deprecated:: 1.13""" + _deprecation_msg_m_a_r_f("fill") + self._series.extend(_create_generic_data_series(fill=v)) + self._fill = v diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/matplotlibbackend/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/matplotlibbackend/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..8623940dadb9272730fdeccc1668374781c2e5cf --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/matplotlibbackend/__init__.py @@ -0,0 +1,5 @@ +from sympy.plotting.backends.matplotlibbackend.matplotlib import ( + MatplotlibBackend, _matplotlib_list +) + +__all__ = ["MatplotlibBackend", "_matplotlib_list"] diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/matplotlibbackend/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/matplotlibbackend/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8eb90a2222c26a0c1b52440cd00f35c8a4cb0e14 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/matplotlibbackend/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/matplotlibbackend/__pycache__/matplotlib.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/matplotlibbackend/__pycache__/matplotlib.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d835af6235e278a1110fde42be3d75269a44f39c Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/matplotlibbackend/__pycache__/matplotlib.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/matplotlibbackend/matplotlib.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/matplotlibbackend/matplotlib.py new file mode 100644 index 0000000000000000000000000000000000000000..f598a10a7cd17d40e18d1438e8c6bb174071d0a6 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/matplotlibbackend/matplotlib.py @@ -0,0 +1,318 @@ +from collections.abc import Callable +from sympy.core.basic import Basic +from sympy.external import import_module +import sympy.plotting.backends.base_backend as base_backend +from sympy.printing.latex import latex + + +# N.B. +# When changing the minimum module version for matplotlib, please change +# the same in the `SymPyDocTestFinder`` in `sympy/testing/runtests.py` + + +def _str_or_latex(label): + if isinstance(label, Basic): + return latex(label, mode='inline') + return str(label) + + +def _matplotlib_list(interval_list): + """ + Returns lists for matplotlib ``fill`` command from a list of bounding + rectangular intervals + """ + xlist = [] + ylist = [] + if len(interval_list): + for intervals in interval_list: + intervalx = intervals[0] + intervaly = intervals[1] + xlist.extend([intervalx.start, intervalx.start, + intervalx.end, intervalx.end, None]) + ylist.extend([intervaly.start, intervaly.end, + intervaly.end, intervaly.start, None]) + else: + #XXX Ugly hack. Matplotlib does not accept empty lists for ``fill`` + xlist.extend((None, None, None, None)) + ylist.extend((None, None, None, None)) + return xlist, ylist + + +# Don't have to check for the success of importing matplotlib in each case; +# we will only be using this backend if we can successfully import matploblib +class MatplotlibBackend(base_backend.Plot): + """ This class implements the functionalities to use Matplotlib with SymPy + plotting functions. + """ + + def __init__(self, *series, **kwargs): + super().__init__(*series, **kwargs) + self.matplotlib = import_module('matplotlib', + import_kwargs={'fromlist': ['pyplot', 'cm', 'collections']}, + min_module_version='1.1.0', catch=(RuntimeError,)) + self.plt = self.matplotlib.pyplot + self.cm = self.matplotlib.cm + self.LineCollection = self.matplotlib.collections.LineCollection + self.aspect = kwargs.get('aspect_ratio', 'auto') + if self.aspect != 'auto': + self.aspect = float(self.aspect[1]) / self.aspect[0] + # PlotGrid can provide its figure and axes to be populated with + # the data from the series. + self._plotgrid_fig = kwargs.pop("fig", None) + self._plotgrid_ax = kwargs.pop("ax", None) + + def _create_figure(self): + def set_spines(ax): + ax.spines['left'].set_position('zero') + ax.spines['right'].set_color('none') + ax.spines['bottom'].set_position('zero') + ax.spines['top'].set_color('none') + ax.xaxis.set_ticks_position('bottom') + ax.yaxis.set_ticks_position('left') + + if self._plotgrid_fig is not None: + self.fig = self._plotgrid_fig + self.ax = self._plotgrid_ax + if not any(s.is_3D for s in self._series): + set_spines(self.ax) + else: + self.fig = self.plt.figure(figsize=self.size) + if any(s.is_3D for s in self._series): + self.ax = self.fig.add_subplot(1, 1, 1, projection="3d") + else: + self.ax = self.fig.add_subplot(1, 1, 1) + set_spines(self.ax) + + @staticmethod + def get_segments(x, y, z=None): + """ Convert two list of coordinates to a list of segments to be used + with Matplotlib's :external:class:`~matplotlib.collections.LineCollection`. + + Parameters + ========== + x : list + List of x-coordinates + + y : list + List of y-coordinates + + z : list + List of z-coordinates for a 3D line. + """ + np = import_module('numpy') + if z is not None: + dim = 3 + points = (x, y, z) + else: + dim = 2 + points = (x, y) + points = np.ma.array(points).T.reshape(-1, 1, dim) + return np.ma.concatenate([points[:-1], points[1:]], axis=1) + + def _process_series(self, series, ax): + np = import_module('numpy') + mpl_toolkits = import_module( + 'mpl_toolkits', import_kwargs={'fromlist': ['mplot3d']}) + + # XXX Workaround for matplotlib issue + # https://github.com/matplotlib/matplotlib/issues/17130 + xlims, ylims, zlims = [], [], [] + + for s in series: + # Create the collections + if s.is_2Dline: + if s.is_parametric: + x, y, param = s.get_data() + else: + x, y = s.get_data() + if (isinstance(s.line_color, (int, float)) or + callable(s.line_color)): + segments = self.get_segments(x, y) + collection = self.LineCollection(segments) + collection.set_array(s.get_color_array()) + ax.add_collection(collection) + else: + lbl = _str_or_latex(s.label) + line, = ax.plot(x, y, label=lbl, color=s.line_color) + elif s.is_contour: + ax.contour(*s.get_data()) + elif s.is_3Dline: + x, y, z, param = s.get_data() + if (isinstance(s.line_color, (int, float)) or + callable(s.line_color)): + art3d = mpl_toolkits.mplot3d.art3d + segments = self.get_segments(x, y, z) + collection = art3d.Line3DCollection(segments) + collection.set_array(s.get_color_array()) + ax.add_collection(collection) + else: + lbl = _str_or_latex(s.label) + ax.plot(x, y, z, label=lbl, color=s.line_color) + + xlims.append(s._xlim) + ylims.append(s._ylim) + zlims.append(s._zlim) + elif s.is_3Dsurface: + if s.is_parametric: + x, y, z, u, v = s.get_data() + else: + x, y, z = s.get_data() + collection = ax.plot_surface(x, y, z, + cmap=getattr(self.cm, 'viridis', self.cm.jet), + rstride=1, cstride=1, linewidth=0.1) + if isinstance(s.surface_color, (float, int, Callable)): + color_array = s.get_color_array() + color_array = color_array.reshape(color_array.size) + collection.set_array(color_array) + else: + collection.set_color(s.surface_color) + + xlims.append(s._xlim) + ylims.append(s._ylim) + zlims.append(s._zlim) + elif s.is_implicit: + points = s.get_data() + if len(points) == 2: + # interval math plotting + x, y = _matplotlib_list(points[0]) + ax.fill(x, y, facecolor=s.line_color, edgecolor='None') + else: + # use contourf or contour depending on whether it is + # an inequality or equality. + # XXX: ``contour`` plots multiple lines. Should be fixed. + ListedColormap = self.matplotlib.colors.ListedColormap + colormap = ListedColormap(["white", s.line_color]) + xarray, yarray, zarray, plot_type = points + if plot_type == 'contour': + ax.contour(xarray, yarray, zarray, cmap=colormap) + else: + ax.contourf(xarray, yarray, zarray, cmap=colormap) + elif s.is_generic: + if s.type == "markers": + # s.rendering_kw["color"] = s.line_color + ax.plot(*s.args, **s.rendering_kw) + elif s.type == "annotations": + ax.annotate(*s.args, **s.rendering_kw) + elif s.type == "fill": + # s.rendering_kw["color"] = s.line_color + ax.fill_between(*s.args, **s.rendering_kw) + elif s.type == "rectangles": + # s.rendering_kw["color"] = s.line_color + ax.add_patch( + self.matplotlib.patches.Rectangle( + *s.args, **s.rendering_kw)) + else: + raise NotImplementedError( + '{} is not supported in the SymPy plotting module ' + 'with matplotlib backend. Please report this issue.' + .format(ax)) + + Axes3D = mpl_toolkits.mplot3d.Axes3D + if not isinstance(ax, Axes3D): + ax.autoscale_view( + scalex=ax.get_autoscalex_on(), + scaley=ax.get_autoscaley_on()) + else: + # XXX Workaround for matplotlib issue + # https://github.com/matplotlib/matplotlib/issues/17130 + if xlims: + xlims = np.array(xlims) + xlim = (np.amin(xlims[:, 0]), np.amax(xlims[:, 1])) + ax.set_xlim(xlim) + else: + ax.set_xlim([0, 1]) + + if ylims: + ylims = np.array(ylims) + ylim = (np.amin(ylims[:, 0]), np.amax(ylims[:, 1])) + ax.set_ylim(ylim) + else: + ax.set_ylim([0, 1]) + + if zlims: + zlims = np.array(zlims) + zlim = (np.amin(zlims[:, 0]), np.amax(zlims[:, 1])) + ax.set_zlim(zlim) + else: + ax.set_zlim([0, 1]) + + # Set global options. + # TODO The 3D stuff + # XXX The order of those is important. + if self.xscale and not isinstance(ax, Axes3D): + ax.set_xscale(self.xscale) + if self.yscale and not isinstance(ax, Axes3D): + ax.set_yscale(self.yscale) + if not isinstance(ax, Axes3D) or self.matplotlib.__version__ >= '1.2.0': # XXX in the distant future remove this check + ax.set_autoscale_on(self.autoscale) + if self.axis_center: + val = self.axis_center + if isinstance(ax, Axes3D): + pass + elif val == 'center': + ax.spines['left'].set_position('center') + ax.spines['bottom'].set_position('center') + elif val == 'auto': + xl, xh = ax.get_xlim() + yl, yh = ax.get_ylim() + pos_left = ('data', 0) if xl*xh <= 0 else 'center' + pos_bottom = ('data', 0) if yl*yh <= 0 else 'center' + ax.spines['left'].set_position(pos_left) + ax.spines['bottom'].set_position(pos_bottom) + else: + ax.spines['left'].set_position(('data', val[0])) + ax.spines['bottom'].set_position(('data', val[1])) + if not self.axis: + ax.set_axis_off() + if self.legend: + if ax.legend(): + ax.legend_.set_visible(self.legend) + if self.margin: + ax.set_xmargin(self.margin) + ax.set_ymargin(self.margin) + if self.title: + ax.set_title(self.title) + if self.xlabel: + xlbl = _str_or_latex(self.xlabel) + ax.set_xlabel(xlbl, position=(1, 0)) + if self.ylabel: + ylbl = _str_or_latex(self.ylabel) + ax.set_ylabel(ylbl, position=(0, 1)) + if isinstance(ax, Axes3D) and self.zlabel: + zlbl = _str_or_latex(self.zlabel) + ax.set_zlabel(zlbl, position=(0, 1)) + + # xlim and ylim should always be set at last so that plot limits + # doesn't get altered during the process. + if self.xlim: + ax.set_xlim(self.xlim) + if self.ylim: + ax.set_ylim(self.ylim) + self.ax.set_aspect(self.aspect) + + + def process_series(self): + """ + Iterates over every ``Plot`` object and further calls + _process_series() + """ + self._create_figure() + self._process_series(self._series, self.ax) + + def show(self): + self.process_series() + #TODO after fixing https://github.com/ipython/ipython/issues/1255 + # you can uncomment the next line and remove the pyplot.show() call + #self.fig.show() + if base_backend._show: + self.fig.tight_layout() + self.plt.show() + else: + self.close() + + def save(self, path): + self.process_series() + self.fig.savefig(path) + + def close(self): + self.plt.close(self.fig) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/textbackend/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/textbackend/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..ca4685e4b7790653a97b712c27b240ade5bb481a --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/textbackend/__init__.py @@ -0,0 +1,3 @@ +from sympy.plotting.backends.textbackend.text import TextBackend + +__all__ = ["TextBackend"] diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/textbackend/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/textbackend/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..005984a73e5e766871b2220352699fa3162159df Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/textbackend/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/textbackend/__pycache__/text.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/textbackend/__pycache__/text.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aa1e36c026c47c027aad22087a1922f5ecdf21ce Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/textbackend/__pycache__/text.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/textbackend/text.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/textbackend/text.py new file mode 100644 index 0000000000000000000000000000000000000000..0917ec78b3463a929c373c98fdd279d84ce4c9e5 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/backends/textbackend/text.py @@ -0,0 +1,24 @@ +import sympy.plotting.backends.base_backend as base_backend +from sympy.plotting.series import LineOver1DRangeSeries +from sympy.plotting.textplot import textplot + + +class TextBackend(base_backend.Plot): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def show(self): + if not base_backend._show: + return + if len(self._series) != 1: + raise ValueError( + 'The TextBackend supports only one graph per Plot.') + elif not isinstance(self._series[0], LineOver1DRangeSeries): + raise ValueError( + 'The TextBackend supports only expressions over a 1D range') + else: + ser = self._series[0] + textplot(ser.expr, ser.start, ser.end) + + def close(self): + pass diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..fb9a6a57f94e931f0c5f5b3dda7b0b6fd31841f4 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/__init__.py @@ -0,0 +1,12 @@ +from .interval_arithmetic import interval +from .lib_interval import (Abs, exp, log, log10, sin, cos, tan, sqrt, + imin, imax, sinh, cosh, tanh, acosh, asinh, atanh, + asin, acos, atan, ceil, floor, And, Or) + +__all__ = [ + 'interval', + + 'Abs', 'exp', 'log', 'log10', 'sin', 'cos', 'tan', 'sqrt', 'imin', 'imax', + 'sinh', 'cosh', 'tanh', 'acosh', 'asinh', 'atanh', 'asin', 'acos', 'atan', + 'ceil', 'floor', 'And', 'Or', +] diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..01baf0890ef8876df18067f776829ed448a86336 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/__pycache__/interval_arithmetic.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/__pycache__/interval_arithmetic.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5d7e4104b99a609f6f666c4b8e37cc6b43af897e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/__pycache__/interval_arithmetic.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/__pycache__/interval_membership.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/__pycache__/interval_membership.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fbfdd30836fb6c4b363652d898624268d2b53cd9 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/__pycache__/interval_membership.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/__pycache__/lib_interval.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/__pycache__/lib_interval.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f81e6c7cad2f3e00872527c56ef549d68b5c00d8 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/__pycache__/lib_interval.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/interval_arithmetic.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/interval_arithmetic.py new file mode 100644 index 0000000000000000000000000000000000000000..fc5c0e2ef118c7cf4f80de53a3590de11130410e --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/interval_arithmetic.py @@ -0,0 +1,413 @@ +""" +Interval Arithmetic for plotting. +This module does not implement interval arithmetic accurately and +hence cannot be used for purposes other than plotting. If you want +to use interval arithmetic, use mpmath's interval arithmetic. + +The module implements interval arithmetic using numpy and +python floating points. The rounding up and down is not handled +and hence this is not an accurate implementation of interval +arithmetic. + +The module uses numpy for speed which cannot be achieved with mpmath. +""" + +# Q: Why use numpy? Why not simply use mpmath's interval arithmetic? +# A: mpmath's interval arithmetic simulates a floating point unit +# and hence is slow, while numpy evaluations are orders of magnitude +# faster. + +# Q: Why create a separate class for intervals? Why not use SymPy's +# Interval Sets? +# A: The functionalities that will be required for plotting is quite +# different from what Interval Sets implement. + +# Q: Why is rounding up and down according to IEEE754 not handled? +# A: It is not possible to do it in both numpy and python. An external +# library has to used, which defeats the whole purpose i.e., speed. Also +# rounding is handled for very few functions in those libraries. + +# Q Will my plots be affected? +# A It will not affect most of the plots. The interval arithmetic +# module based suffers the same problems as that of floating point +# arithmetic. + +from sympy.core.numbers import int_valued +from sympy.core.logic import fuzzy_and +from sympy.simplify.simplify import nsimplify + +from .interval_membership import intervalMembership + + +class interval: + """ Represents an interval containing floating points as start and + end of the interval + The is_valid variable tracks whether the interval obtained as the + result of the function is in the domain and is continuous. + - True: Represents the interval result of a function is continuous and + in the domain of the function. + - False: The interval argument of the function was not in the domain of + the function, hence the is_valid of the result interval is False + - None: The function was not continuous over the interval or + the function's argument interval is partly in the domain of the + function + + A comparison between an interval and a real number, or a + comparison between two intervals may return ``intervalMembership`` + of two 3-valued logic values. + """ + + def __init__(self, *args, is_valid=True, **kwargs): + self.is_valid = is_valid + if len(args) == 1: + if isinstance(args[0], interval): + self.start, self.end = args[0].start, args[0].end + else: + self.start = float(args[0]) + self.end = float(args[0]) + elif len(args) == 2: + if args[0] < args[1]: + self.start = float(args[0]) + self.end = float(args[1]) + else: + self.start = float(args[1]) + self.end = float(args[0]) + + else: + raise ValueError("interval takes a maximum of two float values " + "as arguments") + + @property + def mid(self): + return (self.start + self.end) / 2.0 + + @property + def width(self): + return self.end - self.start + + def __repr__(self): + return "interval(%f, %f)" % (self.start, self.end) + + def __str__(self): + return "[%f, %f]" % (self.start, self.end) + + def __lt__(self, other): + if isinstance(other, (int, float)): + if self.end < other: + return intervalMembership(True, self.is_valid) + elif self.start > other: + return intervalMembership(False, self.is_valid) + else: + return intervalMembership(None, self.is_valid) + + elif isinstance(other, interval): + valid = fuzzy_and([self.is_valid, other.is_valid]) + if self.end < other. start: + return intervalMembership(True, valid) + if self.start > other.end: + return intervalMembership(False, valid) + return intervalMembership(None, valid) + else: + return NotImplemented + + def __gt__(self, other): + if isinstance(other, (int, float)): + if self.start > other: + return intervalMembership(True, self.is_valid) + elif self.end < other: + return intervalMembership(False, self.is_valid) + else: + return intervalMembership(None, self.is_valid) + elif isinstance(other, interval): + return other.__lt__(self) + else: + return NotImplemented + + def __eq__(self, other): + if isinstance(other, (int, float)): + if self.start == other and self.end == other: + return intervalMembership(True, self.is_valid) + if other in self: + return intervalMembership(None, self.is_valid) + else: + return intervalMembership(False, self.is_valid) + + if isinstance(other, interval): + valid = fuzzy_and([self.is_valid, other.is_valid]) + if self.start == other.start and self.end == other.end: + return intervalMembership(True, valid) + elif self.__lt__(other)[0] is not None: + return intervalMembership(False, valid) + else: + return intervalMembership(None, valid) + else: + return NotImplemented + + def __ne__(self, other): + if isinstance(other, (int, float)): + if self.start == other and self.end == other: + return intervalMembership(False, self.is_valid) + if other in self: + return intervalMembership(None, self.is_valid) + else: + return intervalMembership(True, self.is_valid) + + if isinstance(other, interval): + valid = fuzzy_and([self.is_valid, other.is_valid]) + if self.start == other.start and self.end == other.end: + return intervalMembership(False, valid) + if not self.__lt__(other)[0] is None: + return intervalMembership(True, valid) + return intervalMembership(None, valid) + else: + return NotImplemented + + def __le__(self, other): + if isinstance(other, (int, float)): + if self.end <= other: + return intervalMembership(True, self.is_valid) + if self.start > other: + return intervalMembership(False, self.is_valid) + else: + return intervalMembership(None, self.is_valid) + + if isinstance(other, interval): + valid = fuzzy_and([self.is_valid, other.is_valid]) + if self.end <= other.start: + return intervalMembership(True, valid) + if self.start > other.end: + return intervalMembership(False, valid) + return intervalMembership(None, valid) + else: + return NotImplemented + + def __ge__(self, other): + if isinstance(other, (int, float)): + if self.start >= other: + return intervalMembership(True, self.is_valid) + elif self.end < other: + return intervalMembership(False, self.is_valid) + else: + return intervalMembership(None, self.is_valid) + elif isinstance(other, interval): + return other.__le__(self) + + def __add__(self, other): + if isinstance(other, (int, float)): + if self.is_valid: + return interval(self.start + other, self.end + other) + else: + start = self.start + other + end = self.end + other + return interval(start, end, is_valid=self.is_valid) + + elif isinstance(other, interval): + start = self.start + other.start + end = self.end + other.end + valid = fuzzy_and([self.is_valid, other.is_valid]) + return interval(start, end, is_valid=valid) + else: + return NotImplemented + + __radd__ = __add__ + + def __sub__(self, other): + if isinstance(other, (int, float)): + start = self.start - other + end = self.end - other + return interval(start, end, is_valid=self.is_valid) + + elif isinstance(other, interval): + start = self.start - other.end + end = self.end - other.start + valid = fuzzy_and([self.is_valid, other.is_valid]) + return interval(start, end, is_valid=valid) + else: + return NotImplemented + + def __rsub__(self, other): + if isinstance(other, (int, float)): + start = other - self.end + end = other - self.start + return interval(start, end, is_valid=self.is_valid) + elif isinstance(other, interval): + return other.__sub__(self) + else: + return NotImplemented + + def __neg__(self): + if self.is_valid: + return interval(-self.end, -self.start) + else: + return interval(-self.end, -self.start, is_valid=self.is_valid) + + def __mul__(self, other): + if isinstance(other, interval): + if self.is_valid is False or other.is_valid is False: + return interval(-float('inf'), float('inf'), is_valid=False) + elif self.is_valid is None or other.is_valid is None: + return interval(-float('inf'), float('inf'), is_valid=None) + else: + inters = [] + inters.append(self.start * other.start) + inters.append(self.end * other.start) + inters.append(self.start * other.end) + inters.append(self.end * other.end) + start = min(inters) + end = max(inters) + return interval(start, end) + elif isinstance(other, (int, float)): + return interval(self.start*other, self.end*other, is_valid=self.is_valid) + else: + return NotImplemented + + __rmul__ = __mul__ + + def __contains__(self, other): + if isinstance(other, (int, float)): + return self.start <= other and self.end >= other + else: + return self.start <= other.start and other.end <= self.end + + def __rtruediv__(self, other): + if isinstance(other, (int, float)): + other = interval(other) + return other.__truediv__(self) + elif isinstance(other, interval): + return other.__truediv__(self) + else: + return NotImplemented + + def __truediv__(self, other): + # Both None and False are handled + if not self.is_valid: + # Don't divide as the value is not valid + return interval(-float('inf'), float('inf'), is_valid=self.is_valid) + if isinstance(other, (int, float)): + if other == 0: + # Divide by zero encountered. valid nowhere + return interval(-float('inf'), float('inf'), is_valid=False) + else: + return interval(self.start / other, self.end / other) + + elif isinstance(other, interval): + if other.is_valid is False or self.is_valid is False: + return interval(-float('inf'), float('inf'), is_valid=False) + elif other.is_valid is None or self.is_valid is None: + return interval(-float('inf'), float('inf'), is_valid=None) + else: + # denominator contains both signs, i.e. being divided by zero + # return the whole real line with is_valid = None + if 0 in other: + return interval(-float('inf'), float('inf'), is_valid=None) + + # denominator negative + this = self + if other.end < 0: + this = -this + other = -other + + # denominator positive + inters = [] + inters.append(this.start / other.start) + inters.append(this.end / other.start) + inters.append(this.start / other.end) + inters.append(this.end / other.end) + start = max(inters) + end = min(inters) + return interval(start, end) + else: + return NotImplemented + + def __pow__(self, other): + # Implements only power to an integer. + from .lib_interval import exp, log + if not self.is_valid: + return self + if isinstance(other, interval): + return exp(other * log(self)) + elif isinstance(other, (float, int)): + if other < 0: + return 1 / self.__pow__(abs(other)) + else: + if int_valued(other): + return _pow_int(self, other) + else: + return _pow_float(self, other) + else: + return NotImplemented + + def __rpow__(self, other): + if isinstance(other, (float, int)): + if not self.is_valid: + #Don't do anything + return self + elif other < 0: + if self.width > 0: + return interval(-float('inf'), float('inf'), is_valid=False) + else: + power_rational = nsimplify(self.start) + num, denom = power_rational.as_numer_denom() + if denom % 2 == 0: + return interval(-float('inf'), float('inf'), + is_valid=False) + else: + start = -abs(other)**self.start + end = start + return interval(start, end) + else: + return interval(other**self.start, other**self.end) + elif isinstance(other, interval): + return other.__pow__(self) + else: + return NotImplemented + + def __hash__(self): + return hash((self.is_valid, self.start, self.end)) + + +def _pow_float(inter, power): + """Evaluates an interval raised to a floating point.""" + power_rational = nsimplify(power) + num, denom = power_rational.as_numer_denom() + if num % 2 == 0: + start = abs(inter.start)**power + end = abs(inter.end)**power + if start < 0: + ret = interval(0, max(start, end)) + else: + ret = interval(start, end) + return ret + elif denom % 2 == 0: + if inter.end < 0: + return interval(-float('inf'), float('inf'), is_valid=False) + elif inter.start < 0: + return interval(0, inter.end**power, is_valid=None) + else: + return interval(inter.start**power, inter.end**power) + else: + if inter.start < 0: + start = -abs(inter.start)**power + else: + start = inter.start**power + + if inter.end < 0: + end = -abs(inter.end)**power + else: + end = inter.end**power + + return interval(start, end, is_valid=inter.is_valid) + + +def _pow_int(inter, power): + """Evaluates an interval raised to an integer power""" + power = int(power) + if power & 1: + return interval(inter.start**power, inter.end**power) + else: + if inter.start < 0 and inter.end > 0: + start = 0 + end = max(inter.start**power, inter.end**power) + return interval(start, end) + else: + return interval(inter.start**power, inter.end**power) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/interval_membership.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/interval_membership.py new file mode 100644 index 0000000000000000000000000000000000000000..c4887c2d96f0d006b95a8e207a4f4a75940aec23 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/interval_membership.py @@ -0,0 +1,78 @@ +from sympy.core.logic import fuzzy_and, fuzzy_or, fuzzy_not, fuzzy_xor + + +class intervalMembership: + """Represents a boolean expression returned by the comparison of + the interval object. + + Parameters + ========== + + (a, b) : (bool, bool) + The first value determines the comparison as follows: + - True: If the comparison is True throughout the intervals. + - False: If the comparison is False throughout the intervals. + - None: If the comparison is True for some part of the intervals. + + The second value is determined as follows: + - True: If both the intervals in comparison are valid. + - False: If at least one of the intervals is False, else + - None + """ + def __init__(self, a, b): + self._wrapped = (a, b) + + def __getitem__(self, i): + try: + return self._wrapped[i] + except IndexError: + raise IndexError( + "{} must be a valid indexing for the 2-tuple." + .format(i)) + + def __len__(self): + return 2 + + def __iter__(self): + return iter(self._wrapped) + + def __str__(self): + return "intervalMembership({}, {})".format(*self) + __repr__ = __str__ + + def __and__(self, other): + if not isinstance(other, intervalMembership): + raise ValueError( + "The comparison is not supported for {}.".format(other)) + + a1, b1 = self + a2, b2 = other + return intervalMembership(fuzzy_and([a1, a2]), fuzzy_and([b1, b2])) + + def __or__(self, other): + if not isinstance(other, intervalMembership): + raise ValueError( + "The comparison is not supported for {}.".format(other)) + + a1, b1 = self + a2, b2 = other + return intervalMembership(fuzzy_or([a1, a2]), fuzzy_and([b1, b2])) + + def __invert__(self): + a, b = self + return intervalMembership(fuzzy_not(a), b) + + def __xor__(self, other): + if not isinstance(other, intervalMembership): + raise ValueError( + "The comparison is not supported for {}.".format(other)) + + a1, b1 = self + a2, b2 = other + return intervalMembership(fuzzy_xor([a1, a2]), fuzzy_and([b1, b2])) + + def __eq__(self, other): + return self._wrapped == other + + def __ne__(self, other): + return self._wrapped != other diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/lib_interval.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/lib_interval.py new file mode 100644 index 0000000000000000000000000000000000000000..7549a05820d747ce057892f8df1fbcbc61cc3f43 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/lib_interval.py @@ -0,0 +1,452 @@ +""" The module contains implemented functions for interval arithmetic.""" +from functools import reduce + +from sympy.plotting.intervalmath import interval +from sympy.external import import_module + + +def Abs(x): + if isinstance(x, (int, float)): + return interval(abs(x)) + elif isinstance(x, interval): + if x.start < 0 and x.end > 0: + return interval(0, max(abs(x.start), abs(x.end)), is_valid=x.is_valid) + else: + return interval(abs(x.start), abs(x.end)) + else: + raise NotImplementedError + +#Monotonic + + +def exp(x): + """evaluates the exponential of an interval""" + np = import_module('numpy') + if isinstance(x, (int, float)): + return interval(np.exp(x), np.exp(x)) + elif isinstance(x, interval): + return interval(np.exp(x.start), np.exp(x.end), is_valid=x.is_valid) + else: + raise NotImplementedError + + +#Monotonic +def log(x): + """evaluates the natural logarithm of an interval""" + np = import_module('numpy') + if isinstance(x, (int, float)): + if x <= 0: + return interval(-np.inf, np.inf, is_valid=False) + else: + return interval(np.log(x)) + elif isinstance(x, interval): + if not x.is_valid: + return interval(-np.inf, np.inf, is_valid=x.is_valid) + elif x.end <= 0: + return interval(-np.inf, np.inf, is_valid=False) + elif x.start <= 0: + return interval(-np.inf, np.inf, is_valid=None) + + return interval(np.log(x.start), np.log(x.end)) + else: + raise NotImplementedError + + +#Monotonic +def log10(x): + """evaluates the logarithm to the base 10 of an interval""" + np = import_module('numpy') + if isinstance(x, (int, float)): + if x <= 0: + return interval(-np.inf, np.inf, is_valid=False) + else: + return interval(np.log10(x)) + elif isinstance(x, interval): + if not x.is_valid: + return interval(-np.inf, np.inf, is_valid=x.is_valid) + elif x.end <= 0: + return interval(-np.inf, np.inf, is_valid=False) + elif x.start <= 0: + return interval(-np.inf, np.inf, is_valid=None) + return interval(np.log10(x.start), np.log10(x.end)) + else: + raise NotImplementedError + + +#Monotonic +def atan(x): + """evaluates the tan inverse of an interval""" + np = import_module('numpy') + if isinstance(x, (int, float)): + return interval(np.arctan(x)) + elif isinstance(x, interval): + start = np.arctan(x.start) + end = np.arctan(x.end) + return interval(start, end, is_valid=x.is_valid) + else: + raise NotImplementedError + + +#periodic +def sin(x): + """evaluates the sine of an interval""" + np = import_module('numpy') + if isinstance(x, (int, float)): + return interval(np.sin(x)) + elif isinstance(x, interval): + if not x.is_valid: + return interval(-1, 1, is_valid=x.is_valid) + na, __ = divmod(x.start, np.pi / 2.0) + nb, __ = divmod(x.end, np.pi / 2.0) + start = min(np.sin(x.start), np.sin(x.end)) + end = max(np.sin(x.start), np.sin(x.end)) + if nb - na > 4: + return interval(-1, 1, is_valid=x.is_valid) + elif na == nb: + return interval(start, end, is_valid=x.is_valid) + else: + if (na - 1) // 4 != (nb - 1) // 4: + #sin has max + end = 1 + if (na - 3) // 4 != (nb - 3) // 4: + #sin has min + start = -1 + return interval(start, end) + else: + raise NotImplementedError + + +#periodic +def cos(x): + """Evaluates the cos of an interval""" + np = import_module('numpy') + if isinstance(x, (int, float)): + return interval(np.sin(x)) + elif isinstance(x, interval): + if not (np.isfinite(x.start) and np.isfinite(x.end)): + return interval(-1, 1, is_valid=x.is_valid) + na, __ = divmod(x.start, np.pi / 2.0) + nb, __ = divmod(x.end, np.pi / 2.0) + start = min(np.cos(x.start), np.cos(x.end)) + end = max(np.cos(x.start), np.cos(x.end)) + if nb - na > 4: + #differ more than 2*pi + return interval(-1, 1, is_valid=x.is_valid) + elif na == nb: + #in the same quadarant + return interval(start, end, is_valid=x.is_valid) + else: + if (na) // 4 != (nb) // 4: + #cos has max + end = 1 + if (na - 2) // 4 != (nb - 2) // 4: + #cos has min + start = -1 + return interval(start, end, is_valid=x.is_valid) + else: + raise NotImplementedError + + +def tan(x): + """Evaluates the tan of an interval""" + return sin(x) / cos(x) + + +#Monotonic +def sqrt(x): + """Evaluates the square root of an interval""" + np = import_module('numpy') + if isinstance(x, (int, float)): + if x > 0: + return interval(np.sqrt(x)) + else: + return interval(-np.inf, np.inf, is_valid=False) + elif isinstance(x, interval): + #Outside the domain + if x.end < 0: + return interval(-np.inf, np.inf, is_valid=False) + #Partially outside the domain + elif x.start < 0: + return interval(-np.inf, np.inf, is_valid=None) + else: + return interval(np.sqrt(x.start), np.sqrt(x.end), + is_valid=x.is_valid) + else: + raise NotImplementedError + + +def imin(*args): + """Evaluates the minimum of a list of intervals""" + np = import_module('numpy') + if not all(isinstance(arg, (int, float, interval)) for arg in args): + return NotImplementedError + else: + new_args = [a for a in args if isinstance(a, (int, float)) + or a.is_valid] + if len(new_args) == 0: + if all(a.is_valid is False for a in args): + return interval(-np.inf, np.inf, is_valid=False) + else: + return interval(-np.inf, np.inf, is_valid=None) + start_array = [a if isinstance(a, (int, float)) else a.start + for a in new_args] + + end_array = [a if isinstance(a, (int, float)) else a.end + for a in new_args] + return interval(min(start_array), min(end_array)) + + +def imax(*args): + """Evaluates the maximum of a list of intervals""" + np = import_module('numpy') + if not all(isinstance(arg, (int, float, interval)) for arg in args): + return NotImplementedError + else: + new_args = [a for a in args if isinstance(a, (int, float)) + or a.is_valid] + if len(new_args) == 0: + if all(a.is_valid is False for a in args): + return interval(-np.inf, np.inf, is_valid=False) + else: + return interval(-np.inf, np.inf, is_valid=None) + start_array = [a if isinstance(a, (int, float)) else a.start + for a in new_args] + + end_array = [a if isinstance(a, (int, float)) else a.end + for a in new_args] + + return interval(max(start_array), max(end_array)) + + +#Monotonic +def sinh(x): + """Evaluates the hyperbolic sine of an interval""" + np = import_module('numpy') + if isinstance(x, (int, float)): + return interval(np.sinh(x), np.sinh(x)) + elif isinstance(x, interval): + return interval(np.sinh(x.start), np.sinh(x.end), is_valid=x.is_valid) + else: + raise NotImplementedError + + +def cosh(x): + """Evaluates the hyperbolic cos of an interval""" + np = import_module('numpy') + if isinstance(x, (int, float)): + return interval(np.cosh(x), np.cosh(x)) + elif isinstance(x, interval): + #both signs + if x.start < 0 and x.end > 0: + end = max(np.cosh(x.start), np.cosh(x.end)) + return interval(1, end, is_valid=x.is_valid) + else: + #Monotonic + start = np.cosh(x.start) + end = np.cosh(x.end) + return interval(start, end, is_valid=x.is_valid) + else: + raise NotImplementedError + + +#Monotonic +def tanh(x): + """Evaluates the hyperbolic tan of an interval""" + np = import_module('numpy') + if isinstance(x, (int, float)): + return interval(np.tanh(x), np.tanh(x)) + elif isinstance(x, interval): + return interval(np.tanh(x.start), np.tanh(x.end), is_valid=x.is_valid) + else: + raise NotImplementedError + + +def asin(x): + """Evaluates the inverse sine of an interval""" + np = import_module('numpy') + if isinstance(x, (int, float)): + #Outside the domain + if abs(x) > 1: + return interval(-np.inf, np.inf, is_valid=False) + else: + return interval(np.arcsin(x), np.arcsin(x)) + elif isinstance(x, interval): + #Outside the domain + if x.is_valid is False or x.start > 1 or x.end < -1: + return interval(-np.inf, np.inf, is_valid=False) + #Partially outside the domain + elif x.start < -1 or x.end > 1: + return interval(-np.inf, np.inf, is_valid=None) + else: + start = np.arcsin(x.start) + end = np.arcsin(x.end) + return interval(start, end, is_valid=x.is_valid) + + +def acos(x): + """Evaluates the inverse cos of an interval""" + np = import_module('numpy') + if isinstance(x, (int, float)): + if abs(x) > 1: + #Outside the domain + return interval(-np.inf, np.inf, is_valid=False) + else: + return interval(np.arccos(x), np.arccos(x)) + elif isinstance(x, interval): + #Outside the domain + if x.is_valid is False or x.start > 1 or x.end < -1: + return interval(-np.inf, np.inf, is_valid=False) + #Partially outside the domain + elif x.start < -1 or x.end > 1: + return interval(-np.inf, np.inf, is_valid=None) + else: + start = np.arccos(x.start) + end = np.arccos(x.end) + return interval(start, end, is_valid=x.is_valid) + + +def ceil(x): + """Evaluates the ceiling of an interval""" + np = import_module('numpy') + if isinstance(x, (int, float)): + return interval(np.ceil(x)) + elif isinstance(x, interval): + if x.is_valid is False: + return interval(-np.inf, np.inf, is_valid=False) + else: + start = np.ceil(x.start) + end = np.ceil(x.end) + #Continuous over the interval + if start == end: + return interval(start, end, is_valid=x.is_valid) + else: + #Not continuous over the interval + return interval(start, end, is_valid=None) + else: + return NotImplementedError + + +def floor(x): + """Evaluates the floor of an interval""" + np = import_module('numpy') + if isinstance(x, (int, float)): + return interval(np.floor(x)) + elif isinstance(x, interval): + if x.is_valid is False: + return interval(-np.inf, np.inf, is_valid=False) + else: + start = np.floor(x.start) + end = np.floor(x.end) + #continuous over the argument + if start == end: + return interval(start, end, is_valid=x.is_valid) + else: + #not continuous over the interval + return interval(start, end, is_valid=None) + else: + return NotImplementedError + + +def acosh(x): + """Evaluates the inverse hyperbolic cosine of an interval""" + np = import_module('numpy') + if isinstance(x, (int, float)): + #Outside the domain + if x < 1: + return interval(-np.inf, np.inf, is_valid=False) + else: + return interval(np.arccosh(x)) + elif isinstance(x, interval): + #Outside the domain + if x.end < 1: + return interval(-np.inf, np.inf, is_valid=False) + #Partly outside the domain + elif x.start < 1: + return interval(-np.inf, np.inf, is_valid=None) + else: + start = np.arccosh(x.start) + end = np.arccosh(x.end) + return interval(start, end, is_valid=x.is_valid) + else: + return NotImplementedError + + +#Monotonic +def asinh(x): + """Evaluates the inverse hyperbolic sine of an interval""" + np = import_module('numpy') + if isinstance(x, (int, float)): + return interval(np.arcsinh(x)) + elif isinstance(x, interval): + start = np.arcsinh(x.start) + end = np.arcsinh(x.end) + return interval(start, end, is_valid=x.is_valid) + else: + return NotImplementedError + + +def atanh(x): + """Evaluates the inverse hyperbolic tangent of an interval""" + np = import_module('numpy') + if isinstance(x, (int, float)): + #Outside the domain + if abs(x) >= 1: + return interval(-np.inf, np.inf, is_valid=False) + else: + return interval(np.arctanh(x)) + elif isinstance(x, interval): + #outside the domain + if x.is_valid is False or x.start >= 1 or x.end <= -1: + return interval(-np.inf, np.inf, is_valid=False) + #partly outside the domain + elif x.start <= -1 or x.end >= 1: + return interval(-np.inf, np.inf, is_valid=None) + else: + start = np.arctanh(x.start) + end = np.arctanh(x.end) + return interval(start, end, is_valid=x.is_valid) + else: + return NotImplementedError + + +#Three valued logic for interval plotting. + +def And(*args): + """Defines the three valued ``And`` behaviour for a 2-tuple of + three valued logic values""" + def reduce_and(cmp_intervala, cmp_intervalb): + if cmp_intervala[0] is False or cmp_intervalb[0] is False: + first = False + elif cmp_intervala[0] is None or cmp_intervalb[0] is None: + first = None + else: + first = True + if cmp_intervala[1] is False or cmp_intervalb[1] is False: + second = False + elif cmp_intervala[1] is None or cmp_intervalb[1] is None: + second = None + else: + second = True + return (first, second) + return reduce(reduce_and, args) + + +def Or(*args): + """Defines the three valued ``Or`` behaviour for a 2-tuple of + three valued logic values""" + def reduce_or(cmp_intervala, cmp_intervalb): + if cmp_intervala[0] is True or cmp_intervalb[0] is True: + first = True + elif cmp_intervala[0] is None or cmp_intervalb[0] is None: + first = None + else: + first = False + + if cmp_intervala[1] is True or cmp_intervalb[1] is True: + second = True + elif cmp_intervala[1] is None or cmp_intervalb[1] is None: + second = None + else: + second = False + return (first, second) + return reduce(reduce_or, args) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7ff1b45a1d6a2b835201c2ae64410c8b742a9ff4 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/tests/__pycache__/test_interval_functions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/tests/__pycache__/test_interval_functions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5b242f5e5ce7f7798af8e083803be7f2ec0c7cb4 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/tests/__pycache__/test_interval_functions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/tests/__pycache__/test_interval_membership.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/tests/__pycache__/test_interval_membership.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ac0d20a229ab88b2bdc2410ae39986b08ddf32d5 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/tests/__pycache__/test_interval_membership.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/tests/__pycache__/test_intervalmath.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/tests/__pycache__/test_intervalmath.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f162ac12c9fa6a48755f9b0743681ecc9fa0da18 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/tests/__pycache__/test_intervalmath.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/tests/test_interval_functions.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/tests/test_interval_functions.py new file mode 100644 index 0000000000000000000000000000000000000000..861c3660df024d3fbec788a027708348e9929655 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/tests/test_interval_functions.py @@ -0,0 +1,415 @@ +from sympy.external import import_module +from sympy.plotting.intervalmath import ( + Abs, acos, acosh, And, asin, asinh, atan, atanh, ceil, cos, cosh, + exp, floor, imax, imin, interval, log, log10, Or, sin, sinh, sqrt, + tan, tanh, +) + +np = import_module('numpy') +if not np: + disabled = True + + +#requires Numpy. Hence included in interval_functions + + +def test_interval_pow(): + a = 2**interval(1, 2) == interval(2, 4) + assert a == (True, True) + a = interval(1, 2)**interval(1, 2) == interval(1, 4) + assert a == (True, True) + a = interval(-1, 1)**interval(0.5, 2) + assert a.is_valid is None + a = interval(-2, -1) ** interval(1, 2) + assert a.is_valid is False + a = interval(-2, -1) ** (1.0 / 2) + assert a.is_valid is False + a = interval(-1, 1)**(1.0 / 2) + assert a.is_valid is None + a = interval(-1, 1)**(1.0 / 3) == interval(-1, 1) + assert a == (True, True) + a = interval(-1, 1)**2 == interval(0, 1) + assert a == (True, True) + a = interval(-1, 1) ** (1.0 / 29) == interval(-1, 1) + assert a == (True, True) + a = -2**interval(1, 1) == interval(-2, -2) + assert a == (True, True) + + a = interval(1, 2, is_valid=False)**2 + assert a.is_valid is False + + a = (-3)**interval(1, 2) + assert a.is_valid is False + a = (-4)**interval(0.5, 0.5) + assert a.is_valid is False + assert ((-3)**interval(1, 1) == interval(-3, -3)) == (True, True) + + a = interval(8, 64)**(2.0 / 3) + assert abs(a.start - 4) < 1e-10 # eps + assert abs(a.end - 16) < 1e-10 + a = interval(-8, 64)**(2.0 / 3) + assert abs(a.start - 4) < 1e-10 # eps + assert abs(a.end - 16) < 1e-10 + + +def test_exp(): + a = exp(interval(-np.inf, 0)) + assert a.start == np.exp(-np.inf) + assert a.end == np.exp(0) + a = exp(interval(1, 2)) + assert a.start == np.exp(1) + assert a.end == np.exp(2) + a = exp(1) + assert a.start == np.exp(1) + assert a.end == np.exp(1) + + +def test_log(): + a = log(interval(1, 2)) + assert a.start == 0 + assert a.end == np.log(2) + a = log(interval(-1, 1)) + assert a.is_valid is None + a = log(interval(-3, -1)) + assert a.is_valid is False + a = log(-3) + assert a.is_valid is False + a = log(2) + assert a.start == np.log(2) + assert a.end == np.log(2) + + +def test_log10(): + a = log10(interval(1, 2)) + assert a.start == 0 + assert a.end == np.log10(2) + a = log10(interval(-1, 1)) + assert a.is_valid is None + a = log10(interval(-3, -1)) + assert a.is_valid is False + a = log10(-3) + assert a.is_valid is False + a = log10(2) + assert a.start == np.log10(2) + assert a.end == np.log10(2) + + +def test_atan(): + a = atan(interval(0, 1)) + assert a.start == np.arctan(0) + assert a.end == np.arctan(1) + a = atan(1) + assert a.start == np.arctan(1) + assert a.end == np.arctan(1) + + +def test_sin(): + a = sin(interval(0, np.pi / 4)) + assert a.start == np.sin(0) + assert a.end == np.sin(np.pi / 4) + + a = sin(interval(-np.pi / 4, np.pi / 4)) + assert a.start == np.sin(-np.pi / 4) + assert a.end == np.sin(np.pi / 4) + + a = sin(interval(np.pi / 4, 3 * np.pi / 4)) + assert a.start == np.sin(np.pi / 4) + assert a.end == 1 + + a = sin(interval(7 * np.pi / 6, 7 * np.pi / 4)) + assert a.start == -1 + assert a.end == np.sin(7 * np.pi / 6) + + a = sin(interval(0, 3 * np.pi)) + assert a.start == -1 + assert a.end == 1 + + a = sin(interval(np.pi / 3, 7 * np.pi / 4)) + assert a.start == -1 + assert a.end == 1 + + a = sin(np.pi / 4) + assert a.start == np.sin(np.pi / 4) + assert a.end == np.sin(np.pi / 4) + + a = sin(interval(1, 2, is_valid=False)) + assert a.is_valid is False + + +def test_cos(): + a = cos(interval(0, np.pi / 4)) + assert a.start == np.cos(np.pi / 4) + assert a.end == 1 + + a = cos(interval(-np.pi / 4, np.pi / 4)) + assert a.start == np.cos(-np.pi / 4) + assert a.end == 1 + + a = cos(interval(np.pi / 4, 3 * np.pi / 4)) + assert a.start == np.cos(3 * np.pi / 4) + assert a.end == np.cos(np.pi / 4) + + a = cos(interval(3 * np.pi / 4, 5 * np.pi / 4)) + assert a.start == -1 + assert a.end == np.cos(3 * np.pi / 4) + + a = cos(interval(0, 3 * np.pi)) + assert a.start == -1 + assert a.end == 1 + + a = cos(interval(- np.pi / 3, 5 * np.pi / 4)) + assert a.start == -1 + assert a.end == 1 + + a = cos(interval(1, 2, is_valid=False)) + assert a.is_valid is False + + +def test_tan(): + a = tan(interval(0, np.pi / 4)) + assert a.start == 0 + # must match lib_interval definition of tan: + assert a.end == np.sin(np.pi / 4)/np.cos(np.pi / 4) + + a = tan(interval(np.pi / 4, 3 * np.pi / 4)) + #discontinuity + assert a.is_valid is None + + +def test_sqrt(): + a = sqrt(interval(1, 4)) + assert a.start == 1 + assert a.end == 2 + + a = sqrt(interval(0.01, 1)) + assert a.start == np.sqrt(0.01) + assert a.end == 1 + + a = sqrt(interval(-1, 1)) + assert a.is_valid is None + + a = sqrt(interval(-3, -1)) + assert a.is_valid is False + + a = sqrt(4) + assert (a == interval(2, 2)) == (True, True) + + a = sqrt(-3) + assert a.is_valid is False + + +def test_imin(): + a = imin(interval(1, 3), interval(2, 5), interval(-1, 3)) + assert a.start == -1 + assert a.end == 3 + + a = imin(-2, interval(1, 4)) + assert a.start == -2 + assert a.end == -2 + + a = imin(5, interval(3, 4), interval(-2, 2, is_valid=False)) + assert a.start == 3 + assert a.end == 4 + + +def test_imax(): + a = imax(interval(-2, 2), interval(2, 7), interval(-3, 9)) + assert a.start == 2 + assert a.end == 9 + + a = imax(8, interval(1, 4)) + assert a.start == 8 + assert a.end == 8 + + a = imax(interval(1, 2), interval(3, 4), interval(-2, 2, is_valid=False)) + assert a.start == 3 + assert a.end == 4 + + +def test_sinh(): + a = sinh(interval(-1, 1)) + assert a.start == np.sinh(-1) + assert a.end == np.sinh(1) + + a = sinh(1) + assert a.start == np.sinh(1) + assert a.end == np.sinh(1) + + +def test_cosh(): + a = cosh(interval(1, 2)) + assert a.start == np.cosh(1) + assert a.end == np.cosh(2) + a = cosh(interval(-2, -1)) + assert a.start == np.cosh(-1) + assert a.end == np.cosh(-2) + + a = cosh(interval(-2, 1)) + assert a.start == 1 + assert a.end == np.cosh(-2) + + a = cosh(1) + assert a.start == np.cosh(1) + assert a.end == np.cosh(1) + + +def test_tanh(): + a = tanh(interval(-3, 3)) + assert a.start == np.tanh(-3) + assert a.end == np.tanh(3) + + a = tanh(3) + assert a.start == np.tanh(3) + assert a.end == np.tanh(3) + + +def test_asin(): + a = asin(interval(-0.5, 0.5)) + assert a.start == np.arcsin(-0.5) + assert a.end == np.arcsin(0.5) + + a = asin(interval(-1.5, 1.5)) + assert a.is_valid is None + a = asin(interval(-2, -1.5)) + assert a.is_valid is False + + a = asin(interval(0, 2)) + assert a.is_valid is None + + a = asin(interval(2, 5)) + assert a.is_valid is False + + a = asin(0.5) + assert a.start == np.arcsin(0.5) + assert a.end == np.arcsin(0.5) + + a = asin(1.5) + assert a.is_valid is False + + +def test_acos(): + a = acos(interval(-0.5, 0.5)) + assert a.start == np.arccos(0.5) + assert a.end == np.arccos(-0.5) + + a = acos(interval(-1.5, 1.5)) + assert a.is_valid is None + a = acos(interval(-2, -1.5)) + assert a.is_valid is False + + a = acos(interval(0, 2)) + assert a.is_valid is None + + a = acos(interval(2, 5)) + assert a.is_valid is False + + a = acos(0.5) + assert a.start == np.arccos(0.5) + assert a.end == np.arccos(0.5) + + a = acos(1.5) + assert a.is_valid is False + + +def test_ceil(): + a = ceil(interval(0.2, 0.5)) + assert a.start == 1 + assert a.end == 1 + + a = ceil(interval(0.5, 1.5)) + assert a.start == 1 + assert a.end == 2 + assert a.is_valid is None + + a = ceil(interval(-5, 5)) + assert a.is_valid is None + + a = ceil(5.4) + assert a.start == 6 + assert a.end == 6 + + +def test_floor(): + a = floor(interval(0.2, 0.5)) + assert a.start == 0 + assert a.end == 0 + + a = floor(interval(0.5, 1.5)) + assert a.start == 0 + assert a.end == 1 + assert a.is_valid is None + + a = floor(interval(-5, 5)) + assert a.is_valid is None + + a = floor(5.4) + assert a.start == 5 + assert a.end == 5 + + +def test_asinh(): + a = asinh(interval(1, 2)) + assert a.start == np.arcsinh(1) + assert a.end == np.arcsinh(2) + + a = asinh(0.5) + assert a.start == np.arcsinh(0.5) + assert a.end == np.arcsinh(0.5) + + +def test_acosh(): + a = acosh(interval(3, 5)) + assert a.start == np.arccosh(3) + assert a.end == np.arccosh(5) + + a = acosh(interval(0, 3)) + assert a.is_valid is None + a = acosh(interval(-3, 0.5)) + assert a.is_valid is False + + a = acosh(0.5) + assert a.is_valid is False + + a = acosh(2) + assert a.start == np.arccosh(2) + assert a.end == np.arccosh(2) + + +def test_atanh(): + a = atanh(interval(-0.5, 0.5)) + assert a.start == np.arctanh(-0.5) + assert a.end == np.arctanh(0.5) + + a = atanh(interval(0, 3)) + assert a.is_valid is None + + a = atanh(interval(-3, -2)) + assert a.is_valid is False + + a = atanh(0.5) + assert a.start == np.arctanh(0.5) + assert a.end == np.arctanh(0.5) + + a = atanh(1.5) + assert a.is_valid is False + + +def test_Abs(): + assert (Abs(interval(-0.5, 0.5)) == interval(0, 0.5)) == (True, True) + assert (Abs(interval(-3, -2)) == interval(2, 3)) == (True, True) + assert (Abs(-3) == interval(3, 3)) == (True, True) + + +def test_And(): + args = [(True, True), (True, False), (True, None)] + assert And(*args) == (True, False) + + args = [(False, True), (None, None), (True, True)] + assert And(*args) == (False, None) + + +def test_Or(): + args = [(True, True), (True, False), (False, None)] + assert Or(*args) == (True, True) + args = [(None, None), (False, None), (False, False)] + assert Or(*args) == (None, None) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/tests/test_interval_membership.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/tests/test_interval_membership.py new file mode 100644 index 0000000000000000000000000000000000000000..7b7f23680d60a64a6257a84c2476e31a8b5dfce8 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/tests/test_interval_membership.py @@ -0,0 +1,150 @@ +from sympy.core.symbol import Symbol +from sympy.plotting.intervalmath import interval +from sympy.plotting.intervalmath.interval_membership import intervalMembership +from sympy.plotting.experimental_lambdify import experimental_lambdify +from sympy.testing.pytest import raises + + +def test_creation(): + assert intervalMembership(True, True) + raises(TypeError, lambda: intervalMembership(True)) + raises(TypeError, lambda: intervalMembership(True, True, True)) + + +def test_getitem(): + a = intervalMembership(True, False) + assert a[0] is True + assert a[1] is False + raises(IndexError, lambda: a[2]) + + +def test_str(): + a = intervalMembership(True, False) + assert str(a) == 'intervalMembership(True, False)' + assert repr(a) == 'intervalMembership(True, False)' + + +def test_equivalence(): + a = intervalMembership(True, True) + b = intervalMembership(True, False) + assert (a == b) is False + assert (a != b) is True + + a = intervalMembership(True, False) + b = intervalMembership(True, False) + assert (a == b) is True + assert (a != b) is False + + +def test_not(): + x = Symbol('x') + + r1 = x > -1 + r2 = x <= -1 + + i = interval + + f1 = experimental_lambdify((x,), r1) + f2 = experimental_lambdify((x,), r2) + + tt = i(-0.1, 0.1, is_valid=True) + tn = i(-0.1, 0.1, is_valid=None) + tf = i(-0.1, 0.1, is_valid=False) + + assert f1(tt) == ~f2(tt) + assert f1(tn) == ~f2(tn) + assert f1(tf) == ~f2(tf) + + nt = i(0.9, 1.1, is_valid=True) + nn = i(0.9, 1.1, is_valid=None) + nf = i(0.9, 1.1, is_valid=False) + + assert f1(nt) == ~f2(nt) + assert f1(nn) == ~f2(nn) + assert f1(nf) == ~f2(nf) + + ft = i(1.9, 2.1, is_valid=True) + fn = i(1.9, 2.1, is_valid=None) + ff = i(1.9, 2.1, is_valid=False) + + assert f1(ft) == ~f2(ft) + assert f1(fn) == ~f2(fn) + assert f1(ff) == ~f2(ff) + + +def test_boolean(): + # There can be 9*9 test cases in full mapping of the cartesian product. + # But we only consider 3*3 cases for simplicity. + s = [ + intervalMembership(False, False), + intervalMembership(None, None), + intervalMembership(True, True) + ] + + # Reduced tests for 'And' + a1 = [ + intervalMembership(False, False), + intervalMembership(False, False), + intervalMembership(False, False), + intervalMembership(False, False), + intervalMembership(None, None), + intervalMembership(None, None), + intervalMembership(False, False), + intervalMembership(None, None), + intervalMembership(True, True) + ] + a1_iter = iter(a1) + for i in range(len(s)): + for j in range(len(s)): + assert s[i] & s[j] == next(a1_iter) + + # Reduced tests for 'Or' + a1 = [ + intervalMembership(False, False), + intervalMembership(None, False), + intervalMembership(True, False), + intervalMembership(None, False), + intervalMembership(None, None), + intervalMembership(True, None), + intervalMembership(True, False), + intervalMembership(True, None), + intervalMembership(True, True) + ] + a1_iter = iter(a1) + for i in range(len(s)): + for j in range(len(s)): + assert s[i] | s[j] == next(a1_iter) + + # Reduced tests for 'Xor' + a1 = [ + intervalMembership(False, False), + intervalMembership(None, False), + intervalMembership(True, False), + intervalMembership(None, False), + intervalMembership(None, None), + intervalMembership(None, None), + intervalMembership(True, False), + intervalMembership(None, None), + intervalMembership(False, True) + ] + a1_iter = iter(a1) + for i in range(len(s)): + for j in range(len(s)): + assert s[i] ^ s[j] == next(a1_iter) + + # Reduced tests for 'Not' + a1 = [ + intervalMembership(True, False), + intervalMembership(None, None), + intervalMembership(False, True) + ] + a1_iter = iter(a1) + for i in range(len(s)): + assert ~s[i] == next(a1_iter) + + +def test_boolean_errors(): + a = intervalMembership(True, True) + raises(ValueError, lambda: a & 1) + raises(ValueError, lambda: a | 1) + raises(ValueError, lambda: a ^ 1) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/tests/test_intervalmath.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/tests/test_intervalmath.py new file mode 100644 index 0000000000000000000000000000000000000000..e30f217a44b4ea795270c0e2c66b6813b05e63ea --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/intervalmath/tests/test_intervalmath.py @@ -0,0 +1,213 @@ +from sympy.plotting.intervalmath import interval +from sympy.testing.pytest import raises + + +def test_interval(): + assert (interval(1, 1) == interval(1, 1, is_valid=True)) == (True, True) + assert (interval(1, 1) == interval(1, 1, is_valid=False)) == (True, False) + assert (interval(1, 1) == interval(1, 1, is_valid=None)) == (True, None) + assert (interval(1, 1.5) == interval(1, 2)) == (None, True) + assert (interval(0, 1) == interval(2, 3)) == (False, True) + assert (interval(0, 1) == interval(1, 2)) == (None, True) + assert (interval(1, 2) != interval(1, 2)) == (False, True) + assert (interval(1, 3) != interval(2, 3)) == (None, True) + assert (interval(1, 3) != interval(-5, -3)) == (True, True) + assert ( + interval(1, 3, is_valid=False) != interval(-5, -3)) == (True, False) + assert (interval(1, 3, is_valid=None) != interval(-5, 3)) == (None, None) + assert (interval(4, 4) != 4) == (False, True) + assert (interval(1, 1) == 1) == (True, True) + assert (interval(1, 3, is_valid=False) == interval(1, 3)) == (True, False) + assert (interval(1, 3, is_valid=None) == interval(1, 3)) == (True, None) + inter = interval(-5, 5) + assert (interval(inter) == interval(-5, 5)) == (True, True) + assert inter.width == 10 + assert 0 in inter + assert -5 in inter + assert 5 in inter + assert interval(0, 3) in inter + assert interval(-6, 2) not in inter + assert -5.05 not in inter + assert 5.3 not in inter + interb = interval(-float('inf'), float('inf')) + assert 0 in inter + assert inter in interb + assert interval(0, float('inf')) in interb + assert interval(-float('inf'), 5) in interb + assert interval(-1e50, 1e50) in interb + assert ( + -interval(-1, -2, is_valid=False) == interval(1, 2)) == (True, False) + raises(ValueError, lambda: interval(1, 2, 3)) + + +def test_interval_add(): + assert (interval(1, 2) + interval(2, 3) == interval(3, 5)) == (True, True) + assert (1 + interval(1, 2) == interval(2, 3)) == (True, True) + assert (interval(1, 2) + 1 == interval(2, 3)) == (True, True) + compare = (1 + interval(0, float('inf')) == interval(1, float('inf'))) + assert compare == (True, True) + a = 1 + interval(2, 5, is_valid=False) + assert a.is_valid is False + a = 1 + interval(2, 5, is_valid=None) + assert a.is_valid is None + a = interval(2, 5, is_valid=False) + interval(3, 5, is_valid=None) + assert a.is_valid is False + a = interval(3, 5) + interval(-1, 1, is_valid=None) + assert a.is_valid is None + a = interval(2, 5, is_valid=False) + 1 + assert a.is_valid is False + + +def test_interval_sub(): + assert (interval(1, 2) - interval(1, 5) == interval(-4, 1)) == (True, True) + assert (interval(1, 2) - 1 == interval(0, 1)) == (True, True) + assert (1 - interval(1, 2) == interval(-1, 0)) == (True, True) + a = 1 - interval(1, 2, is_valid=False) + assert a.is_valid is False + a = interval(1, 4, is_valid=None) - 1 + assert a.is_valid is None + a = interval(1, 3, is_valid=False) - interval(1, 3) + assert a.is_valid is False + a = interval(1, 3, is_valid=None) - interval(1, 3) + assert a.is_valid is None + + +def test_interval_inequality(): + assert (interval(1, 2) < interval(3, 4)) == (True, True) + assert (interval(1, 2) < interval(2, 4)) == (None, True) + assert (interval(1, 2) < interval(-2, 0)) == (False, True) + assert (interval(1, 2) <= interval(2, 4)) == (True, True) + assert (interval(1, 2) <= interval(1.5, 6)) == (None, True) + assert (interval(2, 3) <= interval(1, 2)) == (None, True) + assert (interval(2, 3) <= interval(1, 1.5)) == (False, True) + assert ( + interval(1, 2, is_valid=False) <= interval(-2, 0)) == (False, False) + assert (interval(1, 2, is_valid=None) <= interval(-2, 0)) == (False, None) + assert (interval(1, 2) <= 1.5) == (None, True) + assert (interval(1, 2) <= 3) == (True, True) + assert (interval(1, 2) <= 0) == (False, True) + assert (interval(5, 8) > interval(2, 3)) == (True, True) + assert (interval(2, 5) > interval(1, 3)) == (None, True) + assert (interval(2, 3) > interval(3.1, 5)) == (False, True) + + assert (interval(-1, 1) == 0) == (None, True) + assert (interval(-1, 1) == 2) == (False, True) + assert (interval(-1, 1) != 0) == (None, True) + assert (interval(-1, 1) != 2) == (True, True) + + assert (interval(3, 5) > 2) == (True, True) + assert (interval(3, 5) < 2) == (False, True) + assert (interval(1, 5) < 2) == (None, True) + assert (interval(1, 5) > 2) == (None, True) + assert (interval(0, 1) > 2) == (False, True) + assert (interval(1, 2) >= interval(0, 1)) == (True, True) + assert (interval(1, 2) >= interval(0, 1.5)) == (None, True) + assert (interval(1, 2) >= interval(3, 4)) == (False, True) + assert (interval(1, 2) >= 0) == (True, True) + assert (interval(1, 2) >= 1.2) == (None, True) + assert (interval(1, 2) >= 3) == (False, True) + assert (2 > interval(0, 1)) == (True, True) + a = interval(-1, 1, is_valid=False) < interval(2, 5, is_valid=None) + assert a == (True, False) + a = interval(-1, 1, is_valid=None) < interval(2, 5, is_valid=False) + assert a == (True, False) + a = interval(-1, 1, is_valid=None) < interval(2, 5, is_valid=None) + assert a == (True, None) + a = interval(-1, 1, is_valid=False) > interval(-5, -2, is_valid=None) + assert a == (True, False) + a = interval(-1, 1, is_valid=None) > interval(-5, -2, is_valid=False) + assert a == (True, False) + a = interval(-1, 1, is_valid=None) > interval(-5, -2, is_valid=None) + assert a == (True, None) + + +def test_interval_mul(): + assert ( + interval(1, 5) * interval(2, 10) == interval(2, 50)) == (True, True) + a = interval(-1, 1) * interval(2, 10) == interval(-10, 10) + assert a == (True, True) + + a = interval(-1, 1) * interval(-5, 3) == interval(-5, 5) + assert a == (True, True) + + assert (interval(1, 3) * 2 == interval(2, 6)) == (True, True) + assert (3 * interval(-1, 2) == interval(-3, 6)) == (True, True) + + a = 3 * interval(1, 2, is_valid=False) + assert a.is_valid is False + + a = 3 * interval(1, 2, is_valid=None) + assert a.is_valid is None + + a = interval(1, 5, is_valid=False) * interval(1, 2, is_valid=None) + assert a.is_valid is False + + +def test_interval_div(): + div = interval(1, 2, is_valid=False) / 3 + assert div == interval(-float('inf'), float('inf'), is_valid=False) + + div = interval(1, 2, is_valid=None) / 3 + assert div == interval(-float('inf'), float('inf'), is_valid=None) + + div = 3 / interval(1, 2, is_valid=None) + assert div == interval(-float('inf'), float('inf'), is_valid=None) + a = interval(1, 2) / 0 + assert a.is_valid is False + a = interval(0.5, 1) / interval(-1, 0) + assert a.is_valid is None + a = interval(0, 1) / interval(0, 1) + assert a.is_valid is None + + a = interval(-1, 1) / interval(-1, 1) + assert a.is_valid is None + + a = interval(-1, 2) / interval(0.5, 1) == interval(-2.0, 4.0) + assert a == (True, True) + a = interval(0, 1) / interval(0.5, 1) == interval(0.0, 2.0) + assert a == (True, True) + a = interval(-1, 0) / interval(0.5, 1) == interval(-2.0, 0.0) + assert a == (True, True) + a = interval(-0.5, -0.25) / interval(0.5, 1) == interval(-1.0, -0.25) + assert a == (True, True) + a = interval(0.5, 1) / interval(0.5, 1) == interval(0.5, 2.0) + assert a == (True, True) + a = interval(0.5, 4) / interval(0.5, 1) == interval(0.5, 8.0) + assert a == (True, True) + a = interval(-1, -0.5) / interval(0.5, 1) == interval(-2.0, -0.5) + assert a == (True, True) + a = interval(-4, -0.5) / interval(0.5, 1) == interval(-8.0, -0.5) + assert a == (True, True) + a = interval(-1, 2) / interval(-2, -0.5) == interval(-4.0, 2.0) + assert a == (True, True) + a = interval(0, 1) / interval(-2, -0.5) == interval(-2.0, 0.0) + assert a == (True, True) + a = interval(-1, 0) / interval(-2, -0.5) == interval(0.0, 2.0) + assert a == (True, True) + a = interval(-0.5, -0.25) / interval(-2, -0.5) == interval(0.125, 1.0) + assert a == (True, True) + a = interval(0.5, 1) / interval(-2, -0.5) == interval(-2.0, -0.25) + assert a == (True, True) + a = interval(0.5, 4) / interval(-2, -0.5) == interval(-8.0, -0.25) + assert a == (True, True) + a = interval(-1, -0.5) / interval(-2, -0.5) == interval(0.25, 2.0) + assert a == (True, True) + a = interval(-4, -0.5) / interval(-2, -0.5) == interval(0.25, 8.0) + assert a == (True, True) + a = interval(-5, 5, is_valid=False) / 2 + assert a.is_valid is False + +def test_hashable(): + ''' + test that interval objects are hashable. + this is required in order to be able to put them into the cache, which + appears to be necessary for plotting in py3k. For details, see: + + https://github.com/sympy/sympy/pull/2101 + https://github.com/sympy/sympy/issues/6533 + ''' + hash(interval(1, 1)) + hash(interval(1, 1, is_valid=True)) + hash(interval(-4, -0.5)) + hash(interval(-2, -0.5)) + hash(interval(0.25, 8.0)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..cd86a505d8c4b8026bd91cde27d441e00223a8bc --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__init__.py @@ -0,0 +1,138 @@ +"""Plotting module that can plot 2D and 3D functions +""" + +from sympy.utilities.decorator import doctest_depends_on + +@doctest_depends_on(modules=('pyglet',)) +def PygletPlot(*args, **kwargs): + """ + + Plot Examples + ============= + + See examples/advanced/pyglet_plotting.py for many more examples. + + >>> from sympy.plotting.pygletplot import PygletPlot as Plot + >>> from sympy.abc import x, y, z + + >>> Plot(x*y**3-y*x**3) + [0]: -x**3*y + x*y**3, 'mode=cartesian' + + >>> p = Plot() + >>> p[1] = x*y + >>> p[1].color = z, (0.4,0.4,0.9), (0.9,0.4,0.4) + + >>> p = Plot() + >>> p[1] = x**2+y**2 + >>> p[2] = -x**2-y**2 + + + Variable Intervals + ================== + + The basic format is [var, min, max, steps], but the + syntax is flexible and arguments left out are taken + from the defaults for the current coordinate mode: + + >>> Plot(x**2) # implies [x,-5,5,100] + [0]: x**2, 'mode=cartesian' + + >>> Plot(x**2, [], []) # [x,-1,1,40], [y,-1,1,40] + [0]: x**2, 'mode=cartesian' + >>> Plot(x**2-y**2, [100], [100]) # [x,-1,1,100], [y,-1,1,100] + [0]: x**2 - y**2, 'mode=cartesian' + >>> Plot(x**2, [x,-13,13,100]) + [0]: x**2, 'mode=cartesian' + >>> Plot(x**2, [-13,13]) # [x,-13,13,100] + [0]: x**2, 'mode=cartesian' + >>> Plot(x**2, [x,-13,13]) # [x,-13,13,100] + [0]: x**2, 'mode=cartesian' + >>> Plot(1*x, [], [x], mode='cylindrical') + ... # [unbound_theta,0,2*Pi,40], [x,-1,1,20] + [0]: x, 'mode=cartesian' + + + Coordinate Modes + ================ + + Plot supports several curvilinear coordinate modes, and + they independent for each plotted function. You can specify + a coordinate mode explicitly with the 'mode' named argument, + but it can be automatically determined for Cartesian or + parametric plots, and therefore must only be specified for + polar, cylindrical, and spherical modes. + + Specifically, Plot(function arguments) and Plot[n] = + (function arguments) will interpret your arguments as a + Cartesian plot if you provide one function and a parametric + plot if you provide two or three functions. Similarly, the + arguments will be interpreted as a curve if one variable is + used, and a surface if two are used. + + Supported mode names by number of variables: + + 1: parametric, cartesian, polar + 2: parametric, cartesian, cylindrical = polar, spherical + + >>> Plot(1, mode='spherical') + + + Calculator-like Interface + ========================= + + >>> p = Plot(visible=False) + >>> f = x**2 + >>> p[1] = f + >>> p[2] = f.diff(x) + >>> p[3] = f.diff(x).diff(x) + >>> p + [1]: x**2, 'mode=cartesian' + [2]: 2*x, 'mode=cartesian' + [3]: 2, 'mode=cartesian' + >>> p.show() + >>> p.clear() + >>> p + + >>> p[1] = x**2+y**2 + >>> p[1].style = 'solid' + >>> p[2] = -x**2-y**2 + >>> p[2].style = 'wireframe' + >>> p[1].color = z, (0.4,0.4,0.9), (0.9,0.4,0.4) + >>> p[1].style = 'both' + >>> p[2].style = 'both' + >>> p.close() + + + Plot Window Keyboard Controls + ============================= + + Screen Rotation: + X,Y axis Arrow Keys, A,S,D,W, Numpad 4,6,8,2 + Z axis Q,E, Numpad 7,9 + + Model Rotation: + Z axis Z,C, Numpad 1,3 + + Zoom: R,F, PgUp,PgDn, Numpad +,- + + Reset Camera: X, Numpad 5 + + Camera Presets: + XY F1 + XZ F2 + YZ F3 + Perspective F4 + + Sensitivity Modifier: SHIFT + + Axes Toggle: + Visible F5 + Colors F6 + + Close Window: ESCAPE + + ============================= + """ + + from sympy.plotting.pygletplot.plot import PygletPlot + return PygletPlot(*args, **kwargs) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..95076be8295a810dc1d1ca4bf1dec4911652087c Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/color_scheme.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/color_scheme.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..141b1b84dccaccc8037456ba2a0a57bf45d1ff27 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/color_scheme.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/managed_window.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/managed_window.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0e25084ecf317495ef3918bf4b016d2eb9be1c4d Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/managed_window.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6fce09505470255276509aed63cf1b5be6b523e5 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_axes.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_axes.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..49fe7dfb295e796977591cbe722075c6af972da0 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_axes.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_camera.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_camera.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..596257d8480a36e8838df365d7e2100b1c7dbf5c Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_camera.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_controller.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_controller.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..900c40ba008a07d6f1889bda2ed6298cbb1a0576 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_controller.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_curve.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_curve.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7c29fd702f4720addd840ac9838f68c8d17e55b0 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_curve.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_interval.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_interval.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9905c17ddec1f1dd31236dbbbfb688b4a8477af1 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_interval.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_mode.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_mode.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dee67493c6b78af34c9315f1e29ecbe348bc3113 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_mode.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_mode_base.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_mode_base.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ff1d5f0b76d3dc6d22ca58c2dd0debc1e9f80c00 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_mode_base.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_modes.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_modes.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c12b2a31faac761481b5cbff9c4b5a8ef479bde5 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_modes.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_object.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_object.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..79151a61f59807085d4a815d379ba9a2c3b2d4d6 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_object.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_rotation.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_rotation.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..046b78cd20f53199f59bfd32b11eabb190860c84 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_rotation.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_surface.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_surface.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6df78c7b640b22f9756615520214f83312d47b7e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_surface.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_window.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_window.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b58db1cc720032a20a67f8527863b68dff0bf2e8 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/plot_window.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/util.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/util.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3c58af167d8d0b0b1f178090bbdfef39de5b0410 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/__pycache__/util.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/color_scheme.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/color_scheme.py new file mode 100644 index 0000000000000000000000000000000000000000..613e777a7f45f54349c47d272aa6d1c157bcd117 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/color_scheme.py @@ -0,0 +1,336 @@ +from sympy.core.basic import Basic +from sympy.core.symbol import (Symbol, symbols) +from sympy.utilities.lambdify import lambdify +from .util import interpolate, rinterpolate, create_bounds, update_bounds +from sympy.utilities.iterables import sift + + +class ColorGradient: + colors = [0.4, 0.4, 0.4], [0.9, 0.9, 0.9] + intervals = 0.0, 1.0 + + def __init__(self, *args): + if len(args) == 2: + self.colors = list(args) + self.intervals = [0.0, 1.0] + elif len(args) > 0: + if len(args) % 2 != 0: + raise ValueError("len(args) should be even") + self.colors = [args[i] for i in range(1, len(args), 2)] + self.intervals = [args[i] for i in range(0, len(args), 2)] + assert len(self.colors) == len(self.intervals) + + def copy(self): + c = ColorGradient() + c.colors = [e[::] for e in self.colors] + c.intervals = self.intervals[::] + return c + + def _find_interval(self, v): + m = len(self.intervals) + i = 0 + while i < m - 1 and self.intervals[i] <= v: + i += 1 + return i + + def _interpolate_axis(self, axis, v): + i = self._find_interval(v) + v = rinterpolate(self.intervals[i - 1], self.intervals[i], v) + return interpolate(self.colors[i - 1][axis], self.colors[i][axis], v) + + def __call__(self, r, g, b): + c = self._interpolate_axis + return c(0, r), c(1, g), c(2, b) + +default_color_schemes = {} # defined at the bottom of this file + + +class ColorScheme: + + def __init__(self, *args, **kwargs): + self.args = args + self.f, self.gradient = None, ColorGradient() + + if len(args) == 1 and not isinstance(args[0], Basic) and callable(args[0]): + self.f = args[0] + elif len(args) == 1 and isinstance(args[0], str): + if args[0] in default_color_schemes: + cs = default_color_schemes[args[0]] + self.f, self.gradient = cs.f, cs.gradient.copy() + else: + self.f = lambdify('x,y,z,u,v', args[0]) + else: + self.f, self.gradient = self._interpret_args(args) + self._test_color_function() + if not isinstance(self.gradient, ColorGradient): + raise ValueError("Color gradient not properly initialized. " + "(Not a ColorGradient instance.)") + + def _interpret_args(self, args): + f, gradient = None, self.gradient + atoms, lists = self._sort_args(args) + s = self._pop_symbol_list(lists) + s = self._fill_in_vars(s) + + # prepare the error message for lambdification failure + f_str = ', '.join(str(fa) for fa in atoms) + s_str = (str(sa) for sa in s) + s_str = ', '.join(sa for sa in s_str if sa.find('unbound') < 0) + f_error = ValueError("Could not interpret arguments " + "%s as functions of %s." % (f_str, s_str)) + + # try to lambdify args + if len(atoms) == 1: + fv = atoms[0] + try: + f = lambdify(s, [fv, fv, fv]) + except TypeError: + raise f_error + + elif len(atoms) == 3: + fr, fg, fb = atoms + try: + f = lambdify(s, [fr, fg, fb]) + except TypeError: + raise f_error + + else: + raise ValueError("A ColorScheme must provide 1 or 3 " + "functions in x, y, z, u, and/or v.") + + # try to intrepret any given color information + if len(lists) == 0: + gargs = [] + + elif len(lists) == 1: + gargs = lists[0] + + elif len(lists) == 2: + try: + (r1, g1, b1), (r2, g2, b2) = lists + except TypeError: + raise ValueError("If two color arguments are given, " + "they must be given in the format " + "(r1, g1, b1), (r2, g2, b2).") + gargs = lists + + elif len(lists) == 3: + try: + (r1, r2), (g1, g2), (b1, b2) = lists + except Exception: + raise ValueError("If three color arguments are given, " + "they must be given in the format " + "(r1, r2), (g1, g2), (b1, b2). To create " + "a multi-step gradient, use the syntax " + "[0, colorStart, step1, color1, ..., 1, " + "colorEnd].") + gargs = [[r1, g1, b1], [r2, g2, b2]] + + else: + raise ValueError("Don't know what to do with collection " + "arguments %s." % (', '.join(str(l) for l in lists))) + + if gargs: + try: + gradient = ColorGradient(*gargs) + except Exception as ex: + raise ValueError(("Could not initialize a gradient " + "with arguments %s. Inner " + "exception: %s") % (gargs, str(ex))) + + return f, gradient + + def _pop_symbol_list(self, lists): + symbol_lists = [] + for l in lists: + mark = True + for s in l: + if s is not None and not isinstance(s, Symbol): + mark = False + break + if mark: + lists.remove(l) + symbol_lists.append(l) + if len(symbol_lists) == 1: + return symbol_lists[0] + elif len(symbol_lists) == 0: + return [] + else: + raise ValueError("Only one list of Symbols " + "can be given for a color scheme.") + + def _fill_in_vars(self, args): + defaults = symbols('x,y,z,u,v') + v_error = ValueError("Could not find what to plot.") + if len(args) == 0: + return defaults + if not isinstance(args, (tuple, list)): + raise v_error + if len(args) == 0: + return defaults + for s in args: + if s is not None and not isinstance(s, Symbol): + raise v_error + # when vars are given explicitly, any vars + # not given are marked 'unbound' as to not + # be accidentally used in an expression + vars = [Symbol('unbound%i' % (i)) for i in range(1, 6)] + # interpret as t + if len(args) == 1: + vars[3] = args[0] + # interpret as u,v + elif len(args) == 2: + if args[0] is not None: + vars[3] = args[0] + if args[1] is not None: + vars[4] = args[1] + # interpret as x,y,z + elif len(args) >= 3: + # allow some of x,y,z to be + # left unbound if not given + if args[0] is not None: + vars[0] = args[0] + if args[1] is not None: + vars[1] = args[1] + if args[2] is not None: + vars[2] = args[2] + # interpret the rest as t + if len(args) >= 4: + vars[3] = args[3] + # ...or u,v + if len(args) >= 5: + vars[4] = args[4] + return vars + + def _sort_args(self, args): + lists, atoms = sift(args, + lambda a: isinstance(a, (tuple, list)), binary=True) + return atoms, lists + + def _test_color_function(self): + if not callable(self.f): + raise ValueError("Color function is not callable.") + try: + result = self.f(0, 0, 0, 0, 0) + if len(result) != 3: + raise ValueError("length should be equal to 3") + except TypeError: + raise ValueError("Color function needs to accept x,y,z,u,v, " + "as arguments even if it doesn't use all of them.") + except AssertionError: + raise ValueError("Color function needs to return 3-tuple r,g,b.") + except Exception: + pass # color function probably not valid at 0,0,0,0,0 + + def __call__(self, x, y, z, u, v): + try: + return self.f(x, y, z, u, v) + except Exception: + return None + + def apply_to_curve(self, verts, u_set, set_len=None, inc_pos=None): + """ + Apply this color scheme to a + set of vertices over a single + independent variable u. + """ + bounds = create_bounds() + cverts = [] + if callable(set_len): + set_len(len(u_set)*2) + # calculate f() = r,g,b for each vert + # and find the min and max for r,g,b + for _u in range(len(u_set)): + if verts[_u] is None: + cverts.append(None) + else: + x, y, z = verts[_u] + u, v = u_set[_u], None + c = self(x, y, z, u, v) + if c is not None: + c = list(c) + update_bounds(bounds, c) + cverts.append(c) + if callable(inc_pos): + inc_pos() + # scale and apply gradient + for _u in range(len(u_set)): + if cverts[_u] is not None: + for _c in range(3): + # scale from [f_min, f_max] to [0,1] + cverts[_u][_c] = rinterpolate(bounds[_c][0], bounds[_c][1], + cverts[_u][_c]) + # apply gradient + cverts[_u] = self.gradient(*cverts[_u]) + if callable(inc_pos): + inc_pos() + return cverts + + def apply_to_surface(self, verts, u_set, v_set, set_len=None, inc_pos=None): + """ + Apply this color scheme to a + set of vertices over two + independent variables u and v. + """ + bounds = create_bounds() + cverts = [] + if callable(set_len): + set_len(len(u_set)*len(v_set)*2) + # calculate f() = r,g,b for each vert + # and find the min and max for r,g,b + for _u in range(len(u_set)): + column = [] + for _v in range(len(v_set)): + if verts[_u][_v] is None: + column.append(None) + else: + x, y, z = verts[_u][_v] + u, v = u_set[_u], v_set[_v] + c = self(x, y, z, u, v) + if c is not None: + c = list(c) + update_bounds(bounds, c) + column.append(c) + if callable(inc_pos): + inc_pos() + cverts.append(column) + # scale and apply gradient + for _u in range(len(u_set)): + for _v in range(len(v_set)): + if cverts[_u][_v] is not None: + # scale from [f_min, f_max] to [0,1] + for _c in range(3): + cverts[_u][_v][_c] = rinterpolate(bounds[_c][0], + bounds[_c][1], cverts[_u][_v][_c]) + # apply gradient + cverts[_u][_v] = self.gradient(*cverts[_u][_v]) + if callable(inc_pos): + inc_pos() + return cverts + + def str_base(self): + return ", ".join(str(a) for a in self.args) + + def __repr__(self): + return "%s" % (self.str_base()) + + +x, y, z, t, u, v = symbols('x,y,z,t,u,v') + +default_color_schemes['rainbow'] = ColorScheme(z, y, x) +default_color_schemes['zfade'] = ColorScheme(z, (0.4, 0.4, 0.97), + (0.97, 0.4, 0.4), (None, None, z)) +default_color_schemes['zfade3'] = ColorScheme(z, (None, None, z), + [0.00, (0.2, 0.2, 1.0), + 0.35, (0.2, 0.8, 0.4), + 0.50, (0.3, 0.9, 0.3), + 0.65, (0.4, 0.8, 0.2), + 1.00, (1.0, 0.2, 0.2)]) + +default_color_schemes['zfade4'] = ColorScheme(z, (None, None, z), + [0.0, (0.3, 0.3, 1.0), + 0.30, (0.3, 1.0, 0.3), + 0.55, (0.95, 1.0, 0.2), + 0.65, (1.0, 0.95, 0.2), + 0.85, (1.0, 0.7, 0.2), + 1.0, (1.0, 0.3, 0.2)]) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/managed_window.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/managed_window.py new file mode 100644 index 0000000000000000000000000000000000000000..81fa2541b4dd9e13534aabfd2a11bf88c479daf8 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/managed_window.py @@ -0,0 +1,106 @@ +from pyglet.window import Window +from pyglet.clock import Clock + +from threading import Thread, Lock + +gl_lock = Lock() + + +class ManagedWindow(Window): + """ + A pyglet window with an event loop which executes automatically + in a separate thread. Behavior is added by creating a subclass + which overrides setup, update, and/or draw. + """ + fps_limit = 30 + default_win_args = {"width": 600, + "height": 500, + "vsync": False, + "resizable": True} + + def __init__(self, **win_args): + """ + It is best not to override this function in the child + class, unless you need to take additional arguments. + Do any OpenGL initialization calls in setup(). + """ + + # check if this is run from the doctester + if win_args.get('runfromdoctester', False): + return + + self.win_args = dict(self.default_win_args, **win_args) + self.Thread = Thread(target=self.__event_loop__) + self.Thread.start() + + def __event_loop__(self, **win_args): + """ + The event loop thread function. Do not override or call + directly (it is called by __init__). + """ + gl_lock.acquire() + try: + try: + super().__init__(**self.win_args) + self.switch_to() + self.setup() + except Exception as e: + print("Window initialization failed: %s" % (str(e))) + self.has_exit = True + finally: + gl_lock.release() + + clock = Clock() + clock.fps_limit = self.fps_limit + while not self.has_exit: + dt = clock.tick() + gl_lock.acquire() + try: + try: + self.switch_to() + self.dispatch_events() + self.clear() + self.update(dt) + self.draw() + self.flip() + except Exception as e: + print("Uncaught exception in event loop: %s" % str(e)) + self.has_exit = True + finally: + gl_lock.release() + super().close() + + def close(self): + """ + Closes the window. + """ + self.has_exit = True + + def setup(self): + """ + Called once before the event loop begins. + Override this method in a child class. This + is the best place to put things like OpenGL + initialization calls. + """ + pass + + def update(self, dt): + """ + Called before draw during each iteration of + the event loop. dt is the elapsed time in + seconds since the last update. OpenGL rendering + calls are best put in draw() rather than here. + """ + pass + + def draw(self): + """ + Called after update during each iteration of + the event loop. Put OpenGL rendering calls + here. + """ + pass + +if __name__ == '__main__': + ManagedWindow() diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot.py new file mode 100644 index 0000000000000000000000000000000000000000..8c3dd3c8d4ce6c660cc07f93a55029eef98e55a2 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot.py @@ -0,0 +1,464 @@ +from threading import RLock + +# it is sufficient to import "pyglet" here once +try: + import pyglet.gl as pgl +except ImportError: + raise ImportError("pyglet is required for plotting.\n " + "visit https://pyglet.org/") + +from sympy.core.numbers import Integer +from sympy.external.gmpy import SYMPY_INTS +from sympy.geometry.entity import GeometryEntity +from sympy.plotting.pygletplot.plot_axes import PlotAxes +from sympy.plotting.pygletplot.plot_mode import PlotMode +from sympy.plotting.pygletplot.plot_object import PlotObject +from sympy.plotting.pygletplot.plot_window import PlotWindow +from sympy.plotting.pygletplot.util import parse_option_string +from sympy.utilities.decorator import doctest_depends_on +from sympy.utilities.iterables import is_sequence + +from time import sleep +from os import getcwd, listdir + +import ctypes + +@doctest_depends_on(modules=('pyglet',)) +class PygletPlot: + """ + Plot Examples + ============= + + See examples/advanced/pyglet_plotting.py for many more examples. + + >>> from sympy.plotting.pygletplot import PygletPlot as Plot + >>> from sympy.abc import x, y, z + + >>> Plot(x*y**3-y*x**3) + [0]: -x**3*y + x*y**3, 'mode=cartesian' + + >>> p = Plot() + >>> p[1] = x*y + >>> p[1].color = z, (0.4,0.4,0.9), (0.9,0.4,0.4) + + >>> p = Plot() + >>> p[1] = x**2+y**2 + >>> p[2] = -x**2-y**2 + + + Variable Intervals + ================== + + The basic format is [var, min, max, steps], but the + syntax is flexible and arguments left out are taken + from the defaults for the current coordinate mode: + + >>> Plot(x**2) # implies [x,-5,5,100] + [0]: x**2, 'mode=cartesian' + >>> Plot(x**2, [], []) # [x,-1,1,40], [y,-1,1,40] + [0]: x**2, 'mode=cartesian' + >>> Plot(x**2-y**2, [100], [100]) # [x,-1,1,100], [y,-1,1,100] + [0]: x**2 - y**2, 'mode=cartesian' + >>> Plot(x**2, [x,-13,13,100]) + [0]: x**2, 'mode=cartesian' + >>> Plot(x**2, [-13,13]) # [x,-13,13,100] + [0]: x**2, 'mode=cartesian' + >>> Plot(x**2, [x,-13,13]) # [x,-13,13,10] + [0]: x**2, 'mode=cartesian' + >>> Plot(1*x, [], [x], mode='cylindrical') + ... # [unbound_theta,0,2*Pi,40], [x,-1,1,20] + [0]: x, 'mode=cartesian' + + + Coordinate Modes + ================ + + Plot supports several curvilinear coordinate modes, and + they independent for each plotted function. You can specify + a coordinate mode explicitly with the 'mode' named argument, + but it can be automatically determined for Cartesian or + parametric plots, and therefore must only be specified for + polar, cylindrical, and spherical modes. + + Specifically, Plot(function arguments) and Plot[n] = + (function arguments) will interpret your arguments as a + Cartesian plot if you provide one function and a parametric + plot if you provide two or three functions. Similarly, the + arguments will be interpreted as a curve if one variable is + used, and a surface if two are used. + + Supported mode names by number of variables: + + 1: parametric, cartesian, polar + 2: parametric, cartesian, cylindrical = polar, spherical + + >>> Plot(1, mode='spherical') + + + Calculator-like Interface + ========================= + + >>> p = Plot(visible=False) + >>> f = x**2 + >>> p[1] = f + >>> p[2] = f.diff(x) + >>> p[3] = f.diff(x).diff(x) + >>> p + [1]: x**2, 'mode=cartesian' + [2]: 2*x, 'mode=cartesian' + [3]: 2, 'mode=cartesian' + >>> p.show() + >>> p.clear() + >>> p + + >>> p[1] = x**2+y**2 + >>> p[1].style = 'solid' + >>> p[2] = -x**2-y**2 + >>> p[2].style = 'wireframe' + >>> p[1].color = z, (0.4,0.4,0.9), (0.9,0.4,0.4) + >>> p[1].style = 'both' + >>> p[2].style = 'both' + >>> p.close() + + + Plot Window Keyboard Controls + ============================= + + Screen Rotation: + X,Y axis Arrow Keys, A,S,D,W, Numpad 4,6,8,2 + Z axis Q,E, Numpad 7,9 + + Model Rotation: + Z axis Z,C, Numpad 1,3 + + Zoom: R,F, PgUp,PgDn, Numpad +,- + + Reset Camera: X, Numpad 5 + + Camera Presets: + XY F1 + XZ F2 + YZ F3 + Perspective F4 + + Sensitivity Modifier: SHIFT + + Axes Toggle: + Visible F5 + Colors F6 + + Close Window: ESCAPE + + ============================= + + """ + + @doctest_depends_on(modules=('pyglet',)) + def __init__(self, *fargs, **win_args): + """ + Positional Arguments + ==================== + + Any given positional arguments are used to + initialize a plot function at index 1. In + other words... + + >>> from sympy.plotting.pygletplot import PygletPlot as Plot + >>> from sympy.abc import x + >>> p = Plot(x**2, visible=False) + + ...is equivalent to... + + >>> p = Plot(visible=False) + >>> p[1] = x**2 + + Note that in earlier versions of the plotting + module, you were able to specify multiple + functions in the initializer. This functionality + has been dropped in favor of better automatic + plot plot_mode detection. + + + Named Arguments + =============== + + axes + An option string of the form + "key1=value1; key2 = value2" which + can use the following options: + + style = ordinate + none OR frame OR box OR ordinate + + stride = 0.25 + val OR (val_x, val_y, val_z) + + overlay = True (draw on top of plot) + True OR False + + colored = False (False uses Black, + True uses colors + R,G,B = X,Y,Z) + True OR False + + label_axes = False (display axis names + at endpoints) + True OR False + + visible = True (show immediately + True OR False + + + The following named arguments are passed as + arguments to window initialization: + + antialiasing = True + True OR False + + ortho = False + True OR False + + invert_mouse_zoom = False + True OR False + + """ + # Register the plot modes + from . import plot_modes # noqa + + self._win_args = win_args + self._window = None + + self._render_lock = RLock() + + self._functions = {} + self._pobjects = [] + self._screenshot = ScreenShot(self) + + axe_options = parse_option_string(win_args.pop('axes', '')) + self.axes = PlotAxes(**axe_options) + self._pobjects.append(self.axes) + + self[0] = fargs + if win_args.get('visible', True): + self.show() + + ## Window Interfaces + + def show(self): + """ + Creates and displays a plot window, or activates it + (gives it focus) if it has already been created. + """ + if self._window and not self._window.has_exit: + self._window.activate() + else: + self._win_args['visible'] = True + self.axes.reset_resources() + + #if hasattr(self, '_doctest_depends_on'): + # self._win_args['runfromdoctester'] = True + + self._window = PlotWindow(self, **self._win_args) + + def close(self): + """ + Closes the plot window. + """ + if self._window: + self._window.close() + + def saveimage(self, outfile=None, format='', size=(600, 500)): + """ + Saves a screen capture of the plot window to an + image file. + + If outfile is given, it can either be a path + or a file object. Otherwise a png image will + be saved to the current working directory. + If the format is omitted, it is determined from + the filename extension. + """ + self._screenshot.save(outfile, format, size) + + ## Function List Interfaces + + def clear(self): + """ + Clears the function list of this plot. + """ + self._render_lock.acquire() + self._functions = {} + self.adjust_all_bounds() + self._render_lock.release() + + def __getitem__(self, i): + """ + Returns the function at position i in the + function list. + """ + return self._functions[i] + + def __setitem__(self, i, args): + """ + Parses and adds a PlotMode to the function + list. + """ + if not (isinstance(i, (SYMPY_INTS, Integer)) and i >= 0): + raise ValueError("Function index must " + "be an integer >= 0.") + + if isinstance(args, PlotObject): + f = args + else: + if (not is_sequence(args)) or isinstance(args, GeometryEntity): + args = [args] + if len(args) == 0: + return # no arguments given + kwargs = {"bounds_callback": self.adjust_all_bounds} + f = PlotMode(*args, **kwargs) + + if f: + self._render_lock.acquire() + self._functions[i] = f + self._render_lock.release() + else: + raise ValueError("Failed to parse '%s'." + % ', '.join(str(a) for a in args)) + + def __delitem__(self, i): + """ + Removes the function in the function list at + position i. + """ + self._render_lock.acquire() + del self._functions[i] + self.adjust_all_bounds() + self._render_lock.release() + + def firstavailableindex(self): + """ + Returns the first unused index in the function list. + """ + i = 0 + self._render_lock.acquire() + while i in self._functions: + i += 1 + self._render_lock.release() + return i + + def append(self, *args): + """ + Parses and adds a PlotMode to the function + list at the first available index. + """ + self.__setitem__(self.firstavailableindex(), args) + + def __len__(self): + """ + Returns the number of functions in the function list. + """ + return len(self._functions) + + def __iter__(self): + """ + Allows iteration of the function list. + """ + return self._functions.itervalues() + + def __repr__(self): + return str(self) + + def __str__(self): + """ + Returns a string containing a new-line separated + list of the functions in the function list. + """ + s = "" + if len(self._functions) == 0: + s += "" + else: + self._render_lock.acquire() + s += "\n".join(["%s[%i]: %s" % ("", i, str(self._functions[i])) + for i in self._functions]) + self._render_lock.release() + return s + + def adjust_all_bounds(self): + self._render_lock.acquire() + self.axes.reset_bounding_box() + for f in self._functions: + self.axes.adjust_bounds(self._functions[f].bounds) + self._render_lock.release() + + def wait_for_calculations(self): + sleep(0) + self._render_lock.acquire() + for f in self._functions: + a = self._functions[f]._get_calculating_verts + b = self._functions[f]._get_calculating_cverts + while a() or b(): + sleep(0) + self._render_lock.release() + +class ScreenShot: + def __init__(self, plot): + self._plot = plot + self.screenshot_requested = False + self.outfile = None + self.format = '' + self.invisibleMode = False + self.flag = 0 + + def __bool__(self): + return self.screenshot_requested + + def _execute_saving(self): + if self.flag < 3: + self.flag += 1 + return + + size_x, size_y = self._plot._window.get_size() + size = size_x*size_y*4*ctypes.sizeof(ctypes.c_ubyte) + image = ctypes.create_string_buffer(size) + pgl.glReadPixels(0, 0, size_x, size_y, pgl.GL_RGBA, pgl.GL_UNSIGNED_BYTE, image) + from PIL import Image + im = Image.frombuffer('RGBA', (size_x, size_y), + image.raw, 'raw', 'RGBA', 0, 1) + im.transpose(Image.FLIP_TOP_BOTTOM).save(self.outfile, self.format) + + self.flag = 0 + self.screenshot_requested = False + if self.invisibleMode: + self._plot._window.close() + + def save(self, outfile=None, format='', size=(600, 500)): + self.outfile = outfile + self.format = format + self.size = size + self.screenshot_requested = True + + if not self._plot._window or self._plot._window.has_exit: + self._plot._win_args['visible'] = False + + self._plot._win_args['width'] = size[0] + self._plot._win_args['height'] = size[1] + + self._plot.axes.reset_resources() + self._plot._window = PlotWindow(self._plot, **self._plot._win_args) + self.invisibleMode = True + + if self.outfile is None: + self.outfile = self._create_unique_path() + print(self.outfile) + + def _create_unique_path(self): + cwd = getcwd() + l = listdir(cwd) + path = '' + i = 0 + while True: + if not 'plot_%s.png' % i in l: + path = cwd + '/plot_%s.png' % i + break + i += 1 + return path diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_axes.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_axes.py new file mode 100644 index 0000000000000000000000000000000000000000..ae26fb0b2fa64e7f7318c51ce3fe5afaa276b48e --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_axes.py @@ -0,0 +1,251 @@ +import pyglet.gl as pgl +from pyglet import font + +from sympy.core import S +from sympy.plotting.pygletplot.plot_object import PlotObject +from sympy.plotting.pygletplot.util import billboard_matrix, dot_product, \ + get_direction_vectors, strided_range, vec_mag, vec_sub +from sympy.utilities.iterables import is_sequence + + +class PlotAxes(PlotObject): + + def __init__(self, *args, + style='', none=None, frame=None, box=None, ordinate=None, + stride=0.25, + visible='', overlay='', colored='', label_axes='', label_ticks='', + tick_length=0.1, + font_face='Arial', font_size=28, + **kwargs): + # initialize style parameter + style = style.lower() + + # allow alias kwargs to override style kwarg + if none is not None: + style = 'none' + if frame is not None: + style = 'frame' + if box is not None: + style = 'box' + if ordinate is not None: + style = 'ordinate' + + if style in ['', 'ordinate']: + self._render_object = PlotAxesOrdinate(self) + elif style in ['frame', 'box']: + self._render_object = PlotAxesFrame(self) + elif style in ['none']: + self._render_object = None + else: + raise ValueError(("Unrecognized axes style %s.") % (style)) + + # initialize stride parameter + try: + stride = eval(stride) + except TypeError: + pass + if is_sequence(stride): + if len(stride) != 3: + raise ValueError("length should be equal to 3") + self._stride = stride + else: + self._stride = [stride, stride, stride] + self._tick_length = float(tick_length) + + # setup bounding box and ticks + self._origin = [0, 0, 0] + self.reset_bounding_box() + + def flexible_boolean(input, default): + if input in [True, False]: + return input + if input in ('f', 'F', 'false', 'False'): + return False + if input in ('t', 'T', 'true', 'True'): + return True + return default + + # initialize remaining parameters + self.visible = flexible_boolean(kwargs, True) + self._overlay = flexible_boolean(overlay, True) + self._colored = flexible_boolean(colored, False) + self._label_axes = flexible_boolean(label_axes, False) + self._label_ticks = flexible_boolean(label_ticks, True) + + # setup label font + self.font_face = font_face + self.font_size = font_size + + # this is also used to reinit the + # font on window close/reopen + self.reset_resources() + + def reset_resources(self): + self.label_font = None + + def reset_bounding_box(self): + self._bounding_box = [[None, None], [None, None], [None, None]] + self._axis_ticks = [[], [], []] + + def draw(self): + if self._render_object: + pgl.glPushAttrib(pgl.GL_ENABLE_BIT | pgl.GL_POLYGON_BIT | pgl.GL_DEPTH_BUFFER_BIT) + if self._overlay: + pgl.glDisable(pgl.GL_DEPTH_TEST) + self._render_object.draw() + pgl.glPopAttrib() + + def adjust_bounds(self, child_bounds): + b = self._bounding_box + c = child_bounds + for i in range(3): + if abs(c[i][0]) is S.Infinity or abs(c[i][1]) is S.Infinity: + continue + b[i][0] = c[i][0] if b[i][0] is None else min([b[i][0], c[i][0]]) + b[i][1] = c[i][1] if b[i][1] is None else max([b[i][1], c[i][1]]) + self._bounding_box = b + self._recalculate_axis_ticks(i) + + def _recalculate_axis_ticks(self, axis): + b = self._bounding_box + if b[axis][0] is None or b[axis][1] is None: + self._axis_ticks[axis] = [] + else: + self._axis_ticks[axis] = strided_range(b[axis][0], b[axis][1], + self._stride[axis]) + + def toggle_visible(self): + self.visible = not self.visible + + def toggle_colors(self): + self._colored = not self._colored + + +class PlotAxesBase(PlotObject): + + def __init__(self, parent_axes): + self._p = parent_axes + + def draw(self): + color = [([0.2, 0.1, 0.3], [0.2, 0.1, 0.3], [0.2, 0.1, 0.3]), + ([0.9, 0.3, 0.5], [0.5, 1.0, 0.5], [0.3, 0.3, 0.9])][self._p._colored] + self.draw_background(color) + self.draw_axis(2, color[2]) + self.draw_axis(1, color[1]) + self.draw_axis(0, color[0]) + + def draw_background(self, color): + pass # optional + + def draw_axis(self, axis, color): + raise NotImplementedError() + + def draw_text(self, text, position, color, scale=1.0): + if len(color) == 3: + color = (color[0], color[1], color[2], 1.0) + + if self._p.label_font is None: + self._p.label_font = font.load(self._p.font_face, + self._p.font_size, + bold=True, italic=False) + + label = font.Text(self._p.label_font, text, + color=color, + valign=font.Text.BASELINE, + halign=font.Text.CENTER) + + pgl.glPushMatrix() + pgl.glTranslatef(*position) + billboard_matrix() + scale_factor = 0.005 * scale + pgl.glScalef(scale_factor, scale_factor, scale_factor) + pgl.glColor4f(0, 0, 0, 0) + label.draw() + pgl.glPopMatrix() + + def draw_line(self, v, color): + o = self._p._origin + pgl.glBegin(pgl.GL_LINES) + pgl.glColor3f(*color) + pgl.glVertex3f(v[0][0] + o[0], v[0][1] + o[1], v[0][2] + o[2]) + pgl.glVertex3f(v[1][0] + o[0], v[1][1] + o[1], v[1][2] + o[2]) + pgl.glEnd() + + +class PlotAxesOrdinate(PlotAxesBase): + + def __init__(self, parent_axes): + super().__init__(parent_axes) + + def draw_axis(self, axis, color): + ticks = self._p._axis_ticks[axis] + radius = self._p._tick_length / 2.0 + if len(ticks) < 2: + return + + # calculate the vector for this axis + axis_lines = [[0, 0, 0], [0, 0, 0]] + axis_lines[0][axis], axis_lines[1][axis] = ticks[0], ticks[-1] + axis_vector = vec_sub(axis_lines[1], axis_lines[0]) + + # calculate angle to the z direction vector + pos_z = get_direction_vectors()[2] + d = abs(dot_product(axis_vector, pos_z)) + d = d / vec_mag(axis_vector) + + # don't draw labels if we're looking down the axis + labels_visible = abs(d - 1.0) > 0.02 + + # draw the ticks and labels + for tick in ticks: + self.draw_tick_line(axis, color, radius, tick, labels_visible) + + # draw the axis line and labels + self.draw_axis_line(axis, color, ticks[0], ticks[-1], labels_visible) + + def draw_axis_line(self, axis, color, a_min, a_max, labels_visible): + axis_line = [[0, 0, 0], [0, 0, 0]] + axis_line[0][axis], axis_line[1][axis] = a_min, a_max + self.draw_line(axis_line, color) + if labels_visible: + self.draw_axis_line_labels(axis, color, axis_line) + + def draw_axis_line_labels(self, axis, color, axis_line): + if not self._p._label_axes: + return + axis_labels = [axis_line[0][::], axis_line[1][::]] + axis_labels[0][axis] -= 0.3 + axis_labels[1][axis] += 0.3 + a_str = ['X', 'Y', 'Z'][axis] + self.draw_text("-" + a_str, axis_labels[0], color) + self.draw_text("+" + a_str, axis_labels[1], color) + + def draw_tick_line(self, axis, color, radius, tick, labels_visible): + tick_axis = {0: 1, 1: 0, 2: 1}[axis] + tick_line = [[0, 0, 0], [0, 0, 0]] + tick_line[0][axis] = tick_line[1][axis] = tick + tick_line[0][tick_axis], tick_line[1][tick_axis] = -radius, radius + self.draw_line(tick_line, color) + if labels_visible: + self.draw_tick_line_label(axis, color, radius, tick) + + def draw_tick_line_label(self, axis, color, radius, tick): + if not self._p._label_axes: + return + tick_label_vector = [0, 0, 0] + tick_label_vector[axis] = tick + tick_label_vector[{0: 1, 1: 0, 2: 1}[axis]] = [-1, 1, 1][ + axis] * radius * 3.5 + self.draw_text(str(tick), tick_label_vector, color, scale=0.5) + + +class PlotAxesFrame(PlotAxesBase): + + def __init__(self, parent_axes): + super().__init__(parent_axes) + + def draw_background(self, color): + pass + + def draw_axis(self, axis, color): + raise NotImplementedError() diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_camera.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_camera.py new file mode 100644 index 0000000000000000000000000000000000000000..43598debac252ffd22beb8690fef30745259c634 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_camera.py @@ -0,0 +1,124 @@ +import pyglet.gl as pgl +from sympy.plotting.pygletplot.plot_rotation import get_spherical_rotatation +from sympy.plotting.pygletplot.util import get_model_matrix, model_to_screen, \ + screen_to_model, vec_subs + + +class PlotCamera: + + min_dist = 0.05 + max_dist = 500.0 + + min_ortho_dist = 100.0 + max_ortho_dist = 10000.0 + + _default_dist = 6.0 + _default_ortho_dist = 600.0 + + rot_presets = { + 'xy': (0, 0, 0), + 'xz': (-90, 0, 0), + 'yz': (0, 90, 0), + 'perspective': (-45, 0, -45) + } + + def __init__(self, window, ortho=False): + self.window = window + self.axes = self.window.plot.axes + self.ortho = ortho + self.reset() + + def init_rot_matrix(self): + pgl.glPushMatrix() + pgl.glLoadIdentity() + self._rot = get_model_matrix() + pgl.glPopMatrix() + + def set_rot_preset(self, preset_name): + self.init_rot_matrix() + if preset_name not in self.rot_presets: + raise ValueError( + "%s is not a valid rotation preset." % preset_name) + r = self.rot_presets[preset_name] + self.euler_rotate(r[0], 1, 0, 0) + self.euler_rotate(r[1], 0, 1, 0) + self.euler_rotate(r[2], 0, 0, 1) + + def reset(self): + self._dist = 0.0 + self._x, self._y = 0.0, 0.0 + self._rot = None + if self.ortho: + self._dist = self._default_ortho_dist + else: + self._dist = self._default_dist + self.init_rot_matrix() + + def mult_rot_matrix(self, rot): + pgl.glPushMatrix() + pgl.glLoadMatrixf(rot) + pgl.glMultMatrixf(self._rot) + self._rot = get_model_matrix() + pgl.glPopMatrix() + + def setup_projection(self): + pgl.glMatrixMode(pgl.GL_PROJECTION) + pgl.glLoadIdentity() + if self.ortho: + # yep, this is pseudo ortho (don't tell anyone) + pgl.gluPerspective( + 0.3, float(self.window.width)/float(self.window.height), + self.min_ortho_dist - 0.01, self.max_ortho_dist + 0.01) + else: + pgl.gluPerspective( + 30.0, float(self.window.width)/float(self.window.height), + self.min_dist - 0.01, self.max_dist + 0.01) + pgl.glMatrixMode(pgl.GL_MODELVIEW) + + def _get_scale(self): + return 1.0, 1.0, 1.0 + + def apply_transformation(self): + pgl.glLoadIdentity() + pgl.glTranslatef(self._x, self._y, -self._dist) + if self._rot is not None: + pgl.glMultMatrixf(self._rot) + pgl.glScalef(*self._get_scale()) + + def spherical_rotate(self, p1, p2, sensitivity=1.0): + mat = get_spherical_rotatation(p1, p2, self.window.width, + self.window.height, sensitivity) + if mat is not None: + self.mult_rot_matrix(mat) + + def euler_rotate(self, angle, x, y, z): + pgl.glPushMatrix() + pgl.glLoadMatrixf(self._rot) + pgl.glRotatef(angle, x, y, z) + self._rot = get_model_matrix() + pgl.glPopMatrix() + + def zoom_relative(self, clicks, sensitivity): + + if self.ortho: + dist_d = clicks * sensitivity * 50.0 + min_dist = self.min_ortho_dist + max_dist = self.max_ortho_dist + else: + dist_d = clicks * sensitivity + min_dist = self.min_dist + max_dist = self.max_dist + + new_dist = (self._dist - dist_d) + if (clicks < 0 and new_dist < max_dist) or new_dist > min_dist: + self._dist = new_dist + + def mouse_translate(self, x, y, dx, dy): + pgl.glPushMatrix() + pgl.glLoadIdentity() + pgl.glTranslatef(0, 0, -self._dist) + z = model_to_screen(0, 0, 0)[2] + d = vec_subs(screen_to_model(x, y, z), screen_to_model(x - dx, y - dy, z)) + pgl.glPopMatrix() + self._x += d[0] + self._y += d[1] diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_controller.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_controller.py new file mode 100644 index 0000000000000000000000000000000000000000..aa7e01e6fd17fddf07b733442208a0a4c9d87d5b --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_controller.py @@ -0,0 +1,218 @@ +from pyglet.window import key +from pyglet.window.mouse import LEFT, RIGHT, MIDDLE +from sympy.plotting.pygletplot.util import get_direction_vectors, get_basis_vectors + + +class PlotController: + + normal_mouse_sensitivity = 4.0 + modified_mouse_sensitivity = 1.0 + + normal_key_sensitivity = 160.0 + modified_key_sensitivity = 40.0 + + keymap = { + key.LEFT: 'left', + key.A: 'left', + key.NUM_4: 'left', + + key.RIGHT: 'right', + key.D: 'right', + key.NUM_6: 'right', + + key.UP: 'up', + key.W: 'up', + key.NUM_8: 'up', + + key.DOWN: 'down', + key.S: 'down', + key.NUM_2: 'down', + + key.Z: 'rotate_z_neg', + key.NUM_1: 'rotate_z_neg', + + key.C: 'rotate_z_pos', + key.NUM_3: 'rotate_z_pos', + + key.Q: 'spin_left', + key.NUM_7: 'spin_left', + key.E: 'spin_right', + key.NUM_9: 'spin_right', + + key.X: 'reset_camera', + key.NUM_5: 'reset_camera', + + key.NUM_ADD: 'zoom_in', + key.PAGEUP: 'zoom_in', + key.R: 'zoom_in', + + key.NUM_SUBTRACT: 'zoom_out', + key.PAGEDOWN: 'zoom_out', + key.F: 'zoom_out', + + key.RSHIFT: 'modify_sensitivity', + key.LSHIFT: 'modify_sensitivity', + + key.F1: 'rot_preset_xy', + key.F2: 'rot_preset_xz', + key.F3: 'rot_preset_yz', + key.F4: 'rot_preset_perspective', + + key.F5: 'toggle_axes', + key.F6: 'toggle_axe_colors', + + key.F8: 'save_image' + } + + def __init__(self, window, *, invert_mouse_zoom=False, **kwargs): + self.invert_mouse_zoom = invert_mouse_zoom + self.window = window + self.camera = window.camera + self.action = { + # Rotation around the view Y (up) vector + 'left': False, + 'right': False, + # Rotation around the view X vector + 'up': False, + 'down': False, + # Rotation around the view Z vector + 'spin_left': False, + 'spin_right': False, + # Rotation around the model Z vector + 'rotate_z_neg': False, + 'rotate_z_pos': False, + # Reset to the default rotation + 'reset_camera': False, + # Performs camera z-translation + 'zoom_in': False, + 'zoom_out': False, + # Use alternative sensitivity (speed) + 'modify_sensitivity': False, + # Rotation presets + 'rot_preset_xy': False, + 'rot_preset_xz': False, + 'rot_preset_yz': False, + 'rot_preset_perspective': False, + # axes + 'toggle_axes': False, + 'toggle_axe_colors': False, + # screenshot + 'save_image': False + } + + def update(self, dt): + z = 0 + if self.action['zoom_out']: + z -= 1 + if self.action['zoom_in']: + z += 1 + if z != 0: + self.camera.zoom_relative(z/10.0, self.get_key_sensitivity()/10.0) + + dx, dy, dz = 0, 0, 0 + if self.action['left']: + dx -= 1 + if self.action['right']: + dx += 1 + if self.action['up']: + dy -= 1 + if self.action['down']: + dy += 1 + if self.action['spin_left']: + dz += 1 + if self.action['spin_right']: + dz -= 1 + + if not self.is_2D(): + if dx != 0: + self.camera.euler_rotate(dx*dt*self.get_key_sensitivity(), + *(get_direction_vectors()[1])) + if dy != 0: + self.camera.euler_rotate(dy*dt*self.get_key_sensitivity(), + *(get_direction_vectors()[0])) + if dz != 0: + self.camera.euler_rotate(dz*dt*self.get_key_sensitivity(), + *(get_direction_vectors()[2])) + else: + self.camera.mouse_translate(0, 0, dx*dt*self.get_key_sensitivity(), + -dy*dt*self.get_key_sensitivity()) + + rz = 0 + if self.action['rotate_z_neg'] and not self.is_2D(): + rz -= 1 + if self.action['rotate_z_pos'] and not self.is_2D(): + rz += 1 + + if rz != 0: + self.camera.euler_rotate(rz*dt*self.get_key_sensitivity(), + *(get_basis_vectors()[2])) + + if self.action['reset_camera']: + self.camera.reset() + + if self.action['rot_preset_xy']: + self.camera.set_rot_preset('xy') + if self.action['rot_preset_xz']: + self.camera.set_rot_preset('xz') + if self.action['rot_preset_yz']: + self.camera.set_rot_preset('yz') + if self.action['rot_preset_perspective']: + self.camera.set_rot_preset('perspective') + + if self.action['toggle_axes']: + self.action['toggle_axes'] = False + self.camera.axes.toggle_visible() + + if self.action['toggle_axe_colors']: + self.action['toggle_axe_colors'] = False + self.camera.axes.toggle_colors() + + if self.action['save_image']: + self.action['save_image'] = False + self.window.plot.saveimage() + + return True + + def get_mouse_sensitivity(self): + if self.action['modify_sensitivity']: + return self.modified_mouse_sensitivity + else: + return self.normal_mouse_sensitivity + + def get_key_sensitivity(self): + if self.action['modify_sensitivity']: + return self.modified_key_sensitivity + else: + return self.normal_key_sensitivity + + def on_key_press(self, symbol, modifiers): + if symbol in self.keymap: + self.action[self.keymap[symbol]] = True + + def on_key_release(self, symbol, modifiers): + if symbol in self.keymap: + self.action[self.keymap[symbol]] = False + + def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers): + if buttons & LEFT: + if self.is_2D(): + self.camera.mouse_translate(x, y, dx, dy) + else: + self.camera.spherical_rotate((x - dx, y - dy), (x, y), + self.get_mouse_sensitivity()) + if buttons & MIDDLE: + self.camera.zoom_relative([1, -1][self.invert_mouse_zoom]*dy, + self.get_mouse_sensitivity()/20.0) + if buttons & RIGHT: + self.camera.mouse_translate(x, y, dx, dy) + + def on_mouse_scroll(self, x, y, dx, dy): + self.camera.zoom_relative([1, -1][self.invert_mouse_zoom]*dy, + self.get_mouse_sensitivity()) + + def is_2D(self): + functions = self.window.plot._functions + for i in functions: + if len(functions[i].i_vars) > 1 or len(functions[i].d_vars) > 2: + return False + return True diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_curve.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_curve.py new file mode 100644 index 0000000000000000000000000000000000000000..6b97dac843f58c76694d424f0b0b7e3499ba5202 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_curve.py @@ -0,0 +1,82 @@ +import pyglet.gl as pgl +from sympy.core import S +from sympy.plotting.pygletplot.plot_mode_base import PlotModeBase + + +class PlotCurve(PlotModeBase): + + style_override = 'wireframe' + + def _on_calculate_verts(self): + self.t_interval = self.intervals[0] + self.t_set = list(self.t_interval.frange()) + self.bounds = [[S.Infinity, S.NegativeInfinity, 0], + [S.Infinity, S.NegativeInfinity, 0], + [S.Infinity, S.NegativeInfinity, 0]] + evaluate = self._get_evaluator() + + self._calculating_verts_pos = 0.0 + self._calculating_verts_len = float(self.t_interval.v_len) + + self.verts = [] + b = self.bounds + for t in self.t_set: + try: + _e = evaluate(t) # calculate vertex + except (NameError, ZeroDivisionError): + _e = None + if _e is not None: # update bounding box + for axis in range(3): + b[axis][0] = min([b[axis][0], _e[axis]]) + b[axis][1] = max([b[axis][1], _e[axis]]) + self.verts.append(_e) + self._calculating_verts_pos += 1.0 + + for axis in range(3): + b[axis][2] = b[axis][1] - b[axis][0] + if b[axis][2] == 0.0: + b[axis][2] = 1.0 + + self.push_wireframe(self.draw_verts(False)) + + def _on_calculate_cverts(self): + if not self.verts or not self.color: + return + + def set_work_len(n): + self._calculating_cverts_len = float(n) + + def inc_work_pos(): + self._calculating_cverts_pos += 1.0 + set_work_len(1) + self._calculating_cverts_pos = 0 + self.cverts = self.color.apply_to_curve(self.verts, + self.t_set, + set_len=set_work_len, + inc_pos=inc_work_pos) + self.push_wireframe(self.draw_verts(True)) + + def calculate_one_cvert(self, t): + vert = self.verts[t] + return self.color(vert[0], vert[1], vert[2], + self.t_set[t], None) + + def draw_verts(self, use_cverts): + def f(): + pgl.glBegin(pgl.GL_LINE_STRIP) + for t in range(len(self.t_set)): + p = self.verts[t] + if p is None: + pgl.glEnd() + pgl.glBegin(pgl.GL_LINE_STRIP) + continue + if use_cverts: + c = self.cverts[t] + if c is None: + c = (0, 0, 0) + pgl.glColor3f(*c) + else: + pgl.glColor3f(*self.default_wireframe_color) + pgl.glVertex3f(*p) + pgl.glEnd() + return f diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_interval.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_interval.py new file mode 100644 index 0000000000000000000000000000000000000000..085ab096915bbc4a3761b71736b4dd14f1ff779f --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_interval.py @@ -0,0 +1,181 @@ +from sympy.core.singleton import S +from sympy.core.symbol import Symbol +from sympy.core.sympify import sympify +from sympy.core.numbers import Integer + + +class PlotInterval: + """ + """ + _v, _v_min, _v_max, _v_steps = None, None, None, None + + def require_all_args(f): + def check(self, *args, **kwargs): + for g in [self._v, self._v_min, self._v_max, self._v_steps]: + if g is None: + raise ValueError("PlotInterval is incomplete.") + return f(self, *args, **kwargs) + return check + + def __init__(self, *args): + if len(args) == 1: + if isinstance(args[0], PlotInterval): + self.fill_from(args[0]) + return + elif isinstance(args[0], str): + try: + args = eval(args[0]) + except TypeError: + s_eval_error = "Could not interpret string %s." + raise ValueError(s_eval_error % (args[0])) + elif isinstance(args[0], (tuple, list)): + args = args[0] + else: + raise ValueError("Not an interval.") + if not isinstance(args, (tuple, list)) or len(args) > 4: + f_error = "PlotInterval must be a tuple or list of length 4 or less." + raise ValueError(f_error) + + args = list(args) + if len(args) > 0 and (args[0] is None or isinstance(args[0], Symbol)): + self.v = args.pop(0) + if len(args) in [2, 3]: + self.v_min = args.pop(0) + self.v_max = args.pop(0) + if len(args) == 1: + self.v_steps = args.pop(0) + elif len(args) == 1: + self.v_steps = args.pop(0) + + def get_v(self): + return self._v + + def set_v(self, v): + if v is None: + self._v = None + return + if not isinstance(v, Symbol): + raise ValueError("v must be a SymPy Symbol.") + self._v = v + + def get_v_min(self): + return self._v_min + + def set_v_min(self, v_min): + if v_min is None: + self._v_min = None + return + try: + self._v_min = sympify(v_min) + float(self._v_min.evalf()) + except TypeError: + raise ValueError("v_min could not be interpreted as a number.") + + def get_v_max(self): + return self._v_max + + def set_v_max(self, v_max): + if v_max is None: + self._v_max = None + return + try: + self._v_max = sympify(v_max) + float(self._v_max.evalf()) + except TypeError: + raise ValueError("v_max could not be interpreted as a number.") + + def get_v_steps(self): + return self._v_steps + + def set_v_steps(self, v_steps): + if v_steps is None: + self._v_steps = None + return + if isinstance(v_steps, int): + v_steps = Integer(v_steps) + elif not isinstance(v_steps, Integer): + raise ValueError("v_steps must be an int or SymPy Integer.") + if v_steps <= S.Zero: + raise ValueError("v_steps must be positive.") + self._v_steps = v_steps + + @require_all_args + def get_v_len(self): + return self.v_steps + 1 + + v = property(get_v, set_v) + v_min = property(get_v_min, set_v_min) + v_max = property(get_v_max, set_v_max) + v_steps = property(get_v_steps, set_v_steps) + v_len = property(get_v_len) + + def fill_from(self, b): + if b.v is not None: + self.v = b.v + if b.v_min is not None: + self.v_min = b.v_min + if b.v_max is not None: + self.v_max = b.v_max + if b.v_steps is not None: + self.v_steps = b.v_steps + + @staticmethod + def try_parse(*args): + """ + Returns a PlotInterval if args can be interpreted + as such, otherwise None. + """ + if len(args) == 1 and isinstance(args[0], PlotInterval): + return args[0] + try: + return PlotInterval(*args) + except ValueError: + return None + + def _str_base(self): + return ",".join([str(self.v), str(self.v_min), + str(self.v_max), str(self.v_steps)]) + + def __repr__(self): + """ + A string representing the interval in class constructor form. + """ + return "PlotInterval(%s)" % (self._str_base()) + + def __str__(self): + """ + A string representing the interval in list form. + """ + return "[%s]" % (self._str_base()) + + @require_all_args + def assert_complete(self): + pass + + @require_all_args + def vrange(self): + """ + Yields v_steps+1 SymPy numbers ranging from + v_min to v_max. + """ + d = (self.v_max - self.v_min) / self.v_steps + for i in range(self.v_steps + 1): + a = self.v_min + (d * Integer(i)) + yield a + + @require_all_args + def vrange2(self): + """ + Yields v_steps pairs of SymPy numbers ranging from + (v_min, v_min + step) to (v_max - step, v_max). + """ + d = (self.v_max - self.v_min) / self.v_steps + a = self.v_min + (d * S.Zero) + for i in range(self.v_steps): + b = self.v_min + (d * Integer(i + 1)) + yield a, b + a = b + + def frange(self): + for i in self.vrange(): + yield float(i.evalf()) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_mode.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_mode.py new file mode 100644 index 0000000000000000000000000000000000000000..f4ee00db9177b98b3259438949836fe5b69416c2 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_mode.py @@ -0,0 +1,400 @@ +from .plot_interval import PlotInterval +from .plot_object import PlotObject +from .util import parse_option_string +from sympy.core.symbol import Symbol +from sympy.core.sympify import sympify +from sympy.geometry.entity import GeometryEntity +from sympy.utilities.iterables import is_sequence + + +class PlotMode(PlotObject): + """ + Grandparent class for plotting + modes. Serves as interface for + registration, lookup, and init + of modes. + + To create a new plot mode, + inherit from PlotModeBase + or one of its children, such + as PlotSurface or PlotCurve. + """ + + ## Class-level attributes + ## used to register and lookup + ## plot modes. See PlotModeBase + ## for descriptions and usage. + + i_vars, d_vars = '', '' + intervals = [] + aliases = [] + is_default = False + + ## Draw is the only method here which + ## is meant to be overridden in child + ## classes, and PlotModeBase provides + ## a base implementation. + def draw(self): + raise NotImplementedError() + + ## Everything else in this file has to + ## do with registration and retrieval + ## of plot modes. This is where I've + ## hidden much of the ugliness of automatic + ## plot mode divination... + + ## Plot mode registry data structures + _mode_alias_list = [] + _mode_map = { + 1: {1: {}, 2: {}}, + 2: {1: {}, 2: {}}, + 3: {1: {}, 2: {}}, + } # [d][i][alias_str]: class + _mode_default_map = { + 1: {}, + 2: {}, + 3: {}, + } # [d][i]: class + _i_var_max, _d_var_max = 2, 3 + + def __new__(cls, *args, **kwargs): + """ + This is the function which interprets + arguments given to Plot.__init__ and + Plot.__setattr__. Returns an initialized + instance of the appropriate child class. + """ + + newargs, newkwargs = PlotMode._extract_options(args, kwargs) + mode_arg = newkwargs.get('mode', '') + + # Interpret the arguments + d_vars, intervals = PlotMode._interpret_args(newargs) + i_vars = PlotMode._find_i_vars(d_vars, intervals) + i, d = max([len(i_vars), len(intervals)]), len(d_vars) + + # Find the appropriate mode + subcls = PlotMode._get_mode(mode_arg, i, d) + + # Create the object + o = object.__new__(subcls) + + # Do some setup for the mode instance + o.d_vars = d_vars + o._fill_i_vars(i_vars) + o._fill_intervals(intervals) + o.options = newkwargs + + return o + + @staticmethod + def _get_mode(mode_arg, i_var_count, d_var_count): + """ + Tries to return an appropriate mode class. + Intended to be called only by __new__. + + mode_arg + Can be a string or a class. If it is a + PlotMode subclass, it is simply returned. + If it is a string, it can an alias for + a mode or an empty string. In the latter + case, we try to find a default mode for + the i_var_count and d_var_count. + + i_var_count + The number of independent variables + needed to evaluate the d_vars. + + d_var_count + The number of dependent variables; + usually the number of functions to + be evaluated in plotting. + + For example, a Cartesian function y = f(x) has + one i_var (x) and one d_var (y). A parametric + form x,y,z = f(u,v), f(u,v), f(u,v) has two + two i_vars (u,v) and three d_vars (x,y,z). + """ + # if the mode_arg is simply a PlotMode class, + # check that the mode supports the numbers + # of independent and dependent vars, then + # return it + try: + m = None + if issubclass(mode_arg, PlotMode): + m = mode_arg + except TypeError: + pass + if m: + if not m._was_initialized: + raise ValueError(("To use unregistered plot mode %s " + "you must first call %s._init_mode().") + % (m.__name__, m.__name__)) + if d_var_count != m.d_var_count: + raise ValueError(("%s can only plot functions " + "with %i dependent variables.") + % (m.__name__, + m.d_var_count)) + if i_var_count > m.i_var_count: + raise ValueError(("%s cannot plot functions " + "with more than %i independent " + "variables.") + % (m.__name__, + m.i_var_count)) + return m + # If it is a string, there are two possibilities. + if isinstance(mode_arg, str): + i, d = i_var_count, d_var_count + if i > PlotMode._i_var_max: + raise ValueError(var_count_error(True, True)) + if d > PlotMode._d_var_max: + raise ValueError(var_count_error(False, True)) + # If the string is '', try to find a suitable + # default mode + if not mode_arg: + return PlotMode._get_default_mode(i, d) + # Otherwise, interpret the string as a mode + # alias (e.g. 'cartesian', 'parametric', etc) + else: + return PlotMode._get_aliased_mode(mode_arg, i, d) + else: + raise ValueError("PlotMode argument must be " + "a class or a string") + + @staticmethod + def _get_default_mode(i, d, i_vars=-1): + if i_vars == -1: + i_vars = i + try: + return PlotMode._mode_default_map[d][i] + except KeyError: + # Keep looking for modes in higher i var counts + # which support the given d var count until we + # reach the max i_var count. + if i < PlotMode._i_var_max: + return PlotMode._get_default_mode(i + 1, d, i_vars) + else: + raise ValueError(("Couldn't find a default mode " + "for %i independent and %i " + "dependent variables.") % (i_vars, d)) + + @staticmethod + def _get_aliased_mode(alias, i, d, i_vars=-1): + if i_vars == -1: + i_vars = i + if alias not in PlotMode._mode_alias_list: + raise ValueError(("Couldn't find a mode called" + " %s. Known modes: %s.") + % (alias, ", ".join(PlotMode._mode_alias_list))) + try: + return PlotMode._mode_map[d][i][alias] + except TypeError: + # Keep looking for modes in higher i var counts + # which support the given d var count and alias + # until we reach the max i_var count. + if i < PlotMode._i_var_max: + return PlotMode._get_aliased_mode(alias, i + 1, d, i_vars) + else: + raise ValueError(("Couldn't find a %s mode " + "for %i independent and %i " + "dependent variables.") + % (alias, i_vars, d)) + + @classmethod + def _register(cls): + """ + Called once for each user-usable plot mode. + For Cartesian2D, it is invoked after the + class definition: Cartesian2D._register() + """ + name = cls.__name__ + cls._init_mode() + + try: + i, d = cls.i_var_count, cls.d_var_count + # Add the mode to _mode_map under all + # given aliases + for a in cls.aliases: + if a not in PlotMode._mode_alias_list: + # Also track valid aliases, so + # we can quickly know when given + # an invalid one in _get_mode. + PlotMode._mode_alias_list.append(a) + PlotMode._mode_map[d][i][a] = cls + if cls.is_default: + # If this mode was marked as the + # default for this d,i combination, + # also set that. + PlotMode._mode_default_map[d][i] = cls + + except Exception as e: + raise RuntimeError(("Failed to register " + "plot mode %s. Reason: %s") + % (name, (str(e)))) + + @classmethod + def _init_mode(cls): + """ + Initializes the plot mode based on + the 'mode-specific parameters' above. + Only intended to be called by + PlotMode._register(). To use a mode without + registering it, you can directly call + ModeSubclass._init_mode(). + """ + def symbols_list(symbol_str): + return [Symbol(s) for s in symbol_str] + + # Convert the vars strs into + # lists of symbols. + cls.i_vars = symbols_list(cls.i_vars) + cls.d_vars = symbols_list(cls.d_vars) + + # Var count is used often, calculate + # it once here + cls.i_var_count = len(cls.i_vars) + cls.d_var_count = len(cls.d_vars) + + if cls.i_var_count > PlotMode._i_var_max: + raise ValueError(var_count_error(True, False)) + if cls.d_var_count > PlotMode._d_var_max: + raise ValueError(var_count_error(False, False)) + + # Try to use first alias as primary_alias + if len(cls.aliases) > 0: + cls.primary_alias = cls.aliases[0] + else: + cls.primary_alias = cls.__name__ + + di = cls.intervals + if len(di) != cls.i_var_count: + raise ValueError("Plot mode must provide a " + "default interval for each i_var.") + for i in range(cls.i_var_count): + # default intervals must be given [min,max,steps] + # (no var, but they must be in the same order as i_vars) + if len(di[i]) != 3: + raise ValueError("length should be equal to 3") + + # Initialize an incomplete interval, + # to later be filled with a var when + # the mode is instantiated. + di[i] = PlotInterval(None, *di[i]) + + # To prevent people from using modes + # without these required fields set up. + cls._was_initialized = True + + _was_initialized = False + + ## Initializer Helper Methods + + @staticmethod + def _find_i_vars(functions, intervals): + i_vars = [] + + # First, collect i_vars in the + # order they are given in any + # intervals. + for i in intervals: + if i.v is None: + continue + elif i.v in i_vars: + raise ValueError(("Multiple intervals given " + "for %s.") % (str(i.v))) + i_vars.append(i.v) + + # Then, find any remaining + # i_vars in given functions + # (aka d_vars) + for f in functions: + for a in f.free_symbols: + if a not in i_vars: + i_vars.append(a) + + return i_vars + + def _fill_i_vars(self, i_vars): + # copy default i_vars + self.i_vars = [Symbol(str(i)) for i in self.i_vars] + # replace with given i_vars + for i in range(len(i_vars)): + self.i_vars[i] = i_vars[i] + + def _fill_intervals(self, intervals): + # copy default intervals + self.intervals = [PlotInterval(i) for i in self.intervals] + # track i_vars used so far + v_used = [] + # fill copy of default + # intervals with given info + for i in range(len(intervals)): + self.intervals[i].fill_from(intervals[i]) + if self.intervals[i].v is not None: + v_used.append(self.intervals[i].v) + # Find any orphan intervals and + # assign them i_vars + for i in range(len(self.intervals)): + if self.intervals[i].v is None: + u = [v for v in self.i_vars if v not in v_used] + if len(u) == 0: + raise ValueError("length should not be equal to 0") + self.intervals[i].v = u[0] + v_used.append(u[0]) + + @staticmethod + def _interpret_args(args): + interval_wrong_order = "PlotInterval %s was given before any function(s)." + interpret_error = "Could not interpret %s as a function or interval." + + functions, intervals = [], [] + if isinstance(args[0], GeometryEntity): + for coords in list(args[0].arbitrary_point()): + functions.append(coords) + intervals.append(PlotInterval.try_parse(args[0].plot_interval())) + else: + for a in args: + i = PlotInterval.try_parse(a) + if i is not None: + if len(functions) == 0: + raise ValueError(interval_wrong_order % (str(i))) + else: + intervals.append(i) + else: + if is_sequence(a, include=str): + raise ValueError(interpret_error % (str(a))) + try: + f = sympify(a) + functions.append(f) + except TypeError: + raise ValueError(interpret_error % str(a)) + + return functions, intervals + + @staticmethod + def _extract_options(args, kwargs): + newkwargs, newargs = {}, [] + for a in args: + if isinstance(a, str): + newkwargs = dict(newkwargs, **parse_option_string(a)) + else: + newargs.append(a) + newkwargs = dict(newkwargs, **kwargs) + return newargs, newkwargs + + +def var_count_error(is_independent, is_plotting): + """ + Used to format an error message which differs + slightly in 4 places. + """ + if is_plotting: + v = "Plotting" + else: + v = "Registering plot modes" + if is_independent: + n, s = PlotMode._i_var_max, "independent" + else: + n, s = PlotMode._d_var_max, "dependent" + return ("%s with more than %i %s variables " + "is not supported.") % (v, n, s) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_mode_base.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_mode_base.py new file mode 100644 index 0000000000000000000000000000000000000000..2c6503650afda122e271bdecb2365c8fa20f2376 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_mode_base.py @@ -0,0 +1,378 @@ +import pyglet.gl as pgl +from sympy.core import S +from sympy.plotting.pygletplot.color_scheme import ColorScheme +from sympy.plotting.pygletplot.plot_mode import PlotMode +from sympy.utilities.iterables import is_sequence +from time import sleep +from threading import Thread, Event, RLock +import warnings + + +class PlotModeBase(PlotMode): + """ + Intended parent class for plotting + modes. Provides base functionality + in conjunction with its parent, + PlotMode. + """ + + ## + ## Class-Level Attributes + ## + + """ + The following attributes are meant + to be set at the class level, and serve + as parameters to the plot mode registry + (in PlotMode). See plot_modes.py for + concrete examples. + """ + + """ + i_vars + 'x' for Cartesian2D + 'xy' for Cartesian3D + etc. + + d_vars + 'y' for Cartesian2D + 'r' for Polar + etc. + """ + i_vars, d_vars = '', '' + + """ + intervals + Default intervals for each i_var, and in the + same order. Specified [min, max, steps]. + No variable can be given (it is bound later). + """ + intervals = [] + + """ + aliases + A list of strings which can be used to + access this mode. + 'cartesian' for Cartesian2D and Cartesian3D + 'polar' for Polar + 'cylindrical', 'polar' for Cylindrical + + Note that _init_mode chooses the first alias + in the list as the mode's primary_alias, which + will be displayed to the end user in certain + contexts. + """ + aliases = [] + + """ + is_default + Whether to set this mode as the default + for arguments passed to PlotMode() containing + the same number of d_vars as this mode and + at most the same number of i_vars. + """ + is_default = False + + """ + All of the above attributes are defined in PlotMode. + The following ones are specific to PlotModeBase. + """ + + """ + A list of the render styles. Do not modify. + """ + styles = {'wireframe': 1, 'solid': 2, 'both': 3} + + """ + style_override + Always use this style if not blank. + """ + style_override = '' + + """ + default_wireframe_color + default_solid_color + Can be used when color is None or being calculated. + Used by PlotCurve and PlotSurface, but not anywhere + in PlotModeBase. + """ + + default_wireframe_color = (0.85, 0.85, 0.85) + default_solid_color = (0.6, 0.6, 0.9) + default_rot_preset = 'xy' + + ## + ## Instance-Level Attributes + ## + + ## 'Abstract' member functions + def _get_evaluator(self): + if self.use_lambda_eval: + try: + e = self._get_lambda_evaluator() + return e + except Exception: + warnings.warn("\nWarning: creating lambda evaluator failed. " + "Falling back on SymPy subs evaluator.") + return self._get_sympy_evaluator() + + def _get_sympy_evaluator(self): + raise NotImplementedError() + + def _get_lambda_evaluator(self): + raise NotImplementedError() + + def _on_calculate_verts(self): + raise NotImplementedError() + + def _on_calculate_cverts(self): + raise NotImplementedError() + + ## Base member functions + def __init__(self, *args, bounds_callback=None, **kwargs): + self.verts = [] + self.cverts = [] + self.bounds = [[S.Infinity, S.NegativeInfinity, 0], + [S.Infinity, S.NegativeInfinity, 0], + [S.Infinity, S.NegativeInfinity, 0]] + self.cbounds = [[S.Infinity, S.NegativeInfinity, 0], + [S.Infinity, S.NegativeInfinity, 0], + [S.Infinity, S.NegativeInfinity, 0]] + + self._draw_lock = RLock() + + self._calculating_verts = Event() + self._calculating_cverts = Event() + self._calculating_verts_pos = 0.0 + self._calculating_verts_len = 0.0 + self._calculating_cverts_pos = 0.0 + self._calculating_cverts_len = 0.0 + + self._max_render_stack_size = 3 + self._draw_wireframe = [-1] + self._draw_solid = [-1] + + self._style = None + self._color = None + + self.predraw = [] + self.postdraw = [] + + self.use_lambda_eval = self.options.pop('use_sympy_eval', None) is None + self.style = self.options.pop('style', '') + self.color = self.options.pop('color', 'rainbow') + self.bounds_callback = bounds_callback + + self._on_calculate() + + def synchronized(f): + def w(self, *args, **kwargs): + self._draw_lock.acquire() + try: + r = f(self, *args, **kwargs) + return r + finally: + self._draw_lock.release() + return w + + @synchronized + def push_wireframe(self, function): + """ + Push a function which performs gl commands + used to build a display list. (The list is + built outside of the function) + """ + assert callable(function) + self._draw_wireframe.append(function) + if len(self._draw_wireframe) > self._max_render_stack_size: + del self._draw_wireframe[1] # leave marker element + + @synchronized + def push_solid(self, function): + """ + Push a function which performs gl commands + used to build a display list. (The list is + built outside of the function) + """ + assert callable(function) + self._draw_solid.append(function) + if len(self._draw_solid) > self._max_render_stack_size: + del self._draw_solid[1] # leave marker element + + def _create_display_list(self, function): + dl = pgl.glGenLists(1) + pgl.glNewList(dl, pgl.GL_COMPILE) + function() + pgl.glEndList() + return dl + + def _render_stack_top(self, render_stack): + top = render_stack[-1] + if top == -1: + return -1 # nothing to display + elif callable(top): + dl = self._create_display_list(top) + render_stack[-1] = (dl, top) + return dl # display newly added list + elif len(top) == 2: + if pgl.GL_TRUE == pgl.glIsList(top[0]): + return top[0] # display stored list + dl = self._create_display_list(top[1]) + render_stack[-1] = (dl, top[1]) + return dl # display regenerated list + + def _draw_solid_display_list(self, dl): + pgl.glPushAttrib(pgl.GL_ENABLE_BIT | pgl.GL_POLYGON_BIT) + pgl.glPolygonMode(pgl.GL_FRONT_AND_BACK, pgl.GL_FILL) + pgl.glCallList(dl) + pgl.glPopAttrib() + + def _draw_wireframe_display_list(self, dl): + pgl.glPushAttrib(pgl.GL_ENABLE_BIT | pgl.GL_POLYGON_BIT) + pgl.glPolygonMode(pgl.GL_FRONT_AND_BACK, pgl.GL_LINE) + pgl.glEnable(pgl.GL_POLYGON_OFFSET_LINE) + pgl.glPolygonOffset(-0.005, -50.0) + pgl.glCallList(dl) + pgl.glPopAttrib() + + @synchronized + def draw(self): + for f in self.predraw: + if callable(f): + f() + if self.style_override: + style = self.styles[self.style_override] + else: + style = self.styles[self._style] + # Draw solid component if style includes solid + if style & 2: + dl = self._render_stack_top(self._draw_solid) + if dl > 0 and pgl.GL_TRUE == pgl.glIsList(dl): + self._draw_solid_display_list(dl) + # Draw wireframe component if style includes wireframe + if style & 1: + dl = self._render_stack_top(self._draw_wireframe) + if dl > 0 and pgl.GL_TRUE == pgl.glIsList(dl): + self._draw_wireframe_display_list(dl) + for f in self.postdraw: + if callable(f): + f() + + def _on_change_color(self, color): + Thread(target=self._calculate_cverts).start() + + def _on_calculate(self): + Thread(target=self._calculate_all).start() + + def _calculate_all(self): + self._calculate_verts() + self._calculate_cverts() + + def _calculate_verts(self): + if self._calculating_verts.is_set(): + return + self._calculating_verts.set() + try: + self._on_calculate_verts() + finally: + self._calculating_verts.clear() + if callable(self.bounds_callback): + self.bounds_callback() + + def _calculate_cverts(self): + if self._calculating_verts.is_set(): + return + while self._calculating_cverts.is_set(): + sleep(0) # wait for previous calculation + self._calculating_cverts.set() + try: + self._on_calculate_cverts() + finally: + self._calculating_cverts.clear() + + def _get_calculating_verts(self): + return self._calculating_verts.is_set() + + def _get_calculating_verts_pos(self): + return self._calculating_verts_pos + + def _get_calculating_verts_len(self): + return self._calculating_verts_len + + def _get_calculating_cverts(self): + return self._calculating_cverts.is_set() + + def _get_calculating_cverts_pos(self): + return self._calculating_cverts_pos + + def _get_calculating_cverts_len(self): + return self._calculating_cverts_len + + ## Property handlers + def _get_style(self): + return self._style + + @synchronized + def _set_style(self, v): + if v is None: + return + if v == '': + step_max = 0 + for i in self.intervals: + if i.v_steps is None: + continue + step_max = max([step_max, int(i.v_steps)]) + v = ['both', 'solid'][step_max > 40] + if v not in self.styles: + raise ValueError("v should be there in self.styles") + if v == self._style: + return + self._style = v + + def _get_color(self): + return self._color + + @synchronized + def _set_color(self, v): + try: + if v is not None: + if is_sequence(v): + v = ColorScheme(*v) + else: + v = ColorScheme(v) + if repr(v) == repr(self._color): + return + self._on_change_color(v) + self._color = v + except Exception as e: + raise RuntimeError("Color change failed. " + "Reason: %s" % (str(e))) + + style = property(_get_style, _set_style) + color = property(_get_color, _set_color) + + calculating_verts = property(_get_calculating_verts) + calculating_verts_pos = property(_get_calculating_verts_pos) + calculating_verts_len = property(_get_calculating_verts_len) + + calculating_cverts = property(_get_calculating_cverts) + calculating_cverts_pos = property(_get_calculating_cverts_pos) + calculating_cverts_len = property(_get_calculating_cverts_len) + + ## String representations + + def __str__(self): + f = ", ".join(str(d) for d in self.d_vars) + o = "'mode=%s'" % (self.primary_alias) + return ", ".join([f, o]) + + def __repr__(self): + f = ", ".join(str(d) for d in self.d_vars) + i = ", ".join(str(i) for i in self.intervals) + d = [('mode', self.primary_alias), + ('color', str(self.color)), + ('style', str(self.style))] + + o = "'%s'" % ("; ".join("%s=%s" % (k, v) + for k, v in d if v != 'None')) + return ", ".join([f, i, o]) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_modes.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_modes.py new file mode 100644 index 0000000000000000000000000000000000000000..e78e0b4ce291b071f684fa3ffc02f456dffe0023 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_modes.py @@ -0,0 +1,209 @@ +from sympy.utilities.lambdify import lambdify +from sympy.core.numbers import pi +from sympy.functions import sin, cos +from sympy.plotting.pygletplot.plot_curve import PlotCurve +from sympy.plotting.pygletplot.plot_surface import PlotSurface + +from math import sin as p_sin +from math import cos as p_cos + + +def float_vec3(f): + def inner(*args): + v = f(*args) + return float(v[0]), float(v[1]), float(v[2]) + return inner + + +class Cartesian2D(PlotCurve): + i_vars, d_vars = 'x', 'y' + intervals = [[-5, 5, 100]] + aliases = ['cartesian'] + is_default = True + + def _get_sympy_evaluator(self): + fy = self.d_vars[0] + x = self.t_interval.v + + @float_vec3 + def e(_x): + return (_x, fy.subs(x, _x), 0.0) + return e + + def _get_lambda_evaluator(self): + fy = self.d_vars[0] + x = self.t_interval.v + return lambdify([x], [x, fy, 0.0]) + + +class Cartesian3D(PlotSurface): + i_vars, d_vars = 'xy', 'z' + intervals = [[-1, 1, 40], [-1, 1, 40]] + aliases = ['cartesian', 'monge'] + is_default = True + + def _get_sympy_evaluator(self): + fz = self.d_vars[0] + x = self.u_interval.v + y = self.v_interval.v + + @float_vec3 + def e(_x, _y): + return (_x, _y, fz.subs(x, _x).subs(y, _y)) + return e + + def _get_lambda_evaluator(self): + fz = self.d_vars[0] + x = self.u_interval.v + y = self.v_interval.v + return lambdify([x, y], [x, y, fz]) + + +class ParametricCurve2D(PlotCurve): + i_vars, d_vars = 't', 'xy' + intervals = [[0, 2*pi, 100]] + aliases = ['parametric'] + is_default = True + + def _get_sympy_evaluator(self): + fx, fy = self.d_vars + t = self.t_interval.v + + @float_vec3 + def e(_t): + return (fx.subs(t, _t), fy.subs(t, _t), 0.0) + return e + + def _get_lambda_evaluator(self): + fx, fy = self.d_vars + t = self.t_interval.v + return lambdify([t], [fx, fy, 0.0]) + + +class ParametricCurve3D(PlotCurve): + i_vars, d_vars = 't', 'xyz' + intervals = [[0, 2*pi, 100]] + aliases = ['parametric'] + is_default = True + + def _get_sympy_evaluator(self): + fx, fy, fz = self.d_vars + t = self.t_interval.v + + @float_vec3 + def e(_t): + return (fx.subs(t, _t), fy.subs(t, _t), fz.subs(t, _t)) + return e + + def _get_lambda_evaluator(self): + fx, fy, fz = self.d_vars + t = self.t_interval.v + return lambdify([t], [fx, fy, fz]) + + +class ParametricSurface(PlotSurface): + i_vars, d_vars = 'uv', 'xyz' + intervals = [[-1, 1, 40], [-1, 1, 40]] + aliases = ['parametric'] + is_default = True + + def _get_sympy_evaluator(self): + fx, fy, fz = self.d_vars + u = self.u_interval.v + v = self.v_interval.v + + @float_vec3 + def e(_u, _v): + return (fx.subs(u, _u).subs(v, _v), + fy.subs(u, _u).subs(v, _v), + fz.subs(u, _u).subs(v, _v)) + return e + + def _get_lambda_evaluator(self): + fx, fy, fz = self.d_vars + u = self.u_interval.v + v = self.v_interval.v + return lambdify([u, v], [fx, fy, fz]) + + +class Polar(PlotCurve): + i_vars, d_vars = 't', 'r' + intervals = [[0, 2*pi, 100]] + aliases = ['polar'] + is_default = False + + def _get_sympy_evaluator(self): + fr = self.d_vars[0] + t = self.t_interval.v + + def e(_t): + _r = float(fr.subs(t, _t)) + return (_r*p_cos(_t), _r*p_sin(_t), 0.0) + return e + + def _get_lambda_evaluator(self): + fr = self.d_vars[0] + t = self.t_interval.v + fx, fy = fr*cos(t), fr*sin(t) + return lambdify([t], [fx, fy, 0.0]) + + +class Cylindrical(PlotSurface): + i_vars, d_vars = 'th', 'r' + intervals = [[0, 2*pi, 40], [-1, 1, 20]] + aliases = ['cylindrical', 'polar'] + is_default = False + + def _get_sympy_evaluator(self): + fr = self.d_vars[0] + t = self.u_interval.v + h = self.v_interval.v + + def e(_t, _h): + _r = float(fr.subs(t, _t).subs(h, _h)) + return (_r*p_cos(_t), _r*p_sin(_t), _h) + return e + + def _get_lambda_evaluator(self): + fr = self.d_vars[0] + t = self.u_interval.v + h = self.v_interval.v + fx, fy = fr*cos(t), fr*sin(t) + return lambdify([t, h], [fx, fy, h]) + + +class Spherical(PlotSurface): + i_vars, d_vars = 'tp', 'r' + intervals = [[0, 2*pi, 40], [0, pi, 20]] + aliases = ['spherical'] + is_default = False + + def _get_sympy_evaluator(self): + fr = self.d_vars[0] + t = self.u_interval.v + p = self.v_interval.v + + def e(_t, _p): + _r = float(fr.subs(t, _t).subs(p, _p)) + return (_r*p_cos(_t)*p_sin(_p), + _r*p_sin(_t)*p_sin(_p), + _r*p_cos(_p)) + return e + + def _get_lambda_evaluator(self): + fr = self.d_vars[0] + t = self.u_interval.v + p = self.v_interval.v + fx = fr * cos(t) * sin(p) + fy = fr * sin(t) * sin(p) + fz = fr * cos(p) + return lambdify([t, p], [fx, fy, fz]) + +Cartesian2D._register() +Cartesian3D._register() +ParametricCurve2D._register() +ParametricCurve3D._register() +ParametricSurface._register() +Polar._register() +Cylindrical._register() +Spherical._register() diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_object.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_object.py new file mode 100644 index 0000000000000000000000000000000000000000..e51040fb8b1a52c49d849b96692f6c0dba329d75 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_object.py @@ -0,0 +1,17 @@ +class PlotObject: + """ + Base class for objects which can be displayed in + a Plot. + """ + visible = True + + def _draw(self): + if self.visible: + self.draw() + + def draw(self): + """ + OpenGL rendering code for the plot object. + Override in base class. + """ + pass diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_rotation.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_rotation.py new file mode 100644 index 0000000000000000000000000000000000000000..11ede2d1c3e74e5470cf601348e494c35720b9a8 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_rotation.py @@ -0,0 +1,68 @@ +try: + from ctypes import c_float +except ImportError: + pass + +import pyglet.gl as pgl +from math import sqrt as _sqrt, acos as _acos, pi + + +def cross(a, b): + return (a[1] * b[2] - a[2] * b[1], + a[2] * b[0] - a[0] * b[2], + a[0] * b[1] - a[1] * b[0]) + + +def dot(a, b): + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + + +def mag(a): + return _sqrt(a[0]**2 + a[1]**2 + a[2]**2) + + +def norm(a): + m = mag(a) + return (a[0] / m, a[1] / m, a[2] / m) + + +def get_sphere_mapping(x, y, width, height): + x = min([max([x, 0]), width]) + y = min([max([y, 0]), height]) + + sr = _sqrt((width/2)**2 + (height/2)**2) + sx = ((x - width / 2) / sr) + sy = ((y - height / 2) / sr) + + sz = 1.0 - sx**2 - sy**2 + + if sz > 0.0: + sz = _sqrt(sz) + return (sx, sy, sz) + else: + sz = 0 + return norm((sx, sy, sz)) + +rad2deg = 180.0 / pi + + +def get_spherical_rotatation(p1, p2, width, height, theta_multiplier): + v1 = get_sphere_mapping(p1[0], p1[1], width, height) + v2 = get_sphere_mapping(p2[0], p2[1], width, height) + + d = min(max([dot(v1, v2), -1]), 1) + + if abs(d - 1.0) < 0.000001: + return None + + raxis = norm( cross(v1, v2) ) + rtheta = theta_multiplier * rad2deg * _acos(d) + + pgl.glPushMatrix() + pgl.glLoadIdentity() + pgl.glRotatef(rtheta, *raxis) + mat = (c_float*16)() + pgl.glGetFloatv(pgl.GL_MODELVIEW_MATRIX, mat) + pgl.glPopMatrix() + + return mat diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_surface.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_surface.py new file mode 100644 index 0000000000000000000000000000000000000000..ed421eebb441d193f4d9b763f56e146c11e5a42c --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_surface.py @@ -0,0 +1,102 @@ +import pyglet.gl as pgl + +from sympy.core import S +from sympy.plotting.pygletplot.plot_mode_base import PlotModeBase + + +class PlotSurface(PlotModeBase): + + default_rot_preset = 'perspective' + + def _on_calculate_verts(self): + self.u_interval = self.intervals[0] + self.u_set = list(self.u_interval.frange()) + self.v_interval = self.intervals[1] + self.v_set = list(self.v_interval.frange()) + self.bounds = [[S.Infinity, S.NegativeInfinity, 0], + [S.Infinity, S.NegativeInfinity, 0], + [S.Infinity, S.NegativeInfinity, 0]] + evaluate = self._get_evaluator() + + self._calculating_verts_pos = 0.0 + self._calculating_verts_len = float( + self.u_interval.v_len*self.v_interval.v_len) + + verts = [] + b = self.bounds + for u in self.u_set: + column = [] + for v in self.v_set: + try: + _e = evaluate(u, v) # calculate vertex + except ZeroDivisionError: + _e = None + if _e is not None: # update bounding box + for axis in range(3): + b[axis][0] = min([b[axis][0], _e[axis]]) + b[axis][1] = max([b[axis][1], _e[axis]]) + column.append(_e) + self._calculating_verts_pos += 1.0 + + verts.append(column) + for axis in range(3): + b[axis][2] = b[axis][1] - b[axis][0] + if b[axis][2] == 0.0: + b[axis][2] = 1.0 + + self.verts = verts + self.push_wireframe(self.draw_verts(False, False)) + self.push_solid(self.draw_verts(False, True)) + + def _on_calculate_cverts(self): + if not self.verts or not self.color: + return + + def set_work_len(n): + self._calculating_cverts_len = float(n) + + def inc_work_pos(): + self._calculating_cverts_pos += 1.0 + set_work_len(1) + self._calculating_cverts_pos = 0 + self.cverts = self.color.apply_to_surface(self.verts, + self.u_set, + self.v_set, + set_len=set_work_len, + inc_pos=inc_work_pos) + self.push_solid(self.draw_verts(True, True)) + + def calculate_one_cvert(self, u, v): + vert = self.verts[u][v] + return self.color(vert[0], vert[1], vert[2], + self.u_set[u], self.v_set[v]) + + def draw_verts(self, use_cverts, use_solid_color): + def f(): + for u in range(1, len(self.u_set)): + pgl.glBegin(pgl.GL_QUAD_STRIP) + for v in range(len(self.v_set)): + pa = self.verts[u - 1][v] + pb = self.verts[u][v] + if pa is None or pb is None: + pgl.glEnd() + pgl.glBegin(pgl.GL_QUAD_STRIP) + continue + if use_cverts: + ca = self.cverts[u - 1][v] + cb = self.cverts[u][v] + if ca is None: + ca = (0, 0, 0) + if cb is None: + cb = (0, 0, 0) + else: + if use_solid_color: + ca = cb = self.default_solid_color + else: + ca = cb = self.default_wireframe_color + pgl.glColor3f(*ca) + pgl.glVertex3f(*pa) + pgl.glColor3f(*cb) + pgl.glVertex3f(*pb) + pgl.glEnd() + return f diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_window.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_window.py new file mode 100644 index 0000000000000000000000000000000000000000..d9df4cc453acb05d7c2d871e9e8efeb36905de5d --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/plot_window.py @@ -0,0 +1,144 @@ +from time import perf_counter + + +import pyglet.gl as pgl + +from sympy.plotting.pygletplot.managed_window import ManagedWindow +from sympy.plotting.pygletplot.plot_camera import PlotCamera +from sympy.plotting.pygletplot.plot_controller import PlotController + + +class PlotWindow(ManagedWindow): + + def __init__(self, plot, antialiasing=True, ortho=False, + invert_mouse_zoom=False, linewidth=1.5, caption="SymPy Plot", + **kwargs): + """ + Named Arguments + =============== + + antialiasing = True + True OR False + ortho = False + True OR False + invert_mouse_zoom = False + True OR False + """ + self.plot = plot + + self.camera = None + self._calculating = False + + self.antialiasing = antialiasing + self.ortho = ortho + self.invert_mouse_zoom = invert_mouse_zoom + self.linewidth = linewidth + self.title = caption + self.last_caption_update = 0 + self.caption_update_interval = 0.2 + self.drawing_first_object = True + + super().__init__(**kwargs) + + def setup(self): + self.camera = PlotCamera(self, ortho=self.ortho) + self.controller = PlotController(self, + invert_mouse_zoom=self.invert_mouse_zoom) + self.push_handlers(self.controller) + + pgl.glClearColor(1.0, 1.0, 1.0, 0.0) + pgl.glClearDepth(1.0) + + pgl.glDepthFunc(pgl.GL_LESS) + pgl.glEnable(pgl.GL_DEPTH_TEST) + + pgl.glEnable(pgl.GL_LINE_SMOOTH) + pgl.glShadeModel(pgl.GL_SMOOTH) + pgl.glLineWidth(self.linewidth) + + pgl.glEnable(pgl.GL_BLEND) + pgl.glBlendFunc(pgl.GL_SRC_ALPHA, pgl.GL_ONE_MINUS_SRC_ALPHA) + + if self.antialiasing: + pgl.glHint(pgl.GL_LINE_SMOOTH_HINT, pgl.GL_NICEST) + pgl.glHint(pgl.GL_POLYGON_SMOOTH_HINT, pgl.GL_NICEST) + + self.camera.setup_projection() + + def on_resize(self, w, h): + super().on_resize(w, h) + if self.camera is not None: + self.camera.setup_projection() + + def update(self, dt): + self.controller.update(dt) + + def draw(self): + self.plot._render_lock.acquire() + self.camera.apply_transformation() + + calc_verts_pos, calc_verts_len = 0, 0 + calc_cverts_pos, calc_cverts_len = 0, 0 + + should_update_caption = (perf_counter() - self.last_caption_update > + self.caption_update_interval) + + if len(self.plot._functions.values()) == 0: + self.drawing_first_object = True + + iterfunctions = iter(self.plot._functions.values()) + + for r in iterfunctions: + if self.drawing_first_object: + self.camera.set_rot_preset(r.default_rot_preset) + self.drawing_first_object = False + + pgl.glPushMatrix() + r._draw() + pgl.glPopMatrix() + + # might as well do this while we are + # iterating and have the lock rather + # than locking and iterating twice + # per frame: + + if should_update_caption: + try: + if r.calculating_verts: + calc_verts_pos += r.calculating_verts_pos + calc_verts_len += r.calculating_verts_len + if r.calculating_cverts: + calc_cverts_pos += r.calculating_cverts_pos + calc_cverts_len += r.calculating_cverts_len + except ValueError: + pass + + for r in self.plot._pobjects: + pgl.glPushMatrix() + r._draw() + pgl.glPopMatrix() + + if should_update_caption: + self.update_caption(calc_verts_pos, calc_verts_len, + calc_cverts_pos, calc_cverts_len) + self.last_caption_update = perf_counter() + + if self.plot._screenshot: + self.plot._screenshot._execute_saving() + + self.plot._render_lock.release() + + def update_caption(self, calc_verts_pos, calc_verts_len, + calc_cverts_pos, calc_cverts_len): + caption = self.title + if calc_verts_len or calc_cverts_len: + caption += " (calculating" + if calc_verts_len > 0: + p = (calc_verts_pos / calc_verts_len) * 100 + caption += " vertices %i%%" % (p) + if calc_cverts_len > 0: + p = (calc_cverts_pos / calc_cverts_len) * 100 + caption += " colors %i%%" % (p) + caption += ")" + if self.caption != caption: + self.set_caption(caption) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..984bf068d4ca52f558a90394da812d74e83df4bf Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/tests/__pycache__/test_plotting.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/tests/__pycache__/test_plotting.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e290d5f2d3c16412df7e6df24e5afb7dc6ea2ec8 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/tests/__pycache__/test_plotting.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/tests/test_plotting.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/tests/test_plotting.py new file mode 100644 index 0000000000000000000000000000000000000000..ddc4aaf3621a8c9056ce0d81c89ca6a0a681bbdb --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/tests/test_plotting.py @@ -0,0 +1,88 @@ +from sympy.external.importtools import import_module + +disabled = False + +# if pyglet.gl fails to import, e.g. opengl is missing, we disable the tests +pyglet_gl = import_module("pyglet.gl", catch=(OSError,)) +pyglet_window = import_module("pyglet.window", catch=(OSError,)) +if not pyglet_gl or not pyglet_window: + disabled = True + + +from sympy.core.symbol import symbols +from sympy.functions.elementary.exponential import log +from sympy.functions.elementary.trigonometric import (cos, sin) +x, y, z = symbols('x, y, z') + + +def test_plot_2d(): + from sympy.plotting.pygletplot import PygletPlot + p = PygletPlot(x, [x, -5, 5, 4], visible=False) + p.wait_for_calculations() + + +def test_plot_2d_discontinuous(): + from sympy.plotting.pygletplot import PygletPlot + p = PygletPlot(1/x, [x, -1, 1, 2], visible=False) + p.wait_for_calculations() + + +def test_plot_3d(): + from sympy.plotting.pygletplot import PygletPlot + p = PygletPlot(x*y, [x, -5, 5, 5], [y, -5, 5, 5], visible=False) + p.wait_for_calculations() + + +def test_plot_3d_discontinuous(): + from sympy.plotting.pygletplot import PygletPlot + p = PygletPlot(1/x, [x, -3, 3, 6], [y, -1, 1, 1], visible=False) + p.wait_for_calculations() + + +def test_plot_2d_polar(): + from sympy.plotting.pygletplot import PygletPlot + p = PygletPlot(1/x, [x, -1, 1, 4], 'mode=polar', visible=False) + p.wait_for_calculations() + + +def test_plot_3d_cylinder(): + from sympy.plotting.pygletplot import PygletPlot + p = PygletPlot( + 1/y, [x, 0, 6.282, 4], [y, -1, 1, 4], 'mode=polar;style=solid', + visible=False) + p.wait_for_calculations() + + +def test_plot_3d_spherical(): + from sympy.plotting.pygletplot import PygletPlot + p = PygletPlot( + 1, [x, 0, 6.282, 4], [y, 0, 3.141, + 4], 'mode=spherical;style=wireframe', + visible=False) + p.wait_for_calculations() + + +def test_plot_2d_parametric(): + from sympy.plotting.pygletplot import PygletPlot + p = PygletPlot(sin(x), cos(x), [x, 0, 6.282, 4], visible=False) + p.wait_for_calculations() + + +def test_plot_3d_parametric(): + from sympy.plotting.pygletplot import PygletPlot + p = PygletPlot(sin(x), cos(x), x/5.0, [x, 0, 6.282, 4], visible=False) + p.wait_for_calculations() + + +def _test_plot_log(): + from sympy.plotting.pygletplot import PygletPlot + p = PygletPlot(log(x), [x, 0, 6.282, 4], 'mode=polar', visible=False) + p.wait_for_calculations() + + +def test_plot_integral(): + # Make sure it doesn't treat x as an independent variable + from sympy.plotting.pygletplot import PygletPlot + from sympy.integrals.integrals import Integral + p = PygletPlot(Integral(z*x, (x, 1, z), (z, 1, y)), visible=False) + p.wait_for_calculations() diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/util.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/util.py new file mode 100644 index 0000000000000000000000000000000000000000..43b882ca18274dcdb273cf35680016453db3c698 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/pygletplot/util.py @@ -0,0 +1,188 @@ +try: + from ctypes import c_float, c_int, c_double +except ImportError: + pass + +import pyglet.gl as pgl +from sympy.core import S + + +def get_model_matrix(array_type=c_float, glGetMethod=pgl.glGetFloatv): + """ + Returns the current modelview matrix. + """ + m = (array_type*16)() + glGetMethod(pgl.GL_MODELVIEW_MATRIX, m) + return m + + +def get_projection_matrix(array_type=c_float, glGetMethod=pgl.glGetFloatv): + """ + Returns the current modelview matrix. + """ + m = (array_type*16)() + glGetMethod(pgl.GL_PROJECTION_MATRIX, m) + return m + + +def get_viewport(): + """ + Returns the current viewport. + """ + m = (c_int*4)() + pgl.glGetIntegerv(pgl.GL_VIEWPORT, m) + return m + + +def get_direction_vectors(): + m = get_model_matrix() + return ((m[0], m[4], m[8]), + (m[1], m[5], m[9]), + (m[2], m[6], m[10])) + + +def get_view_direction_vectors(): + m = get_model_matrix() + return ((m[0], m[1], m[2]), + (m[4], m[5], m[6]), + (m[8], m[9], m[10])) + + +def get_basis_vectors(): + return ((1, 0, 0), (0, 1, 0), (0, 0, 1)) + + +def screen_to_model(x, y, z): + m = get_model_matrix(c_double, pgl.glGetDoublev) + p = get_projection_matrix(c_double, pgl.glGetDoublev) + w = get_viewport() + mx, my, mz = c_double(), c_double(), c_double() + pgl.gluUnProject(x, y, z, m, p, w, mx, my, mz) + return float(mx.value), float(my.value), float(mz.value) + + +def model_to_screen(x, y, z): + m = get_model_matrix(c_double, pgl.glGetDoublev) + p = get_projection_matrix(c_double, pgl.glGetDoublev) + w = get_viewport() + mx, my, mz = c_double(), c_double(), c_double() + pgl.gluProject(x, y, z, m, p, w, mx, my, mz) + return float(mx.value), float(my.value), float(mz.value) + + +def vec_subs(a, b): + return tuple(a[i] - b[i] for i in range(len(a))) + + +def billboard_matrix(): + """ + Removes rotational components of + current matrix so that primitives + are always drawn facing the viewer. + + |1|0|0|x| + |0|1|0|x| + |0|0|1|x| (x means left unchanged) + |x|x|x|x| + """ + m = get_model_matrix() + # XXX: for i in range(11): m[i] = i ? + m[0] = 1 + m[1] = 0 + m[2] = 0 + m[4] = 0 + m[5] = 1 + m[6] = 0 + m[8] = 0 + m[9] = 0 + m[10] = 1 + pgl.glLoadMatrixf(m) + + +def create_bounds(): + return [[S.Infinity, S.NegativeInfinity, 0], + [S.Infinity, S.NegativeInfinity, 0], + [S.Infinity, S.NegativeInfinity, 0]] + + +def update_bounds(b, v): + if v is None: + return + for axis in range(3): + b[axis][0] = min([b[axis][0], v[axis]]) + b[axis][1] = max([b[axis][1], v[axis]]) + + +def interpolate(a_min, a_max, a_ratio): + return a_min + a_ratio * (a_max - a_min) + + +def rinterpolate(a_min, a_max, a_value): + a_range = a_max - a_min + if a_max == a_min: + a_range = 1.0 + return (a_value - a_min) / float(a_range) + + +def interpolate_color(color1, color2, ratio): + return tuple(interpolate(color1[i], color2[i], ratio) for i in range(3)) + + +def scale_value(v, v_min, v_len): + return (v - v_min) / v_len + + +def scale_value_list(flist): + v_min, v_max = min(flist), max(flist) + v_len = v_max - v_min + return [scale_value(f, v_min, v_len) for f in flist] + + +def strided_range(r_min, r_max, stride, max_steps=50): + o_min, o_max = r_min, r_max + if abs(r_min - r_max) < 0.001: + return [] + try: + range(int(r_min - r_max)) + except (TypeError, OverflowError): + return [] + if r_min > r_max: + raise ValueError("r_min cannot be greater than r_max") + r_min_s = (r_min % stride) + r_max_s = stride - (r_max % stride) + if abs(r_max_s - stride) < 0.001: + r_max_s = 0.0 + r_min -= r_min_s + r_max += r_max_s + r_steps = int((r_max - r_min)/stride) + if max_steps and r_steps > max_steps: + return strided_range(o_min, o_max, stride*2) + return [r_min] + [r_min + e*stride for e in range(1, r_steps + 1)] + [r_max] + + +def parse_option_string(s): + if not isinstance(s, str): + return None + options = {} + for token in s.split(';'): + pieces = token.split('=') + if len(pieces) == 1: + option, value = pieces[0], "" + elif len(pieces) == 2: + option, value = pieces + else: + raise ValueError("Plot option string '%s' is malformed." % (s)) + options[option.strip()] = value.strip() + return options + + +def dot_product(v1, v2): + return sum(v1[i]*v2[i] for i in range(3)) + + +def vec_sub(v1, v2): + return tuple(v1[i] - v2[i] for i in range(3)) + + +def vec_mag(v): + return sum(v[i]**2 for i in range(3))**(0.5) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..701a86cff0912dc8e1f231760198544605c1805c Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/__pycache__/test_experimental_lambdify.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/__pycache__/test_experimental_lambdify.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..266e70f19eb830b8dfdb4d2a2bb5a7cd3a80d194 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/__pycache__/test_experimental_lambdify.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/__pycache__/test_plot.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/__pycache__/test_plot.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2bfcc0b78a4e10202da46be7e39deec823077ce2 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/__pycache__/test_plot.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/__pycache__/test_plot_implicit.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/__pycache__/test_plot_implicit.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..05cb4bc930ea3080a42a0fb9e0d261124911d0a8 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/__pycache__/test_plot_implicit.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/__pycache__/test_textplot.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/__pycache__/test_textplot.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6da429c95f51832a148252cddd92145c6e627576 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/__pycache__/test_textplot.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/__pycache__/test_utils.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/__pycache__/test_utils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cdc8756df4e01eaa17fcc900248796ade0927cac Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/__pycache__/test_utils.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_experimental_lambdify.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_experimental_lambdify.py new file mode 100644 index 0000000000000000000000000000000000000000..95839d668762be7be94d0de5092594306ceeadbd --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_experimental_lambdify.py @@ -0,0 +1,77 @@ +from sympy.core.symbol import symbols, Symbol +from sympy.functions import Max +from sympy.plotting.experimental_lambdify import experimental_lambdify +from sympy.plotting.intervalmath.interval_arithmetic import \ + interval, intervalMembership + + +# Tests for exception handling in experimental_lambdify +def test_experimental_lambify(): + x = Symbol('x') + f = experimental_lambdify([x], Max(x, 5)) + # XXX should f be tested? If f(2) is attempted, an + # error is raised because a complex produced during wrapping of the arg + # is being compared with an int. + assert Max(2, 5) == 5 + assert Max(5, 7) == 7 + + x = Symbol('x-3') + f = experimental_lambdify([x], x + 1) + assert f(1) == 2 + + +def test_composite_boolean_region(): + x, y = symbols('x y') + + r1 = (x - 1)**2 + y**2 < 2 + r2 = (x + 1)**2 + y**2 < 2 + + f = experimental_lambdify((x, y), r1 & r2) + a = (interval(-0.1, 0.1), interval(-0.1, 0.1)) + assert f(*a) == intervalMembership(True, True) + a = (interval(-1.1, -0.9), interval(-0.1, 0.1)) + assert f(*a) == intervalMembership(False, True) + a = (interval(0.9, 1.1), interval(-0.1, 0.1)) + assert f(*a) == intervalMembership(False, True) + a = (interval(-0.1, 0.1), interval(1.9, 2.1)) + assert f(*a) == intervalMembership(False, True) + + f = experimental_lambdify((x, y), r1 | r2) + a = (interval(-0.1, 0.1), interval(-0.1, 0.1)) + assert f(*a) == intervalMembership(True, True) + a = (interval(-1.1, -0.9), interval(-0.1, 0.1)) + assert f(*a) == intervalMembership(True, True) + a = (interval(0.9, 1.1), interval(-0.1, 0.1)) + assert f(*a) == intervalMembership(True, True) + a = (interval(-0.1, 0.1), interval(1.9, 2.1)) + assert f(*a) == intervalMembership(False, True) + + f = experimental_lambdify((x, y), r1 & ~r2) + a = (interval(-0.1, 0.1), interval(-0.1, 0.1)) + assert f(*a) == intervalMembership(False, True) + a = (interval(-1.1, -0.9), interval(-0.1, 0.1)) + assert f(*a) == intervalMembership(False, True) + a = (interval(0.9, 1.1), interval(-0.1, 0.1)) + assert f(*a) == intervalMembership(True, True) + a = (interval(-0.1, 0.1), interval(1.9, 2.1)) + assert f(*a) == intervalMembership(False, True) + + f = experimental_lambdify((x, y), ~r1 & r2) + a = (interval(-0.1, 0.1), interval(-0.1, 0.1)) + assert f(*a) == intervalMembership(False, True) + a = (interval(-1.1, -0.9), interval(-0.1, 0.1)) + assert f(*a) == intervalMembership(True, True) + a = (interval(0.9, 1.1), interval(-0.1, 0.1)) + assert f(*a) == intervalMembership(False, True) + a = (interval(-0.1, 0.1), interval(1.9, 2.1)) + assert f(*a) == intervalMembership(False, True) + + f = experimental_lambdify((x, y), ~r1 & ~r2) + a = (interval(-0.1, 0.1), interval(-0.1, 0.1)) + assert f(*a) == intervalMembership(False, True) + a = (interval(-1.1, -0.9), interval(-0.1, 0.1)) + assert f(*a) == intervalMembership(False, True) + a = (interval(0.9, 1.1), interval(-0.1, 0.1)) + assert f(*a) == intervalMembership(False, True) + a = (interval(-0.1, 0.1), interval(1.9, 2.1)) + assert f(*a) == intervalMembership(True, True) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_plot.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_plot.py new file mode 100644 index 0000000000000000000000000000000000000000..e5246c38a19552222aa62720d3f5e9e320344662 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_plot.py @@ -0,0 +1,1344 @@ +import os +from tempfile import TemporaryDirectory +import pytest +from sympy.concrete.summations import Sum +from sympy.core.numbers import (I, oo, pi) +from sympy.core.relational import Ne +from sympy.core.symbol import Symbol, symbols +from sympy.functions.elementary.exponential import (LambertW, exp, exp_polar, log) +from sympy.functions.elementary.miscellaneous import (real_root, sqrt) +from sympy.functions.elementary.piecewise import Piecewise +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.functions.elementary.miscellaneous import Min +from sympy.functions.special.hyper import meijerg +from sympy.integrals.integrals import Integral +from sympy.logic.boolalg import And +from sympy.core.singleton import S +from sympy.core.sympify import sympify +from sympy.external import import_module +from sympy.plotting.plot import ( + Plot, plot, plot_parametric, plot3d_parametric_line, plot3d, + plot3d_parametric_surface) +from sympy.plotting.plot import ( + unset_show, plot_contour, PlotGrid, MatplotlibBackend, TextBackend) +from sympy.plotting.series import ( + LineOver1DRangeSeries, Parametric2DLineSeries, Parametric3DLineSeries, + ParametricSurfaceSeries, SurfaceOver2DRangeSeries) +from sympy.testing.pytest import skip, skip_under_pyodide, warns, raises, warns_deprecated_sympy +from sympy.utilities import lambdify as lambdify_ +from sympy.utilities.exceptions import ignore_warnings + +unset_show() + + +matplotlib = import_module( + 'matplotlib', min_module_version='1.1.0', catch=(RuntimeError,)) + + +class DummyBackendNotOk(Plot): + """ Used to verify if users can create their own backends. + This backend is meant to raise NotImplementedError for methods `show`, + `save`, `close`. + """ + def __new__(cls, *args, **kwargs): + return object.__new__(cls) + + +class DummyBackendOk(Plot): + """ Used to verify if users can create their own backends. + This backend is meant to pass all tests. + """ + def __new__(cls, *args, **kwargs): + return object.__new__(cls) + + def show(self): + pass + + def save(self): + pass + + def close(self): + pass + +def test_basic_plotting_backend(): + x = Symbol('x') + plot(x, (x, 0, 3), backend='text') + plot(x**2 + 1, (x, 0, 3), backend='text') + +@pytest.mark.parametrize("adaptive", [True, False]) +def test_plot_and_save_1(adaptive): + if not matplotlib: + skip("Matplotlib not the default backend") + + x = Symbol('x') + y = Symbol('y') + + with TemporaryDirectory(prefix='sympy_') as tmpdir: + ### + # Examples from the 'introduction' notebook + ### + p = plot(x, legend=True, label='f1', adaptive=adaptive, n=10) + p = plot(x*sin(x), x*cos(x), label='f2', adaptive=adaptive, n=10) + p.extend(p) + p[0].line_color = lambda a: a + p[1].line_color = 'b' + p.title = 'Big title' + p.xlabel = 'the x axis' + p[1].label = 'straight line' + p.legend = True + p.aspect_ratio = (1, 1) + p.xlim = (-15, 20) + filename = 'test_basic_options_and_colors.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + p.extend(plot(x + 1, adaptive=adaptive, n=10)) + p.append(plot(x + 3, x**2, adaptive=adaptive, n=10)[1]) + filename = 'test_plot_extend_append.png' + p.save(os.path.join(tmpdir, filename)) + + p[2] = plot(x**2, (x, -2, 3), adaptive=adaptive, n=10) + filename = 'test_plot_setitem.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + p = plot(sin(x), (x, -2*pi, 4*pi), adaptive=adaptive, n=10) + filename = 'test_line_explicit.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + p = plot(sin(x), adaptive=adaptive, n=10) + filename = 'test_line_default_range.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + p = plot((x**2, (x, -5, 5)), (x**3, (x, -3, 3)), adaptive=adaptive, n=10) + filename = 'test_line_multiple_range.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + raises(ValueError, lambda: plot(x, y)) + + #Piecewise plots + p = plot(Piecewise((1, x > 0), (0, True)), (x, -1, 1), adaptive=adaptive, n=10) + filename = 'test_plot_piecewise.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + p = plot(Piecewise((x, x < 1), (x**2, True)), (x, -3, 3), adaptive=adaptive, n=10) + filename = 'test_plot_piecewise_2.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + # test issue 7471 + p1 = plot(x, adaptive=adaptive, n=10) + p2 = plot(3, adaptive=adaptive, n=10) + p1.extend(p2) + filename = 'test_horizontal_line.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + # test issue 10925 + f = Piecewise((-1, x < -1), (x, And(-1 <= x, x < 0)), \ + (x**2, And(0 <= x, x < 1)), (x**3, x >= 1)) + p = plot(f, (x, -3, 3), adaptive=adaptive, n=10) + filename = 'test_plot_piecewise_3.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + +@pytest.mark.parametrize("adaptive", [True, False]) +def test_plot_and_save_2(adaptive): + if not matplotlib: + skip("Matplotlib not the default backend") + + x = Symbol('x') + y = Symbol('y') + z = Symbol('z') + + with TemporaryDirectory(prefix='sympy_') as tmpdir: + #parametric 2d plots. + #Single plot with default range. + p = plot_parametric(sin(x), cos(x), adaptive=adaptive, n=10) + filename = 'test_parametric.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + #Single plot with range. + p = plot_parametric( + sin(x), cos(x), (x, -5, 5), legend=True, label='parametric_plot', + adaptive=adaptive, n=10) + filename = 'test_parametric_range.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + #Multiple plots with same range. + p = plot_parametric((sin(x), cos(x)), (x, sin(x)), + adaptive=adaptive, n=10) + filename = 'test_parametric_multiple.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + #Multiple plots with different ranges. + p = plot_parametric( + (sin(x), cos(x), (x, -3, 3)), (x, sin(x), (x, -5, 5)), + adaptive=adaptive, n=10) + filename = 'test_parametric_multiple_ranges.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + #depth of recursion specified. + p = plot_parametric(x, sin(x), depth=13, + adaptive=adaptive, n=10) + filename = 'test_recursion_depth.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + #No adaptive sampling. + p = plot_parametric(cos(x), sin(x), adaptive=False, n=500) + filename = 'test_adaptive.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + #3d parametric plots + p = plot3d_parametric_line( + sin(x), cos(x), x, legend=True, label='3d_parametric_plot', + adaptive=adaptive, n=10) + filename = 'test_3d_line.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + p = plot3d_parametric_line( + (sin(x), cos(x), x, (x, -5, 5)), (cos(x), sin(x), x, (x, -3, 3)), + adaptive=adaptive, n=10) + filename = 'test_3d_line_multiple.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + p = plot3d_parametric_line(sin(x), cos(x), x, n=30, + adaptive=adaptive) + filename = 'test_3d_line_points.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + # 3d surface single plot. + p = plot3d(x * y, adaptive=adaptive, n=10) + filename = 'test_surface.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + # Multiple 3D plots with same range. + p = plot3d(-x * y, x * y, (x, -5, 5), adaptive=adaptive, n=10) + filename = 'test_surface_multiple.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + # Multiple 3D plots with different ranges. + p = plot3d( + (x * y, (x, -3, 3), (y, -3, 3)), (-x * y, (x, -3, 3), (y, -3, 3)), + adaptive=adaptive, n=10) + filename = 'test_surface_multiple_ranges.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + # Single Parametric 3D plot + p = plot3d_parametric_surface(sin(x + y), cos(x - y), x - y, + adaptive=adaptive, n=10) + filename = 'test_parametric_surface.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + # Multiple Parametric 3D plots. + p = plot3d_parametric_surface( + (x*sin(z), x*cos(z), z, (x, -5, 5), (z, -5, 5)), + (sin(x + y), cos(x - y), x - y, (x, -5, 5), (y, -5, 5)), + adaptive=adaptive, n=10) + filename = 'test_parametric_surface.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + # Single Contour plot. + p = plot_contour(sin(x)*sin(y), (x, -5, 5), (y, -5, 5), + adaptive=adaptive, n=10) + filename = 'test_contour_plot.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + # Multiple Contour plots with same range. + p = plot_contour(x**2 + y**2, x**3 + y**3, (x, -5, 5), (y, -5, 5), + adaptive=adaptive, n=10) + filename = 'test_contour_plot.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + # Multiple Contour plots with different range. + p = plot_contour( + (x**2 + y**2, (x, -5, 5), (y, -5, 5)), + (x**3 + y**3, (x, -3, 3), (y, -3, 3)), + adaptive=adaptive, n=10) + filename = 'test_contour_plot.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + +@pytest.mark.parametrize("adaptive", [True, False]) +def test_plot_and_save_3(adaptive): + if not matplotlib: + skip("Matplotlib not the default backend") + + x = Symbol('x') + y = Symbol('y') + z = Symbol('z') + + with TemporaryDirectory(prefix='sympy_') as tmpdir: + ### + # Examples from the 'colors' notebook + ### + + p = plot(sin(x), adaptive=adaptive, n=10) + p[0].line_color = lambda a: a + filename = 'test_colors_line_arity1.png' + p.save(os.path.join(tmpdir, filename)) + + p[0].line_color = lambda a, b: b + filename = 'test_colors_line_arity2.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + p = plot(x*sin(x), x*cos(x), (x, 0, 10), adaptive=adaptive, n=10) + p[0].line_color = lambda a: a + filename = 'test_colors_param_line_arity1.png' + p.save(os.path.join(tmpdir, filename)) + + p[0].line_color = lambda a, b: a + filename = 'test_colors_param_line_arity1.png' + p.save(os.path.join(tmpdir, filename)) + + p[0].line_color = lambda a, b: b + filename = 'test_colors_param_line_arity2b.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + p = plot3d_parametric_line( + sin(x) + 0.1*sin(x)*cos(7*x), + cos(x) + 0.1*cos(x)*cos(7*x), + 0.1*sin(7*x), + (x, 0, 2*pi), adaptive=adaptive, n=10) + p[0].line_color = lambdify_(x, sin(4*x)) + filename = 'test_colors_3d_line_arity1.png' + p.save(os.path.join(tmpdir, filename)) + p[0].line_color = lambda a, b: b + filename = 'test_colors_3d_line_arity2.png' + p.save(os.path.join(tmpdir, filename)) + p[0].line_color = lambda a, b, c: c + filename = 'test_colors_3d_line_arity3.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + p = plot3d(sin(x)*y, (x, 0, 6*pi), (y, -5, 5), adaptive=adaptive, n=10) + p[0].surface_color = lambda a: a + filename = 'test_colors_surface_arity1.png' + p.save(os.path.join(tmpdir, filename)) + p[0].surface_color = lambda a, b: b + filename = 'test_colors_surface_arity2.png' + p.save(os.path.join(tmpdir, filename)) + p[0].surface_color = lambda a, b, c: c + filename = 'test_colors_surface_arity3a.png' + p.save(os.path.join(tmpdir, filename)) + p[0].surface_color = lambdify_((x, y, z), sqrt((x - 3*pi)**2 + y**2)) + filename = 'test_colors_surface_arity3b.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + p = plot3d_parametric_surface(x * cos(4 * y), x * sin(4 * y), y, + (x, -1, 1), (y, -1, 1), adaptive=adaptive, n=10) + p[0].surface_color = lambda a: a + filename = 'test_colors_param_surf_arity1.png' + p.save(os.path.join(tmpdir, filename)) + p[0].surface_color = lambda a, b: a*b + filename = 'test_colors_param_surf_arity2.png' + p.save(os.path.join(tmpdir, filename)) + p[0].surface_color = lambdify_((x, y, z), sqrt(x**2 + y**2 + z**2)) + filename = 'test_colors_param_surf_arity3.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + +@pytest.mark.parametrize("adaptive", [True]) +def test_plot_and_save_4(adaptive): + if not matplotlib: + skip("Matplotlib not the default backend") + + x = Symbol('x') + y = Symbol('y') + + ### + # Examples from the 'advanced' notebook + ### + + with TemporaryDirectory(prefix='sympy_') as tmpdir: + i = Integral(log((sin(x)**2 + 1)*sqrt(x**2 + 1)), (x, 0, y)) + p = plot(i, (y, 1, 5), adaptive=adaptive, n=10, force_real_eval=True) + filename = 'test_advanced_integral.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + +@pytest.mark.parametrize("adaptive", [True, False]) +def test_plot_and_save_5(adaptive): + if not matplotlib: + skip("Matplotlib not the default backend") + + x = Symbol('x') + y = Symbol('y') + + with TemporaryDirectory(prefix='sympy_') as tmpdir: + s = Sum(1/x**y, (x, 1, oo)) + p = plot(s, (y, 2, 10), adaptive=adaptive, n=10) + filename = 'test_advanced_inf_sum.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + p = plot(Sum(1/x, (x, 1, y)), (y, 2, 10), show=False, + adaptive=adaptive, n=10) + p[0].only_integers = True + p[0].steps = True + filename = 'test_advanced_fin_sum.png' + + # XXX: This should be fixed in experimental_lambdify or by using + # ordinary lambdify so that it doesn't warn. The error results from + # passing an array of values as the integration limit. + # + # UserWarning: The evaluation of the expression is problematic. We are + # trying a failback method that may still work. Please report this as a + # bug. + with ignore_warnings(UserWarning): + p.save(os.path.join(tmpdir, filename)) + + p._backend.close() + + +@pytest.mark.parametrize("adaptive", [True, False]) +def test_plot_and_save_6(adaptive): + if not matplotlib: + skip("Matplotlib not the default backend") + + x = Symbol('x') + + with TemporaryDirectory(prefix='sympy_') as tmpdir: + filename = 'test.png' + ### + # Test expressions that can not be translated to np and generate complex + # results. + ### + p = plot(sin(x) + I*cos(x)) + p.save(os.path.join(tmpdir, filename)) + + with ignore_warnings(RuntimeWarning): + p = plot(sqrt(sqrt(-x))) + p.save(os.path.join(tmpdir, filename)) + + p = plot(LambertW(x)) + p.save(os.path.join(tmpdir, filename)) + p = plot(sqrt(LambertW(x))) + p.save(os.path.join(tmpdir, filename)) + + #Characteristic function of a StudentT distribution with nu=10 + x1 = 5 * x**2 * exp_polar(-I*pi)/2 + m1 = meijerg(((1 / 2,), ()), ((5, 0, 1 / 2), ()), x1) + x2 = 5*x**2 * exp_polar(I*pi)/2 + m2 = meijerg(((1/2,), ()), ((5, 0, 1/2), ()), x2) + expr = (m1 + m2) / (48 * pi) + with warns( + UserWarning, + match="The evaluation with NumPy/SciPy failed", + test_stacklevel=False, + ): + p = plot(expr, (x, 1e-6, 1e-2), adaptive=adaptive, n=10) + p.save(os.path.join(tmpdir, filename)) + + +@pytest.mark.parametrize("adaptive", [True, False]) +def test_plotgrid_and_save(adaptive): + if not matplotlib: + skip("Matplotlib not the default backend") + + x = Symbol('x') + y = Symbol('y') + + with TemporaryDirectory(prefix='sympy_') as tmpdir: + p1 = plot(x, adaptive=adaptive, n=10) + p2 = plot_parametric((sin(x), cos(x)), (x, sin(x)), show=False, + adaptive=adaptive, n=10) + p3 = plot_parametric( + cos(x), sin(x), adaptive=adaptive, n=10, show=False) + p4 = plot3d_parametric_line(sin(x), cos(x), x, show=False, + adaptive=adaptive, n=10) + # symmetric grid + p = PlotGrid(2, 2, p1, p2, p3, p4) + filename = 'test_grid1.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + # grid size greater than the number of subplots + p = PlotGrid(3, 4, p1, p2, p3, p4) + filename = 'test_grid2.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + p5 = plot(cos(x),(x, -pi, pi), show=False, adaptive=adaptive, n=10) + p5[0].line_color = lambda a: a + p6 = plot(Piecewise((1, x > 0), (0, True)), (x, -1, 1), show=False, + adaptive=adaptive, n=10) + p7 = plot_contour( + (x**2 + y**2, (x, -5, 5), (y, -5, 5)), + (x**3 + y**3, (x, -3, 3), (y, -3, 3)), show=False, + adaptive=adaptive, n=10) + # unsymmetric grid (subplots in one line) + p = PlotGrid(1, 3, p5, p6, p7) + filename = 'test_grid3.png' + p.save(os.path.join(tmpdir, filename)) + p._backend.close() + + +@pytest.mark.parametrize("adaptive", [True, False]) +def test_append_issue_7140(adaptive): + if not matplotlib: + skip("Matplotlib not the default backend") + + x = Symbol('x') + p1 = plot(x, adaptive=adaptive, n=10) + p2 = plot(x**2, adaptive=adaptive, n=10) + plot(x + 2, adaptive=adaptive, n=10) + + # append a series + p2.append(p1[0]) + assert len(p2._series) == 2 + + with raises(TypeError): + p1.append(p2) + + with raises(TypeError): + p1.append(p2._series) + + +@pytest.mark.parametrize("adaptive", [True, False]) +def test_issue_15265(adaptive): + if not matplotlib: + skip("Matplotlib not the default backend") + + x = Symbol('x') + eqn = sin(x) + + p = plot(eqn, xlim=(-S.Pi, S.Pi), ylim=(-1, 1), adaptive=adaptive, n=10) + p._backend.close() + + p = plot(eqn, xlim=(-1, 1), ylim=(-S.Pi, S.Pi), adaptive=adaptive, n=10) + p._backend.close() + + p = plot(eqn, xlim=(-1, 1), adaptive=adaptive, n=10, + ylim=(sympify('-3.14'), sympify('3.14'))) + p._backend.close() + + p = plot(eqn, adaptive=adaptive, n=10, + xlim=(sympify('-3.14'), sympify('3.14')), ylim=(-1, 1)) + p._backend.close() + + raises(ValueError, + lambda: plot(eqn, adaptive=adaptive, n=10, + xlim=(-S.ImaginaryUnit, 1), ylim=(-1, 1))) + + raises(ValueError, + lambda: plot(eqn, adaptive=adaptive, n=10, + xlim=(-1, 1), ylim=(-1, S.ImaginaryUnit))) + + raises(ValueError, + lambda: plot(eqn, adaptive=adaptive, n=10, + xlim=(S.NegativeInfinity, 1), ylim=(-1, 1))) + + raises(ValueError, + lambda: plot(eqn, adaptive=adaptive, n=10, + xlim=(-1, 1), ylim=(-1, S.Infinity))) + + +def test_empty_Plot(): + if not matplotlib: + skip("Matplotlib not the default backend") + + # No exception showing an empty plot + plot() + # Plot is only a base class: doesn't implement any logic for showing + # images + p = Plot() + raises(NotImplementedError, lambda: p.show()) + + +@pytest.mark.parametrize("adaptive", [True, False]) +def test_issue_17405(adaptive): + if not matplotlib: + skip("Matplotlib not the default backend") + + x = Symbol('x') + f = x**0.3 - 10*x**3 + x**2 + p = plot(f, (x, -10, 10), adaptive=adaptive, n=30, show=False) + # Random number of segments, probably more than 100, but we want to see + # that there are segments generated, as opposed to when the bug was present + + # RuntimeWarning: invalid value encountered in double_scalars + with ignore_warnings(RuntimeWarning): + assert len(p[0].get_data()[0]) >= 30 + + +@pytest.mark.parametrize("adaptive", [True, False]) +def test_logplot_PR_16796(adaptive): + if not matplotlib: + skip("Matplotlib not the default backend") + + x = Symbol('x') + p = plot(x, (x, .001, 100), adaptive=adaptive, n=30, + xscale='log', show=False) + # Random number of segments, probably more than 100, but we want to see + # that there are segments generated, as opposed to when the bug was present + assert len(p[0].get_data()[0]) >= 30 + assert p[0].end == 100.0 + assert p[0].start == .001 + + +@pytest.mark.parametrize("adaptive", [True, False]) +def test_issue_16572(adaptive): + if not matplotlib: + skip("Matplotlib not the default backend") + + x = Symbol('x') + p = plot(LambertW(x), show=False, adaptive=adaptive, n=30) + # Random number of segments, probably more than 50, but we want to see + # that there are segments generated, as opposed to when the bug was present + assert len(p[0].get_data()[0]) >= 30 + + +@pytest.mark.parametrize("adaptive", [True, False]) +def test_issue_11865(adaptive): + if not matplotlib: + skip("Matplotlib not the default backend") + + k = Symbol('k', integer=True) + f = Piecewise((-I*exp(I*pi*k)/k + I*exp(-I*pi*k)/k, Ne(k, 0)), (2*pi, True)) + p = plot(f, show=False, adaptive=adaptive, n=30) + # Random number of segments, probably more than 100, but we want to see + # that there are segments generated, as opposed to when the bug was present + # and that there are no exceptions. + assert len(p[0].get_data()[0]) >= 30 + + +@skip_under_pyodide("Warnings not emitted in Pyodide because of lack of WASM fp exception support") +def test_issue_11461(): + if not matplotlib: + skip("Matplotlib not the default backend") + + x = Symbol('x') + p = plot(real_root((log(x/(x-2))), 3), show=False, adaptive=True) + with warns( + RuntimeWarning, + match="invalid value encountered in", + test_stacklevel=False, + ): + # Random number of segments, probably more than 100, but we want to see + # that there are segments generated, as opposed to when the bug was present + # and that there are no exceptions. + assert len(p[0].get_data()[0]) >= 30 + + +@pytest.mark.parametrize("adaptive", [True, False]) +def test_issue_11764(adaptive): + if not matplotlib: + skip("Matplotlib not the default backend") + + x = Symbol('x') + p = plot_parametric(cos(x), sin(x), (x, 0, 2 * pi), + aspect_ratio=(1,1), show=False, adaptive=adaptive, n=30) + assert p.aspect_ratio == (1, 1) + # Random number of segments, probably more than 100, but we want to see + # that there are segments generated, as opposed to when the bug was present + assert len(p[0].get_data()[0]) >= 30 + + +@pytest.mark.parametrize("adaptive", [True, False]) +def test_issue_13516(adaptive): + if not matplotlib: + skip("Matplotlib not the default backend") + + x = Symbol('x') + + pm = plot(sin(x), backend="matplotlib", show=False, adaptive=adaptive, n=30) + assert pm.backend == MatplotlibBackend + assert len(pm[0].get_data()[0]) >= 30 + + pt = plot(sin(x), backend="text", show=False, adaptive=adaptive, n=30) + assert pt.backend == TextBackend + assert len(pt[0].get_data()[0]) >= 30 + + pd = plot(sin(x), backend="default", show=False, adaptive=adaptive, n=30) + assert pd.backend == MatplotlibBackend + assert len(pd[0].get_data()[0]) >= 30 + + p = plot(sin(x), show=False, adaptive=adaptive, n=30) + assert p.backend == MatplotlibBackend + assert len(p[0].get_data()[0]) >= 30 + + +@pytest.mark.parametrize("adaptive", [True, False]) +def test_plot_limits(adaptive): + if not matplotlib: + skip("Matplotlib not the default backend") + + x = Symbol('x') + p = plot(x, x**2, (x, -10, 10), adaptive=adaptive, n=10) + backend = p._backend + + xmin, xmax = backend.ax.get_xlim() + assert abs(xmin + 10) < 2 + assert abs(xmax - 10) < 2 + ymin, ymax = backend.ax.get_ylim() + assert abs(ymin + 10) < 10 + assert abs(ymax - 100) < 10 + + +@pytest.mark.parametrize("adaptive", [True, False]) +def test_plot3d_parametric_line_limits(adaptive): + if not matplotlib: + skip("Matplotlib not the default backend") + + x = Symbol('x') + + v1 = (2*cos(x), 2*sin(x), 2*x, (x, -5, 5)) + v2 = (sin(x), cos(x), x, (x, -5, 5)) + p = plot3d_parametric_line(v1, v2, adaptive=adaptive, n=60) + backend = p._backend + + xmin, xmax = backend.ax.get_xlim() + assert abs(xmin + 2) < 1e-2 + assert abs(xmax - 2) < 1e-2 + ymin, ymax = backend.ax.get_ylim() + assert abs(ymin + 2) < 1e-2 + assert abs(ymax - 2) < 1e-2 + zmin, zmax = backend.ax.get_zlim() + assert abs(zmin + 10) < 1e-2 + assert abs(zmax - 10) < 1e-2 + + p = plot3d_parametric_line(v2, v1, adaptive=adaptive, n=60) + backend = p._backend + + xmin, xmax = backend.ax.get_xlim() + assert abs(xmin + 2) < 1e-2 + assert abs(xmax - 2) < 1e-2 + ymin, ymax = backend.ax.get_ylim() + assert abs(ymin + 2) < 1e-2 + assert abs(ymax - 2) < 1e-2 + zmin, zmax = backend.ax.get_zlim() + assert abs(zmin + 10) < 1e-2 + assert abs(zmax - 10) < 1e-2 + + +@pytest.mark.parametrize("adaptive", [True, False]) +def test_plot_size(adaptive): + if not matplotlib: + skip("Matplotlib not the default backend") + + x = Symbol('x') + + p1 = plot(sin(x), backend="matplotlib", size=(8, 4), + adaptive=adaptive, n=10) + s1 = p1._backend.fig.get_size_inches() + assert (s1[0] == 8) and (s1[1] == 4) + p2 = plot(sin(x), backend="matplotlib", size=(5, 10), + adaptive=adaptive, n=10) + s2 = p2._backend.fig.get_size_inches() + assert (s2[0] == 5) and (s2[1] == 10) + p3 = PlotGrid(2, 1, p1, p2, size=(6, 2), + adaptive=adaptive, n=10) + s3 = p3._backend.fig.get_size_inches() + assert (s3[0] == 6) and (s3[1] == 2) + + with raises(ValueError): + plot(sin(x), backend="matplotlib", size=(-1, 3)) + + +def test_issue_20113(): + if not matplotlib: + skip("Matplotlib not the default backend") + + x = Symbol('x') + + # verify the capability to use custom backends + plot(sin(x), backend=Plot, show=False) + p2 = plot(sin(x), backend=MatplotlibBackend, show=False) + assert p2.backend == MatplotlibBackend + assert len(p2[0].get_data()[0]) >= 30 + p3 = plot(sin(x), backend=DummyBackendOk, show=False) + assert p3.backend == DummyBackendOk + assert len(p3[0].get_data()[0]) >= 30 + + # test for an improper coded backend + p4 = plot(sin(x), backend=DummyBackendNotOk, show=False) + assert p4.backend == DummyBackendNotOk + assert len(p4[0].get_data()[0]) >= 30 + with raises(NotImplementedError): + p4.show() + with raises(NotImplementedError): + p4.save("test/path") + with raises(NotImplementedError): + p4._backend.close() + + +def test_custom_coloring(): + x = Symbol('x') + y = Symbol('y') + plot(cos(x), line_color=lambda a: a) + plot(cos(x), line_color=1) + plot(cos(x), line_color="r") + plot_parametric(cos(x), sin(x), line_color=lambda a: a) + plot_parametric(cos(x), sin(x), line_color=1) + plot_parametric(cos(x), sin(x), line_color="r") + plot3d_parametric_line(cos(x), sin(x), x, line_color=lambda a: a) + plot3d_parametric_line(cos(x), sin(x), x, line_color=1) + plot3d_parametric_line(cos(x), sin(x), x, line_color="r") + plot3d_parametric_surface(cos(x + y), sin(x - y), x - y, + (x, -5, 5), (y, -5, 5), + surface_color=lambda a, b: a**2 + b**2) + plot3d_parametric_surface(cos(x + y), sin(x - y), x - y, + (x, -5, 5), (y, -5, 5), + surface_color=1) + plot3d_parametric_surface(cos(x + y), sin(x - y), x - y, + (x, -5, 5), (y, -5, 5), + surface_color="r") + plot3d(x*y, (x, -5, 5), (y, -5, 5), + surface_color=lambda a, b: a**2 + b**2) + plot3d(x*y, (x, -5, 5), (y, -5, 5), surface_color=1) + plot3d(x*y, (x, -5, 5), (y, -5, 5), surface_color="r") + + +@pytest.mark.parametrize("adaptive", [True, False]) +def test_deprecated_get_segments(adaptive): + if not matplotlib: + skip("Matplotlib not the default backend") + + x = Symbol('x') + f = sin(x) + p = plot(f, (x, -10, 10), show=False, adaptive=adaptive, n=10) + with warns_deprecated_sympy(): + p[0].get_segments() + + +@pytest.mark.parametrize("adaptive", [True, False]) +def test_generic_data_series(adaptive): + # verify that no errors are raised when generic data series are used + if not matplotlib: + skip("Matplotlib not the default backend") + + x = Symbol("x") + p = plot(x, + markers=[{"args":[[0, 1], [0, 1]], "marker": "*", "linestyle": "none"}], + annotations=[{"text": "test", "xy": (0, 0)}], + fill={"x": [0, 1, 2, 3], "y1": [0, 1, 2, 3]}, + rectangles=[{"xy": (0, 0), "width": 5, "height": 1}], + adaptive=adaptive, n=10) + assert len(p._backend.ax.collections) == 1 + assert len(p._backend.ax.patches) == 1 + assert len(p._backend.ax.lines) == 2 + assert len(p._backend.ax.texts) == 1 + + +def test_deprecated_markers_annotations_rectangles_fill(): + if not matplotlib: + skip("Matplotlib not the default backend") + + x = Symbol('x') + p = plot(sin(x), (x, -10, 10), show=False) + with warns_deprecated_sympy(): + p.markers = [{"args":[[0, 1], [0, 1]], "marker": "*", "linestyle": "none"}] + assert len(p._series) == 2 + with warns_deprecated_sympy(): + p.annotations = [{"text": "test", "xy": (0, 0)}] + assert len(p._series) == 3 + with warns_deprecated_sympy(): + p.fill = {"x": [0, 1, 2, 3], "y1": [0, 1, 2, 3]} + assert len(p._series) == 4 + with warns_deprecated_sympy(): + p.rectangles = [{"xy": (0, 0), "width": 5, "height": 1}] + assert len(p._series) == 5 + + +def test_back_compatibility(): + if not matplotlib: + skip("Matplotlib not the default backend") + + x = Symbol('x') + y = Symbol('y') + p = plot(sin(x), adaptive=False, n=5) + assert len(p[0].get_points()) == 2 + assert len(p[0].get_data()) == 2 + p = plot_parametric(cos(x), sin(x), (x, 0, 2), adaptive=False, n=5) + assert len(p[0].get_points()) == 2 + assert len(p[0].get_data()) == 3 + p = plot3d_parametric_line(cos(x), sin(x), x, (x, 0, 2), + adaptive=False, n=5) + assert len(p[0].get_points()) == 3 + assert len(p[0].get_data()) == 4 + p = plot3d(cos(x**2 + y**2), (x, -pi, pi), (y, -pi, pi), n=5) + assert len(p[0].get_meshes()) == 3 + assert len(p[0].get_data()) == 3 + p = plot_contour(cos(x**2 + y**2), (x, -pi, pi), (y, -pi, pi), n=5) + assert len(p[0].get_meshes()) == 3 + assert len(p[0].get_data()) == 3 + p = plot3d_parametric_surface(x * cos(y), x * sin(y), x * cos(4 * y) / 2, + (x, 0, pi), (y, 0, 2*pi), n=5) + assert len(p[0].get_meshes()) == 3 + assert len(p[0].get_data()) == 5 + + +def test_plot_arguments(): + ### Test arguments for plot() + if not matplotlib: + skip("Matplotlib not the default backend") + + x, y = symbols("x, y") + + # single expressions + p = plot(x + 1) + assert isinstance(p[0], LineOver1DRangeSeries) + assert p[0].expr == x + 1 + assert p[0].ranges == [(x, -10, 10)] + assert p[0].get_label(False) == "x + 1" + assert p[0].rendering_kw == {} + + # single expressions custom label + p = plot(x + 1, "label") + assert isinstance(p[0], LineOver1DRangeSeries) + assert p[0].expr == x + 1 + assert p[0].ranges == [(x, -10, 10)] + assert p[0].get_label(False) == "label" + assert p[0].rendering_kw == {} + + # single expressions with range + p = plot(x + 1, (x, -2, 2)) + assert p[0].ranges == [(x, -2, 2)] + + # single expressions with range, label and rendering-kw dictionary + p = plot(x + 1, (x, -2, 2), "test", {"color": "r"}) + assert p[0].get_label(False) == "test" + assert p[0].rendering_kw == {"color": "r"} + + # multiple expressions + p = plot(x + 1, x**2) + assert isinstance(p[0], LineOver1DRangeSeries) + assert p[0].expr == x + 1 + assert p[0].ranges == [(x, -10, 10)] + assert p[0].get_label(False) == "x + 1" + assert p[0].rendering_kw == {} + assert isinstance(p[1], LineOver1DRangeSeries) + assert p[1].expr == x**2 + assert p[1].ranges == [(x, -10, 10)] + assert p[1].get_label(False) == "x**2" + assert p[1].rendering_kw == {} + + # multiple expressions over the same range + p = plot(x + 1, x**2, (x, 0, 5)) + assert p[0].ranges == [(x, 0, 5)] + assert p[1].ranges == [(x, 0, 5)] + + # multiple expressions over the same range with the same rendering kws + p = plot(x + 1, x**2, (x, 0, 5), {"color": "r"}) + assert p[0].ranges == [(x, 0, 5)] + assert p[1].ranges == [(x, 0, 5)] + assert p[0].rendering_kw == {"color": "r"} + assert p[1].rendering_kw == {"color": "r"} + + # multiple expressions with different ranges, labels and rendering kws + p = plot( + (x + 1, (x, 0, 5)), + (x**2, (x, -2, 2), "test", {"color": "r"})) + assert isinstance(p[0], LineOver1DRangeSeries) + assert p[0].expr == x + 1 + assert p[0].ranges == [(x, 0, 5)] + assert p[0].get_label(False) == "x + 1" + assert p[0].rendering_kw == {} + assert isinstance(p[1], LineOver1DRangeSeries) + assert p[1].expr == x**2 + assert p[1].ranges == [(x, -2, 2)] + assert p[1].get_label(False) == "test" + assert p[1].rendering_kw == {"color": "r"} + + # single argument: lambda function + f = lambda t: t + p = plot(lambda t: t) + assert isinstance(p[0], LineOver1DRangeSeries) + assert callable(p[0].expr) + assert p[0].ranges[0][1:] == (-10, 10) + assert p[0].get_label(False) == "" + assert p[0].rendering_kw == {} + + # single argument: lambda function + custom range and label + p = plot(f, ("t", -5, 6), "test") + assert p[0].ranges[0][1:] == (-5, 6) + assert p[0].get_label(False) == "test" + + +def test_plot_parametric_arguments(): + ### Test arguments for plot_parametric() + if not matplotlib: + skip("Matplotlib not the default backend") + + x, y = symbols("x, y") + + # single parametric expression + p = plot_parametric(x + 1, x) + assert isinstance(p[0], Parametric2DLineSeries) + assert p[0].expr == (x + 1, x) + assert p[0].ranges == [(x, -10, 10)] + assert p[0].get_label(False) == "x" + assert p[0].rendering_kw == {} + + # single parametric expression with custom range, label and rendering kws + p = plot_parametric(x + 1, x, (x, -2, 2), "test", + {"cmap": "Reds"}) + assert p[0].expr == (x + 1, x) + assert p[0].ranges == [(x, -2, 2)] + assert p[0].get_label(False) == "test" + assert p[0].rendering_kw == {"cmap": "Reds"} + + p = plot_parametric((x + 1, x), (x, -2, 2), "test") + assert p[0].expr == (x + 1, x) + assert p[0].ranges == [(x, -2, 2)] + assert p[0].get_label(False) == "test" + assert p[0].rendering_kw == {} + + # multiple parametric expressions same symbol + p = plot_parametric((x + 1, x), (x ** 2, x + 1)) + assert p[0].expr == (x + 1, x) + assert p[0].ranges == [(x, -10, 10)] + assert p[0].get_label(False) == "x" + assert p[0].rendering_kw == {} + assert p[1].expr == (x ** 2, x + 1) + assert p[1].ranges == [(x, -10, 10)] + assert p[1].get_label(False) == "x" + assert p[1].rendering_kw == {} + + # multiple parametric expressions different symbols + p = plot_parametric((x + 1, x), (y ** 2, y + 1, "test")) + assert p[0].expr == (x + 1, x) + assert p[0].ranges == [(x, -10, 10)] + assert p[0].get_label(False) == "x" + assert p[0].rendering_kw == {} + assert p[1].expr == (y ** 2, y + 1) + assert p[1].ranges == [(y, -10, 10)] + assert p[1].get_label(False) == "test" + assert p[1].rendering_kw == {} + + # multiple parametric expressions same range + p = plot_parametric((x + 1, x), (x ** 2, x + 1), (x, -2, 2)) + assert p[0].expr == (x + 1, x) + assert p[0].ranges == [(x, -2, 2)] + assert p[0].get_label(False) == "x" + assert p[0].rendering_kw == {} + assert p[1].expr == (x ** 2, x + 1) + assert p[1].ranges == [(x, -2, 2)] + assert p[1].get_label(False) == "x" + assert p[1].rendering_kw == {} + + # multiple parametric expressions, custom ranges and labels + p = plot_parametric( + (x + 1, x, (x, -2, 2), "test1"), + (x ** 2, x + 1, (x, -3, 3), "test2", {"cmap": "Reds"})) + assert p[0].expr == (x + 1, x) + assert p[0].ranges == [(x, -2, 2)] + assert p[0].get_label(False) == "test1" + assert p[0].rendering_kw == {} + assert p[1].expr == (x ** 2, x + 1) + assert p[1].ranges == [(x, -3, 3)] + assert p[1].get_label(False) == "test2" + assert p[1].rendering_kw == {"cmap": "Reds"} + + # single argument: lambda function + fx = lambda t: t + fy = lambda t: 2 * t + p = plot_parametric(fx, fy) + assert all(callable(t) for t in p[0].expr) + assert p[0].ranges[0][1:] == (-10, 10) + assert "Dummy" in p[0].get_label(False) + assert p[0].rendering_kw == {} + + # single argument: lambda function + custom range + label + p = plot_parametric(fx, fy, ("t", 0, 2), "test") + assert all(callable(t) for t in p[0].expr) + assert p[0].ranges[0][1:] == (0, 2) + assert p[0].get_label(False) == "test" + assert p[0].rendering_kw == {} + + +def test_plot3d_parametric_line_arguments(): + ### Test arguments for plot3d_parametric_line() + if not matplotlib: + skip("Matplotlib not the default backend") + + x, y = symbols("x, y") + + # single parametric expression + p = plot3d_parametric_line(x + 1, x, sin(x)) + assert isinstance(p[0], Parametric3DLineSeries) + assert p[0].expr == (x + 1, x, sin(x)) + assert p[0].ranges == [(x, -10, 10)] + assert p[0].get_label(False) == "x" + assert p[0].rendering_kw == {} + + # single parametric expression with custom range, label and rendering kws + p = plot3d_parametric_line(x + 1, x, sin(x), (x, -2, 2), + "test", {"cmap": "Reds"}) + assert isinstance(p[0], Parametric3DLineSeries) + assert p[0].expr == (x + 1, x, sin(x)) + assert p[0].ranges == [(x, -2, 2)] + assert p[0].get_label(False) == "test" + assert p[0].rendering_kw == {"cmap": "Reds"} + + p = plot3d_parametric_line((x + 1, x, sin(x)), (x, -2, 2), "test") + assert p[0].expr == (x + 1, x, sin(x)) + assert p[0].ranges == [(x, -2, 2)] + assert p[0].get_label(False) == "test" + assert p[0].rendering_kw == {} + + # multiple parametric expression same symbol + p = plot3d_parametric_line( + (x + 1, x, sin(x)), (x ** 2, 1, cos(x), {"cmap": "Reds"})) + assert p[0].expr == (x + 1, x, sin(x)) + assert p[0].ranges == [(x, -10, 10)] + assert p[0].get_label(False) == "x" + assert p[0].rendering_kw == {} + assert p[1].expr == (x ** 2, 1, cos(x)) + assert p[1].ranges == [(x, -10, 10)] + assert p[1].get_label(False) == "x" + assert p[1].rendering_kw == {"cmap": "Reds"} + + # multiple parametric expression different symbols + p = plot3d_parametric_line((x + 1, x, sin(x)), (y ** 2, 1, cos(y))) + assert p[0].expr == (x + 1, x, sin(x)) + assert p[0].ranges == [(x, -10, 10)] + assert p[0].get_label(False) == "x" + assert p[0].rendering_kw == {} + assert p[1].expr == (y ** 2, 1, cos(y)) + assert p[1].ranges == [(y, -10, 10)] + assert p[1].get_label(False) == "y" + assert p[1].rendering_kw == {} + + # multiple parametric expression, custom ranges and labels + p = plot3d_parametric_line( + (x + 1, x, sin(x)), + (x ** 2, 1, cos(x), (x, -2, 2), "test", {"cmap": "Reds"})) + assert p[0].expr == (x + 1, x, sin(x)) + assert p[0].ranges == [(x, -10, 10)] + assert p[0].get_label(False) == "x" + assert p[0].rendering_kw == {} + assert p[1].expr == (x ** 2, 1, cos(x)) + assert p[1].ranges == [(x, -2, 2)] + assert p[1].get_label(False) == "test" + assert p[1].rendering_kw == {"cmap": "Reds"} + + # single argument: lambda function + fx = lambda t: t + fy = lambda t: 2 * t + fz = lambda t: 3 * t + p = plot3d_parametric_line(fx, fy, fz) + assert all(callable(t) for t in p[0].expr) + assert p[0].ranges[0][1:] == (-10, 10) + assert "Dummy" in p[0].get_label(False) + assert p[0].rendering_kw == {} + + # single argument: lambda function + custom range + label + p = plot3d_parametric_line(fx, fy, fz, ("t", 0, 2), "test") + assert all(callable(t) for t in p[0].expr) + assert p[0].ranges[0][1:] == (0, 2) + assert p[0].get_label(False) == "test" + assert p[0].rendering_kw == {} + + +def test_plot3d_plot_contour_arguments(): + ### Test arguments for plot3d() and plot_contour() + if not matplotlib: + skip("Matplotlib not the default backend") + + x, y = symbols("x, y") + + # single expression + p = plot3d(x + y) + assert isinstance(p[0], SurfaceOver2DRangeSeries) + assert p[0].expr == x + y + assert p[0].ranges[0] == (x, -10, 10) or (y, -10, 10) + assert p[0].ranges[1] == (x, -10, 10) or (y, -10, 10) + assert p[0].get_label(False) == "x + y" + assert p[0].rendering_kw == {} + + # single expression, custom range, label and rendering kws + p = plot3d(x + y, (x, -2, 2), "test", {"cmap": "Reds"}) + assert isinstance(p[0], SurfaceOver2DRangeSeries) + assert p[0].expr == x + y + assert p[0].ranges[0] == (x, -2, 2) + assert p[0].ranges[1] == (y, -10, 10) + assert p[0].get_label(False) == "test" + assert p[0].rendering_kw == {"cmap": "Reds"} + + p = plot3d(x + y, (x, -2, 2), (y, -4, 4), "test") + assert p[0].ranges[0] == (x, -2, 2) + assert p[0].ranges[1] == (y, -4, 4) + + # multiple expressions + p = plot3d(x + y, x * y) + assert p[0].expr == x + y + assert p[0].ranges[0] == (x, -10, 10) or (y, -10, 10) + assert p[0].ranges[1] == (x, -10, 10) or (y, -10, 10) + assert p[0].get_label(False) == "x + y" + assert p[0].rendering_kw == {} + assert p[1].expr == x * y + assert p[1].ranges[0] == (x, -10, 10) or (y, -10, 10) + assert p[1].ranges[1] == (x, -10, 10) or (y, -10, 10) + assert p[1].get_label(False) == "x*y" + assert p[1].rendering_kw == {} + + # multiple expressions, same custom ranges + p = plot3d(x + y, x * y, (x, -2, 2), (y, -4, 4)) + assert p[0].expr == x + y + assert p[0].ranges[0] == (x, -2, 2) + assert p[0].ranges[1] == (y, -4, 4) + assert p[0].get_label(False) == "x + y" + assert p[0].rendering_kw == {} + assert p[1].expr == x * y + assert p[1].ranges[0] == (x, -2, 2) + assert p[1].ranges[1] == (y, -4, 4) + assert p[1].get_label(False) == "x*y" + assert p[1].rendering_kw == {} + + # multiple expressions, custom ranges, labels and rendering kws + p = plot3d( + (x + y, (x, -2, 2), (y, -4, 4)), + (x * y, (x, -3, 3), (y, -6, 6), "test", {"cmap": "Reds"})) + assert p[0].expr == x + y + assert p[0].ranges[0] == (x, -2, 2) + assert p[0].ranges[1] == (y, -4, 4) + assert p[0].get_label(False) == "x + y" + assert p[0].rendering_kw == {} + assert p[1].expr == x * y + assert p[1].ranges[0] == (x, -3, 3) + assert p[1].ranges[1] == (y, -6, 6) + assert p[1].get_label(False) == "test" + assert p[1].rendering_kw == {"cmap": "Reds"} + + # single expression: lambda function + f = lambda x, y: x + y + p = plot3d(f) + assert callable(p[0].expr) + assert p[0].ranges[0][1:] == (-10, 10) + assert p[0].ranges[1][1:] == (-10, 10) + assert p[0].get_label(False) == "" + assert p[0].rendering_kw == {} + + # single expression: lambda function + custom ranges + label + p = plot3d(f, ("a", -5, 3), ("b", -2, 1), "test") + assert callable(p[0].expr) + assert p[0].ranges[0][1:] == (-5, 3) + assert p[0].ranges[1][1:] == (-2, 1) + assert p[0].get_label(False) == "test" + assert p[0].rendering_kw == {} + + # test issue 25818 + # single expression, custom range, min/max functions + p = plot3d(Min(x, y), (x, 0, 10), (y, 0, 10)) + assert isinstance(p[0], SurfaceOver2DRangeSeries) + assert p[0].expr == Min(x, y) + assert p[0].ranges[0] == (x, 0, 10) + assert p[0].ranges[1] == (y, 0, 10) + assert p[0].get_label(False) == "Min(x, y)" + assert p[0].rendering_kw == {} + + +def test_plot3d_parametric_surface_arguments(): + ### Test arguments for plot3d_parametric_surface() + if not matplotlib: + skip("Matplotlib not the default backend") + + x, y = symbols("x, y") + + # single parametric expression + p = plot3d_parametric_surface(x + y, cos(x + y), sin(x + y)) + assert isinstance(p[0], ParametricSurfaceSeries) + assert p[0].expr == (x + y, cos(x + y), sin(x + y)) + assert p[0].ranges[0] == (x, -10, 10) or (y, -10, 10) + assert p[0].ranges[1] == (x, -10, 10) or (y, -10, 10) + assert p[0].get_label(False) == "(x + y, cos(x + y), sin(x + y))" + assert p[0].rendering_kw == {} + + # single parametric expression, custom ranges, labels and rendering kws + p = plot3d_parametric_surface(x + y, cos(x + y), sin(x + y), + (x, -2, 2), (y, -4, 4), "test", {"cmap": "Reds"}) + assert isinstance(p[0], ParametricSurfaceSeries) + assert p[0].expr == (x + y, cos(x + y), sin(x + y)) + assert p[0].ranges[0] == (x, -2, 2) + assert p[0].ranges[1] == (y, -4, 4) + assert p[0].get_label(False) == "test" + assert p[0].rendering_kw == {"cmap": "Reds"} + + # multiple parametric expressions + p = plot3d_parametric_surface( + (x + y, cos(x + y), sin(x + y)), + (x - y, cos(x - y), sin(x - y), "test")) + assert p[0].expr == (x + y, cos(x + y), sin(x + y)) + assert p[0].ranges[0] == (x, -10, 10) or (y, -10, 10) + assert p[0].ranges[1] == (x, -10, 10) or (y, -10, 10) + assert p[0].get_label(False) == "(x + y, cos(x + y), sin(x + y))" + assert p[0].rendering_kw == {} + assert p[1].expr == (x - y, cos(x - y), sin(x - y)) + assert p[1].ranges[0] == (x, -10, 10) or (y, -10, 10) + assert p[1].ranges[1] == (x, -10, 10) or (y, -10, 10) + assert p[1].get_label(False) == "test" + assert p[1].rendering_kw == {} + + # multiple parametric expressions, custom ranges and labels + p = plot3d_parametric_surface( + (x + y, cos(x + y), sin(x + y), (x, -2, 2), "test"), + (x - y, cos(x - y), sin(x - y), (x, -3, 3), (y, -4, 4), + "test2", {"cmap": "Reds"})) + assert p[0].expr == (x + y, cos(x + y), sin(x + y)) + assert p[0].ranges[0] == (x, -2, 2) + assert p[0].ranges[1] == (y, -10, 10) + assert p[0].get_label(False) == "test" + assert p[0].rendering_kw == {} + assert p[1].expr == (x - y, cos(x - y), sin(x - y)) + assert p[1].ranges[0] == (x, -3, 3) + assert p[1].ranges[1] == (y, -4, 4) + assert p[1].get_label(False) == "test2" + assert p[1].rendering_kw == {"cmap": "Reds"} + + # lambda functions instead of symbolic expressions for a single 3D + # parametric surface + p = plot3d_parametric_surface( + lambda u, v: u, lambda u, v: v, lambda u, v: u + v, + ("u", 0, 2), ("v", -3, 4)) + assert all(callable(t) for t in p[0].expr) + assert p[0].ranges[0][1:] == (-0, 2) + assert p[0].ranges[1][1:] == (-3, 4) + assert p[0].get_label(False) == "" + assert p[0].rendering_kw == {} + + # lambda functions instead of symbolic expressions for multiple 3D + # parametric surfaces + p = plot3d_parametric_surface( + (lambda u, v: u, lambda u, v: v, lambda u, v: u + v, + ("u", 0, 2), ("v", -3, 4)), + (lambda u, v: v, lambda u, v: u, lambda u, v: u - v, + ("u", -2, 3), ("v", -4, 5), "test")) + assert all(callable(t) for t in p[0].expr) + assert p[0].ranges[0][1:] == (0, 2) + assert p[0].ranges[1][1:] == (-3, 4) + assert p[0].get_label(False) == "" + assert p[0].rendering_kw == {} + assert all(callable(t) for t in p[1].expr) + assert p[1].ranges[0][1:] == (-2, 3) + assert p[1].ranges[1][1:] == (-4, 5) + assert p[1].get_label(False) == "test" + assert p[1].rendering_kw == {} diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_plot_implicit.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_plot_implicit.py new file mode 100644 index 0000000000000000000000000000000000000000..73c7b186c83f0b64d5f6f4cc5cd9f6a08efef43a --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_plot_implicit.py @@ -0,0 +1,146 @@ +from sympy.core.numbers import (I, pi) +from sympy.core.relational import Eq +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.elementary.complexes import re +from sympy.functions.elementary.exponential import exp +from sympy.functions.elementary.trigonometric import (cos, sin, tan) +from sympy.logic.boolalg import (And, Or) +from sympy.plotting.plot_implicit import plot_implicit +from sympy.plotting.plot import unset_show +from tempfile import NamedTemporaryFile, mkdtemp +from sympy.testing.pytest import skip, warns, XFAIL +from sympy.external import import_module +from sympy.testing.tmpfiles import TmpFileManager + +import os + +#Set plots not to show +unset_show() + +def tmp_file(dir=None, name=''): + return NamedTemporaryFile( + suffix='.png', dir=dir, delete=False).name + +def plot_and_save(expr, *args, name='', dir=None, **kwargs): + p = plot_implicit(expr, *args, **kwargs) + p.save(tmp_file(dir=dir, name=name)) + # Close the plot to avoid a warning from matplotlib + p._backend.close() + +def plot_implicit_tests(name): + temp_dir = mkdtemp() + TmpFileManager.tmp_folder(temp_dir) + x = Symbol('x') + y = Symbol('y') + #implicit plot tests + plot_and_save(Eq(y, cos(x)), (x, -5, 5), (y, -2, 2), name=name, dir=temp_dir) + plot_and_save(Eq(y**2, x**3 - x), (x, -5, 5), + (y, -4, 4), name=name, dir=temp_dir) + plot_and_save(y > 1 / x, (x, -5, 5), + (y, -2, 2), name=name, dir=temp_dir) + plot_and_save(y < 1 / tan(x), (x, -5, 5), + (y, -2, 2), name=name, dir=temp_dir) + plot_and_save(y >= 2 * sin(x) * cos(x), (x, -5, 5), + (y, -2, 2), name=name, dir=temp_dir) + plot_and_save(y <= x**2, (x, -3, 3), + (y, -1, 5), name=name, dir=temp_dir) + + #Test all input args for plot_implicit + plot_and_save(Eq(y**2, x**3 - x), dir=temp_dir) + plot_and_save(Eq(y**2, x**3 - x), adaptive=False, dir=temp_dir) + plot_and_save(Eq(y**2, x**3 - x), adaptive=False, n=500, dir=temp_dir) + plot_and_save(y > x, (x, -5, 5), dir=temp_dir) + plot_and_save(And(y > exp(x), y > x + 2), dir=temp_dir) + plot_and_save(Or(y > x, y > -x), dir=temp_dir) + plot_and_save(x**2 - 1, (x, -5, 5), dir=temp_dir) + plot_and_save(x**2 - 1, dir=temp_dir) + plot_and_save(y > x, depth=-5, dir=temp_dir) + plot_and_save(y > x, depth=5, dir=temp_dir) + plot_and_save(y > cos(x), adaptive=False, dir=temp_dir) + plot_and_save(y < cos(x), adaptive=False, dir=temp_dir) + plot_and_save(And(y > cos(x), Or(y > x, Eq(y, x))), dir=temp_dir) + plot_and_save(y - cos(pi / x), dir=temp_dir) + + plot_and_save(x**2 - 1, title='An implicit plot', dir=temp_dir) + +@XFAIL +def test_no_adaptive_meshing(): + matplotlib = import_module('matplotlib', min_module_version='1.1.0', catch=(RuntimeError,)) + if matplotlib: + try: + temp_dir = mkdtemp() + TmpFileManager.tmp_folder(temp_dir) + x = Symbol('x') + y = Symbol('y') + # Test plots which cannot be rendered using the adaptive algorithm + + # This works, but it triggers a deprecation warning from sympify(). The + # code needs to be updated to detect if interval math is supported without + # relying on random AttributeErrors. + with warns(UserWarning, match="Adaptive meshing could not be applied"): + plot_and_save(Eq(y, re(cos(x) + I*sin(x))), name='test', dir=temp_dir) + finally: + TmpFileManager.cleanup() + else: + skip("Matplotlib not the default backend") +def test_line_color(): + x, y = symbols('x, y') + p = plot_implicit(x**2 + y**2 - 1, line_color="green", show=False) + assert p._series[0].line_color == "green" + p = plot_implicit(x**2 + y**2 - 1, line_color='r', show=False) + assert p._series[0].line_color == "r" + +def test_matplotlib(): + matplotlib = import_module('matplotlib', min_module_version='1.1.0', catch=(RuntimeError,)) + if matplotlib: + try: + plot_implicit_tests('test') + test_line_color() + finally: + TmpFileManager.cleanup() + else: + skip("Matplotlib not the default backend") + + +def test_region_and(): + matplotlib = import_module('matplotlib', min_module_version='1.1.0', catch=(RuntimeError,)) + if not matplotlib: + skip("Matplotlib not the default backend") + + from matplotlib.testing.compare import compare_images + test_directory = os.path.dirname(os.path.abspath(__file__)) + + try: + temp_dir = mkdtemp() + TmpFileManager.tmp_folder(temp_dir) + + x, y = symbols('x y') + + r1 = (x - 1)**2 + y**2 < 2 + r2 = (x + 1)**2 + y**2 < 2 + + test_filename = tmp_file(dir=temp_dir, name="test_region_and") + cmp_filename = os.path.join(test_directory, "test_region_and.png") + p = plot_implicit(r1 & r2, x, y) + p.save(test_filename) + compare_images(cmp_filename, test_filename, 0.005) + + test_filename = tmp_file(dir=temp_dir, name="test_region_or") + cmp_filename = os.path.join(test_directory, "test_region_or.png") + p = plot_implicit(r1 | r2, x, y) + p.save(test_filename) + compare_images(cmp_filename, test_filename, 0.005) + + test_filename = tmp_file(dir=temp_dir, name="test_region_not") + cmp_filename = os.path.join(test_directory, "test_region_not.png") + p = plot_implicit(~r1, x, y) + p.save(test_filename) + compare_images(cmp_filename, test_filename, 0.005) + + test_filename = tmp_file(dir=temp_dir, name="test_region_xor") + cmp_filename = os.path.join(test_directory, "test_region_xor.png") + p = plot_implicit(r1 ^ r2, x, y) + p.save(test_filename) + compare_images(cmp_filename, test_filename, 0.005) + finally: + TmpFileManager.cleanup() diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_region_and.png b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_region_and.png new file mode 100644 index 0000000000000000000000000000000000000000..61dda4c2054e5e4bd5018cb84af86a832e81886a Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_region_and.png differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_region_not.png b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_region_not.png new file mode 100644 index 0000000000000000000000000000000000000000..29d3d47b5a95346cb7c44655c12a2a63e6c7a857 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_region_not.png differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_region_or.png b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_region_or.png new file mode 100644 index 0000000000000000000000000000000000000000..8a6329dd8dd368c37e431a7741e0869ec84f8f68 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_region_or.png differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_region_xor.png b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_region_xor.png new file mode 100644 index 0000000000000000000000000000000000000000..1a48862909d3ad09a5f4d306bf6c8f96117d080c Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_region_xor.png differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_series.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_series.py new file mode 100644 index 0000000000000000000000000000000000000000..9fdacbd73aef18b07d2e14ce444b709654ee6f23 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_series.py @@ -0,0 +1,1771 @@ +from sympy import ( + latex, exp, symbols, I, pi, sin, cos, tan, log, sqrt, + re, im, arg, frac, Sum, S, Abs, lambdify, + Function, dsolve, Eq, floor, Tuple +) +from sympy.external import import_module +from sympy.plotting.series import ( + LineOver1DRangeSeries, Parametric2DLineSeries, Parametric3DLineSeries, + SurfaceOver2DRangeSeries, ContourSeries, ParametricSurfaceSeries, + ImplicitSeries, _set_discretization_points, List2DSeries +) +from sympy.testing.pytest import raises, warns, XFAIL, skip, ignore_warnings + +np = import_module('numpy') + + +def test_adaptive(): + # verify that adaptive-related keywords produces the expected results + if not np: + skip("numpy not installed.") + + x, y = symbols("x, y") + + s1 = LineOver1DRangeSeries(sin(x), (x, -10, 10), "", adaptive=True, + depth=2) + x1, _ = s1.get_data() + s2 = LineOver1DRangeSeries(sin(x), (x, -10, 10), "", adaptive=True, + depth=5) + x2, _ = s2.get_data() + s3 = LineOver1DRangeSeries(sin(x), (x, -10, 10), "", adaptive=True) + x3, _ = s3.get_data() + assert len(x1) < len(x2) < len(x3) + + s1 = Parametric2DLineSeries(cos(x), sin(x), (x, 0, 2*pi), + adaptive=True, depth=2) + x1, _, _, = s1.get_data() + s2 = Parametric2DLineSeries(cos(x), sin(x), (x, 0, 2*pi), + adaptive=True, depth=5) + x2, _, _ = s2.get_data() + s3 = Parametric2DLineSeries(cos(x), sin(x), (x, 0, 2*pi), + adaptive=True) + x3, _, _ = s3.get_data() + assert len(x1) < len(x2) < len(x3) + + +def test_detect_poles(): + if not np: + skip("numpy not installed.") + + x, u = symbols("x, u") + + s1 = LineOver1DRangeSeries(tan(x), (x, -pi, pi), + adaptive=False, n=1000, detect_poles=False) + xx1, yy1 = s1.get_data() + s2 = LineOver1DRangeSeries(tan(x), (x, -pi, pi), + adaptive=False, n=1000, detect_poles=True, eps=0.01) + xx2, yy2 = s2.get_data() + # eps is too small: doesn't detect any poles + s3 = LineOver1DRangeSeries(tan(x), (x, -pi, pi), + adaptive=False, n=1000, detect_poles=True, eps=1e-06) + xx3, yy3 = s3.get_data() + s4 = LineOver1DRangeSeries(tan(x), (x, -pi, pi), + adaptive=False, n=1000, detect_poles="symbolic") + xx4, yy4 = s4.get_data() + + assert np.allclose(xx1, xx2) and np.allclose(xx1, xx3) and np.allclose(xx1, xx4) + assert not np.any(np.isnan(yy1)) + assert not np.any(np.isnan(yy3)) + assert np.any(np.isnan(yy2)) + assert np.any(np.isnan(yy4)) + assert len(s2.poles_locations) == len(s3.poles_locations) == 0 + assert len(s4.poles_locations) == 2 + assert np.allclose(np.abs(s4.poles_locations), np.pi / 2) + + with warns( + UserWarning, + match="NumPy is unable to evaluate with complex numbers some of", + test_stacklevel=False, + ): + s1 = LineOver1DRangeSeries(frac(x), (x, -10, 10), + adaptive=False, n=1000, detect_poles=False) + s2 = LineOver1DRangeSeries(frac(x), (x, -10, 10), + adaptive=False, n=1000, detect_poles=True, eps=0.05) + s3 = LineOver1DRangeSeries(frac(x), (x, -10, 10), + adaptive=False, n=1000, detect_poles="symbolic") + xx1, yy1 = s1.get_data() + xx2, yy2 = s2.get_data() + xx3, yy3 = s3.get_data() + assert np.allclose(xx1, xx2) and np.allclose(xx1, xx3) + assert not np.any(np.isnan(yy1)) + assert np.any(np.isnan(yy2)) and np.any(np.isnan(yy2)) + assert not np.allclose(yy1, yy2, equal_nan=True) + # The poles below are actually step discontinuities. + assert len(s3.poles_locations) == 21 + + s1 = LineOver1DRangeSeries(tan(u * x), (x, -pi, pi), params={u: 1}, + adaptive=False, n=1000, detect_poles=False) + xx1, yy1 = s1.get_data() + s2 = LineOver1DRangeSeries(tan(u * x), (x, -pi, pi), params={u: 1}, + adaptive=False, n=1000, detect_poles=True, eps=0.01) + xx2, yy2 = s2.get_data() + # eps is too small: doesn't detect any poles + s3 = LineOver1DRangeSeries(tan(u * x), (x, -pi, pi), params={u: 1}, + adaptive=False, n=1000, detect_poles=True, eps=1e-06) + xx3, yy3 = s3.get_data() + s4 = LineOver1DRangeSeries(tan(u * x), (x, -pi, pi), params={u: 1}, + adaptive=False, n=1000, detect_poles="symbolic") + xx4, yy4 = s4.get_data() + + assert np.allclose(xx1, xx2) and np.allclose(xx1, xx3) and np.allclose(xx1, xx4) + assert not np.any(np.isnan(yy1)) + assert not np.any(np.isnan(yy3)) + assert np.any(np.isnan(yy2)) + assert np.any(np.isnan(yy4)) + assert len(s2.poles_locations) == len(s3.poles_locations) == 0 + assert len(s4.poles_locations) == 2 + assert np.allclose(np.abs(s4.poles_locations), np.pi / 2) + + with warns( + UserWarning, + match="NumPy is unable to evaluate with complex numbers some of", + test_stacklevel=False, + ): + u, v = symbols("u, v", real=True) + n = S(1) / 3 + f = (u + I * v)**n + r, i = re(f), im(f) + s1 = Parametric2DLineSeries(r.subs(u, -2), i.subs(u, -2), (v, -2, 2), + adaptive=False, n=1000, detect_poles=False) + s2 = Parametric2DLineSeries(r.subs(u, -2), i.subs(u, -2), (v, -2, 2), + adaptive=False, n=1000, detect_poles=True) + with ignore_warnings(RuntimeWarning): + xx1, yy1, pp1 = s1.get_data() + assert not np.isnan(yy1).any() + xx2, yy2, pp2 = s2.get_data() + assert np.isnan(yy2).any() + + with warns( + UserWarning, + match="NumPy is unable to evaluate with complex numbers some of", + test_stacklevel=False, + ): + f = (x * u + x * I * v)**n + r, i = re(f), im(f) + s1 = Parametric2DLineSeries(r.subs(u, -2), i.subs(u, -2), + (v, -2, 2), params={x: 1}, + adaptive=False, n1=1000, detect_poles=False) + s2 = Parametric2DLineSeries(r.subs(u, -2), i.subs(u, -2), + (v, -2, 2), params={x: 1}, + adaptive=False, n1=1000, detect_poles=True) + with ignore_warnings(RuntimeWarning): + xx1, yy1, pp1 = s1.get_data() + assert not np.isnan(yy1).any() + xx2, yy2, pp2 = s2.get_data() + assert np.isnan(yy2).any() + + +def test_number_discretization_points(): + # verify that the different ways to set the number of discretization + # points are consistent with each other. + if not np: + skip("numpy not installed.") + + x, y, z = symbols("x:z") + + for pt in [LineOver1DRangeSeries, Parametric2DLineSeries, + Parametric3DLineSeries]: + kw1 = _set_discretization_points({"n": 10}, pt) + kw2 = _set_discretization_points({"n": [10, 20, 30]}, pt) + kw3 = _set_discretization_points({"n1": 10}, pt) + assert all(("n1" in kw) and kw["n1"] == 10 for kw in [kw1, kw2, kw3]) + + for pt in [SurfaceOver2DRangeSeries, ContourSeries, ParametricSurfaceSeries, + ImplicitSeries]: + kw1 = _set_discretization_points({"n": 10}, pt) + kw2 = _set_discretization_points({"n": [10, 20, 30]}, pt) + kw3 = _set_discretization_points({"n1": 10, "n2": 20}, pt) + assert kw1["n1"] == kw1["n2"] == 10 + assert all((kw["n1"] == 10) and (kw["n2"] == 20) for kw in [kw2, kw3]) + + # verify that line-related series can deal with large float number of + # discretization points + LineOver1DRangeSeries(cos(x), (x, -5, 5), adaptive=False, n=1e04).get_data() + + +def test_list2dseries(): + if not np: + skip("numpy not installed.") + + xx = np.linspace(-3, 3, 10) + yy1 = np.cos(xx) + yy2 = np.linspace(-3, 3, 20) + + # same number of elements: everything is fine + s = List2DSeries(xx, yy1) + assert not s.is_parametric + # different number of elements: error + raises(ValueError, lambda: List2DSeries(xx, yy2)) + + # no color func: returns only x, y components and s in not parametric + s = List2DSeries(xx, yy1) + xxs, yys = s.get_data() + assert np.allclose(xx, xxs) + assert np.allclose(yy1, yys) + assert not s.is_parametric + + +def test_interactive_vs_noninteractive(): + # verify that if a *Series class receives a `params` dictionary, it sets + # is_interactive=True + x, y, z, u, v = symbols("x, y, z, u, v") + + s = LineOver1DRangeSeries(cos(x), (x, -5, 5)) + assert not s.is_interactive + s = LineOver1DRangeSeries(u * cos(x), (x, -5, 5), params={u: 1}) + assert s.is_interactive + + s = Parametric2DLineSeries(cos(x), sin(x), (x, -5, 5)) + assert not s.is_interactive + s = Parametric2DLineSeries(u * cos(x), u * sin(x), (x, -5, 5), + params={u: 1}) + assert s.is_interactive + + s = Parametric3DLineSeries(cos(x), sin(x), x, (x, -5, 5)) + assert not s.is_interactive + s = Parametric3DLineSeries(u * cos(x), u * sin(x), x, (x, -5, 5), + params={u: 1}) + assert s.is_interactive + + s = SurfaceOver2DRangeSeries(cos(x * y), (x, -5, 5), (y, -5, 5)) + assert not s.is_interactive + s = SurfaceOver2DRangeSeries(u * cos(x * y), (x, -5, 5), (y, -5, 5), + params={u: 1}) + assert s.is_interactive + + s = ContourSeries(cos(x * y), (x, -5, 5), (y, -5, 5)) + assert not s.is_interactive + s = ContourSeries(u * cos(x * y), (x, -5, 5), (y, -5, 5), + params={u: 1}) + assert s.is_interactive + + s = ParametricSurfaceSeries(u * cos(v), v * sin(u), u + v, + (u, -5, 5), (v, -5, 5)) + assert not s.is_interactive + s = ParametricSurfaceSeries(u * cos(v * x), v * sin(u), u + v, + (u, -5, 5), (v, -5, 5), params={x: 1}) + assert s.is_interactive + + +def test_lin_log_scale(): + # Verify that data series create the correct spacing in the data. + if not np: + skip("numpy not installed.") + + x, y, z = symbols("x, y, z") + + s = LineOver1DRangeSeries(x, (x, 1, 10), adaptive=False, n=50, + xscale="linear") + xx, _ = s.get_data() + assert np.isclose(xx[1] - xx[0], xx[-1] - xx[-2]) + + s = LineOver1DRangeSeries(x, (x, 1, 10), adaptive=False, n=50, + xscale="log") + xx, _ = s.get_data() + assert not np.isclose(xx[1] - xx[0], xx[-1] - xx[-2]) + + s = Parametric2DLineSeries( + cos(x), sin(x), (x, pi / 2, 1.5 * pi), adaptive=False, n=50, + xscale="linear") + _, _, param = s.get_data() + assert np.isclose(param[1] - param[0], param[-1] - param[-2]) + + s = Parametric2DLineSeries( + cos(x), sin(x), (x, pi / 2, 1.5 * pi), adaptive=False, n=50, + xscale="log") + _, _, param = s.get_data() + assert not np.isclose(param[1] - param[0], param[-1] - param[-2]) + + s = Parametric3DLineSeries( + cos(x), sin(x), x, (x, pi / 2, 1.5 * pi), adaptive=False, n=50, + xscale="linear") + _, _, _, param = s.get_data() + assert np.isclose(param[1] - param[0], param[-1] - param[-2]) + + s = Parametric3DLineSeries( + cos(x), sin(x), x, (x, pi / 2, 1.5 * pi), adaptive=False, n=50, + xscale="log") + _, _, _, param = s.get_data() + assert not np.isclose(param[1] - param[0], param[-1] - param[-2]) + + s = SurfaceOver2DRangeSeries( + cos(x ** 2 + y ** 2), (x, 1, 5), (y, 1, 5), n=10, + xscale="linear", yscale="linear") + xx, yy, _ = s.get_data() + assert np.isclose(xx[0, 1] - xx[0, 0], xx[0, -1] - xx[0, -2]) + assert np.isclose(yy[1, 0] - yy[0, 0], yy[-1, 0] - yy[-2, 0]) + + s = SurfaceOver2DRangeSeries( + cos(x ** 2 + y ** 2), (x, 1, 5), (y, 1, 5), n=10, + xscale="log", yscale="log") + xx, yy, _ = s.get_data() + assert not np.isclose(xx[0, 1] - xx[0, 0], xx[0, -1] - xx[0, -2]) + assert not np.isclose(yy[1, 0] - yy[0, 0], yy[-1, 0] - yy[-2, 0]) + + s = ImplicitSeries( + cos(x ** 2 + y ** 2) > 0, (x, 1, 5), (y, 1, 5), + n1=10, n2=10, xscale="linear", yscale="linear", adaptive=False) + xx, yy, _, _ = s.get_data() + assert np.isclose(xx[0, 1] - xx[0, 0], xx[0, -1] - xx[0, -2]) + assert np.isclose(yy[1, 0] - yy[0, 0], yy[-1, 0] - yy[-2, 0]) + + s = ImplicitSeries( + cos(x ** 2 + y ** 2) > 0, (x, 1, 5), (y, 1, 5), + n=10, xscale="log", yscale="log", adaptive=False) + xx, yy, _, _ = s.get_data() + assert not np.isclose(xx[0, 1] - xx[0, 0], xx[0, -1] - xx[0, -2]) + assert not np.isclose(yy[1, 0] - yy[0, 0], yy[-1, 0] - yy[-2, 0]) + + +def test_rendering_kw(): + # verify that each series exposes the `rendering_kw` attribute + if not np: + skip("numpy not installed.") + + u, v, x, y, z = symbols("u, v, x:z") + + s = List2DSeries([1, 2, 3], [4, 5, 6]) + assert isinstance(s.rendering_kw, dict) + + s = LineOver1DRangeSeries(1, (x, -5, 5)) + assert isinstance(s.rendering_kw, dict) + + s = Parametric2DLineSeries(sin(x), cos(x), (x, 0, pi)) + assert isinstance(s.rendering_kw, dict) + + s = Parametric3DLineSeries(cos(x), sin(x), x, (x, 0, 2 * pi)) + assert isinstance(s.rendering_kw, dict) + + s = SurfaceOver2DRangeSeries(x + y, (x, -2, 2), (y, -3, 3)) + assert isinstance(s.rendering_kw, dict) + + s = ContourSeries(x + y, (x, -2, 2), (y, -3, 3)) + assert isinstance(s.rendering_kw, dict) + + s = ParametricSurfaceSeries(1, x, y, (x, 0, 1), (y, 0, 1)) + assert isinstance(s.rendering_kw, dict) + + +def test_data_shape(): + # Verify that the series produces the correct data shape when the input + # expression is a number. + if not np: + skip("numpy not installed.") + + u, x, y, z = symbols("u, x:z") + + # scalar expression: it should return a numpy ones array + s = LineOver1DRangeSeries(1, (x, -5, 5)) + xx, yy = s.get_data() + assert len(xx) == len(yy) + assert np.all(yy == 1) + + s = LineOver1DRangeSeries(1, (x, -5, 5), adaptive=False, n=10) + xx, yy = s.get_data() + assert len(xx) == len(yy) == 10 + assert np.all(yy == 1) + + s = Parametric2DLineSeries(sin(x), 1, (x, 0, pi)) + xx, yy, param = s.get_data() + assert (len(xx) == len(yy)) and (len(xx) == len(param)) + assert np.all(yy == 1) + + s = Parametric2DLineSeries(1, sin(x), (x, 0, pi)) + xx, yy, param = s.get_data() + assert (len(xx) == len(yy)) and (len(xx) == len(param)) + assert np.all(xx == 1) + + s = Parametric2DLineSeries(sin(x), 1, (x, 0, pi), adaptive=False) + xx, yy, param = s.get_data() + assert (len(xx) == len(yy)) and (len(xx) == len(param)) + assert np.all(yy == 1) + + s = Parametric2DLineSeries(1, sin(x), (x, 0, pi), adaptive=False) + xx, yy, param = s.get_data() + assert (len(xx) == len(yy)) and (len(xx) == len(param)) + assert np.all(xx == 1) + + s = Parametric3DLineSeries(cos(x), sin(x), 1, (x, 0, 2 * pi)) + xx, yy, zz, param = s.get_data() + assert (len(xx) == len(yy)) and (len(xx) == len(zz)) and (len(xx) == len(param)) + assert np.all(zz == 1) + + s = Parametric3DLineSeries(cos(x), 1, x, (x, 0, 2 * pi)) + xx, yy, zz, param = s.get_data() + assert (len(xx) == len(yy)) and (len(xx) == len(zz)) and (len(xx) == len(param)) + assert np.all(yy == 1) + + s = Parametric3DLineSeries(1, sin(x), x, (x, 0, 2 * pi)) + xx, yy, zz, param = s.get_data() + assert (len(xx) == len(yy)) and (len(xx) == len(zz)) and (len(xx) == len(param)) + assert np.all(xx == 1) + + s = SurfaceOver2DRangeSeries(1, (x, -2, 2), (y, -3, 3)) + xx, yy, zz = s.get_data() + assert (xx.shape == yy.shape) and (xx.shape == zz.shape) + assert np.all(zz == 1) + + s = ParametricSurfaceSeries(1, x, y, (x, 0, 1), (y, 0, 1)) + xx, yy, zz, uu, vv = s.get_data() + assert xx.shape == yy.shape == zz.shape == uu.shape == vv.shape + assert np.all(xx == 1) + + s = ParametricSurfaceSeries(1, 1, y, (x, 0, 1), (y, 0, 1)) + xx, yy, zz, uu, vv = s.get_data() + assert xx.shape == yy.shape == zz.shape == uu.shape == vv.shape + assert np.all(yy == 1) + + s = ParametricSurfaceSeries(x, 1, 1, (x, 0, 1), (y, 0, 1)) + xx, yy, zz, uu, vv = s.get_data() + assert xx.shape == yy.shape == zz.shape == uu.shape == vv.shape + assert np.all(zz == 1) + + +def test_only_integers(): + if not np: + skip("numpy not installed.") + + x, y, u, v = symbols("x, y, u, v") + + s = LineOver1DRangeSeries(sin(x), (x, -5.5, 4.5), "", + adaptive=False, only_integers=True) + xx, _ = s.get_data() + assert len(xx) == 10 + assert xx[0] == -5 and xx[-1] == 4 + + s = Parametric2DLineSeries(cos(x), sin(x), (x, 0, 2 * pi), "", + adaptive=False, only_integers=True) + _, _, p = s.get_data() + assert len(p) == 7 + assert p[0] == 0 and p[-1] == 6 + + s = Parametric3DLineSeries(cos(x), sin(x), x, (x, 0, 2 * pi), "", + adaptive=False, only_integers=True) + _, _, _, p = s.get_data() + assert len(p) == 7 + assert p[0] == 0 and p[-1] == 6 + + s = SurfaceOver2DRangeSeries(cos(x**2 + y**2), (x, -5.5, 5.5), + (y, -3.5, 3.5), "", + adaptive=False, only_integers=True) + xx, yy, _ = s.get_data() + assert xx.shape == yy.shape == (7, 11) + assert np.allclose(xx[:, 0] - (-5) * np.ones(7), 0) + assert np.allclose(xx[0, :] - np.linspace(-5, 5, 11), 0) + assert np.allclose(yy[:, 0] - np.linspace(-3, 3, 7), 0) + assert np.allclose(yy[0, :] - (-3) * np.ones(11), 0) + + r = 2 + sin(7 * u + 5 * v) + expr = ( + r * cos(u) * sin(v), + r * sin(u) * sin(v), + r * cos(v) + ) + s = ParametricSurfaceSeries(*expr, (u, 0, 2 * pi), (v, 0, pi), "", + adaptive=False, only_integers=True) + xx, yy, zz, uu, vv = s.get_data() + assert xx.shape == yy.shape == zz.shape == uu.shape == vv.shape == (4, 7) + + # only_integers also works with scalar expressions + s = LineOver1DRangeSeries(1, (x, -5.5, 4.5), "", + adaptive=False, only_integers=True) + xx, _ = s.get_data() + assert len(xx) == 10 + assert xx[0] == -5 and xx[-1] == 4 + + s = Parametric2DLineSeries(cos(x), 1, (x, 0, 2 * pi), "", + adaptive=False, only_integers=True) + _, _, p = s.get_data() + assert len(p) == 7 + assert p[0] == 0 and p[-1] == 6 + + s = SurfaceOver2DRangeSeries(1, (x, -5.5, 5.5), (y, -3.5, 3.5), "", + adaptive=False, only_integers=True) + xx, yy, _ = s.get_data() + assert xx.shape == yy.shape == (7, 11) + assert np.allclose(xx[:, 0] - (-5) * np.ones(7), 0) + assert np.allclose(xx[0, :] - np.linspace(-5, 5, 11), 0) + assert np.allclose(yy[:, 0] - np.linspace(-3, 3, 7), 0) + assert np.allclose(yy[0, :] - (-3) * np.ones(11), 0) + + r = 2 + sin(7 * u + 5 * v) + expr = ( + r * cos(u) * sin(v), + 1, + r * cos(v) + ) + s = ParametricSurfaceSeries(*expr, (u, 0, 2 * pi), (v, 0, pi), "", + adaptive=False, only_integers=True) + xx, yy, zz, uu, vv = s.get_data() + assert xx.shape == yy.shape == zz.shape == uu.shape == vv.shape == (4, 7) + + +def test_is_point_is_filled(): + # verify that `is_point` and `is_filled` are attributes and that they + # they receive the correct values + if not np: + skip("numpy not installed.") + + x, u = symbols("x, u") + + s = LineOver1DRangeSeries(cos(x), (x, -5, 5), "", + is_point=False, is_filled=True) + assert (not s.is_point) and s.is_filled + s = LineOver1DRangeSeries(cos(x), (x, -5, 5), "", + is_point=True, is_filled=False) + assert s.is_point and (not s.is_filled) + + s = List2DSeries([0, 1, 2], [3, 4, 5], + is_point=False, is_filled=True) + assert (not s.is_point) and s.is_filled + s = List2DSeries([0, 1, 2], [3, 4, 5], + is_point=True, is_filled=False) + assert s.is_point and (not s.is_filled) + + s = Parametric2DLineSeries(cos(x), sin(x), (x, -5, 5), + is_point=False, is_filled=True) + assert (not s.is_point) and s.is_filled + s = Parametric2DLineSeries(cos(x), sin(x), (x, -5, 5), + is_point=True, is_filled=False) + assert s.is_point and (not s.is_filled) + + s = Parametric3DLineSeries(cos(x), sin(x), x, (x, -5, 5), + is_point=False, is_filled=True) + assert (not s.is_point) and s.is_filled + s = Parametric3DLineSeries(cos(x), sin(x), x, (x, -5, 5), + is_point=True, is_filled=False) + assert s.is_point and (not s.is_filled) + + +def test_is_filled_2d(): + # verify that the is_filled attribute is exposed by the following series + x, y = symbols("x, y") + + expr = cos(x**2 + y**2) + ranges = (x, -2, 2), (y, -2, 2) + + s = ContourSeries(expr, *ranges) + assert s.is_filled + s = ContourSeries(expr, *ranges, is_filled=True) + assert s.is_filled + s = ContourSeries(expr, *ranges, is_filled=False) + assert not s.is_filled + + +def test_steps(): + if not np: + skip("numpy not installed.") + + x, u = symbols("x, u") + + def do_test(s1, s2): + if (not s1.is_parametric) and s1.is_2Dline: + xx1, _ = s1.get_data() + xx2, _ = s2.get_data() + elif s1.is_parametric and s1.is_2Dline: + xx1, _, _ = s1.get_data() + xx2, _, _ = s2.get_data() + elif (not s1.is_parametric) and s1.is_3Dline: + xx1, _, _ = s1.get_data() + xx2, _, _ = s2.get_data() + else: + xx1, _, _, _ = s1.get_data() + xx2, _, _, _ = s2.get_data() + assert len(xx1) != len(xx2) + + s1 = LineOver1DRangeSeries(cos(x), (x, -5, 5), "", + adaptive=False, n=40, steps=False) + s2 = LineOver1DRangeSeries(cos(x), (x, -5, 5), "", + adaptive=False, n=40, steps=True) + do_test(s1, s2) + + s1 = List2DSeries([0, 1, 2], [3, 4, 5], steps=False) + s2 = List2DSeries([0, 1, 2], [3, 4, 5], steps=True) + do_test(s1, s2) + + s1 = Parametric2DLineSeries(cos(x), sin(x), (x, -5, 5), + adaptive=False, n=40, steps=False) + s2 = Parametric2DLineSeries(cos(x), sin(x), (x, -5, 5), + adaptive=False, n=40, steps=True) + do_test(s1, s2) + + s1 = Parametric3DLineSeries(cos(x), sin(x), x, (x, -5, 5), + adaptive=False, n=40, steps=False) + s2 = Parametric3DLineSeries(cos(x), sin(x), x, (x, -5, 5), + adaptive=False, n=40, steps=True) + do_test(s1, s2) + + +def test_interactive_data(): + # verify that InteractiveSeries produces the same numerical data as their + # corresponding non-interactive series. + if not np: + skip("numpy not installed.") + + u, x, y, z = symbols("u, x:z") + + def do_test(data1, data2): + assert len(data1) == len(data2) + for d1, d2 in zip(data1, data2): + assert np.allclose(d1, d2) + + s1 = LineOver1DRangeSeries(u * cos(x), (x, -5, 5), params={u: 1}, n=50) + s2 = LineOver1DRangeSeries(cos(x), (x, -5, 5), adaptive=False, n=50) + do_test(s1.get_data(), s2.get_data()) + + s1 = Parametric2DLineSeries( + u * cos(x), u * sin(x), (x, -5, 5), params={u: 1}, n=50) + s2 = Parametric2DLineSeries(cos(x), sin(x), (x, -5, 5), + adaptive=False, n=50) + do_test(s1.get_data(), s2.get_data()) + + s1 = Parametric3DLineSeries( + u * cos(x), u * sin(x), u * x, (x, -5, 5), + params={u: 1}, n=50) + s2 = Parametric3DLineSeries(cos(x), sin(x), x, (x, -5, 5), + adaptive=False, n=50) + do_test(s1.get_data(), s2.get_data()) + + s1 = SurfaceOver2DRangeSeries( + u * cos(x ** 2 + y ** 2), (x, -3, 3), (y, -3, 3), + params={u: 1}, n1=50, n2=50,) + s2 = SurfaceOver2DRangeSeries( + cos(x ** 2 + y ** 2), (x, -3, 3), (y, -3, 3), + adaptive=False, n1=50, n2=50) + do_test(s1.get_data(), s2.get_data()) + + s1 = ParametricSurfaceSeries( + u * cos(x + y), sin(x + y), x - y, (x, -3, 3), (y, -3, 3), + params={u: 1}, n1=50, n2=50,) + s2 = ParametricSurfaceSeries( + cos(x + y), sin(x + y), x - y, (x, -3, 3), (y, -3, 3), + adaptive=False, n1=50, n2=50,) + do_test(s1.get_data(), s2.get_data()) + + # real part of a complex function evaluated over a real line with numpy + expr = re((z ** 2 + 1) / (z ** 2 - 1)) + s1 = LineOver1DRangeSeries(u * expr, (z, -3, 3), adaptive=False, n=50, + modules=None, params={u: 1}) + s2 = LineOver1DRangeSeries(expr, (z, -3, 3), adaptive=False, n=50, + modules=None) + do_test(s1.get_data(), s2.get_data()) + + # real part of a complex function evaluated over a real line with mpmath + expr = re((z ** 2 + 1) / (z ** 2 - 1)) + s1 = LineOver1DRangeSeries(u * expr, (z, -3, 3), n=50, modules="mpmath", + params={u: 1}) + s2 = LineOver1DRangeSeries(expr, (z, -3, 3), + adaptive=False, n=50, modules="mpmath") + do_test(s1.get_data(), s2.get_data()) + + +def test_list2dseries_interactive(): + if not np: + skip("numpy not installed.") + + x, y, u = symbols("x, y, u") + + s = List2DSeries([1, 2, 3], [1, 2, 3]) + assert not s.is_interactive + + # symbolic expressions as coordinates, but no ``params`` + raises(ValueError, lambda: List2DSeries([cos(x)], [sin(x)])) + + # too few parameters + raises(ValueError, + lambda: List2DSeries([cos(x), y], [sin(x), 2], params={u: 1})) + + s = List2DSeries([cos(x)], [sin(x)], params={x: 1}) + assert s.is_interactive + + s = List2DSeries([x, 2, 3, 4], [4, 3, 2, x], params={x: 3}) + xx, yy = s.get_data() + assert np.allclose(xx, [3, 2, 3, 4]) + assert np.allclose(yy, [4, 3, 2, 3]) + assert not s.is_parametric + + # numeric lists + params is present -> interactive series and + # lists are converted to Tuple. + s = List2DSeries([1, 2, 3], [1, 2, 3], params={x: 1}) + assert s.is_interactive + assert isinstance(s.list_x, Tuple) + assert isinstance(s.list_y, Tuple) + + +def test_mpmath(): + # test that the argument of complex functions evaluated with mpmath + # might be different than the one computed with Numpy (different + # behaviour at branch cuts) + if not np: + skip("numpy not installed.") + + z, u = symbols("z, u") + + s1 = LineOver1DRangeSeries(im(sqrt(-z)), (z, 1e-03, 5), + adaptive=True, modules=None, force_real_eval=True) + s2 = LineOver1DRangeSeries(im(sqrt(-z)), (z, 1e-03, 5), + adaptive=True, modules="mpmath", force_real_eval=True) + xx1, yy1 = s1.get_data() + xx2, yy2 = s2.get_data() + assert np.all(yy1 < 0) + assert np.all(yy2 > 0) + + s1 = LineOver1DRangeSeries(im(sqrt(-z)), (z, -5, 5), + adaptive=False, n=20, modules=None, force_real_eval=True) + s2 = LineOver1DRangeSeries(im(sqrt(-z)), (z, -5, 5), + adaptive=False, n=20, modules="mpmath", force_real_eval=True) + xx1, yy1 = s1.get_data() + xx2, yy2 = s2.get_data() + assert np.allclose(xx1, xx2) + assert not np.allclose(yy1, yy2) + + +def test_str(): + u, x, y, z = symbols("u, x:z") + + s = LineOver1DRangeSeries(cos(x), (x, -4, 3)) + assert str(s) == "cartesian line: cos(x) for x over (-4.0, 3.0)" + + d = {"return": "real"} + s = LineOver1DRangeSeries(cos(x), (x, -4, 3), **d) + assert str(s) == "cartesian line: re(cos(x)) for x over (-4.0, 3.0)" + + d = {"return": "imag"} + s = LineOver1DRangeSeries(cos(x), (x, -4, 3), **d) + assert str(s) == "cartesian line: im(cos(x)) for x over (-4.0, 3.0)" + + d = {"return": "abs"} + s = LineOver1DRangeSeries(cos(x), (x, -4, 3), **d) + assert str(s) == "cartesian line: abs(cos(x)) for x over (-4.0, 3.0)" + + d = {"return": "arg"} + s = LineOver1DRangeSeries(cos(x), (x, -4, 3), **d) + assert str(s) == "cartesian line: arg(cos(x)) for x over (-4.0, 3.0)" + + s = LineOver1DRangeSeries(cos(u * x), (x, -4, 3), params={u: 1}) + assert str(s) == "interactive cartesian line: cos(u*x) for x over (-4.0, 3.0) and parameters (u,)" + + s = LineOver1DRangeSeries(cos(u * x), (x, -u, 3*y), params={u: 1, y: 1}) + assert str(s) == "interactive cartesian line: cos(u*x) for x over (-u, 3*y) and parameters (u, y)" + + s = Parametric2DLineSeries(cos(x), sin(x), (x, -4, 3)) + assert str(s) == "parametric cartesian line: (cos(x), sin(x)) for x over (-4.0, 3.0)" + + s = Parametric2DLineSeries(cos(u * x), sin(x), (x, -4, 3), params={u: 1}) + assert str(s) == "interactive parametric cartesian line: (cos(u*x), sin(x)) for x over (-4.0, 3.0) and parameters (u,)" + + s = Parametric2DLineSeries(cos(u * x), sin(x), (x, -u, 3*y), params={u: 1, y:1}) + assert str(s) == "interactive parametric cartesian line: (cos(u*x), sin(x)) for x over (-u, 3*y) and parameters (u, y)" + + s = Parametric3DLineSeries(cos(x), sin(x), x, (x, -4, 3)) + assert str(s) == "3D parametric cartesian line: (cos(x), sin(x), x) for x over (-4.0, 3.0)" + + s = Parametric3DLineSeries(cos(u*x), sin(x), x, (x, -4, 3), params={u: 1}) + assert str(s) == "interactive 3D parametric cartesian line: (cos(u*x), sin(x), x) for x over (-4.0, 3.0) and parameters (u,)" + + s = Parametric3DLineSeries(cos(u*x), sin(x), x, (x, -u, 3*y), params={u: 1, y: 1}) + assert str(s) == "interactive 3D parametric cartesian line: (cos(u*x), sin(x), x) for x over (-u, 3*y) and parameters (u, y)" + + s = SurfaceOver2DRangeSeries(cos(x * y), (x, -4, 3), (y, -2, 5)) + assert str(s) == "cartesian surface: cos(x*y) for x over (-4.0, 3.0) and y over (-2.0, 5.0)" + + s = SurfaceOver2DRangeSeries(cos(u * x * y), (x, -4, 3), (y, -2, 5), params={u: 1}) + assert str(s) == "interactive cartesian surface: cos(u*x*y) for x over (-4.0, 3.0) and y over (-2.0, 5.0) and parameters (u,)" + + s = SurfaceOver2DRangeSeries(cos(u * x * y), (x, -4*u, 3), (y, -2, 5*u), params={u: 1}) + assert str(s) == "interactive cartesian surface: cos(u*x*y) for x over (-4*u, 3.0) and y over (-2.0, 5*u) and parameters (u,)" + + s = ContourSeries(cos(x * y), (x, -4, 3), (y, -2, 5)) + assert str(s) == "contour: cos(x*y) for x over (-4.0, 3.0) and y over (-2.0, 5.0)" + + s = ContourSeries(cos(u * x * y), (x, -4, 3), (y, -2, 5), params={u: 1}) + assert str(s) == "interactive contour: cos(u*x*y) for x over (-4.0, 3.0) and y over (-2.0, 5.0) and parameters (u,)" + + s = ParametricSurfaceSeries(cos(x * y), sin(x * y), x * y, + (x, -4, 3), (y, -2, 5)) + assert str(s) == "parametric cartesian surface: (cos(x*y), sin(x*y), x*y) for x over (-4.0, 3.0) and y over (-2.0, 5.0)" + + s = ParametricSurfaceSeries(cos(u * x * y), sin(x * y), x * y, + (x, -4, 3), (y, -2, 5), params={u: 1}) + assert str(s) == "interactive parametric cartesian surface: (cos(u*x*y), sin(x*y), x*y) for x over (-4.0, 3.0) and y over (-2.0, 5.0) and parameters (u,)" + + s = ImplicitSeries(x < y, (x, -5, 4), (y, -3, 2)) + assert str(s) == "Implicit expression: x < y for x over (-5.0, 4.0) and y over (-3.0, 2.0)" + + +def test_use_cm(): + # verify that the `use_cm` attribute is implemented. + if not np: + skip("numpy not installed.") + + u, x, y, z = symbols("u, x:z") + + s = List2DSeries([1, 2, 3, 4], [5, 6, 7, 8], use_cm=True) + assert s.use_cm + s = List2DSeries([1, 2, 3, 4], [5, 6, 7, 8], use_cm=False) + assert not s.use_cm + + s = Parametric2DLineSeries(cos(x), sin(x), (x, -4, 3), use_cm=True) + assert s.use_cm + s = Parametric2DLineSeries(cos(x), sin(x), (x, -4, 3), use_cm=False) + assert not s.use_cm + + s = Parametric3DLineSeries(cos(x), sin(x), x, (x, -4, 3), + use_cm=True) + assert s.use_cm + s = Parametric3DLineSeries(cos(x), sin(x), x, (x, -4, 3), + use_cm=False) + assert not s.use_cm + + s = SurfaceOver2DRangeSeries(cos(x * y), (x, -4, 3), (y, -2, 5), + use_cm=True) + assert s.use_cm + s = SurfaceOver2DRangeSeries(cos(x * y), (x, -4, 3), (y, -2, 5), + use_cm=False) + assert not s.use_cm + + s = ParametricSurfaceSeries(cos(x * y), sin(x * y), x * y, + (x, -4, 3), (y, -2, 5), use_cm=True) + assert s.use_cm + s = ParametricSurfaceSeries(cos(x * y), sin(x * y), x * y, + (x, -4, 3), (y, -2, 5), use_cm=False) + assert not s.use_cm + + +def test_surface_use_cm(): + # verify that SurfaceOver2DRangeSeries and ParametricSurfaceSeries get + # the same value for use_cm + + x, y, u, v = symbols("x, y, u, v") + + # they read the same value from default settings + s1 = SurfaceOver2DRangeSeries(cos(x**2 + y**2), (x, -2, 2), (y, -2, 2)) + s2 = ParametricSurfaceSeries(u * cos(v), u * sin(v), u, + (u, 0, 1), (v, 0 , 2*pi)) + assert s1.use_cm == s2.use_cm + + # they get the same value + s1 = SurfaceOver2DRangeSeries(cos(x**2 + y**2), (x, -2, 2), (y, -2, 2), + use_cm=False) + s2 = ParametricSurfaceSeries(u * cos(v), u * sin(v), u, + (u, 0, 1), (v, 0 , 2*pi), use_cm=False) + assert s1.use_cm == s2.use_cm + + # they get the same value + s1 = SurfaceOver2DRangeSeries(cos(x**2 + y**2), (x, -2, 2), (y, -2, 2), + use_cm=True) + s2 = ParametricSurfaceSeries(u * cos(v), u * sin(v), u, + (u, 0, 1), (v, 0 , 2*pi), use_cm=True) + assert s1.use_cm == s2.use_cm + + +def test_sums(): + # test that data series are able to deal with sums + if not np: + skip("numpy not installed.") + + x, y, u = symbols("x, y, u") + + def do_test(data1, data2): + assert len(data1) == len(data2) + for d1, d2 in zip(data1, data2): + assert np.allclose(d1, d2) + + s = LineOver1DRangeSeries(Sum(1 / x ** y, (x, 1, 1000)), (y, 2, 10), + adaptive=False, only_integers=True) + xx, yy = s.get_data() + + s1 = LineOver1DRangeSeries(Sum(1 / x, (x, 1, y)), (y, 2, 10), + adaptive=False, only_integers=True) + xx1, yy1 = s1.get_data() + + s2 = LineOver1DRangeSeries(Sum(u / x, (x, 1, y)), (y, 2, 10), + params={u: 1}, only_integers=True) + xx2, yy2 = s2.get_data() + xx1 = xx1.astype(float) + xx2 = xx2.astype(float) + do_test([xx1, yy1], [xx2, yy2]) + + s = LineOver1DRangeSeries(Sum(1 / x, (x, 1, y)), (y, 2, 10), + adaptive=True) + with warns( + UserWarning, + match="The evaluation with NumPy/SciPy failed", + test_stacklevel=False, + ): + raises(TypeError, lambda: s.get_data()) + + +def test_apply_transforms(): + # verify that transformation functions get applied to the output + # of data series + if not np: + skip("numpy not installed.") + + x, y, z, u, v = symbols("x:z, u, v") + + s1 = LineOver1DRangeSeries(cos(x), (x, -2*pi, 2*pi), adaptive=False, n=10) + s2 = LineOver1DRangeSeries(cos(x), (x, -2*pi, 2*pi), adaptive=False, n=10, + tx=np.rad2deg) + s3 = LineOver1DRangeSeries(cos(x), (x, -2*pi, 2*pi), adaptive=False, n=10, + ty=np.rad2deg) + s4 = LineOver1DRangeSeries(cos(x), (x, -2*pi, 2*pi), adaptive=False, n=10, + tx=np.rad2deg, ty=np.rad2deg) + + x1, y1 = s1.get_data() + x2, y2 = s2.get_data() + x3, y3 = s3.get_data() + x4, y4 = s4.get_data() + assert np.isclose(x1[0], -2*np.pi) and np.isclose(x1[-1], 2*np.pi) + assert (y1.min() < -0.9) and (y1.max() > 0.9) + assert np.isclose(x2[0], -360) and np.isclose(x2[-1], 360) + assert (y2.min() < -0.9) and (y2.max() > 0.9) + assert np.isclose(x3[0], -2*np.pi) and np.isclose(x3[-1], 2*np.pi) + assert (y3.min() < -52) and (y3.max() > 52) + assert np.isclose(x4[0], -360) and np.isclose(x4[-1], 360) + assert (y4.min() < -52) and (y4.max() > 52) + + xx = np.linspace(-2*np.pi, 2*np.pi, 10) + yy = np.cos(xx) + s1 = List2DSeries(xx, yy) + s2 = List2DSeries(xx, yy, tx=np.rad2deg, ty=np.rad2deg) + x1, y1 = s1.get_data() + x2, y2 = s2.get_data() + assert np.isclose(x1[0], -2*np.pi) and np.isclose(x1[-1], 2*np.pi) + assert (y1.min() < -0.9) and (y1.max() > 0.9) + assert np.isclose(x2[0], -360) and np.isclose(x2[-1], 360) + assert (y2.min() < -52) and (y2.max() > 52) + + s1 = Parametric2DLineSeries( + sin(x), cos(x), (x, -pi, pi), adaptive=False, n=10) + s2 = Parametric2DLineSeries( + sin(x), cos(x), (x, -pi, pi), adaptive=False, n=10, + tx=np.rad2deg, ty=np.rad2deg, tp=np.rad2deg) + x1, y1, a1 = s1.get_data() + x2, y2, a2 = s2.get_data() + assert np.allclose(x1, np.deg2rad(x2)) + assert np.allclose(y1, np.deg2rad(y2)) + assert np.allclose(a1, np.deg2rad(a2)) + + s1 = Parametric3DLineSeries( + sin(x), cos(x), x, (x, -pi, pi), adaptive=False, n=10) + s2 = Parametric3DLineSeries( + sin(x), cos(x), x, (x, -pi, pi), adaptive=False, n=10, tp=np.rad2deg) + x1, y1, z1, a1 = s1.get_data() + x2, y2, z2, a2 = s2.get_data() + assert np.allclose(x1, x2) + assert np.allclose(y1, y2) + assert np.allclose(z1, z2) + assert np.allclose(a1, np.deg2rad(a2)) + + s1 = SurfaceOver2DRangeSeries( + cos(x**2 + y**2), (x, -2*pi, 2*pi), (y, -2*pi, 2*pi), + adaptive=False, n1=10, n2=10) + s2 = SurfaceOver2DRangeSeries( + cos(x**2 + y**2), (x, -2*pi, 2*pi), (y, -2*pi, 2*pi), + adaptive=False, n1=10, n2=10, + tx=np.rad2deg, ty=lambda x: 2*x, tz=lambda x: 3*x) + x1, y1, z1 = s1.get_data() + x2, y2, z2 = s2.get_data() + assert np.allclose(x1, np.deg2rad(x2)) + assert np.allclose(y1, y2 / 2) + assert np.allclose(z1, z2 / 3) + + s1 = ParametricSurfaceSeries( + u + v, u - v, u * v, (u, 0, 2*pi), (v, 0, pi), + adaptive=False, n1=10, n2=10) + s2 = ParametricSurfaceSeries( + u + v, u - v, u * v, (u, 0, 2*pi), (v, 0, pi), + adaptive=False, n1=10, n2=10, + tx=np.rad2deg, ty=lambda x: 2*x, tz=lambda x: 3*x) + x1, y1, z1, u1, v1 = s1.get_data() + x2, y2, z2, u2, v2 = s2.get_data() + assert np.allclose(x1, np.deg2rad(x2)) + assert np.allclose(y1, y2 / 2) + assert np.allclose(z1, z2 / 3) + assert np.allclose(u1, u2) + assert np.allclose(v1, v2) + + +def test_series_labels(): + # verify that series return the correct label, depending on the plot + # type and input arguments. If the user set custom label on a data series, + # it should returned un-modified. + if not np: + skip("numpy not installed.") + + x, y, z, u, v = symbols("x, y, z, u, v") + wrapper = "$%s$" + + expr = cos(x) + s1 = LineOver1DRangeSeries(expr, (x, -2, 2), None) + s2 = LineOver1DRangeSeries(expr, (x, -2, 2), "test") + assert s1.get_label(False) == str(expr) + assert s1.get_label(True) == wrapper % latex(expr) + assert s2.get_label(False) == "test" + assert s2.get_label(True) == "test" + + s1 = List2DSeries([0, 1, 2, 3], [0, 1, 2, 3], "test") + assert s1.get_label(False) == "test" + assert s1.get_label(True) == "test" + + expr = (cos(x), sin(x)) + s1 = Parametric2DLineSeries(*expr, (x, -2, 2), None, use_cm=True) + s2 = Parametric2DLineSeries(*expr, (x, -2, 2), "test", use_cm=True) + s3 = Parametric2DLineSeries(*expr, (x, -2, 2), None, use_cm=False) + s4 = Parametric2DLineSeries(*expr, (x, -2, 2), "test", use_cm=False) + assert s1.get_label(False) == "x" + assert s1.get_label(True) == wrapper % "x" + assert s2.get_label(False) == "test" + assert s2.get_label(True) == "test" + assert s3.get_label(False) == str(expr) + assert s3.get_label(True) == wrapper % latex(expr) + assert s4.get_label(False) == "test" + assert s4.get_label(True) == "test" + + expr = (cos(x), sin(x), x) + s1 = Parametric3DLineSeries(*expr, (x, -2, 2), None, use_cm=True) + s2 = Parametric3DLineSeries(*expr, (x, -2, 2), "test", use_cm=True) + s3 = Parametric3DLineSeries(*expr, (x, -2, 2), None, use_cm=False) + s4 = Parametric3DLineSeries(*expr, (x, -2, 2), "test", use_cm=False) + assert s1.get_label(False) == "x" + assert s1.get_label(True) == wrapper % "x" + assert s2.get_label(False) == "test" + assert s2.get_label(True) == "test" + assert s3.get_label(False) == str(expr) + assert s3.get_label(True) == wrapper % latex(expr) + assert s4.get_label(False) == "test" + assert s4.get_label(True) == "test" + + expr = cos(x**2 + y**2) + s1 = SurfaceOver2DRangeSeries(expr, (x, -2, 2), (y, -2, 2), None) + s2 = SurfaceOver2DRangeSeries(expr, (x, -2, 2), (y, -2, 2), "test") + assert s1.get_label(False) == str(expr) + assert s1.get_label(True) == wrapper % latex(expr) + assert s2.get_label(False) == "test" + assert s2.get_label(True) == "test" + + expr = (cos(x - y), sin(x + y), x - y) + s1 = ParametricSurfaceSeries(*expr, (x, -2, 2), (y, -2, 2), None) + s2 = ParametricSurfaceSeries(*expr, (x, -2, 2), (y, -2, 2), "test") + assert s1.get_label(False) == str(expr) + assert s1.get_label(True) == wrapper % latex(expr) + assert s2.get_label(False) == "test" + assert s2.get_label(True) == "test" + + expr = Eq(cos(x - y), 0) + s1 = ImplicitSeries(expr, (x, -10, 10), (y, -10, 10), None) + s2 = ImplicitSeries(expr, (x, -10, 10), (y, -10, 10), "test") + assert s1.get_label(False) == str(expr) + assert s1.get_label(True) == wrapper % latex(expr) + assert s2.get_label(False) == "test" + assert s2.get_label(True) == "test" + + +def test_is_polar_2d_parametric(): + # verify that Parametric2DLineSeries isable to apply polar discretization, + # which is used when polar_plot is executed with polar_axis=True + if not np: + skip("numpy not installed.") + + t, u = symbols("t u") + + # NOTE: a sufficiently big n must be provided, or else tests + # are going to fail + # No colormap + f = sin(4 * t) + s1 = Parametric2DLineSeries(f * cos(t), f * sin(t), (t, 0, 2*pi), + adaptive=False, n=10, is_polar=False, use_cm=False) + x1, y1, p1 = s1.get_data() + s2 = Parametric2DLineSeries(f * cos(t), f * sin(t), (t, 0, 2*pi), + adaptive=False, n=10, is_polar=True, use_cm=False) + th, r, p2 = s2.get_data() + assert (not np.allclose(x1, th)) and (not np.allclose(y1, r)) + assert np.allclose(p1, p2) + + # With colormap + s3 = Parametric2DLineSeries(f * cos(t), f * sin(t), (t, 0, 2*pi), + adaptive=False, n=10, is_polar=False, color_func=lambda t: 2*t) + x3, y3, p3 = s3.get_data() + s4 = Parametric2DLineSeries(f * cos(t), f * sin(t), (t, 0, 2*pi), + adaptive=False, n=10, is_polar=True, color_func=lambda t: 2*t) + th4, r4, p4 = s4.get_data() + assert np.allclose(p3, p4) and (not np.allclose(p1, p3)) + assert np.allclose(x3, x1) and np.allclose(y3, y1) + assert np.allclose(th4, th) and np.allclose(r4, r) + + +def test_is_polar_3d(): + # verify that SurfaceOver2DRangeSeries is able to apply + # polar discretization + if not np: + skip("numpy not installed.") + + x, y, t = symbols("x, y, t") + expr = (x**2 - 1)**2 + s1 = SurfaceOver2DRangeSeries(expr, (x, 0, 1.5), (y, 0, 2 * pi), + n=10, adaptive=False, is_polar=False) + s2 = SurfaceOver2DRangeSeries(expr, (x, 0, 1.5), (y, 0, 2 * pi), + n=10, adaptive=False, is_polar=True) + x1, y1, z1 = s1.get_data() + x2, y2, z2 = s2.get_data() + x22, y22 = x1 * np.cos(y1), x1 * np.sin(y1) + assert np.allclose(x2, x22) + assert np.allclose(y2, y22) + + +def test_color_func(): + # verify that eval_color_func produces the expected results in order to + # maintain back compatibility with the old sympy.plotting module + if not np: + skip("numpy not installed.") + + x, y, z, u, v = symbols("x, y, z, u, v") + + # color func: returns x, y, color and s is parametric + xx = np.linspace(-3, 3, 10) + yy1 = np.cos(xx) + s = List2DSeries(xx, yy1, color_func=lambda x, y: 2 * x, use_cm=True) + xxs, yys, col = s.get_data() + assert np.allclose(xx, xxs) + assert np.allclose(yy1, yys) + assert np.allclose(2 * xx, col) + assert s.is_parametric + + s = List2DSeries(xx, yy1, color_func=lambda x, y: 2 * x, use_cm=False) + assert len(s.get_data()) == 2 + assert not s.is_parametric + + s = Parametric2DLineSeries(cos(x), sin(x), (x, 0, 2*pi), + adaptive=False, n=10, color_func=lambda t: t) + xx, yy, col = s.get_data() + assert (not np.allclose(xx, col)) and (not np.allclose(yy, col)) + s = Parametric2DLineSeries(cos(x), sin(x), (x, 0, 2*pi), + adaptive=False, n=10, color_func=lambda x, y: x * y) + xx, yy, col = s.get_data() + assert np.allclose(col, xx * yy) + s = Parametric2DLineSeries(cos(x), sin(x), (x, 0, 2*pi), + adaptive=False, n=10, color_func=lambda x, y, t: x * y * t) + xx, yy, col = s.get_data() + assert np.allclose(col, xx * yy * np.linspace(0, 2*np.pi, 10)) + + s = Parametric3DLineSeries(cos(x), sin(x), x, (x, 0, 2*pi), + adaptive=False, n=10, color_func=lambda t: t) + xx, yy, zz, col = s.get_data() + assert (not np.allclose(xx, col)) and (not np.allclose(yy, col)) + s = Parametric3DLineSeries(cos(x), sin(x), x, (x, 0, 2*pi), + adaptive=False, n=10, color_func=lambda x, y, z: x * y * z) + xx, yy, zz, col = s.get_data() + assert np.allclose(col, xx * yy * zz) + s = Parametric3DLineSeries(cos(x), sin(x), x, (x, 0, 2*pi), + adaptive=False, n=10, color_func=lambda x, y, z, t: x * y * z * t) + xx, yy, zz, col = s.get_data() + assert np.allclose(col, xx * yy * zz * np.linspace(0, 2*np.pi, 10)) + + s = SurfaceOver2DRangeSeries(cos(x**2 + y**2), (x, -2, 2), (y, -2, 2), + adaptive=False, n1=10, n2=10, color_func=lambda x: x) + xx, yy, zz = s.get_data() + col = s.eval_color_func(xx, yy, zz) + assert np.allclose(xx, col) + s = SurfaceOver2DRangeSeries(cos(x**2 + y**2), (x, -2, 2), (y, -2, 2), + adaptive=False, n1=10, n2=10, color_func=lambda x, y: x * y) + xx, yy, zz = s.get_data() + col = s.eval_color_func(xx, yy, zz) + assert np.allclose(xx * yy, col) + s = SurfaceOver2DRangeSeries(cos(x**2 + y**2), (x, -2, 2), (y, -2, 2), + adaptive=False, n1=10, n2=10, color_func=lambda x, y, z: x * y * z) + xx, yy, zz = s.get_data() + col = s.eval_color_func(xx, yy, zz) + assert np.allclose(xx * yy * zz, col) + + s = ParametricSurfaceSeries(1, x, y, (x, 0, 1), (y, 0, 1), adaptive=False, + n1=10, n2=10, color_func=lambda u:u) + xx, yy, zz, uu, vv = s.get_data() + col = s.eval_color_func(xx, yy, zz, uu, vv) + assert np.allclose(uu, col) + s = ParametricSurfaceSeries(1, x, y, (x, 0, 1), (y, 0, 1), adaptive=False, + n1=10, n2=10, color_func=lambda u, v: u * v) + xx, yy, zz, uu, vv = s.get_data() + col = s.eval_color_func(xx, yy, zz, uu, vv) + assert np.allclose(uu * vv, col) + s = ParametricSurfaceSeries(1, x, y, (x, 0, 1), (y, 0, 1), adaptive=False, + n1=10, n2=10, color_func=lambda x, y, z: x * y * z) + xx, yy, zz, uu, vv = s.get_data() + col = s.eval_color_func(xx, yy, zz, uu, vv) + assert np.allclose(xx * yy * zz, col) + s = ParametricSurfaceSeries(1, x, y, (x, 0, 1), (y, 0, 1), adaptive=False, + n1=10, n2=10, color_func=lambda x, y, z, u, v: x * y * z * u * v) + xx, yy, zz, uu, vv = s.get_data() + col = s.eval_color_func(xx, yy, zz, uu, vv) + assert np.allclose(xx * yy * zz * uu * vv, col) + + # Interactive Series + s = List2DSeries([0, 1, 2, x], [x, 2, 3, 4], + color_func=lambda x, y: 2 * x, params={x: 1}, use_cm=True) + xx, yy, col = s.get_data() + assert np.allclose(xx, [0, 1, 2, 1]) + assert np.allclose(yy, [1, 2, 3, 4]) + assert np.allclose(2 * xx, col) + assert s.is_parametric and s.use_cm + + s = List2DSeries([0, 1, 2, x], [x, 2, 3, 4], + color_func=lambda x, y: 2 * x, params={x: 1}, use_cm=False) + assert len(s.get_data()) == 2 + assert not s.is_parametric + + +def test_color_func_scalar_val(): + # verify that eval_color_func returns a numpy array even when color_func + # evaluates to a scalar value + if not np: + skip("numpy not installed.") + + x, y = symbols("x, y") + + s = Parametric2DLineSeries(cos(x), sin(x), (x, 0, 2*pi), + adaptive=False, n=10, color_func=lambda t: 1) + xx, yy, col = s.get_data() + assert np.allclose(col, np.ones(xx.shape)) + + s = Parametric3DLineSeries(cos(x), sin(x), x, (x, 0, 2*pi), + adaptive=False, n=10, color_func=lambda t: 1) + xx, yy, zz, col = s.get_data() + assert np.allclose(col, np.ones(xx.shape)) + + s = SurfaceOver2DRangeSeries(cos(x**2 + y**2), (x, -2, 2), (y, -2, 2), + adaptive=False, n1=10, n2=10, color_func=lambda x: 1) + xx, yy, zz = s.get_data() + assert np.allclose(s.eval_color_func(xx), np.ones(xx.shape)) + + s = ParametricSurfaceSeries(1, x, y, (x, 0, 1), (y, 0, 1), adaptive=False, + n1=10, n2=10, color_func=lambda u: 1) + xx, yy, zz, uu, vv = s.get_data() + col = s.eval_color_func(xx, yy, zz, uu, vv) + assert np.allclose(col, np.ones(xx.shape)) + + +def test_color_func_expression(): + # verify that color_func is able to deal with instances of Expr: they will + # be lambdified with the same signature used for the main expression. + if not np: + skip("numpy not installed.") + + x, y = symbols("x, y") + + s1 = Parametric2DLineSeries(cos(x), sin(x), (x, 0, 2*pi), + color_func=sin(x), adaptive=False, n=10, use_cm=True) + s2 = Parametric2DLineSeries(cos(x), sin(x), (x, 0, 2*pi), + color_func=lambda x: np.cos(x), adaptive=False, n=10, use_cm=True) + # the following statement should not raise errors + d1 = s1.get_data() + assert callable(s1.color_func) + d2 = s2.get_data() + assert not np.allclose(d1[-1], d2[-1]) + + s = SurfaceOver2DRangeSeries(cos(x**2 + y**2), (x, -pi, pi), (y, -pi, pi), + color_func=sin(x**2 + y**2), adaptive=False, n1=5, n2=5) + # the following statement should not raise errors + s.get_data() + assert callable(s.color_func) + + xx = [1, 2, 3, 4, 5] + yy = [1, 2, 3, 4, 5] + raises(TypeError, + lambda : List2DSeries(xx, yy, use_cm=True, color_func=sin(x))) + + +def test_line_surface_color(): + # verify the back-compatibility with the old sympy.plotting module. + # By setting line_color or surface_color to be a callable, it will set + # the color_func attribute. + + x, y, z = symbols("x, y, z") + + s = LineOver1DRangeSeries(sin(x), (x, -5, 5), adaptive=False, n=10, + line_color=lambda x: x) + assert (s.line_color is None) and callable(s.color_func) + + s = Parametric2DLineSeries(cos(x), sin(x), (x, 0, 2*pi), + adaptive=False, n=10, line_color=lambda t: t) + assert (s.line_color is None) and callable(s.color_func) + + s = SurfaceOver2DRangeSeries(cos(x**2 + y**2), (x, -2, 2), (y, -2, 2), + n1=10, n2=10, surface_color=lambda x: x) + assert (s.surface_color is None) and callable(s.color_func) + + +def test_complex_adaptive_false(): + # verify that series with adaptive=False is evaluated with discretized + # ranges of type complex. + if not np: + skip("numpy not installed.") + + x, y, u = symbols("x y u") + + def do_test(data1, data2): + assert len(data1) == len(data2) + for d1, d2 in zip(data1, data2): + assert np.allclose(d1, d2) + + expr1 = sqrt(x) * exp(-x**2) + expr2 = sqrt(u * x) * exp(-x**2) + s1 = LineOver1DRangeSeries(im(expr1), (x, -5, 5), adaptive=False, n=10) + s2 = LineOver1DRangeSeries(im(expr2), (x, -5, 5), + adaptive=False, n=10, params={u: 1}) + data1 = s1.get_data() + data2 = s2.get_data() + + do_test(data1, data2) + assert (not np.allclose(data1[1], 0)) and (not np.allclose(data2[1], 0)) + + s1 = Parametric2DLineSeries(re(expr1), im(expr1), (x, -pi, pi), + adaptive=False, n=10) + s2 = Parametric2DLineSeries(re(expr2), im(expr2), (x, -pi, pi), + adaptive=False, n=10, params={u: 1}) + data1 = s1.get_data() + data2 = s2.get_data() + do_test(data1, data2) + assert (not np.allclose(data1[1], 0)) and (not np.allclose(data2[1], 0)) + + s1 = SurfaceOver2DRangeSeries(im(expr1), (x, -5, 5), (y, -10, 10), + adaptive=False, n1=30, n2=3) + s2 = SurfaceOver2DRangeSeries(im(expr2), (x, -5, 5), (y, -10, 10), + adaptive=False, n1=30, n2=3, params={u: 1}) + data1 = s1.get_data() + data2 = s2.get_data() + do_test(data1, data2) + assert (not np.allclose(data1[1], 0)) and (not np.allclose(data2[1], 0)) + + +def test_expr_is_lambda_function(): + # verify that when a numpy function is provided, the series will be able + # to evaluate it. Also, label should be empty in order to prevent some + # backend from crashing. + if not np: + skip("numpy not installed.") + + f = lambda x: np.cos(x) + s1 = LineOver1DRangeSeries(f, ("x", -5, 5), adaptive=True, depth=3) + s1.get_data() + s2 = LineOver1DRangeSeries(f, ("x", -5, 5), adaptive=False, n=10) + s2.get_data() + assert s1.label == s2.label == "" + + fx = lambda x: np.cos(x) + fy = lambda x: np.sin(x) + s1 = Parametric2DLineSeries(fx, fy, ("x", 0, 2*pi), + adaptive=True, adaptive_goal=0.1) + s1.get_data() + s2 = Parametric2DLineSeries(fx, fy, ("x", 0, 2*pi), + adaptive=False, n=10) + s2.get_data() + assert s1.label == s2.label == "" + + fz = lambda x: x + s1 = Parametric3DLineSeries(fx, fy, fz, ("x", 0, 2*pi), + adaptive=True, adaptive_goal=0.1) + s1.get_data() + s2 = Parametric3DLineSeries(fx, fy, fz, ("x", 0, 2*pi), + adaptive=False, n=10) + s2.get_data() + assert s1.label == s2.label == "" + + f = lambda x, y: np.cos(x**2 + y**2) + s1 = SurfaceOver2DRangeSeries(f, ("a", -2, 2), ("b", -3, 3), + adaptive=False, n1=10, n2=10) + s1.get_data() + s2 = ContourSeries(f, ("a", -2, 2), ("b", -3, 3), + adaptive=False, n1=10, n2=10) + s2.get_data() + assert s1.label == s2.label == "" + + fx = lambda u, v: np.cos(u + v) + fy = lambda u, v: np.sin(u - v) + fz = lambda u, v: u * v + s1 = ParametricSurfaceSeries(fx, fy, fz, ("u", 0, pi), ("v", 0, 2*pi), + adaptive=False, n1=10, n2=10) + s1.get_data() + assert s1.label == "" + + raises(TypeError, lambda: List2DSeries(lambda t: t, lambda t: t)) + raises(TypeError, lambda : ImplicitSeries(lambda t: np.sin(t), + ("x", -5, 5), ("y", -6, 6))) + + +def test_show_in_legend_lines(): + # verify that lines series correctly set the show_in_legend attribute + x, u = symbols("x, u") + + s = LineOver1DRangeSeries(cos(x), (x, -2, 2), "test", show_in_legend=True) + assert s.show_in_legend + s = LineOver1DRangeSeries(cos(x), (x, -2, 2), "test", show_in_legend=False) + assert not s.show_in_legend + + s = Parametric2DLineSeries(cos(x), sin(x), (x, 0, 1), "test", + show_in_legend=True) + assert s.show_in_legend + s = Parametric2DLineSeries(cos(x), sin(x), (x, 0, 1), "test", + show_in_legend=False) + assert not s.show_in_legend + + s = Parametric3DLineSeries(cos(x), sin(x), x, (x, 0, 1), "test", + show_in_legend=True) + assert s.show_in_legend + s = Parametric3DLineSeries(cos(x), sin(x), x, (x, 0, 1), "test", + show_in_legend=False) + assert not s.show_in_legend + + +@XFAIL +def test_particular_case_1_with_adaptive_true(): + # Verify that symbolic expressions and numerical lambda functions are + # evaluated with the same algorithm. + if not np: + skip("numpy not installed.") + + # NOTE: xfail because sympy's adaptive algorithm is not deterministic + + def do_test(a, b): + with warns( + RuntimeWarning, + match="invalid value encountered in scalar power", + test_stacklevel=False, + ): + d1 = a.get_data() + d2 = b.get_data() + for t, v in zip(d1, d2): + assert np.allclose(t, v) + + n = symbols("n") + a = S(2) / 3 + epsilon = 0.01 + xn = (n**3 + n**2)**(S(1)/3) - (n**3 - n**2)**(S(1)/3) + expr = Abs(xn - a) - epsilon + math_func = lambdify([n], expr) + s1 = LineOver1DRangeSeries(expr, (n, -10, 10), "", + adaptive=True, depth=3) + s2 = LineOver1DRangeSeries(math_func, ("n", -10, 10), "", + adaptive=True, depth=3) + do_test(s1, s2) + + +def test_particular_case_1_with_adaptive_false(): + # Verify that symbolic expressions and numerical lambda functions are + # evaluated with the same algorithm. In particular, uniform evaluation + # is going to use np.vectorize, which correctly evaluates the following + # mathematical function. + if not np: + skip("numpy not installed.") + + def do_test(a, b): + d1 = a.get_data() + d2 = b.get_data() + for t, v in zip(d1, d2): + assert np.allclose(t, v) + + n = symbols("n") + a = S(2) / 3 + epsilon = 0.01 + xn = (n**3 + n**2)**(S(1)/3) - (n**3 - n**2)**(S(1)/3) + expr = Abs(xn - a) - epsilon + math_func = lambdify([n], expr) + + s3 = LineOver1DRangeSeries(expr, (n, -10, 10), "", + adaptive=False, n=10) + s4 = LineOver1DRangeSeries(math_func, ("n", -10, 10), "", + adaptive=False, n=10) + do_test(s3, s4) + + +def test_complex_params_number_eval(): + # The main expression contains terms like sqrt(xi - 1), with + # parameter (0 <= xi <= 1). + # There shouldn't be any NaN values on the output. + if not np: + skip("numpy not installed.") + + xi, wn, x0, v0, t = symbols("xi, omega_n, x0, v0, t") + x = Function("x")(t) + eq = x.diff(t, 2) + 2 * xi * wn * x.diff(t) + wn**2 * x + sol = dsolve(eq, x, ics={x.subs(t, 0): x0, x.diff(t).subs(t, 0): v0}) + params = { + wn: 0.5, + xi: 0.25, + x0: 0.45, + v0: 0.0 + } + s = LineOver1DRangeSeries(sol.rhs, (t, 0, 100), adaptive=False, n=5, + params=params) + x, y = s.get_data() + assert not np.isnan(x).any() + assert not np.isnan(y).any() + + + # Fourier Series of a sawtooth wave + # The main expression contains a Sum with a symbolic upper range. + # The lambdified code looks like: + # sum(blablabla for for n in range(1, m+1)) + # But range requires integer numbers, whereas per above example, the series + # casts parameters to complex. Verify that the series is able to detect + # upper bounds in summations and cast it to int in order to get successful + # evaluation + x, T, n, m = symbols("x, T, n, m") + fs = S(1) / 2 - (1 / pi) * Sum(sin(2 * n * pi * x / T) / n, (n, 1, m)) + params = { + T: 4.5, + m: 5 + } + s = LineOver1DRangeSeries(fs, (x, 0, 10), adaptive=False, n=5, + params=params) + x, y = s.get_data() + assert not np.isnan(x).any() + assert not np.isnan(y).any() + + +def test_complex_range_line_plot_1(): + # verify that univariate functions are evaluated with a complex + # data range (with zero imaginary part). There shouldn't be any + # NaN value in the output. + if not np: + skip("numpy not installed.") + + x, u = symbols("x, u") + expr1 = im(sqrt(x) * exp(-x**2)) + expr2 = im(sqrt(u * x) * exp(-x**2)) + s1 = LineOver1DRangeSeries(expr1, (x, -10, 10), adaptive=True, + adaptive_goal=0.1) + s2 = LineOver1DRangeSeries(expr1, (x, -10, 10), adaptive=False, n=30) + s3 = LineOver1DRangeSeries(expr2, (x, -10, 10), adaptive=False, n=30, + params={u: 1}) + + with ignore_warnings(RuntimeWarning): + data1 = s1.get_data() + data2 = s2.get_data() + data3 = s3.get_data() + + assert not np.isnan(data1[1]).any() + assert not np.isnan(data2[1]).any() + assert not np.isnan(data3[1]).any() + assert np.allclose(data2[0], data3[0]) and np.allclose(data2[1], data3[1]) + + +@XFAIL +def test_complex_range_line_plot_2(): + # verify that univariate functions are evaluated with a complex + # data range (with non-zero imaginary part). There shouldn't be any + # NaN value in the output. + if not np: + skip("numpy not installed.") + + # NOTE: xfail because sympy's adaptive algorithm is unable to deal with + # complex number. + + x, u = symbols("x, u") + + # adaptive and uniform meshing should produce the same data. + # because of the adaptive nature, just compare the first and last points + # of both series. + s1 = LineOver1DRangeSeries(abs(sqrt(x)), (x, -5-2j, 5-2j), adaptive=True) + s2 = LineOver1DRangeSeries(abs(sqrt(x)), (x, -5-2j, 5-2j), adaptive=False, + n=10) + with warns( + RuntimeWarning, + match="invalid value encountered in sqrt", + test_stacklevel=False, + ): + d1 = s1.get_data() + d2 = s2.get_data() + xx1 = [d1[0][0], d1[0][-1]] + xx2 = [d2[0][0], d2[0][-1]] + yy1 = [d1[1][0], d1[1][-1]] + yy2 = [d2[1][0], d2[1][-1]] + assert np.allclose(xx1, xx2) + assert np.allclose(yy1, yy2) + + +def test_force_real_eval(): + # verify that force_real_eval=True produces inconsistent results when + # compared with evaluation of complex domain. + if not np: + skip("numpy not installed.") + + x = symbols("x") + + expr = im(sqrt(x) * exp(-x**2)) + s1 = LineOver1DRangeSeries(expr, (x, -10, 10), adaptive=False, n=10, + force_real_eval=False) + s2 = LineOver1DRangeSeries(expr, (x, -10, 10), adaptive=False, n=10, + force_real_eval=True) + d1 = s1.get_data() + with ignore_warnings(RuntimeWarning): + d2 = s2.get_data() + assert not np.allclose(d1[1], 0) + assert np.allclose(d2[1], 0) + + +def test_contour_series_show_clabels(): + # verify that a contour series has the abiliy to set the visibility of + # labels to contour lines + + x, y = symbols("x, y") + s = ContourSeries(cos(x*y), (x, -2, 2), (y, -2, 2)) + assert s.show_clabels + + s = ContourSeries(cos(x*y), (x, -2, 2), (y, -2, 2), clabels=True) + assert s.show_clabels + + s = ContourSeries(cos(x*y), (x, -2, 2), (y, -2, 2), clabels=False) + assert not s.show_clabels + + +def test_LineOver1DRangeSeries_complex_range(): + # verify that LineOver1DRangeSeries can accept a complex range + # if the imaginary part of the start and end values are the same + + x = symbols("x") + + LineOver1DRangeSeries(sqrt(x), (x, -10, 10)) + LineOver1DRangeSeries(sqrt(x), (x, -10-2j, 10-2j)) + raises(ValueError, + lambda : LineOver1DRangeSeries(sqrt(x), (x, -10-2j, 10+2j))) + + +def test_symbolic_plotting_ranges(): + # verify that data series can use symbolic plotting ranges + if not np: + skip("numpy not installed.") + + x, y, z, a, b = symbols("x, y, z, a, b") + + def do_test(s1, s2, new_params): + d1 = s1.get_data() + d2 = s2.get_data() + for u, v in zip(d1, d2): + assert np.allclose(u, v) + s2.params = new_params + d2 = s2.get_data() + for u, v in zip(d1, d2): + assert not np.allclose(u, v) + + s1 = LineOver1DRangeSeries(sin(x), (x, 0, 1), adaptive=False, n=10) + s2 = LineOver1DRangeSeries(sin(x), (x, a, b), params={a: 0, b: 1}, + adaptive=False, n=10) + do_test(s1, s2, {a: 0.5, b: 1.5}) + + # missing a parameter + raises(ValueError, + lambda : LineOver1DRangeSeries(sin(x), (x, a, b), params={a: 1}, n=10)) + + s1 = Parametric2DLineSeries(cos(x), sin(x), (x, 0, 1), adaptive=False, n=10) + s2 = Parametric2DLineSeries(cos(x), sin(x), (x, a, b), params={a: 0, b: 1}, + adaptive=False, n=10) + do_test(s1, s2, {a: 0.5, b: 1.5}) + + # missing a parameter + raises(ValueError, + lambda : Parametric2DLineSeries(cos(x), sin(x), (x, a, b), + params={a: 0}, adaptive=False, n=10)) + + s1 = Parametric3DLineSeries(cos(x), sin(x), x, (x, 0, 1), + adaptive=False, n=10) + s2 = Parametric3DLineSeries(cos(x), sin(x), x, (x, a, b), + params={a: 0, b: 1}, adaptive=False, n=10) + do_test(s1, s2, {a: 0.5, b: 1.5}) + + # missing a parameter + raises(ValueError, + lambda : Parametric3DLineSeries(cos(x), sin(x), x, (x, a, b), + params={a: 0}, adaptive=False, n=10)) + + s1 = SurfaceOver2DRangeSeries(cos(x**2 + y**2), (x, -pi, pi), (y, -pi, pi), + adaptive=False, n1=5, n2=5) + s2 = SurfaceOver2DRangeSeries(cos(x**2 + y**2), (x, -pi * a, pi * a), + (y, -pi * b, pi * b), params={a: 1, b: 1}, + adaptive=False, n1=5, n2=5) + do_test(s1, s2, {a: 0.5, b: 1.5}) + + # missing a parameter + raises(ValueError, + lambda : SurfaceOver2DRangeSeries(cos(x**2 + y**2), + (x, -pi * a, pi * a), (y, -pi * b, pi * b), params={a: 1}, + adaptive=False, n1=5, n2=5)) + # one range symbol is included into another range's minimum or maximum val + raises(ValueError, + lambda : SurfaceOver2DRangeSeries(cos(x**2 + y**2), + (x, -pi * a + y, pi * a), (y, -pi * b, pi * b), params={a: 1}, + adaptive=False, n1=5, n2=5)) + + s1 = ParametricSurfaceSeries( + cos(x - y), sin(x + y), x - y, (x, -2, 2), (y, -2, 2), n1=5, n2=5) + s2 = ParametricSurfaceSeries( + cos(x - y), sin(x + y), x - y, (x, -2 * a, 2), (y, -2, 2 * b), + params={a: 1, b: 1}, n1=5, n2=5) + do_test(s1, s2, {a: 0.5, b: 1.5}) + + # missing a parameter + raises(ValueError, + lambda : ParametricSurfaceSeries( + cos(x - y), sin(x + y), x - y, (x, -2 * a, 2), (y, -2, 2 * b), + params={a: 1}, n1=5, n2=5)) + + +def test_exclude_points(): + # verify that exclude works as expected + if not np: + skip("numpy not installed.") + + x = symbols("x") + + expr = (floor(x) + S.Half) / (1 - (x - S.Half)**2) + + with warns( + UserWarning, + match="NumPy is unable to evaluate with complex numbers some", + test_stacklevel=False, + ): + s = LineOver1DRangeSeries(expr, (x, -3.5, 3.5), adaptive=False, n=100, + exclude=list(range(-3, 4))) + xx, yy = s.get_data() + assert not np.isnan(xx).any() + assert np.count_nonzero(np.isnan(yy)) == 7 + assert len(xx) > 100 + + e1 = log(floor(x)) * cos(x) + e2 = log(floor(x)) * sin(x) + with warns( + UserWarning, + match="NumPy is unable to evaluate with complex numbers some", + test_stacklevel=False, + ): + s = Parametric2DLineSeries(e1, e2, (x, 1, 12), adaptive=False, n=100, + exclude=list(range(1, 13))) + xx, yy, pp = s.get_data() + assert not np.isnan(pp).any() + assert np.count_nonzero(np.isnan(xx)) == 11 + assert np.count_nonzero(np.isnan(yy)) == 11 + assert len(xx) > 100 + + +def test_unwrap(): + # verify that unwrap works as expected + if not np: + skip("numpy not installed.") + + x, y = symbols("x, y") + expr = 1 / (x**3 + 2*x**2 + x) + expr = arg(expr.subs(x, I*y*2*pi)) + s1 = LineOver1DRangeSeries(expr, (y, 1e-05, 1e05), xscale="log", + adaptive=False, n=10, unwrap=False) + s2 = LineOver1DRangeSeries(expr, (y, 1e-05, 1e05), xscale="log", + adaptive=False, n=10, unwrap=True) + s3 = LineOver1DRangeSeries(expr, (y, 1e-05, 1e05), xscale="log", + adaptive=False, n=10, unwrap={"period": 4}) + x1, y1 = s1.get_data() + x2, y2 = s2.get_data() + x3, y3 = s3.get_data() + assert np.allclose(x1, x2) + # there must not be nan values in the results of these evaluations + assert all(not np.isnan(t).any() for t in [y1, y2, y3]) + assert not np.allclose(y1, y2) + assert not np.allclose(y1, y3) + assert not np.allclose(y2, y3) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_textplot.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_textplot.py new file mode 100644 index 0000000000000000000000000000000000000000..928085c627e5230f2ac4a8ce0bbac5354ab35d51 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_textplot.py @@ -0,0 +1,203 @@ +from sympy.core.singleton import S +from sympy.core.symbol import Symbol +from sympy.functions.elementary.exponential import log +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import sin +from sympy.plotting.textplot import textplot_str + +from sympy.utilities.exceptions import ignore_warnings + + +def test_axes_alignment(): + x = Symbol('x') + lines = [ + ' 1 | ..', + ' | ... ', + ' | .. ', + ' | ... ', + ' | ... ', + ' | .. ', + ' | ... ', + ' | ... ', + ' | .. ', + ' | ... ', + ' 0 |--------------------------...--------------------------', + ' | ... ', + ' | .. ', + ' | ... ', + ' | ... ', + ' | .. ', + ' | ... ', + ' | ... ', + ' | .. ', + ' | ... ', + ' -1 |_______________________________________________________', + ' -1 0 1' + ] + assert lines == list(textplot_str(x, -1, 1)) + + lines = [ + ' 1 | ..', + ' | .... ', + ' | ... ', + ' | ... ', + ' | .... ', + ' | ... ', + ' | ... ', + ' | .... ', + ' 0 |--------------------------...--------------------------', + ' | .... ', + ' | ... ', + ' | ... ', + ' | .... ', + ' | ... ', + ' | ... ', + ' | .... ', + ' -1 |_______________________________________________________', + ' -1 0 1' + ] + assert lines == list(textplot_str(x, -1, 1, H=17)) + + +def test_singularity(): + x = Symbol('x') + lines = [ + ' 54 | . ', + ' | ', + ' | ', + ' | ', + ' | ',' | ', + ' | ', + ' | ', + ' | ', + ' | ', + ' 27.5 |--.----------------------------------------------------', + ' | ', + ' | ', + ' | ', + ' | . ', + ' | \\ ', + ' | \\ ', + ' | .. ', + ' | ... ', + ' | ............. ', + ' 1 |_______________________________________________________', + ' 0 0.5 1' + ] + assert lines == list(textplot_str(1/x, 0, 1)) + + lines = [ + ' 0 | ......', + ' | ........ ', + ' | ........ ', + ' | ...... ', + ' | ..... ', + ' | .... ', + ' | ... ', + ' | .. ', + ' | ... ', + ' | / ', + ' -2 |-------..----------------------------------------------', + ' | / ', + ' | / ', + ' | / ', + ' | . ', + ' | ', + ' | . ', + ' | ', + ' | ', + ' | ', + ' -4 |_______________________________________________________', + ' 0 0.5 1' + ] + # RuntimeWarning: divide by zero encountered in log + with ignore_warnings(RuntimeWarning): + assert lines == list(textplot_str(log(x), 0, 1)) + + +def test_sinc(): + x = Symbol('x') + lines = [ + ' 1 | . . ', + ' | . . ', + ' | ', + ' | . . ', + ' | ', + ' | . . ', + ' | ', + ' | ', + ' | . . ', + ' | ', + ' 0.4 |-------------------------------------------------------', + ' | . . ', + ' | ', + ' | . . ', + ' | ', + ' | ..... ..... ', + ' | .. \\ . . / .. ', + ' | / \\ / \\ ', + ' |/ \\ . . / \\', + ' | \\ / \\ / ', + ' -0.2 |_______________________________________________________', + ' -10 0 10' + ] + # RuntimeWarning: invalid value encountered in double_scalars + with ignore_warnings(RuntimeWarning): + assert lines == list(textplot_str(sin(x)/x, -10, 10)) + + +def test_imaginary(): + x = Symbol('x') + lines = [ + ' 1 | ..', + ' | .. ', + ' | ... ', + ' | .. ', + ' | .. ', + ' | .. ', + ' | .. ', + ' | .. ', + ' | .. ', + ' | / ', + ' 0.5 |----------------------------------/--------------------', + ' | .. ', + ' | / ', + ' | . ', + ' | ', + ' | . ', + ' | . ', + ' | ', + ' | ', + ' | ', + ' 0 |_______________________________________________________', + ' -1 0 1' + ] + # RuntimeWarning: invalid value encountered in sqrt + with ignore_warnings(RuntimeWarning): + assert list(textplot_str(sqrt(x), -1, 1)) == lines + + lines = [ + ' 1 | ', + ' | ', + ' | ', + ' | ', + ' | ', + ' | ', + ' | ', + ' | ', + ' | ', + ' | ', + ' 0 |-------------------------------------------------------', + ' | ', + ' | ', + ' | ', + ' | ', + ' | ', + ' | ', + ' | ', + ' | ', + ' | ', + ' -1 |_______________________________________________________', + ' -1 0 1' + ] + assert list(textplot_str(S.ImaginaryUnit, -1, 1)) == lines diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_utils.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..4206a8b001319552c2e2be1aeb46057e6f708912 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/plotting/tests/test_utils.py @@ -0,0 +1,110 @@ +from pytest import raises +from sympy import ( + symbols, Expr, Tuple, Integer, cos, solveset, FiniteSet, ImageSet) +from sympy.plotting.utils import ( + _create_ranges, _plot_sympify, extract_solution) +from sympy.physics.mechanics import ReferenceFrame, Vector as MechVector +from sympy.vector import CoordSys3D, Vector + + +def test_plot_sympify(): + x, y = symbols("x, y") + + # argument is already sympified + args = x + y + r = _plot_sympify(args) + assert r == args + + # one argument needs to be sympified + args = (x + y, 1) + r = _plot_sympify(args) + assert isinstance(r, (list, tuple, Tuple)) and len(r) == 2 + assert isinstance(r[0], Expr) + assert isinstance(r[1], Integer) + + # string and dict should not be sympified + args = (x + y, (x, 0, 1), "str", 1, {1: 1, 2: 2.0}) + r = _plot_sympify(args) + assert isinstance(r, (list, tuple, Tuple)) and len(r) == 5 + assert isinstance(r[0], Expr) + assert isinstance(r[1], Tuple) + assert isinstance(r[2], str) + assert isinstance(r[3], Integer) + assert isinstance(r[4], dict) and isinstance(r[4][1], int) and isinstance(r[4][2], float) + + # nested arguments containing strings + args = ((x + y, (y, 0, 1), "a"), (x + 1, (x, 0, 1), "$f_{1}$")) + r = _plot_sympify(args) + assert isinstance(r, (list, tuple, Tuple)) and len(r) == 2 + assert isinstance(r[0], Tuple) + assert isinstance(r[0][1], Tuple) + assert isinstance(r[0][1][1], Integer) + assert isinstance(r[0][2], str) + assert isinstance(r[1], Tuple) + assert isinstance(r[1][1], Tuple) + assert isinstance(r[1][1][1], Integer) + assert isinstance(r[1][2], str) + + # vectors from sympy.physics.vectors module are not sympified + # vectors from sympy.vectors are sympified + # in both cases, no error should be raised + R = ReferenceFrame("R") + v1 = 2 * R.x + R.y + C = CoordSys3D("C") + v2 = 2 * C.i + C.j + args = (v1, v2) + r = _plot_sympify(args) + assert isinstance(r, (list, tuple, Tuple)) and len(r) == 2 + assert isinstance(v1, MechVector) + assert isinstance(v2, Vector) + + +def test_create_ranges(): + x, y = symbols("x, y") + + # user don't provide any range -> return a default range + r = _create_ranges({x}, [], 1) + assert isinstance(r, (list, tuple, Tuple)) and len(r) == 1 + assert isinstance(r[0], (Tuple, tuple)) + assert r[0] == (x, -10, 10) + + r = _create_ranges({x, y}, [], 2) + assert isinstance(r, (list, tuple, Tuple)) and len(r) == 2 + assert isinstance(r[0], (Tuple, tuple)) + assert isinstance(r[1], (Tuple, tuple)) + assert r[0] == (x, -10, 10) or (y, -10, 10) + assert r[1] == (y, -10, 10) or (x, -10, 10) + assert r[0] != r[1] + + # not enough ranges provided by the user -> create default ranges + r = _create_ranges( + {x, y}, + [ + (x, 0, 1), + ], + 2, + ) + assert isinstance(r, (list, tuple, Tuple)) and len(r) == 2 + assert isinstance(r[0], (Tuple, tuple)) + assert isinstance(r[1], (Tuple, tuple)) + assert r[0] == (x, 0, 1) or (y, -10, 10) + assert r[1] == (y, -10, 10) or (x, 0, 1) + assert r[0] != r[1] + + # too many free symbols + raises(ValueError, lambda: _create_ranges({x, y}, [], 1)) + raises(ValueError, lambda: _create_ranges({x, y}, [(x, 0, 5), (y, 0, 1)], 1)) + + +def test_extract_solution(): + x = symbols("x") + + sol = solveset(cos(10 * x)) + assert sol.has(ImageSet) + res = extract_solution(sol) + assert len(res) == 20 + assert isinstance(res, FiniteSet) + + res = extract_solution(sol, 20) + assert len(res) == 40 + assert isinstance(res, FiniteSet) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bd9978ba87747018efcdbfdb6d94e3157a48ac03 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/__pycache__/extensions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/__pycache__/extensions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e85da2667da8bf3b95cfadfba7b8c180950c7c8b Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/__pycache__/extensions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/__pycache__/homomorphisms.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/__pycache__/homomorphisms.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d19143b50bb21b68322d7bb31cb7daf4b629983d Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/__pycache__/homomorphisms.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/__pycache__/ideals.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/__pycache__/ideals.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1e1176f779073fa4ac0f73494a8a4e936b0cbb55 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/__pycache__/ideals.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/__pycache__/modules.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/__pycache__/modules.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b988225e645f7b462858cba19fd47d6ae282a796 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/__pycache__/modules.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a569383d82dd7950cd5d00b705c9b4452065861e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/__pycache__/test_extensions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/__pycache__/test_extensions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..94a1e7c70a96299d5292598b129dd38d6361d805 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/__pycache__/test_extensions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/__pycache__/test_homomorphisms.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/__pycache__/test_homomorphisms.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..52b0cb1bea1c92ad3e62adc5b1cf49ef26ca4f94 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/__pycache__/test_homomorphisms.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/__pycache__/test_ideals.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/__pycache__/test_ideals.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f877baa78ee8476ab6f168c9f1262df629ca456a Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/__pycache__/test_ideals.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/__pycache__/test_modules.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/__pycache__/test_modules.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0174e38ba6577b4217972b2d3a36ca2da2ef7704 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/__pycache__/test_modules.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/test_extensions.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/test_extensions.py new file mode 100644 index 0000000000000000000000000000000000000000..4becf4fd800a7a34c16989adaaf97e312c18f01c --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/test_extensions.py @@ -0,0 +1,196 @@ +from sympy.core.symbol import symbols +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.polys import QQ, ZZ +from sympy.polys.polytools import Poly +from sympy.polys.polyerrors import NotInvertible +from sympy.polys.agca.extensions import FiniteExtension +from sympy.polys.domainmatrix import DomainMatrix + +from sympy.testing.pytest import raises + +from sympy.abc import x, y, t + + +def test_FiniteExtension(): + # Gaussian integers + A = FiniteExtension(Poly(x**2 + 1, x)) + assert A.rank == 2 + assert str(A) == 'ZZ[x]/(x**2 + 1)' + i = A.generator + assert i.parent() is A + + assert i*i == A(-1) + raises(TypeError, lambda: i*()) + + assert A.basis == (A.one, i) + assert A(1) == A.one + assert i**2 == A(-1) + assert i**2 != -1 # no coercion + assert (2 + i)*(1 - i) == 3 - i + assert (1 + i)**8 == A(16) + assert A(1).inverse() == A(1) + raises(NotImplementedError, lambda: A(2).inverse()) + + # Finite field of order 27 + F = FiniteExtension(Poly(x**3 - x + 1, x, modulus=3)) + assert F.rank == 3 + a = F.generator # also generates the cyclic group F - {0} + assert F.basis == (F(1), a, a**2) + assert a**27 == a + assert a**26 == F(1) + assert a**13 == F(-1) + assert a**9 == a + 1 + assert a**3 == a - 1 + assert a**6 == a**2 + a + 1 + assert F(x**2 + x).inverse() == 1 - a + assert F(x + 2)**(-1) == F(x + 2).inverse() + assert a**19 * a**(-19) == F(1) + assert (a - 1) / (2*a**2 - 1) == a**2 + 1 + assert (a - 1) // (2*a**2 - 1) == a**2 + 1 + assert 2/(a**2 + 1) == a**2 - a + 1 + assert (a**2 + 1)/2 == -a**2 - 1 + raises(NotInvertible, lambda: F(0).inverse()) + + # Function field of an elliptic curve + K = FiniteExtension(Poly(t**2 - x**3 - x + 1, t, field=True)) + assert K.rank == 2 + assert str(K) == 'ZZ(x)[t]/(t**2 - x**3 - x + 1)' + y = K.generator + c = 1/(x**3 - x**2 + x - 1) + assert ((y + x)*(y - x)).inverse() == K(c) + assert (y + x)*(y - x)*c == K(1) # explicit inverse of y + x + + +def test_FiniteExtension_eq_hash(): + # Test eq and hash + p1 = Poly(x**2 - 2, x, domain=ZZ) + p2 = Poly(x**2 - 2, x, domain=QQ) + K1 = FiniteExtension(p1) + K2 = FiniteExtension(p2) + assert K1 == FiniteExtension(Poly(x**2 - 2)) + assert K2 != FiniteExtension(Poly(x**2 - 2)) + assert len({K1, K2, FiniteExtension(p1)}) == 2 + + +def test_FiniteExtension_mod(): + # Test mod + K = FiniteExtension(Poly(x**3 + 1, x, domain=QQ)) + xf = K(x) + assert (xf**2 - 1) % 1 == K.zero + assert 1 % (xf**2 - 1) == K.zero + assert (xf**2 - 1) / (xf - 1) == xf + 1 + assert (xf**2 - 1) // (xf - 1) == xf + 1 + assert (xf**2 - 1) % (xf - 1) == K.zero + raises(ZeroDivisionError, lambda: (xf**2 - 1) % 0) + raises(TypeError, lambda: xf % []) + raises(TypeError, lambda: [] % xf) + + # Test mod over ring + K = FiniteExtension(Poly(x**3 + 1, x, domain=ZZ)) + xf = K(x) + assert (xf**2 - 1) % 1 == K.zero + raises(NotImplementedError, lambda: (xf**2 - 1) % (xf - 1)) + + +def test_FiniteExtension_from_sympy(): + # Test to_sympy/from_sympy + K = FiniteExtension(Poly(x**3 + 1, x, domain=ZZ)) + xf = K(x) + assert K.from_sympy(x) == xf + assert K.to_sympy(xf) == x + + +def test_FiniteExtension_set_domain(): + KZ = FiniteExtension(Poly(x**2 + 1, x, domain='ZZ')) + KQ = FiniteExtension(Poly(x**2 + 1, x, domain='QQ')) + assert KZ.set_domain(QQ) == KQ + + +def test_FiniteExtension_exquo(): + # Test exquo + K = FiniteExtension(Poly(x**4 + 1)) + xf = K(x) + assert K.exquo(xf**2 - 1, xf - 1) == xf + 1 + + +def test_FiniteExtension_convert(): + # Test from_MonogenicFiniteExtension + K1 = FiniteExtension(Poly(x**2 + 1)) + K2 = QQ[x] + x1, x2 = K1(x), K2(x) + assert K1.convert(x2) == x1 + assert K2.convert(x1) == x2 + + K = FiniteExtension(Poly(x**2 - 1, domain=QQ)) + assert K.convert_from(QQ(1, 2), QQ) == K.one/2 + + +def test_FiniteExtension_division_ring(): + # Test division in FiniteExtension over a ring + KQ = FiniteExtension(Poly(x**2 - 1, x, domain=QQ)) + KZ = FiniteExtension(Poly(x**2 - 1, x, domain=ZZ)) + KQt = FiniteExtension(Poly(x**2 - 1, x, domain=QQ[t])) + KQtf = FiniteExtension(Poly(x**2 - 1, x, domain=QQ.frac_field(t))) + assert KQ.is_Field is True + assert KZ.is_Field is False + assert KQt.is_Field is False + assert KQtf.is_Field is True + for K in KQ, KZ, KQt, KQtf: + xK = K.convert(x) + assert xK / K.one == xK + assert xK // K.one == xK + assert xK % K.one == K.zero + raises(ZeroDivisionError, lambda: xK / K.zero) + raises(ZeroDivisionError, lambda: xK // K.zero) + raises(ZeroDivisionError, lambda: xK % K.zero) + if K.is_Field: + assert xK / xK == K.one + assert xK // xK == K.one + assert xK % xK == K.zero + else: + raises(NotImplementedError, lambda: xK / xK) + raises(NotImplementedError, lambda: xK // xK) + raises(NotImplementedError, lambda: xK % xK) + + +def test_FiniteExtension_Poly(): + K = FiniteExtension(Poly(x**2 - 2)) + p = Poly(x, y, domain=K) + assert p.domain == K + assert p.as_expr() == x + assert (p**2).as_expr() == 2 + + K = FiniteExtension(Poly(x**2 - 2, x, domain=QQ)) + K2 = FiniteExtension(Poly(t**2 - 2, t, domain=K)) + assert str(K2) == 'QQ[x]/(x**2 - 2)[t]/(t**2 - 2)' + + eK = K2.convert(x + t) + assert K2.to_sympy(eK) == x + t + assert K2.to_sympy(eK ** 2) == 4 + 2*x*t + p = Poly(x + t, y, domain=K2) + assert p**2 == Poly(4 + 2*x*t, y, domain=K2) + + +def test_FiniteExtension_sincos_jacobian(): + # Use FiniteExtensino to compute the Jacobian of a matrix involving sin + # and cos of different symbols. + r, p, t = symbols('rho, phi, theta') + elements = [ + [sin(p)*cos(t), r*cos(p)*cos(t), -r*sin(p)*sin(t)], + [sin(p)*sin(t), r*cos(p)*sin(t), r*sin(p)*cos(t)], + [ cos(p), -r*sin(p), 0], + ] + + def make_extension(K): + K = FiniteExtension(Poly(sin(p)**2+cos(p)**2-1, sin(p), domain=K[cos(p)])) + K = FiniteExtension(Poly(sin(t)**2+cos(t)**2-1, sin(t), domain=K[cos(t)])) + return K + + Ksc1 = make_extension(ZZ[r]) + Ksc2 = make_extension(ZZ)[r] + + for K in [Ksc1, Ksc2]: + elements_K = [[K.convert(e) for e in row] for row in elements] + J = DomainMatrix(elements_K, (3, 3), K) + det = J.charpoly()[-1] * (-K.one)**3 + assert det == K.convert(r**2*sin(p)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/test_homomorphisms.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/test_homomorphisms.py new file mode 100644 index 0000000000000000000000000000000000000000..2e63838e09ed9b9436a58a7d8041175e731bc4ef --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/test_homomorphisms.py @@ -0,0 +1,113 @@ +"""Tests for homomorphisms.""" + +from sympy.core.singleton import S +from sympy.polys.domains.rationalfield import QQ +from sympy.abc import x, y +from sympy.polys.agca import homomorphism +from sympy.testing.pytest import raises + + +def test_printing(): + R = QQ.old_poly_ring(x) + + assert str(homomorphism(R.free_module(1), R.free_module(1), [0])) == \ + 'Matrix([[0]]) : QQ[x]**1 -> QQ[x]**1' + assert str(homomorphism(R.free_module(2), R.free_module(2), [0, 0])) == \ + 'Matrix([ \n[0, 0], : QQ[x]**2 -> QQ[x]**2\n[0, 0]]) ' + assert str(homomorphism(R.free_module(1), R.free_module(1) / [[x]], [0])) == \ + 'Matrix([[0]]) : QQ[x]**1 -> QQ[x]**1/<[x]>' + assert str(R.free_module(0).identity_hom()) == 'Matrix(0, 0, []) : QQ[x]**0 -> QQ[x]**0' + +def test_operations(): + F = QQ.old_poly_ring(x).free_module(2) + G = QQ.old_poly_ring(x).free_module(3) + f = F.identity_hom() + g = homomorphism(F, F, [0, [1, x]]) + h = homomorphism(F, F, [[1, 0], 0]) + i = homomorphism(F, G, [[1, 0, 0], [0, 1, 0]]) + + assert f == f + assert f != g + assert f != i + assert (f != F.identity_hom()) is False + assert 2*f == f*2 == homomorphism(F, F, [[2, 0], [0, 2]]) + assert f/2 == homomorphism(F, F, [[S.Half, 0], [0, S.Half]]) + assert f + g == homomorphism(F, F, [[1, 0], [1, x + 1]]) + assert f - g == homomorphism(F, F, [[1, 0], [-1, 1 - x]]) + assert f*g == g == g*f + assert h*g == homomorphism(F, F, [0, [1, 0]]) + assert g*h == homomorphism(F, F, [0, 0]) + assert i*f == i + assert f([1, 2]) == [1, 2] + assert g([1, 2]) == [2, 2*x] + + assert i.restrict_domain(F.submodule([x, x]))([x, x]) == i([x, x]) + h1 = h.quotient_domain(F.submodule([0, 1])) + assert h1([1, 0]) == h([1, 0]) + assert h1.restrict_domain(h1.domain.submodule([x, 0]))([x, 0]) == h([x, 0]) + + raises(TypeError, lambda: f/g) + raises(TypeError, lambda: f + 1) + raises(TypeError, lambda: f + i) + raises(TypeError, lambda: f - 1) + raises(TypeError, lambda: f*i) + + +def test_creation(): + F = QQ.old_poly_ring(x).free_module(3) + G = QQ.old_poly_ring(x).free_module(2) + SM = F.submodule([1, 1, 1]) + Q = F / SM + SQ = Q.submodule([1, 0, 0]) + + matrix = [[1, 0], [0, 1], [-1, -1]] + h = homomorphism(F, G, matrix) + h2 = homomorphism(Q, G, matrix) + assert h.quotient_domain(SM) == h2 + raises(ValueError, lambda: h.quotient_domain(F.submodule([1, 0, 0]))) + assert h2.restrict_domain(SQ) == homomorphism(SQ, G, matrix) + raises(ValueError, lambda: h.restrict_domain(G)) + raises(ValueError, lambda: h.restrict_codomain(G.submodule([1, 0]))) + raises(ValueError, lambda: h.quotient_codomain(F)) + + im = [[1, 0, 0], [0, 1, 0], [0, 0, 1]] + for M in [F, SM, Q, SQ]: + assert M.identity_hom() == homomorphism(M, M, im) + assert SM.inclusion_hom() == homomorphism(SM, F, im) + assert SQ.inclusion_hom() == homomorphism(SQ, Q, im) + assert Q.quotient_hom() == homomorphism(F, Q, im) + assert SQ.quotient_hom() == homomorphism(SQ.base, SQ, im) + + class conv: + def convert(x, y=None): + return x + + class dummy: + container = conv() + + def submodule(*args): + return None + raises(TypeError, lambda: homomorphism(dummy(), G, matrix)) + raises(TypeError, lambda: homomorphism(F, dummy(), matrix)) + raises( + ValueError, lambda: homomorphism(QQ.old_poly_ring(x, y).free_module(3), G, matrix)) + raises(ValueError, lambda: homomorphism(F, G, [0, 0])) + + +def test_properties(): + R = QQ.old_poly_ring(x, y) + F = R.free_module(2) + h = homomorphism(F, F, [[x, 0], [y, 0]]) + assert h.kernel() == F.submodule([-y, x]) + assert h.image() == F.submodule([x, 0], [y, 0]) + assert not h.is_injective() + assert not h.is_surjective() + assert h.restrict_codomain(h.image()).is_surjective() + assert h.restrict_domain(F.submodule([1, 0])).is_injective() + assert h.quotient_domain( + h.kernel()).restrict_codomain(h.image()).is_isomorphism() + + R2 = QQ.old_poly_ring(x, y, order=(("lex", x), ("ilex", y))) / [x**2 + 1] + F = R2.free_module(2) + h = homomorphism(F, F, [[x, 0], [y, y + 1]]) + assert h.is_isomorphism() diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/test_ideals.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/test_ideals.py new file mode 100644 index 0000000000000000000000000000000000000000..b7fff0674b54a22e2a5acba5110d62d96a877074 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/test_ideals.py @@ -0,0 +1,131 @@ +"""Test ideals.py code.""" + +from sympy.polys import QQ, ilex +from sympy.abc import x, y, z +from sympy.testing.pytest import raises + + +def test_ideal_operations(): + R = QQ.old_poly_ring(x, y) + I = R.ideal(x) + J = R.ideal(y) + S = R.ideal(x*y) + T = R.ideal(x, y) + + assert not (I == J) + assert I == I + + assert I.union(J) == T + assert I + J == T + assert I + T == T + + assert not I.subset(T) + assert T.subset(I) + + assert I.product(J) == S + assert I*J == S + assert x*J == S + assert I*y == S + assert R.convert(x)*J == S + assert I*R.convert(y) == S + + assert not I.is_zero() + assert not J.is_whole_ring() + + assert R.ideal(x**2 + 1, x).is_whole_ring() + assert R.ideal() == R.ideal(0) + assert R.ideal().is_zero() + + assert T.contains(x*y) + assert T.subset([x, y]) + + assert T.in_terms_of_generators(x) == [R(1), R(0)] + + assert T**0 == R.ideal(1) + assert T**1 == T + assert T**2 == R.ideal(x**2, y**2, x*y) + assert I**5 == R.ideal(x**5) + + +def test_exceptions(): + I = QQ.old_poly_ring(x).ideal(x) + J = QQ.old_poly_ring(y).ideal(1) + raises(ValueError, lambda: I.union(x)) + raises(ValueError, lambda: I + J) + raises(ValueError, lambda: I * J) + raises(ValueError, lambda: I.union(J)) + assert (I == J) is False + assert I != J + + +def test_nontriv_global(): + R = QQ.old_poly_ring(x, y, z) + + def contains(I, f): + return R.ideal(*I).contains(f) + + assert contains([x, y], x) + assert contains([x, y], x + y) + assert not contains([x, y], 1) + assert not contains([x, y], z) + assert contains([x**2 + y, x**2 + x], x - y) + assert not contains([x + y + z, x*y + x*z + y*z, x*y*z], x**2) + assert contains([x + y + z, x*y + x*z + y*z, x*y*z], x**3) + assert contains([x + y + z, x*y + x*z + y*z, x*y*z], x**4) + assert not contains([x + y + z, x*y + x*z + y*z, x*y*z], x*y**2) + assert contains([x + y + z, x*y + x*z + y*z, x*y*z], x**4 + y**3 + 2*z*y*x) + assert contains([x + y + z, x*y + x*z + y*z, x*y*z], x*y*z) + assert contains([x, 1 + x + y, 5 - 7*y], 1) + assert contains( + [x**3 + y**3, y**3 + z**3, z**3 + x**3, x**2*y + x**2*z + y**2*z], + x**3) + assert not contains( + [x**3 + y**3, y**3 + z**3, z**3 + x**3, x**2*y + x**2*z + y**2*z], + x**2 + y**2) + + # compare local order + assert not contains([x*(1 + x + y), y*(1 + z)], x) + assert not contains([x*(1 + x + y), y*(1 + z)], x + y) + + +def test_nontriv_local(): + R = QQ.old_poly_ring(x, y, z, order=ilex) + + def contains(I, f): + return R.ideal(*I).contains(f) + + assert contains([x, y], x) + assert contains([x, y], x + y) + assert not contains([x, y], 1) + assert not contains([x, y], z) + assert contains([x**2 + y, x**2 + x], x - y) + assert not contains([x + y + z, x*y + x*z + y*z, x*y*z], x**2) + assert contains([x*(1 + x + y), y*(1 + z)], x) + assert contains([x*(1 + x + y), y*(1 + z)], x + y) + + +def test_intersection(): + R = QQ.old_poly_ring(x, y, z) + # SCA, example 1.8.11 + assert R.ideal(x, y).intersect(R.ideal(y**2, z)) == R.ideal(y**2, y*z, x*z) + + assert R.ideal(x, y).intersect(R.ideal()).is_zero() + + R = QQ.old_poly_ring(x, y, z, order="ilex") + assert R.ideal(x, y).intersect(R.ideal(y**2 + y**2*z, z + z*x**3*y)) == \ + R.ideal(y**2, y*z, x*z) + + +def test_quotient(): + # SCA, example 1.8.13 + R = QQ.old_poly_ring(x, y, z) + assert R.ideal(x, y).quotient(R.ideal(y**2, z)) == R.ideal(x, y) + + +def test_reduction(): + from sympy.polys.distributedmodules import sdm_nf_buchberger_reduced + R = QQ.old_poly_ring(x, y) + I = R.ideal(x**5, y) + e = R.convert(x**3 + y**2) + assert I.reduce_element(e) == e + assert I.reduce_element(e, NF=sdm_nf_buchberger_reduced) == R.convert(x**3) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/test_modules.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/test_modules.py new file mode 100644 index 0000000000000000000000000000000000000000..29c2d4ce45f452f6f61420654be64a67d13b396b --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/agca/tests/test_modules.py @@ -0,0 +1,408 @@ +"""Test modules.py code.""" + +from sympy.polys.agca.modules import FreeModule, ModuleOrder, FreeModulePolyRing +from sympy.polys import CoercionFailed, QQ, lex, grlex, ilex, ZZ +from sympy.abc import x, y, z +from sympy.testing.pytest import raises +from sympy.core.numbers import Rational + + +def test_FreeModuleElement(): + M = QQ.old_poly_ring(x).free_module(3) + e = M.convert([1, x, x**2]) + f = [QQ.old_poly_ring(x).convert(1), QQ.old_poly_ring(x).convert(x), QQ.old_poly_ring(x).convert(x**2)] + assert list(e) == f + assert f[0] == e[0] + assert f[1] == e[1] + assert f[2] == e[2] + raises(IndexError, lambda: e[3]) + + g = M.convert([x, 0, 0]) + assert e + g == M.convert([x + 1, x, x**2]) + assert f + g == M.convert([x + 1, x, x**2]) + assert -e == M.convert([-1, -x, -x**2]) + assert e - g == M.convert([1 - x, x, x**2]) + assert e != g + + assert M.convert([x, x, x]) / QQ.old_poly_ring(x).convert(x) == [1, 1, 1] + R = QQ.old_poly_ring(x, order="ilex") + assert R.free_module(1).convert([x]) / R.convert(x) == [1] + + +def test_FreeModule(): + M1 = FreeModule(QQ.old_poly_ring(x), 2) + assert M1 == FreeModule(QQ.old_poly_ring(x), 2) + assert M1 != FreeModule(QQ.old_poly_ring(y), 2) + assert M1 != FreeModule(QQ.old_poly_ring(x), 3) + M2 = FreeModule(QQ.old_poly_ring(x, order="ilex"), 2) + + assert [x, 1] in M1 + assert [x] not in M1 + assert [2, y] not in M1 + assert [1/(x + 1), 2] not in M1 + + e = M1.convert([x, x**2 + 1]) + X = QQ.old_poly_ring(x).convert(x) + assert e == [X, X**2 + 1] + assert e == [x, x**2 + 1] + assert 2*e == [2*x, 2*x**2 + 2] + assert e*2 == [2*x, 2*x**2 + 2] + assert e/2 == [x/2, (x**2 + 1)/2] + assert x*e == [x**2, x**3 + x] + assert e*x == [x**2, x**3 + x] + assert X*e == [x**2, x**3 + x] + assert e*X == [x**2, x**3 + x] + + assert [x, 1] in M2 + assert [x] not in M2 + assert [2, y] not in M2 + assert [1/(x + 1), 2] in M2 + + e = M2.convert([x, x**2 + 1]) + X = QQ.old_poly_ring(x, order="ilex").convert(x) + assert e == [X, X**2 + 1] + assert e == [x, x**2 + 1] + assert 2*e == [2*x, 2*x**2 + 2] + assert e*2 == [2*x, 2*x**2 + 2] + assert e/2 == [x/2, (x**2 + 1)/2] + assert x*e == [x**2, x**3 + x] + assert e*x == [x**2, x**3 + x] + assert e/(1 + x) == [x/(1 + x), (x**2 + 1)/(1 + x)] + assert X*e == [x**2, x**3 + x] + assert e*X == [x**2, x**3 + x] + + M3 = FreeModule(QQ.old_poly_ring(x, y), 2) + assert M3.convert(e) == M3.convert([x, x**2 + 1]) + + assert not M3.is_submodule(0) + assert not M3.is_zero() + + raises(NotImplementedError, lambda: ZZ.old_poly_ring(x).free_module(2)) + raises(NotImplementedError, lambda: FreeModulePolyRing(ZZ, 2)) + raises(CoercionFailed, lambda: M1.convert(QQ.old_poly_ring(x).free_module(3) + .convert([1, 2, 3]))) + raises(CoercionFailed, lambda: M3.convert(1)) + + +def test_ModuleOrder(): + o1 = ModuleOrder(lex, grlex, False) + o2 = ModuleOrder(ilex, lex, False) + + assert o1 == ModuleOrder(lex, grlex, False) + assert (o1 != ModuleOrder(lex, grlex, False)) is False + assert o1 != o2 + + assert o1((1, 2, 3)) == (1, (5, (2, 3))) + assert o2((1, 2, 3)) == (-1, (2, 3)) + + +def test_SubModulePolyRing_global(): + R = QQ.old_poly_ring(x, y) + F = R.free_module(3) + Fd = F.submodule([1, 0, 0], [1, 2, 0], [1, 2, 3]) + M = F.submodule([x**2 + y**2, 1, 0], [x, y, 1]) + + assert F == Fd + assert Fd == F + assert F != M + assert M != F + assert Fd != M + assert M != Fd + assert Fd == F.submodule(*F.basis()) + + assert Fd.is_full_module() + assert not M.is_full_module() + assert not Fd.is_zero() + assert not M.is_zero() + assert Fd.submodule().is_zero() + + assert M.contains([x**2 + y**2 + x, 1 + y, 1]) + assert not M.contains([x**2 + y**2 + x, 1 + y, 2]) + assert M.contains([y**2, 1 - x*y, -x]) + + assert not F.submodule([1 + x, 0, 0]) == F.submodule([1, 0, 0]) + assert F.submodule([1, 0, 0], [0, 1, 0]).union(F.submodule([0, 0, 1])) == F + assert not M.is_submodule(0) + + m = F.convert([x**2 + y**2, 1, 0]) + n = M.convert(m) + assert m.module is F + assert n.module is M + + raises(ValueError, lambda: M.submodule([1, 0, 0])) + raises(TypeError, lambda: M.union(1)) + raises(ValueError, lambda: M.union(R.free_module(1).submodule([x]))) + + assert F.submodule([x, x, x]) != F.submodule([x, x, x], order="ilex") + + +def test_SubModulePolyRing_local(): + R = QQ.old_poly_ring(x, y, order=ilex) + F = R.free_module(3) + Fd = F.submodule([1 + x, 0, 0], [1 + y, 2 + 2*y, 0], [1, 2, 3]) + M = F.submodule([x**2 + y**2, 1, 0], [x, y, 1]) + + assert F == Fd + assert Fd == F + assert F != M + assert M != F + assert Fd != M + assert M != Fd + assert Fd == F.submodule(*F.basis()) + + assert Fd.is_full_module() + assert not M.is_full_module() + assert not Fd.is_zero() + assert not M.is_zero() + assert Fd.submodule().is_zero() + + assert M.contains([x**2 + y**2 + x, 1 + y, 1]) + assert not M.contains([x**2 + y**2 + x, 1 + y, 2]) + assert M.contains([y**2, 1 - x*y, -x]) + + assert F.submodule([1 + x, 0, 0]) == F.submodule([1, 0, 0]) + assert F.submodule( + [1, 0, 0], [0, 1, 0]).union(F.submodule([0, 0, 1 + x*y])) == F + + raises(ValueError, lambda: M.submodule([1, 0, 0])) + + +def test_SubModulePolyRing_nontriv_global(): + R = QQ.old_poly_ring(x, y, z) + F = R.free_module(1) + + def contains(I, f): + return F.submodule(*[[g] for g in I]).contains([f]) + + assert contains([x, y], x) + assert contains([x, y], x + y) + assert not contains([x, y], 1) + assert not contains([x, y], z) + assert contains([x**2 + y, x**2 + x], x - y) + assert not contains([x + y + z, x*y + x*z + y*z, x*y*z], x**2) + assert contains([x + y + z, x*y + x*z + y*z, x*y*z], x**3) + assert contains([x + y + z, x*y + x*z + y*z, x*y*z], x**4) + assert not contains([x + y + z, x*y + x*z + y*z, x*y*z], x*y**2) + assert contains([x + y + z, x*y + x*z + y*z, x*y*z], x**4 + y**3 + 2*z*y*x) + assert contains([x + y + z, x*y + x*z + y*z, x*y*z], x*y*z) + assert contains([x, 1 + x + y, 5 - 7*y], 1) + assert contains( + [x**3 + y**3, y**3 + z**3, z**3 + x**3, x**2*y + x**2*z + y**2*z], + x**3) + assert not contains( + [x**3 + y**3, y**3 + z**3, z**3 + x**3, x**2*y + x**2*z + y**2*z], + x**2 + y**2) + + # compare local order + assert not contains([x*(1 + x + y), y*(1 + z)], x) + assert not contains([x*(1 + x + y), y*(1 + z)], x + y) + + +def test_SubModulePolyRing_nontriv_local(): + R = QQ.old_poly_ring(x, y, z, order=ilex) + F = R.free_module(1) + + def contains(I, f): + return F.submodule(*[[g] for g in I]).contains([f]) + + assert contains([x, y], x) + assert contains([x, y], x + y) + assert not contains([x, y], 1) + assert not contains([x, y], z) + assert contains([x**2 + y, x**2 + x], x - y) + assert not contains([x + y + z, x*y + x*z + y*z, x*y*z], x**2) + assert contains([x*(1 + x + y), y*(1 + z)], x) + assert contains([x*(1 + x + y), y*(1 + z)], x + y) + + +def test_syzygy(): + R = QQ.old_poly_ring(x, y, z) + M = R.free_module(1).submodule([x*y], [y*z], [x*z]) + S = R.free_module(3).submodule([0, x, -y], [z, -x, 0]) + assert M.syzygy_module() == S + + M2 = M / ([x*y*z],) + S2 = R.free_module(3).submodule([z, 0, 0], [0, x, 0], [0, 0, y]) + assert M2.syzygy_module() == S2 + + F = R.free_module(3) + assert F.submodule(*F.basis()).syzygy_module() == F.submodule() + + R2 = QQ.old_poly_ring(x, y, z) / [x*y*z] + M3 = R2.free_module(1).submodule([x*y], [y*z], [x*z]) + S3 = R2.free_module(3).submodule([z, 0, 0], [0, x, 0], [0, 0, y]) + assert M3.syzygy_module() == S3 + + +def test_in_terms_of_generators(): + R = QQ.old_poly_ring(x, order="ilex") + M = R.free_module(2).submodule([2*x, 0], [1, 2]) + assert M.in_terms_of_generators( + [x, x]) == [R.convert(Rational(1, 4)), R.convert(x/2)] + raises(ValueError, lambda: M.in_terms_of_generators([1, 0])) + + M = R.free_module(2) / ([x, 0], [1, 1]) + SM = M.submodule([1, x]) + assert SM.in_terms_of_generators([2, 0]) == [R.convert(-2/(x - 1))] + + R = QQ.old_poly_ring(x, y) / [x**2 - y**2] + M = R.free_module(2) + SM = M.submodule([x, 0], [0, y]) + assert SM.in_terms_of_generators( + [x**2, x**2]) == [R.convert(x), R.convert(y)] + + +def test_QuotientModuleElement(): + R = QQ.old_poly_ring(x) + F = R.free_module(3) + N = F.submodule([1, x, x**2]) + M = F/N + e = M.convert([x**2, 2, 0]) + + assert M.convert([x + 1, x**2 + x, x**3 + x**2]) == 0 + assert e == [x**2, 2, 0] + N == F.convert([x**2, 2, 0]) + N == \ + M.convert(F.convert([x**2, 2, 0])) + + assert M.convert([x**2 + 1, 2*x + 2, x**2]) == e + [0, x, 0] == \ + e + M.convert([0, x, 0]) == e + F.convert([0, x, 0]) + assert M.convert([x**2 + 1, 2, x**2]) == e - [0, x, 0] == \ + e - M.convert([0, x, 0]) == e - F.convert([0, x, 0]) + assert M.convert([0, 2, 0]) == M.convert([x**2, 4, 0]) - e == \ + [x**2, 4, 0] - e == F.convert([x**2, 4, 0]) - e + assert M.convert([x**3 + x**2, 2*x + 2, 0]) == (1 + x)*e == \ + R.convert(1 + x)*e == e*(1 + x) == e*R.convert(1 + x) + assert -e == [-x**2, -2, 0] + + f = [x, x, 0] + N + assert M.convert([1, 1, 0]) == f / x == f / R.convert(x) + + M2 = F/[(2, 2*x, 2*x**2), (0, 0, 1)] + G = R.free_module(2) + M3 = G/[[1, x]] + M4 = F.submodule([1, x, x**2], [1, 0, 0]) / N + raises(CoercionFailed, lambda: M.convert(G.convert([1, x]))) + raises(CoercionFailed, lambda: M.convert(M3.convert([1, x]))) + raises(CoercionFailed, lambda: M.convert(M2.convert([1, x, x]))) + assert M2.convert(M.convert([2, x, x**2])) == [2, x, 0] + assert M.convert(M4.convert([2, 0, 0])) == [2, 0, 0] + + +def test_QuotientModule(): + R = QQ.old_poly_ring(x) + F = R.free_module(3) + N = F.submodule([1, x, x**2]) + M = F/N + + assert M != F + assert M != N + assert M == F / [(1, x, x**2)] + assert not M.is_zero() + assert (F / F.basis()).is_zero() + + SQ = F.submodule([1, x, x**2], [2, 0, 0]) / N + assert SQ == M.submodule([2, x, x**2]) + assert SQ != M.submodule([2, 1, 0]) + assert SQ != M + assert M.is_submodule(SQ) + assert not SQ.is_full_module() + + raises(ValueError, lambda: N/F) + raises(ValueError, lambda: F.submodule([2, 0, 0]) / N) + raises(ValueError, lambda: R.free_module(2)/F) + raises(CoercionFailed, lambda: F.convert(M.convert([1, x, x**2]))) + + M1 = F / [[1, 1, 1]] + M2 = M1.submodule([1, 0, 0], [0, 1, 0]) + assert M1 == M2 + + +def test_ModulesQuotientRing(): + R = QQ.old_poly_ring(x, y, order=(("lex", x), ("ilex", y))) / [x**2 + 1] + M1 = R.free_module(2) + assert M1 == R.free_module(2) + assert M1 != QQ.old_poly_ring(x).free_module(2) + assert M1 != R.free_module(3) + + assert [x, 1] in M1 + assert [x] not in M1 + assert [1/(R.convert(x) + 1), 2] in M1 + assert [1, 2/(1 + y)] in M1 + assert [1, 2/y] not in M1 + + assert M1.convert([x**2, y]) == [-1, y] + + F = R.free_module(3) + Fd = F.submodule([x**2, 0, 0], [1, 2, 0], [1, 2, 3]) + M = F.submodule([x**2 + y**2, 1, 0], [x, y, 1]) + + assert F == Fd + assert Fd == F + assert F != M + assert M != F + assert Fd != M + assert M != Fd + assert Fd == F.submodule(*F.basis()) + + assert Fd.is_full_module() + assert not M.is_full_module() + assert not Fd.is_zero() + assert not M.is_zero() + assert Fd.submodule().is_zero() + + assert M.contains([x**2 + y**2 + x, -x**2 + y, 1]) + assert not M.contains([x**2 + y**2 + x, 1 + y, 2]) + assert M.contains([y**2, 1 - x*y, -x]) + + assert F.submodule([x, 0, 0]) == F.submodule([1, 0, 0]) + assert not F.submodule([y, 0, 0]) == F.submodule([1, 0, 0]) + assert F.submodule([1, 0, 0], [0, 1, 0]).union(F.submodule([0, 0, 1])) == F + assert not M.is_submodule(0) + + +def test_module_mul(): + R = QQ.old_poly_ring(x) + M = R.free_module(2) + S1 = M.submodule([x, 0], [0, x]) + S2 = M.submodule([x**2, 0], [0, x**2]) + I = R.ideal(x) + + assert I*M == M*I == S1 == x*M == M*x + assert I*S1 == S2 == x*S1 + + +def test_intersection(): + # SCA, example 2.8.5 + F = QQ.old_poly_ring(x, y).free_module(2) + M1 = F.submodule([x, y], [y, 1]) + M2 = F.submodule([0, y - 1], [x, 1], [y, x]) + I = F.submodule([x, y], [y**2 - y, y - 1], [x*y + y, x + 1]) + I1, rel1, rel2 = M1.intersect(M2, relations=True) + assert I1 == M2.intersect(M1) == I + for i, g in enumerate(I1.gens): + assert g == sum(c*x for c, x in zip(rel1[i], M1.gens)) \ + == sum(d*y for d, y in zip(rel2[i], M2.gens)) + + assert F.submodule([x, y]).intersect(F.submodule([y, x])).is_zero() + + +def test_quotient(): + # SCA, example 2.8.6 + R = QQ.old_poly_ring(x, y, z) + F = R.free_module(2) + assert F.submodule([x*y, x*z], [y*z, x*y]).module_quotient( + F.submodule([y, z], [z, y])) == QQ.old_poly_ring(x, y, z).ideal(x**2*y**2 - x*y*z**2) + assert F.submodule([x, y]).module_quotient(F.submodule()).is_whole_ring() + + M = F.submodule([x**2, x**2], [y**2, y**2]) + N = F.submodule([x + y, x + y]) + q, rel = M.module_quotient(N, relations=True) + assert q == R.ideal(y**2, x - y) + for i, g in enumerate(q.gens): + assert g*N.gens[0] == sum(c*x for c, x in zip(rel[i], M.gens)) + + +def test_groebner_extendend(): + M = QQ.old_poly_ring(x, y, z).free_module(3).submodule([x + 1, y, 1], [x*y, z, z**2]) + G, R = M._groebner_vec(extended=True) + for i, g in enumerate(G): + assert g == sum(c*gen for c, gen in zip(R[i], M.gens)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/benchmarks/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/benchmarks/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d8a6598c0fb7376d000893501919c35f0cd2eb9f Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/benchmarks/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/benchmarks/__pycache__/bench_galoispolys.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/benchmarks/__pycache__/bench_galoispolys.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aca56e6b290cc89f3e911704dcfe6909f2470bd3 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/benchmarks/__pycache__/bench_galoispolys.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/benchmarks/__pycache__/bench_groebnertools.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/benchmarks/__pycache__/bench_groebnertools.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cd168f9d73923ef319ce875451829dc82c29ba2b Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/benchmarks/__pycache__/bench_groebnertools.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5ee51c3e6c4419b4f1267e14633c8fa744bb7ed8 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/algebraicfield.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/algebraicfield.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2633567490f56ac250898d9a64a720258c236ab6 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/algebraicfield.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/characteristiczero.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/characteristiczero.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8f8ab4ae4418cd6cb8ca8af53281e1f88a07a510 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/characteristiczero.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/complexfield.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/complexfield.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..23fbc63a3558c47f23393a0765eb87cb246d42b8 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/complexfield.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/compositedomain.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/compositedomain.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7e4e44279a4684ce462f007e2b0d472b697cca08 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/compositedomain.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/domain.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/domain.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f9bc4fe8a480d189e7d6350b1d8ca3e639e7e520 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/domain.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/expressiondomain.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/expressiondomain.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1cceb2778914174370b410c930751d9cab32a6cd Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/expressiondomain.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/expressionrawdomain.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/expressionrawdomain.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7848242408aad3c8d4cc26d0ea08e236ce5b1ca5 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/expressionrawdomain.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/fractionfield.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/fractionfield.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e3bc07911c81d7878b06cb7425d75f2e3c9fb9f5 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/fractionfield.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/gmpyfinitefield.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/gmpyfinitefield.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5164b808247d28b3e2c1138fe26a0f2025a5700a Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/gmpyfinitefield.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/gmpyintegerring.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/gmpyintegerring.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..82ada2734165078fee3b059fc3de2b66b250c0c7 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/gmpyintegerring.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/integerring.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/integerring.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3dcaf8009ad3d884f7265fc29f6a46c8df014ef3 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/integerring.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/modularinteger.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/modularinteger.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9a267e67c69067e0f63a9537f48f68236e80895c Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/modularinteger.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/mpelements.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/mpelements.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8180b1f298e50cdace1bba751465cd31bb93f11b Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/mpelements.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/old_fractionfield.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/old_fractionfield.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c1169643f306a1e4e21d7c0cb6b7df848f1fe520 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/old_fractionfield.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/old_polynomialring.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/old_polynomialring.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..395a893eaa8fde5fb735739fcba900fe2be2e65b Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/old_polynomialring.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/polynomialring.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/polynomialring.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..98b9fb781f23a0fc1b78b261cdee1e0bb4c1a35c Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/polynomialring.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/pythonfinitefield.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/pythonfinitefield.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6bb0e000b80877500463c46e3bc4a8b83df71259 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/pythonfinitefield.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/pythonintegerring.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/pythonintegerring.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f492a7585bf09c73867f0b9e741a50100b088244 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/pythonintegerring.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/pythonrational.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/pythonrational.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..53f453dace78ef03b3b3e1724f78e03a712c26c3 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/pythonrational.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/pythonrationalfield.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/pythonrationalfield.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..695c32c34e38883e7405242b961cd5b74817efa9 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/pythonrationalfield.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/quotientring.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/quotientring.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0e44cc6862381732f134a8c6163edf5ec1513d86 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/quotientring.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/rationalfield.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/rationalfield.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e398c15f042c94ded87dbd1fcd31b7b7ea902697 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/rationalfield.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/realfield.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/realfield.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fb7791de604df6739ddb5c860d28e15c8e1d136b Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/realfield.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/simpledomain.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/simpledomain.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7c59551cead25f0f6f2a33332529c4a87d970500 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/__pycache__/simpledomain.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..79f830a5b1ef0dddac2ae83bacfad3fdaf82927b Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/tests/__pycache__/test_polynomialring.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/tests/__pycache__/test_polynomialring.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ddb56b4b9ac4705ece69118a4afd703d77d9516c Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/tests/__pycache__/test_polynomialring.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/tests/__pycache__/test_quotientring.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/tests/__pycache__/test_quotientring.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6870d957225408d9729cfc4d68aa7ab26efb4c76 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/domains/tests/__pycache__/test_quotientring.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..778473ac83c5294369ae8da7ba57a9cf77d07355 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/_dfm.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/_dfm.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9180c8db082d01d19aa96e0cba68eec90f72b874 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/_dfm.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/_typing.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/_typing.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e1cfc451d216d7ce870ae1e4617b92088fe3ce99 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/_typing.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/ddm.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/ddm.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..059483ba0411d33b7e4660b9d5103a37d201d683 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/ddm.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/dense.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/dense.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bb8c7432dad649c14f8e36db37bcec6b8c4a4e4c Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/dense.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/dfm.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/dfm.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2f2e5462bc7d9df2cd521b0db7e78e7a27599f91 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/dfm.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/domainscalar.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/domainscalar.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1499969b7f901bf474d4bd1eeaae9389aa862f94 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/domainscalar.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/eigen.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/eigen.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a79cafe73ad1ff2f982d25cb3e7f47db9ed5cc94 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/eigen.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/exceptions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/exceptions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3a36495a14ee8c5d0c44002582e758b1863c9e1d Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/exceptions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/linsolve.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/linsolve.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..645f53f8b9a2247aee250c7fb0f753e170b6908c Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/linsolve.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/lll.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/lll.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e4ba0ea8c3a340945c45a4f72a029cb91d31fcd9 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/lll.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/normalforms.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/normalforms.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2e0f1f23b333329dcfe94edba3f653c2d02758fc Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/normalforms.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/rref.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/rref.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ffff8da0aa2a5791693d9d1bbfd4abd4212a273d Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/rref.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/sdm.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/sdm.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..96f6b673b809a2a97d47f283dd2e369b5496eb91 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/__pycache__/sdm.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dd8d5bf65916f43143b73156b8eb76fc916f2e36 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_ddm.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_ddm.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f018303a564cc128c97195cdf68e3e278b0fe17d Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_ddm.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_dense.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_dense.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ebab7f97b41aef538488da003404479d046e093a Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_dense.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_domainscalar.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_domainscalar.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a3818d45d1abc5ec30c8f47681717643dbbe96bf Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_domainscalar.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_eigen.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_eigen.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b7067830501dab5848708bdb674f14f366ae558c Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_eigen.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_fflu.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_fflu.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..029d6f1f7baa7615865047a1330c8246570c7858 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_fflu.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_inverse.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_inverse.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..428682873437b2d9530d05a2f66aa86b73c3f2b5 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_inverse.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_linsolve.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_linsolve.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e3862354f127a7a3aaa966171c9886db0a5fb576 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_linsolve.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_lll.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_lll.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..da2d5e8b0f01c3187ee4c7e3da11fe55ee2123f6 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_lll.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_normalforms.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_normalforms.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9416f2f1e2706bb50e2615df9beb392f8b540fa8 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_normalforms.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_nullspace.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_nullspace.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..08355ea43b060407a24aef9ea0bff2d3199203d1 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_nullspace.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_rref.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_rref.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e89f53b5628e9146fb002b4891ff294a67009b26 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_rref.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_sdm.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_sdm.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b79a62c96a259d7c89bca0d34c80584468e9659f Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_sdm.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_xxm.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_xxm.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e2f79eb62e2e7cdd9ff2f515850d0a5c4f91d2b6 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/__pycache__/test_xxm.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_ddm.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_ddm.py new file mode 100644 index 0000000000000000000000000000000000000000..44c862461e85d503696e621874c10d67d8ee1f1d --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_ddm.py @@ -0,0 +1,558 @@ +from sympy.testing.pytest import raises +from sympy.external.gmpy import GROUND_TYPES + +from sympy.polys import ZZ, QQ + +from sympy.polys.matrices.ddm import DDM +from sympy.polys.matrices.exceptions import ( + DMShapeError, DMNonInvertibleMatrixError, DMDomainError, + DMBadInputError) + + +def test_DDM_init(): + items = [[ZZ(0), ZZ(1), ZZ(2)], [ZZ(3), ZZ(4), ZZ(5)]] + shape = (2, 3) + ddm = DDM(items, shape, ZZ) + assert ddm.shape == shape + assert ddm.rows == 2 + assert ddm.cols == 3 + assert ddm.domain == ZZ + + raises(DMBadInputError, lambda: DDM([[ZZ(2), ZZ(3)]], (2, 2), ZZ)) + raises(DMBadInputError, lambda: DDM([[ZZ(1)], [ZZ(2), ZZ(3)]], (2, 2), ZZ)) + + +def test_DDM_getsetitem(): + ddm = DDM([[ZZ(2), ZZ(3)], [ZZ(4), ZZ(5)]], (2, 2), ZZ) + + assert ddm[0][0] == ZZ(2) + assert ddm[0][1] == ZZ(3) + assert ddm[1][0] == ZZ(4) + assert ddm[1][1] == ZZ(5) + + raises(IndexError, lambda: ddm[2][0]) + raises(IndexError, lambda: ddm[0][2]) + + ddm[0][0] = ZZ(-1) + assert ddm[0][0] == ZZ(-1) + + +def test_DDM_str(): + ddm = DDM([[ZZ(0), ZZ(1)], [ZZ(2), ZZ(3)]], (2, 2), ZZ) + if GROUND_TYPES == 'gmpy': # pragma: no cover + assert str(ddm) == '[[0, 1], [2, 3]]' + assert repr(ddm) == 'DDM([[mpz(0), mpz(1)], [mpz(2), mpz(3)]], (2, 2), ZZ)' + else: # pragma: no cover + assert repr(ddm) == 'DDM([[0, 1], [2, 3]], (2, 2), ZZ)' + assert str(ddm) == '[[0, 1], [2, 3]]' + + +def test_DDM_eq(): + items = [[ZZ(0), ZZ(1)], [ZZ(2), ZZ(3)]] + ddm1 = DDM(items, (2, 2), ZZ) + ddm2 = DDM(items, (2, 2), ZZ) + + assert (ddm1 == ddm1) is True + assert (ddm1 == items) is False + assert (items == ddm1) is False + assert (ddm1 == ddm2) is True + assert (ddm2 == ddm1) is True + + assert (ddm1 != ddm1) is False + assert (ddm1 != items) is True + assert (items != ddm1) is True + assert (ddm1 != ddm2) is False + assert (ddm2 != ddm1) is False + + ddm3 = DDM([[ZZ(0), ZZ(1)], [ZZ(3), ZZ(3)]], (2, 2), ZZ) + ddm3 = DDM(items, (2, 2), QQ) + + assert (ddm1 == ddm3) is False + assert (ddm3 == ddm1) is False + assert (ddm1 != ddm3) is True + assert (ddm3 != ddm1) is True + + +def test_DDM_convert_to(): + ddm = DDM([[ZZ(1), ZZ(2)]], (1, 2), ZZ) + assert ddm.convert_to(ZZ) == ddm + ddmq = ddm.convert_to(QQ) + assert ddmq.domain == QQ + + +def test_DDM_zeros(): + ddmz = DDM.zeros((3, 4), QQ) + assert list(ddmz) == [[QQ(0)] * 4] * 3 + assert ddmz.shape == (3, 4) + assert ddmz.domain == QQ + +def test_DDM_ones(): + ddmone = DDM.ones((2, 3), QQ) + assert list(ddmone) == [[QQ(1)] * 3] * 2 + assert ddmone.shape == (2, 3) + assert ddmone.domain == QQ + +def test_DDM_eye(): + ddmz = DDM.eye(3, QQ) + f = lambda i, j: QQ(1) if i == j else QQ(0) + assert list(ddmz) == [[f(i, j) for i in range(3)] for j in range(3)] + assert ddmz.shape == (3, 3) + assert ddmz.domain == QQ + + +def test_DDM_copy(): + ddm1 = DDM([[QQ(1)], [QQ(2)]], (2, 1), QQ) + ddm2 = ddm1.copy() + assert (ddm1 == ddm2) is True + ddm1[0][0] = QQ(-1) + assert (ddm1 == ddm2) is False + ddm2[0][0] = QQ(-1) + assert (ddm1 == ddm2) is True + + +def test_DDM_transpose(): + ddm = DDM([[QQ(1)], [QQ(2)]], (2, 1), QQ) + ddmT = DDM([[QQ(1), QQ(2)]], (1, 2), QQ) + assert ddm.transpose() == ddmT + ddm02 = DDM([], (0, 2), QQ) + ddm02T = DDM([[], []], (2, 0), QQ) + assert ddm02.transpose() == ddm02T + assert ddm02T.transpose() == ddm02 + ddm0 = DDM([], (0, 0), QQ) + assert ddm0.transpose() == ddm0 + + +def test_DDM_add(): + A = DDM([[ZZ(1)], [ZZ(2)]], (2, 1), ZZ) + B = DDM([[ZZ(3)], [ZZ(4)]], (2, 1), ZZ) + C = DDM([[ZZ(4)], [ZZ(6)]], (2, 1), ZZ) + AQ = DDM([[QQ(1)], [QQ(2)]], (2, 1), QQ) + assert A + B == A.add(B) == C + + raises(DMShapeError, lambda: A + DDM([[ZZ(5)]], (1, 1), ZZ)) + raises(TypeError, lambda: A + ZZ(1)) + raises(TypeError, lambda: ZZ(1) + A) + raises(DMDomainError, lambda: A + AQ) + raises(DMDomainError, lambda: AQ + A) + + +def test_DDM_sub(): + A = DDM([[ZZ(1)], [ZZ(2)]], (2, 1), ZZ) + B = DDM([[ZZ(3)], [ZZ(4)]], (2, 1), ZZ) + C = DDM([[ZZ(-2)], [ZZ(-2)]], (2, 1), ZZ) + AQ = DDM([[QQ(1)], [QQ(2)]], (2, 1), QQ) + D = DDM([[ZZ(5)]], (1, 1), ZZ) + assert A - B == A.sub(B) == C + + raises(TypeError, lambda: A - ZZ(1)) + raises(TypeError, lambda: ZZ(1) - A) + raises(DMShapeError, lambda: A - D) + raises(DMShapeError, lambda: D - A) + raises(DMShapeError, lambda: A.sub(D)) + raises(DMShapeError, lambda: D.sub(A)) + raises(DMDomainError, lambda: A - AQ) + raises(DMDomainError, lambda: AQ - A) + raises(DMDomainError, lambda: A.sub(AQ)) + raises(DMDomainError, lambda: AQ.sub(A)) + + +def test_DDM_neg(): + A = DDM([[ZZ(1)], [ZZ(2)]], (2, 1), ZZ) + An = DDM([[ZZ(-1)], [ZZ(-2)]], (2, 1), ZZ) + assert -A == A.neg() == An + assert -An == An.neg() == A + + +def test_DDM_mul(): + A = DDM([[ZZ(1)]], (1, 1), ZZ) + A2 = DDM([[ZZ(2)]], (1, 1), ZZ) + assert A * ZZ(2) == A2 + assert ZZ(2) * A == A2 + raises(TypeError, lambda: [[1]] * A) + raises(TypeError, lambda: A * [[1]]) + + +def test_DDM_matmul(): + A = DDM([[ZZ(1)], [ZZ(2)]], (2, 1), ZZ) + B = DDM([[ZZ(3), ZZ(4)]], (1, 2), ZZ) + AB = DDM([[ZZ(3), ZZ(4)], [ZZ(6), ZZ(8)]], (2, 2), ZZ) + BA = DDM([[ZZ(11)]], (1, 1), ZZ) + + assert A @ B == A.matmul(B) == AB + assert B @ A == B.matmul(A) == BA + + raises(TypeError, lambda: A @ 1) + raises(TypeError, lambda: A @ [[3, 4]]) + + Bq = DDM([[QQ(3), QQ(4)]], (1, 2), QQ) + + raises(DMDomainError, lambda: A @ Bq) + raises(DMDomainError, lambda: Bq @ A) + + C = DDM([[ZZ(1)]], (1, 1), ZZ) + + assert A @ C == A.matmul(C) == A + + raises(DMShapeError, lambda: C @ A) + raises(DMShapeError, lambda: C.matmul(A)) + + Z04 = DDM([], (0, 4), ZZ) + Z40 = DDM([[]]*4, (4, 0), ZZ) + Z50 = DDM([[]]*5, (5, 0), ZZ) + Z05 = DDM([], (0, 5), ZZ) + Z45 = DDM([[0] * 5] * 4, (4, 5), ZZ) + Z54 = DDM([[0] * 4] * 5, (5, 4), ZZ) + Z00 = DDM([], (0, 0), ZZ) + + assert Z04 @ Z45 == Z04.matmul(Z45) == Z05 + assert Z45 @ Z50 == Z45.matmul(Z50) == Z40 + assert Z00 @ Z04 == Z00.matmul(Z04) == Z04 + assert Z50 @ Z00 == Z50.matmul(Z00) == Z50 + assert Z00 @ Z00 == Z00.matmul(Z00) == Z00 + assert Z50 @ Z04 == Z50.matmul(Z04) == Z54 + + raises(DMShapeError, lambda: Z05 @ Z40) + raises(DMShapeError, lambda: Z05.matmul(Z40)) + + +def test_DDM_hstack(): + A = DDM([[ZZ(1), ZZ(2), ZZ(3)]], (1, 3), ZZ) + B = DDM([[ZZ(4), ZZ(5)]], (1, 2), ZZ) + C = DDM([[ZZ(6)]], (1, 1), ZZ) + + Ah = A.hstack(B) + assert Ah.shape == (1, 5) + assert Ah.domain == ZZ + assert Ah == DDM([[ZZ(1), ZZ(2), ZZ(3), ZZ(4), ZZ(5)]], (1, 5), ZZ) + + Ah = A.hstack(B, C) + assert Ah.shape == (1, 6) + assert Ah.domain == ZZ + assert Ah == DDM([[ZZ(1), ZZ(2), ZZ(3), ZZ(4), ZZ(5), ZZ(6)]], (1, 6), ZZ) + + +def test_DDM_vstack(): + A = DDM([[ZZ(1)], [ZZ(2)], [ZZ(3)]], (3, 1), ZZ) + B = DDM([[ZZ(4)], [ZZ(5)]], (2, 1), ZZ) + C = DDM([[ZZ(6)]], (1, 1), ZZ) + + Ah = A.vstack(B) + assert Ah.shape == (5, 1) + assert Ah.domain == ZZ + assert Ah == DDM([[ZZ(1)], [ZZ(2)], [ZZ(3)], [ZZ(4)], [ZZ(5)]], (5, 1), ZZ) + + Ah = A.vstack(B, C) + assert Ah.shape == (6, 1) + assert Ah.domain == ZZ + assert Ah == DDM([[ZZ(1)], [ZZ(2)], [ZZ(3)], [ZZ(4)], [ZZ(5)], [ZZ(6)]], (6, 1), ZZ) + + +def test_DDM_applyfunc(): + A = DDM([[ZZ(1), ZZ(2), ZZ(3)]], (1, 3), ZZ) + B = DDM([[ZZ(2), ZZ(4), ZZ(6)]], (1, 3), ZZ) + assert A.applyfunc(lambda x: 2*x, ZZ) == B + +def test_DDM_rref(): + + A = DDM([], (0, 4), QQ) + assert A.rref() == (A, []) + + A = DDM([[QQ(0), QQ(1)], [QQ(1), QQ(1)]], (2, 2), QQ) + Ar = DDM([[QQ(1), QQ(0)], [QQ(0), QQ(1)]], (2, 2), QQ) + pivots = [0, 1] + assert A.rref() == (Ar, pivots) + + A = DDM([[QQ(1), QQ(2), QQ(1)], [QQ(3), QQ(4), QQ(1)]], (2, 3), QQ) + Ar = DDM([[QQ(1), QQ(0), QQ(-1)], [QQ(0), QQ(1), QQ(1)]], (2, 3), QQ) + pivots = [0, 1] + assert A.rref() == (Ar, pivots) + + A = DDM([[QQ(3), QQ(4), QQ(1)], [QQ(1), QQ(2), QQ(1)]], (2, 3), QQ) + Ar = DDM([[QQ(1), QQ(0), QQ(-1)], [QQ(0), QQ(1), QQ(1)]], (2, 3), QQ) + pivots = [0, 1] + assert A.rref() == (Ar, pivots) + + A = DDM([[QQ(1), QQ(0)], [QQ(1), QQ(3)], [QQ(0), QQ(1)]], (3, 2), QQ) + Ar = DDM([[QQ(1), QQ(0)], [QQ(0), QQ(1)], [QQ(0), QQ(0)]], (3, 2), QQ) + pivots = [0, 1] + assert A.rref() == (Ar, pivots) + + A = DDM([[QQ(1), QQ(0), QQ(1)], [QQ(3), QQ(0), QQ(1)]], (2, 3), QQ) + Ar = DDM([[QQ(1), QQ(0), QQ(0)], [QQ(0), QQ(0), QQ(1)]], (2, 3), QQ) + pivots = [0, 2] + assert A.rref() == (Ar, pivots) + + +def test_DDM_nullspace(): + # more tests are in test_nullspace.py + A = DDM([[QQ(1), QQ(1)], [QQ(1), QQ(1)]], (2, 2), QQ) + Anull = DDM([[QQ(-1), QQ(1)]], (1, 2), QQ) + nonpivots = [1] + assert A.nullspace() == (Anull, nonpivots) + + +def test_DDM_particular(): + A = DDM([[QQ(1), QQ(0)]], (1, 2), QQ) + assert A.particular() == DDM.zeros((1, 1), QQ) + + +def test_DDM_det(): + # 0x0 case + A = DDM([], (0, 0), ZZ) + assert A.det() == ZZ(1) + + # 1x1 case + A = DDM([[ZZ(2)]], (1, 1), ZZ) + assert A.det() == ZZ(2) + + # 2x2 case + A = DDM([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + assert A.det() == ZZ(-2) + + # 3x3 with swap + A = DDM([[ZZ(1), ZZ(2), ZZ(3)], [ZZ(1), ZZ(2), ZZ(4)], [ZZ(1), ZZ(2), ZZ(5)]], (3, 3), ZZ) + assert A.det() == ZZ(0) + + # 2x2 QQ case + A = DDM([[QQ(1, 2), QQ(1, 2)], [QQ(1, 3), QQ(1, 4)]], (2, 2), QQ) + assert A.det() == QQ(-1, 24) + + # Nonsquare error + A = DDM([[ZZ(1)], [ZZ(2)]], (2, 1), ZZ) + raises(DMShapeError, lambda: A.det()) + + # Nonsquare error with empty matrix + A = DDM([], (0, 1), ZZ) + raises(DMShapeError, lambda: A.det()) + + +def test_DDM_inv(): + A = DDM([[QQ(1, 1), QQ(2, 1)], [QQ(3, 1), QQ(4, 1)]], (2, 2), QQ) + Ainv = DDM([[QQ(-2, 1), QQ(1, 1)], [QQ(3, 2), QQ(-1, 2)]], (2, 2), QQ) + assert A.inv() == Ainv + + A = DDM([[QQ(1), QQ(2)]], (1, 2), QQ) + raises(DMShapeError, lambda: A.inv()) + + A = DDM([[ZZ(2)]], (1, 1), ZZ) + raises(DMDomainError, lambda: A.inv()) + + A = DDM([], (0, 0), QQ) + assert A.inv() == A + + A = DDM([[QQ(1), QQ(2)], [QQ(2), QQ(4)]], (2, 2), QQ) + raises(DMNonInvertibleMatrixError, lambda: A.inv()) + + +def test_DDM_lu(): + A = DDM([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ) + L, U, swaps = A.lu() + assert L == DDM([[QQ(1), QQ(0)], [QQ(3), QQ(1)]], (2, 2), QQ) + assert U == DDM([[QQ(1), QQ(2)], [QQ(0), QQ(-2)]], (2, 2), QQ) + assert swaps == [] + + A = [[1, 0, 0, 0], [0, 0, 0, 0], [0, 0, 1, 1], [0, 0, 1, 2]] + Lexp = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 1, 1]] + Uexp = [[1, 0, 0, 0], [0, 0, 0, 0], [0, 0, 1, 1], [0, 0, 0, 1]] + to_dom = lambda rows, dom: [[dom(e) for e in row] for row in rows] + A = DDM(to_dom(A, QQ), (4, 4), QQ) + Lexp = DDM(to_dom(Lexp, QQ), (4, 4), QQ) + Uexp = DDM(to_dom(Uexp, QQ), (4, 4), QQ) + L, U, swaps = A.lu() + assert L == Lexp + assert U == Uexp + assert swaps == [] + + +def test_DDM_lu_solve(): + # Basic example + A = DDM([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ) + b = DDM([[QQ(1)], [QQ(2)]], (2, 1), QQ) + x = DDM([[QQ(0)], [QQ(1, 2)]], (2, 1), QQ) + assert A.lu_solve(b) == x + + # Example with swaps + A = DDM([[QQ(0), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ) + assert A.lu_solve(b) == x + + # Overdetermined, consistent + A = DDM([[QQ(1), QQ(2)], [QQ(3), QQ(4)], [QQ(5), QQ(6)]], (3, 2), QQ) + b = DDM([[QQ(1)], [QQ(2)], [QQ(3)]], (3, 1), QQ) + assert A.lu_solve(b) == x + + # Overdetermined, inconsistent + b = DDM([[QQ(1)], [QQ(2)], [QQ(4)]], (3, 1), QQ) + raises(DMNonInvertibleMatrixError, lambda: A.lu_solve(b)) + + # Square, noninvertible + A = DDM([[QQ(1), QQ(2)], [QQ(1), QQ(2)]], (2, 2), QQ) + b = DDM([[QQ(1)], [QQ(2)]], (2, 1), QQ) + raises(DMNonInvertibleMatrixError, lambda: A.lu_solve(b)) + + # Underdetermined + A = DDM([[QQ(1), QQ(2)]], (1, 2), QQ) + b = DDM([[QQ(3)]], (1, 1), QQ) + raises(NotImplementedError, lambda: A.lu_solve(b)) + + # Domain mismatch + bz = DDM([[ZZ(1)], [ZZ(2)]], (2, 1), ZZ) + raises(DMDomainError, lambda: A.lu_solve(bz)) + + # Shape mismatch + b3 = DDM([[QQ(1)], [QQ(2)], [QQ(3)]], (3, 1), QQ) + raises(DMShapeError, lambda: A.lu_solve(b3)) + + +def test_DDM_charpoly(): + A = DDM([], (0, 0), ZZ) + assert A.charpoly() == [ZZ(1)] + + A = DDM([ + [ZZ(1), ZZ(2), ZZ(3)], + [ZZ(4), ZZ(5), ZZ(6)], + [ZZ(7), ZZ(8), ZZ(9)]], (3, 3), ZZ) + Avec = [ZZ(1), ZZ(-15), ZZ(-18), ZZ(0)] + assert A.charpoly() == Avec + + A = DDM([[ZZ(1), ZZ(2)]], (1, 2), ZZ) + raises(DMShapeError, lambda: A.charpoly()) + + +def test_DDM_getitem(): + dm = DDM([ + [ZZ(1), ZZ(2), ZZ(3)], + [ZZ(4), ZZ(5), ZZ(6)], + [ZZ(7), ZZ(8), ZZ(9)]], (3, 3), ZZ) + + assert dm.getitem(1, 1) == ZZ(5) + assert dm.getitem(1, -2) == ZZ(5) + assert dm.getitem(-1, -3) == ZZ(7) + + raises(IndexError, lambda: dm.getitem(3, 3)) + + +def test_DDM_setitem(): + dm = DDM.zeros((3, 3), ZZ) + dm.setitem(0, 0, 1) + dm.setitem(1, -2, 1) + dm.setitem(-1, -1, 1) + assert dm == DDM.eye(3, ZZ) + + raises(IndexError, lambda: dm.setitem(3, 3, 0)) + + +def test_DDM_extract_slice(): + dm = DDM([ + [ZZ(1), ZZ(2), ZZ(3)], + [ZZ(4), ZZ(5), ZZ(6)], + [ZZ(7), ZZ(8), ZZ(9)]], (3, 3), ZZ) + + assert dm.extract_slice(slice(0, 3), slice(0, 3)) == dm + assert dm.extract_slice(slice(1, 3), slice(-2)) == DDM([[4], [7]], (2, 1), ZZ) + assert dm.extract_slice(slice(1, 3), slice(-2)) == DDM([[4], [7]], (2, 1), ZZ) + assert dm.extract_slice(slice(2, 3), slice(-2)) == DDM([[ZZ(7)]], (1, 1), ZZ) + assert dm.extract_slice(slice(0, 2), slice(-2)) == DDM([[1], [4]], (2, 1), ZZ) + assert dm.extract_slice(slice(-1), slice(-1)) == DDM([[1, 2], [4, 5]], (2, 2), ZZ) + + assert dm.extract_slice(slice(2), slice(3, 4)) == DDM([[], []], (2, 0), ZZ) + assert dm.extract_slice(slice(3, 4), slice(2)) == DDM([], (0, 2), ZZ) + assert dm.extract_slice(slice(3, 4), slice(3, 4)) == DDM([], (0, 0), ZZ) + + +def test_DDM_extract(): + dm1 = DDM([ + [ZZ(1), ZZ(2), ZZ(3)], + [ZZ(4), ZZ(5), ZZ(6)], + [ZZ(7), ZZ(8), ZZ(9)]], (3, 3), ZZ) + dm2 = DDM([ + [ZZ(6), ZZ(4)], + [ZZ(3), ZZ(1)]], (2, 2), ZZ) + assert dm1.extract([1, 0], [2, 0]) == dm2 + assert dm1.extract([-2, 0], [-1, 0]) == dm2 + + assert dm1.extract([], []) == DDM.zeros((0, 0), ZZ) + assert dm1.extract([1], []) == DDM.zeros((1, 0), ZZ) + assert dm1.extract([], [1]) == DDM.zeros((0, 1), ZZ) + + raises(IndexError, lambda: dm2.extract([2], [0])) + raises(IndexError, lambda: dm2.extract([0], [2])) + raises(IndexError, lambda: dm2.extract([-3], [0])) + raises(IndexError, lambda: dm2.extract([0], [-3])) + + +def test_DDM_flat(): + dm = DDM([ + [ZZ(6), ZZ(4)], + [ZZ(3), ZZ(1)]], (2, 2), ZZ) + assert dm.flat() == [ZZ(6), ZZ(4), ZZ(3), ZZ(1)] + + +def test_DDM_is_zero_matrix(): + A = DDM([[QQ(1), QQ(0)], [QQ(0), QQ(0)]], (2, 2), QQ) + Azero = DDM.zeros((1, 2), QQ) + assert A.is_zero_matrix() is False + assert Azero.is_zero_matrix() is True + + +def test_DDM_is_upper(): + # Wide matrices: + A = DDM([ + [QQ(1), QQ(2), QQ(3), QQ(4)], + [QQ(0), QQ(5), QQ(6), QQ(7)], + [QQ(0), QQ(0), QQ(8), QQ(9)] + ], (3, 4), QQ) + B = DDM([ + [QQ(1), QQ(2), QQ(3), QQ(4)], + [QQ(0), QQ(5), QQ(6), QQ(7)], + [QQ(0), QQ(7), QQ(8), QQ(9)] + ], (3, 4), QQ) + assert A.is_upper() is True + assert B.is_upper() is False + + # Tall matrices: + A = DDM([ + [QQ(1), QQ(2), QQ(3)], + [QQ(0), QQ(5), QQ(6)], + [QQ(0), QQ(0), QQ(8)], + [QQ(0), QQ(0), QQ(0)] + ], (4, 3), QQ) + B = DDM([ + [QQ(1), QQ(2), QQ(3)], + [QQ(0), QQ(5), QQ(6)], + [QQ(0), QQ(0), QQ(8)], + [QQ(0), QQ(0), QQ(10)] + ], (4, 3), QQ) + assert A.is_upper() is True + assert B.is_upper() is False + + +def test_DDM_is_lower(): + # Tall matrices: + A = DDM([ + [QQ(1), QQ(2), QQ(3), QQ(4)], + [QQ(0), QQ(5), QQ(6), QQ(7)], + [QQ(0), QQ(0), QQ(8), QQ(9)] + ], (3, 4), QQ).transpose() + B = DDM([ + [QQ(1), QQ(2), QQ(3), QQ(4)], + [QQ(0), QQ(5), QQ(6), QQ(7)], + [QQ(0), QQ(7), QQ(8), QQ(9)] + ], (3, 4), QQ).transpose() + assert A.is_lower() is True + assert B.is_lower() is False + + # Wide matrices: + A = DDM([ + [QQ(1), QQ(2), QQ(3)], + [QQ(0), QQ(5), QQ(6)], + [QQ(0), QQ(0), QQ(8)], + [QQ(0), QQ(0), QQ(0)] + ], (4, 3), QQ).transpose() + B = DDM([ + [QQ(1), QQ(2), QQ(3)], + [QQ(0), QQ(5), QQ(6)], + [QQ(0), QQ(0), QQ(8)], + [QQ(0), QQ(0), QQ(10)] + ], (4, 3), QQ).transpose() + assert A.is_lower() is True + assert B.is_lower() is False diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_dense.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_dense.py new file mode 100644 index 0000000000000000000000000000000000000000..75315ebf6b2ae7d53b4a5737578d3ac5ed4ea36a --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_dense.py @@ -0,0 +1,350 @@ +from sympy.testing.pytest import raises + +from sympy.polys import ZZ, QQ + +from sympy.polys.matrices.ddm import DDM +from sympy.polys.matrices.dense import ( + ddm_transpose, + ddm_iadd, ddm_isub, ddm_ineg, ddm_imatmul, ddm_imul, ddm_irref, + ddm_idet, ddm_iinv, ddm_ilu, ddm_ilu_split, ddm_ilu_solve, ddm_berk) + +from sympy.polys.matrices.exceptions import ( + DMDomainError, + DMNonInvertibleMatrixError, + DMNonSquareMatrixError, + DMShapeError, +) + + +def test_ddm_transpose(): + a = [[1, 2], [3, 4]] + assert ddm_transpose(a) == [[1, 3], [2, 4]] + + +def test_ddm_iadd(): + a = [[1, 2], [3, 4]] + b = [[5, 6], [7, 8]] + ddm_iadd(a, b) + assert a == [[6, 8], [10, 12]] + + +def test_ddm_isub(): + a = [[1, 2], [3, 4]] + b = [[5, 6], [7, 8]] + ddm_isub(a, b) + assert a == [[-4, -4], [-4, -4]] + + +def test_ddm_ineg(): + a = [[1, 2], [3, 4]] + ddm_ineg(a) + assert a == [[-1, -2], [-3, -4]] + + +def test_ddm_matmul(): + a = [[1, 2], [3, 4]] + ddm_imul(a, 2) + assert a == [[2, 4], [6, 8]] + + a = [[1, 2], [3, 4]] + ddm_imul(a, 0) + assert a == [[0, 0], [0, 0]] + + +def test_ddm_imatmul(): + a = [[1, 2, 3], [4, 5, 6]] + b = [[1, 2], [3, 4], [5, 6]] + + c1 = [[0, 0], [0, 0]] + ddm_imatmul(c1, a, b) + assert c1 == [[22, 28], [49, 64]] + + c2 = [[0, 0, 0], [0, 0, 0], [0, 0, 0]] + ddm_imatmul(c2, b, a) + assert c2 == [[9, 12, 15], [19, 26, 33], [29, 40, 51]] + + b3 = [[1], [2], [3]] + c3 = [[0], [0]] + ddm_imatmul(c3, a, b3) + assert c3 == [[14], [32]] + + +def test_ddm_irref(): + # Empty matrix + A = [] + Ar = [] + pivots = [] + assert ddm_irref(A) == pivots + assert A == Ar + + # Standard square case + A = [[QQ(0), QQ(1)], [QQ(1), QQ(1)]] + Ar = [[QQ(1), QQ(0)], [QQ(0), QQ(1)]] + pivots = [0, 1] + assert ddm_irref(A) == pivots + assert A == Ar + + # m < n case + A = [[QQ(1), QQ(2), QQ(1)], [QQ(3), QQ(4), QQ(1)]] + Ar = [[QQ(1), QQ(0), QQ(-1)], [QQ(0), QQ(1), QQ(1)]] + pivots = [0, 1] + assert ddm_irref(A) == pivots + assert A == Ar + + # same m < n but reversed + A = [[QQ(3), QQ(4), QQ(1)], [QQ(1), QQ(2), QQ(1)]] + Ar = [[QQ(1), QQ(0), QQ(-1)], [QQ(0), QQ(1), QQ(1)]] + pivots = [0, 1] + assert ddm_irref(A) == pivots + assert A == Ar + + # m > n case + A = [[QQ(1), QQ(0)], [QQ(1), QQ(3)], [QQ(0), QQ(1)]] + Ar = [[QQ(1), QQ(0)], [QQ(0), QQ(1)], [QQ(0), QQ(0)]] + pivots = [0, 1] + assert ddm_irref(A) == pivots + assert A == Ar + + # Example with missing pivot + A = [[QQ(1), QQ(0), QQ(1)], [QQ(3), QQ(0), QQ(1)]] + Ar = [[QQ(1), QQ(0), QQ(0)], [QQ(0), QQ(0), QQ(1)]] + pivots = [0, 2] + assert ddm_irref(A) == pivots + assert A == Ar + + # Example with missing pivot and no replacement + A = [[QQ(0), QQ(1)], [QQ(0), QQ(2)], [QQ(1), QQ(0)]] + Ar = [[QQ(1), QQ(0)], [QQ(0), QQ(1)], [QQ(0), QQ(0)]] + pivots = [0, 1] + assert ddm_irref(A) == pivots + assert A == Ar + + +def test_ddm_idet(): + A = [] + assert ddm_idet(A, ZZ) == ZZ(1) + + A = [[ZZ(2)]] + assert ddm_idet(A, ZZ) == ZZ(2) + + A = [[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]] + assert ddm_idet(A, ZZ) == ZZ(-2) + + A = [[ZZ(1), ZZ(2), ZZ(3)], [ZZ(1), ZZ(2), ZZ(4)], [ZZ(1), ZZ(3), ZZ(5)]] + assert ddm_idet(A, ZZ) == ZZ(-1) + + A = [[ZZ(1), ZZ(2), ZZ(3)], [ZZ(1), ZZ(2), ZZ(4)], [ZZ(1), ZZ(2), ZZ(5)]] + assert ddm_idet(A, ZZ) == ZZ(0) + + A = [[QQ(1, 2), QQ(1, 2)], [QQ(1, 3), QQ(1, 4)]] + assert ddm_idet(A, QQ) == QQ(-1, 24) + + +def test_ddm_inv(): + A = [] + Ainv = [] + ddm_iinv(Ainv, A, QQ) + assert Ainv == A + + A = [] + Ainv = [] + raises(DMDomainError, lambda: ddm_iinv(Ainv, A, ZZ)) + + A = [[QQ(1), QQ(2)]] + Ainv = [[QQ(0), QQ(0)]] + raises(DMNonSquareMatrixError, lambda: ddm_iinv(Ainv, A, QQ)) + + A = [[QQ(1, 1), QQ(2, 1)], [QQ(3, 1), QQ(4, 1)]] + Ainv = [[QQ(0), QQ(0)], [QQ(0), QQ(0)]] + Ainv_expected = [[QQ(-2, 1), QQ(1, 1)], [QQ(3, 2), QQ(-1, 2)]] + ddm_iinv(Ainv, A, QQ) + assert Ainv == Ainv_expected + + A = [[QQ(1, 1), QQ(2, 1)], [QQ(2, 1), QQ(4, 1)]] + Ainv = [[QQ(0), QQ(0)], [QQ(0), QQ(0)]] + raises(DMNonInvertibleMatrixError, lambda: ddm_iinv(Ainv, A, QQ)) + + +def test_ddm_ilu(): + A = [] + Alu = [] + swaps = ddm_ilu(A) + assert A == Alu + assert swaps == [] + + A = [[]] + Alu = [[]] + swaps = ddm_ilu(A) + assert A == Alu + assert swaps == [] + + A = [[QQ(1), QQ(2)], [QQ(3), QQ(4)]] + Alu = [[QQ(1), QQ(2)], [QQ(3), QQ(-2)]] + swaps = ddm_ilu(A) + assert A == Alu + assert swaps == [] + + A = [[QQ(0), QQ(2)], [QQ(3), QQ(4)]] + Alu = [[QQ(3), QQ(4)], [QQ(0), QQ(2)]] + swaps = ddm_ilu(A) + assert A == Alu + assert swaps == [(0, 1)] + + A = [[QQ(1), QQ(2), QQ(3)], [QQ(4), QQ(5), QQ(6)], [QQ(7), QQ(8), QQ(9)]] + Alu = [[QQ(1), QQ(2), QQ(3)], [QQ(4), QQ(-3), QQ(-6)], [QQ(7), QQ(2), QQ(0)]] + swaps = ddm_ilu(A) + assert A == Alu + assert swaps == [] + + A = [[QQ(0), QQ(1), QQ(2)], [QQ(0), QQ(1), QQ(3)], [QQ(1), QQ(1), QQ(2)]] + Alu = [[QQ(1), QQ(1), QQ(2)], [QQ(0), QQ(1), QQ(3)], [QQ(0), QQ(1), QQ(-1)]] + swaps = ddm_ilu(A) + assert A == Alu + assert swaps == [(0, 2)] + + A = [[QQ(1), QQ(2), QQ(3)], [QQ(4), QQ(5), QQ(6)]] + Alu = [[QQ(1), QQ(2), QQ(3)], [QQ(4), QQ(-3), QQ(-6)]] + swaps = ddm_ilu(A) + assert A == Alu + assert swaps == [] + + A = [[QQ(1), QQ(2)], [QQ(3), QQ(4)], [QQ(5), QQ(6)]] + Alu = [[QQ(1), QQ(2)], [QQ(3), QQ(-2)], [QQ(5), QQ(2)]] + swaps = ddm_ilu(A) + assert A == Alu + assert swaps == [] + + +def test_ddm_ilu_split(): + U = [] + L = [] + Uexp = [] + Lexp = [] + swaps = ddm_ilu_split(L, U, QQ) + assert U == Uexp + assert L == Lexp + assert swaps == [] + + U = [[]] + L = [[QQ(1)]] + Uexp = [[]] + Lexp = [[QQ(1)]] + swaps = ddm_ilu_split(L, U, QQ) + assert U == Uexp + assert L == Lexp + assert swaps == [] + + U = [[QQ(1), QQ(2)], [QQ(3), QQ(4)]] + L = [[QQ(1), QQ(0)], [QQ(0), QQ(1)]] + Uexp = [[QQ(1), QQ(2)], [QQ(0), QQ(-2)]] + Lexp = [[QQ(1), QQ(0)], [QQ(3), QQ(1)]] + swaps = ddm_ilu_split(L, U, QQ) + assert U == Uexp + assert L == Lexp + assert swaps == [] + + U = [[QQ(1), QQ(2), QQ(3)], [QQ(4), QQ(5), QQ(6)]] + L = [[QQ(1), QQ(0)], [QQ(0), QQ(1)]] + Uexp = [[QQ(1), QQ(2), QQ(3)], [QQ(0), QQ(-3), QQ(-6)]] + Lexp = [[QQ(1), QQ(0)], [QQ(4), QQ(1)]] + swaps = ddm_ilu_split(L, U, QQ) + assert U == Uexp + assert L == Lexp + assert swaps == [] + + U = [[QQ(1), QQ(2)], [QQ(3), QQ(4)], [QQ(5), QQ(6)]] + L = [[QQ(1), QQ(0), QQ(0)], [QQ(0), QQ(1), QQ(0)], [QQ(0), QQ(0), QQ(1)]] + Uexp = [[QQ(1), QQ(2)], [QQ(0), QQ(-2)], [QQ(0), QQ(0)]] + Lexp = [[QQ(1), QQ(0), QQ(0)], [QQ(3), QQ(1), QQ(0)], [QQ(5), QQ(2), QQ(1)]] + swaps = ddm_ilu_split(L, U, QQ) + assert U == Uexp + assert L == Lexp + assert swaps == [] + + +def test_ddm_ilu_solve(): + # Basic example + # A = [[QQ(1), QQ(2)], [QQ(3), QQ(4)]] + U = [[QQ(1), QQ(2)], [QQ(0), QQ(-2)]] + L = [[QQ(1), QQ(0)], [QQ(3), QQ(1)]] + swaps = [] + b = DDM([[QQ(1)], [QQ(2)]], (2, 1), QQ) + x = DDM([[QQ(0)], [QQ(0)]], (2, 1), QQ) + xexp = DDM([[QQ(0)], [QQ(1, 2)]], (2, 1), QQ) + ddm_ilu_solve(x, L, U, swaps, b) + assert x == xexp + + # Example with swaps + # A = [[QQ(0), QQ(2)], [QQ(3), QQ(4)]] + U = [[QQ(3), QQ(4)], [QQ(0), QQ(2)]] + L = [[QQ(1), QQ(0)], [QQ(0), QQ(1)]] + swaps = [(0, 1)] + b = DDM([[QQ(1)], [QQ(2)]], (2, 1), QQ) + x = DDM([[QQ(0)], [QQ(0)]], (2, 1), QQ) + xexp = DDM([[QQ(0)], [QQ(1, 2)]], (2, 1), QQ) + ddm_ilu_solve(x, L, U, swaps, b) + assert x == xexp + + # Overdetermined, consistent + # A = DDM([[QQ(1), QQ(2)], [QQ(3), QQ(4)], [QQ(5), QQ(6)]], (3, 2), QQ) + U = [[QQ(1), QQ(2)], [QQ(0), QQ(-2)], [QQ(0), QQ(0)]] + L = [[QQ(1), QQ(0), QQ(0)], [QQ(3), QQ(1), QQ(0)], [QQ(5), QQ(2), QQ(1)]] + swaps = [] + b = DDM([[QQ(1)], [QQ(2)], [QQ(3)]], (3, 1), QQ) + x = DDM([[QQ(0)], [QQ(0)]], (2, 1), QQ) + xexp = DDM([[QQ(0)], [QQ(1, 2)]], (2, 1), QQ) + ddm_ilu_solve(x, L, U, swaps, b) + assert x == xexp + + # Overdetermined, inconsistent + b = DDM([[QQ(1)], [QQ(2)], [QQ(4)]], (3, 1), QQ) + raises(DMNonInvertibleMatrixError, lambda: ddm_ilu_solve(x, L, U, swaps, b)) + + # Square, noninvertible + # A = DDM([[QQ(1), QQ(2)], [QQ(1), QQ(2)]], (2, 2), QQ) + U = [[QQ(1), QQ(2)], [QQ(0), QQ(0)]] + L = [[QQ(1), QQ(0)], [QQ(1), QQ(1)]] + swaps = [] + b = DDM([[QQ(1)], [QQ(2)]], (2, 1), QQ) + raises(DMNonInvertibleMatrixError, lambda: ddm_ilu_solve(x, L, U, swaps, b)) + + # Underdetermined + # A = DDM([[QQ(1), QQ(2)]], (1, 2), QQ) + U = [[QQ(1), QQ(2)]] + L = [[QQ(1)]] + swaps = [] + b = DDM([[QQ(3)]], (1, 1), QQ) + raises(NotImplementedError, lambda: ddm_ilu_solve(x, L, U, swaps, b)) + + # Shape mismatch + b3 = DDM([[QQ(1)], [QQ(2)], [QQ(3)]], (3, 1), QQ) + raises(DMShapeError, lambda: ddm_ilu_solve(x, L, U, swaps, b3)) + + # Empty shape mismatch + U = [[QQ(1)]] + L = [[QQ(1)]] + swaps = [] + x = [[QQ(1)]] + b = [] + raises(DMShapeError, lambda: ddm_ilu_solve(x, L, U, swaps, b)) + + # Empty system + U = [] + L = [] + swaps = [] + b = [] + x = [] + ddm_ilu_solve(x, L, U, swaps, b) + assert x == [] + + +def test_ddm_charpoly(): + A = [] + assert ddm_berk(A, ZZ) == [[ZZ(1)]] + + A = [[ZZ(1), ZZ(2), ZZ(3)], [ZZ(4), ZZ(5), ZZ(6)], [ZZ(7), ZZ(8), ZZ(9)]] + Avec = [[ZZ(1)], [ZZ(-15)], [ZZ(-18)], [ZZ(0)]] + assert ddm_berk(A, ZZ) == Avec + + A = DDM([[ZZ(1), ZZ(2)]], (1, 2), ZZ) + raises(DMShapeError, lambda: ddm_berk(A, ZZ)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_domainmatrix.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_domainmatrix.py new file mode 100644 index 0000000000000000000000000000000000000000..2f45029fb080ca91e98ea04aa4717fa675492052 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_domainmatrix.py @@ -0,0 +1,1383 @@ +from sympy.external.gmpy import GROUND_TYPES + +from sympy import Integer, Rational, S, sqrt, Matrix, symbols +from sympy import FF, ZZ, QQ, QQ_I, EXRAW + +from sympy.polys.matrices.domainmatrix import DomainMatrix, DomainScalar, DM +from sympy.polys.matrices.exceptions import ( + DMBadInputError, DMDomainError, DMShapeError, DMFormatError, DMNotAField, + DMNonSquareMatrixError, DMNonInvertibleMatrixError, +) +from sympy.polys.matrices.ddm import DDM +from sympy.polys.matrices.sdm import SDM + +from sympy.testing.pytest import raises + + +def test_DM(): + ddm = DDM([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + A = DM([[1, 2], [3, 4]], ZZ) + if GROUND_TYPES != 'flint': + assert A.rep == ddm + else: + assert A.rep == ddm.to_dfm() + assert A.shape == (2, 2) + assert A.domain == ZZ + + +def test_DomainMatrix_init(): + lol = [[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]] + dod = {0: {0: ZZ(1), 1:ZZ(2)}, 1: {0:ZZ(3), 1:ZZ(4)}} + ddm = DDM(lol, (2, 2), ZZ) + sdm = SDM(dod, (2, 2), ZZ) + + A = DomainMatrix(lol, (2, 2), ZZ) + if GROUND_TYPES != 'flint': + assert A.rep == ddm + else: + assert A.rep == ddm.to_dfm() + assert A.shape == (2, 2) + assert A.domain == ZZ + + A = DomainMatrix(dod, (2, 2), ZZ) + assert A.rep == sdm + assert A.shape == (2, 2) + assert A.domain == ZZ + + raises(TypeError, lambda: DomainMatrix(ddm, (2, 2), ZZ)) + raises(TypeError, lambda: DomainMatrix(sdm, (2, 2), ZZ)) + raises(TypeError, lambda: DomainMatrix(Matrix([[1]]), (1, 1), ZZ)) + + for fmt, rep in [('sparse', sdm), ('dense', ddm)]: + if fmt == 'dense' and GROUND_TYPES == 'flint': + rep = rep.to_dfm() + A = DomainMatrix(lol, (2, 2), ZZ, fmt=fmt) + assert A.rep == rep + A = DomainMatrix(dod, (2, 2), ZZ, fmt=fmt) + assert A.rep == rep + + raises(ValueError, lambda: DomainMatrix(lol, (2, 2), ZZ, fmt='invalid')) + + raises(DMBadInputError, lambda: DomainMatrix([[ZZ(1), ZZ(2)]], (2, 2), ZZ)) + + # uses copy + was = [i.copy() for i in lol] + A[0,0] = ZZ(42) + assert was == lol + + +def test_DomainMatrix_from_rep(): + ddm = DDM([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + A = DomainMatrix.from_rep(ddm) + # XXX: Should from_rep convert to DFM? + assert A.rep == ddm + assert A.shape == (2, 2) + assert A.domain == ZZ + + sdm = SDM({0: {0: ZZ(1), 1:ZZ(2)}, 1: {0:ZZ(3), 1:ZZ(4)}}, (2, 2), ZZ) + A = DomainMatrix.from_rep(sdm) + assert A.rep == sdm + assert A.shape == (2, 2) + assert A.domain == ZZ + + A = DomainMatrix([[ZZ(1)]], (1, 1), ZZ) + raises(TypeError, lambda: DomainMatrix.from_rep(A)) + + +def test_DomainMatrix_from_list(): + ddm = DDM([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + A = DomainMatrix.from_list([[1, 2], [3, 4]], ZZ) + if GROUND_TYPES != 'flint': + assert A.rep == ddm + else: + assert A.rep == ddm.to_dfm() + assert A.shape == (2, 2) + assert A.domain == ZZ + + dom = FF(7) + ddm = DDM([[dom(1), dom(2)], [dom(3), dom(4)]], (2, 2), dom) + A = DomainMatrix.from_list([[1, 2], [3, 4]], dom) + if GROUND_TYPES != 'flint': + assert A.rep == ddm + else: + assert A.rep == ddm.to_dfm() + assert A.shape == (2, 2) + assert A.domain == dom + + dom = FF(2**127-1) + ddm = DDM([[dom(1), dom(2)], [dom(3), dom(4)]], (2, 2), dom) + A = DomainMatrix.from_list([[1, 2], [3, 4]], dom) + if GROUND_TYPES != 'flint': + assert A.rep == ddm + else: + assert A.rep == ddm.to_dfm() + assert A.shape == (2, 2) + assert A.domain == dom + + ddm = DDM([[QQ(1, 2), QQ(3, 1)], [QQ(1, 4), QQ(5, 1)]], (2, 2), QQ) + A = DomainMatrix.from_list([[(1, 2), (3, 1)], [(1, 4), (5, 1)]], QQ) + if GROUND_TYPES != 'flint': + assert A.rep == ddm + else: + assert A.rep == ddm.to_dfm() + assert A.shape == (2, 2) + assert A.domain == QQ + + +def test_DomainMatrix_from_list_sympy(): + ddm = DDM([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + A = DomainMatrix.from_list_sympy(2, 2, [[1, 2], [3, 4]]) + if GROUND_TYPES != 'flint': + assert A.rep == ddm + else: + assert A.rep == ddm.to_dfm() + assert A.shape == (2, 2) + assert A.domain == ZZ + + K = QQ.algebraic_field(sqrt(2)) + ddm = DDM( + [[K.convert(1 + sqrt(2)), K.convert(2 + sqrt(2))], + [K.convert(3 + sqrt(2)), K.convert(4 + sqrt(2))]], + (2, 2), + K + ) + A = DomainMatrix.from_list_sympy( + 2, 2, [[1 + sqrt(2), 2 + sqrt(2)], [3 + sqrt(2), 4 + sqrt(2)]], + extension=True) + assert A.rep == ddm + assert A.shape == (2, 2) + assert A.domain == K + + +def test_DomainMatrix_from_dict_sympy(): + sdm = SDM({0: {0: QQ(1, 2)}, 1: {1: QQ(2, 3)}}, (2, 2), QQ) + sympy_dict = {0: {0: Rational(1, 2)}, 1: {1: Rational(2, 3)}} + A = DomainMatrix.from_dict_sympy(2, 2, sympy_dict) + assert A.rep == sdm + assert A.shape == (2, 2) + assert A.domain == QQ + + fds = DomainMatrix.from_dict_sympy + raises(DMBadInputError, lambda: fds(2, 2, {3: {0: Rational(1, 2)}})) + raises(DMBadInputError, lambda: fds(2, 2, {0: {3: Rational(1, 2)}})) + + +def test_DomainMatrix_from_Matrix(): + sdm = SDM({0: {0: ZZ(1), 1: ZZ(2)}, 1: {0: ZZ(3), 1: ZZ(4)}}, (2, 2), ZZ) + A = DomainMatrix.from_Matrix(Matrix([[1, 2], [3, 4]])) + assert A.rep == sdm + assert A.shape == (2, 2) + assert A.domain == ZZ + + K = QQ.algebraic_field(sqrt(2)) + sdm = SDM( + {0: {0: K.convert(1 + sqrt(2)), 1: K.convert(2 + sqrt(2))}, + 1: {0: K.convert(3 + sqrt(2)), 1: K.convert(4 + sqrt(2))}}, + (2, 2), + K + ) + A = DomainMatrix.from_Matrix( + Matrix([[1 + sqrt(2), 2 + sqrt(2)], [3 + sqrt(2), 4 + sqrt(2)]]), + extension=True) + assert A.rep == sdm + assert A.shape == (2, 2) + assert A.domain == K + + A = DomainMatrix.from_Matrix(Matrix([[QQ(1, 2), QQ(3, 4)], [QQ(0, 1), QQ(0, 1)]]), fmt='dense') + ddm = DDM([[QQ(1, 2), QQ(3, 4)], [QQ(0, 1), QQ(0, 1)]], (2, 2), QQ) + + if GROUND_TYPES != 'flint': + assert A.rep == ddm + else: + assert A.rep == ddm.to_dfm() + assert A.shape == (2, 2) + assert A.domain == QQ + + +def test_DomainMatrix_eq(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + assert A == A + B = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(1)]], (2, 2), ZZ) + assert A != B + C = [[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]] + assert A != C + + +def test_DomainMatrix_unify_eq(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + B1 = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ) + B2 = DomainMatrix([[QQ(1), QQ(3)], [QQ(3), QQ(4)]], (2, 2), QQ) + B3 = DomainMatrix([[ZZ(1)]], (1, 1), ZZ) + assert A.unify_eq(B1) is True + assert A.unify_eq(B2) is False + assert A.unify_eq(B3) is False + + +def test_DomainMatrix_get_domain(): + K, items = DomainMatrix.get_domain([1, 2, 3, 4]) + assert items == [ZZ(1), ZZ(2), ZZ(3), ZZ(4)] + assert K == ZZ + + K, items = DomainMatrix.get_domain([1, 2, 3, Rational(1, 2)]) + assert items == [QQ(1), QQ(2), QQ(3), QQ(1, 2)] + assert K == QQ + + +def test_DomainMatrix_convert_to(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + Aq = A.convert_to(QQ) + assert Aq == DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ) + + +def test_DomainMatrix_choose_domain(): + A = [[1, 2], [3, 0]] + assert DM(A, QQ).choose_domain() == DM(A, ZZ) + assert DM(A, QQ).choose_domain(field=True) == DM(A, QQ) + assert DM(A, ZZ).choose_domain(field=True) == DM(A, QQ) + + x = symbols('x') + B = [[1, x], [x**2, x**3]] + assert DM(B, QQ[x]).choose_domain(field=True) == DM(B, ZZ.frac_field(x)) + + +def test_DomainMatrix_to_flat_nz(): + Adm = DM([[1, 2], [3, 0]], ZZ) + Addm = Adm.rep.to_ddm() + Asdm = Adm.rep.to_sdm() + for A in [Adm, Addm, Asdm]: + elems, data = A.to_flat_nz() + assert A.from_flat_nz(elems, data, A.domain) == A + elemsq = [QQ(e) for e in elems] + assert A.from_flat_nz(elemsq, data, QQ) == A.convert_to(QQ) + elems2 = [2*e for e in elems] + assert A.from_flat_nz(elems2, data, A.domain) == 2*A + + +def test_DomainMatrix_to_sympy(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + assert A.to_sympy() == A.convert_to(EXRAW) + + +def test_DomainMatrix_to_field(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + Aq = A.to_field() + assert Aq == DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ) + + +def test_DomainMatrix_to_sparse(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + A_sparse = A.to_sparse() + assert A_sparse.rep == {0: {0: 1, 1: 2}, 1: {0: 3, 1: 4}} + + +def test_DomainMatrix_to_dense(): + A = DomainMatrix({0: {0: 1, 1: 2}, 1: {0: 3, 1: 4}}, (2, 2), ZZ) + A_dense = A.to_dense() + ddm = DDM([[1, 2], [3, 4]], (2, 2), ZZ) + if GROUND_TYPES != 'flint': + assert A_dense.rep == ddm + else: + assert A_dense.rep == ddm.to_dfm() + + +def test_DomainMatrix_unify(): + Az = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + Aq = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ) + assert Az.unify(Az) == (Az, Az) + assert Az.unify(Aq) == (Aq, Aq) + assert Aq.unify(Az) == (Aq, Aq) + assert Aq.unify(Aq) == (Aq, Aq) + + As = DomainMatrix({0: {1: ZZ(1)}, 1:{0:ZZ(2)}}, (2, 2), ZZ) + Ad = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + + assert As.unify(As) == (As, As) + assert Ad.unify(Ad) == (Ad, Ad) + + Bs, Bd = As.unify(Ad, fmt='dense') + assert Bs.rep == DDM([[0, 1], [2, 0]], (2, 2), ZZ).to_dfm_or_ddm() + assert Bd.rep == DDM([[1, 2],[3, 4]], (2, 2), ZZ).to_dfm_or_ddm() + + Bs, Bd = As.unify(Ad, fmt='sparse') + assert Bs.rep == SDM({0: {1: 1}, 1: {0: 2}}, (2, 2), ZZ) + assert Bd.rep == SDM({0: {0: 1, 1: 2}, 1: {0: 3, 1: 4}}, (2, 2), ZZ) + + raises(ValueError, lambda: As.unify(Ad, fmt='invalid')) + + +def test_DomainMatrix_to_Matrix(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + A_Matrix = Matrix([[1, 2], [3, 4]]) + assert A.to_Matrix() == A_Matrix + assert A.to_sparse().to_Matrix() == A_Matrix + assert A.convert_to(QQ).to_Matrix() == A_Matrix + assert A.convert_to(QQ.algebraic_field(sqrt(2))).to_Matrix() == A_Matrix + + +def test_DomainMatrix_to_list(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + assert A.to_list() == [[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]] + + +def test_DomainMatrix_to_list_flat(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + assert A.to_list_flat() == [ZZ(1), ZZ(2), ZZ(3), ZZ(4)] + + +def test_DomainMatrix_flat(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + assert A.flat() == [ZZ(1), ZZ(2), ZZ(3), ZZ(4)] + + +def test_DomainMatrix_from_list_flat(): + nums = [ZZ(1), ZZ(2), ZZ(3), ZZ(4)] + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + + assert DomainMatrix.from_list_flat(nums, (2, 2), ZZ) == A + assert DDM.from_list_flat(nums, (2, 2), ZZ) == A.rep.to_ddm() + assert SDM.from_list_flat(nums, (2, 2), ZZ) == A.rep.to_sdm() + + assert A == A.from_list_flat(A.to_list_flat(), A.shape, A.domain) + + raises(DMBadInputError, DomainMatrix.from_list_flat, nums, (2, 3), ZZ) + raises(DMBadInputError, DDM.from_list_flat, nums, (2, 3), ZZ) + raises(DMBadInputError, SDM.from_list_flat, nums, (2, 3), ZZ) + + +def test_DomainMatrix_to_dod(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + assert A.to_dod() == {0: {0: ZZ(1), 1:ZZ(2)}, 1: {0:ZZ(3), 1:ZZ(4)}} + A = DomainMatrix([[ZZ(1), ZZ(0)], [ZZ(0), ZZ(4)]], (2, 2), ZZ) + assert A.to_dod() == {0: {0: ZZ(1)}, 1: {1: ZZ(4)}} + + +def test_DomainMatrix_from_dod(): + items = {0: {0: ZZ(1), 1:ZZ(2)}, 1: {0:ZZ(3), 1:ZZ(4)}} + A = DM([[1, 2], [3, 4]], ZZ) + assert DomainMatrix.from_dod(items, (2, 2), ZZ) == A.to_sparse() + assert A.from_dod_like(items) == A + assert A.from_dod_like(items, QQ) == A.convert_to(QQ) + + +def test_DomainMatrix_to_dok(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + assert A.to_dok() == {(0, 0):ZZ(1), (0, 1):ZZ(2), (1, 0):ZZ(3), (1, 1):ZZ(4)} + A = DomainMatrix([[ZZ(1), ZZ(0)], [ZZ(0), ZZ(4)]], (2, 2), ZZ) + dok = {(0, 0):ZZ(1), (1, 1):ZZ(4)} + assert A.to_dok() == dok + assert A.to_dense().to_dok() == dok + assert A.to_sparse().to_dok() == dok + assert A.rep.to_ddm().to_dok() == dok + assert A.rep.to_sdm().to_dok() == dok + + +def test_DomainMatrix_from_dok(): + items = {(0, 0): ZZ(1), (1, 1): ZZ(2)} + A = DM([[1, 0], [0, 2]], ZZ) + assert DomainMatrix.from_dok(items, (2, 2), ZZ) == A.to_sparse() + assert DDM.from_dok(items, (2, 2), ZZ) == A.rep.to_ddm() + assert SDM.from_dok(items, (2, 2), ZZ) == A.rep.to_sdm() + + +def test_DomainMatrix_repr(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + assert repr(A) == 'DomainMatrix([[1, 2], [3, 4]], (2, 2), ZZ)' + + +def test_DomainMatrix_transpose(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + AT = DomainMatrix([[ZZ(1), ZZ(3)], [ZZ(2), ZZ(4)]], (2, 2), ZZ) + assert A.transpose() == AT + + +def test_DomainMatrix_is_zero_matrix(): + A = DomainMatrix([[ZZ(1)]], (1, 1), ZZ) + B = DomainMatrix([[ZZ(0)]], (1, 1), ZZ) + assert A.is_zero_matrix is False + assert B.is_zero_matrix is True + + +def test_DomainMatrix_is_upper(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(0), ZZ(4)]], (2, 2), ZZ) + B = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + assert A.is_upper is True + assert B.is_upper is False + + +def test_DomainMatrix_is_lower(): + A = DomainMatrix([[ZZ(1), ZZ(0)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + B = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + assert A.is_lower is True + assert B.is_lower is False + + +def test_DomainMatrix_is_diagonal(): + A = DM([[1, 0], [0, 4]], ZZ) + B = DM([[1, 2], [3, 4]], ZZ) + assert A.is_diagonal is A.to_sparse().is_diagonal is True + assert B.is_diagonal is B.to_sparse().is_diagonal is False + + +def test_DomainMatrix_is_square(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + B = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)], [ZZ(5), ZZ(6)]], (3, 2), ZZ) + assert A.is_square is True + assert B.is_square is False + + +def test_DomainMatrix_diagonal(): + A = DM([[1, 2], [3, 4]], ZZ) + assert A.diagonal() == A.to_sparse().diagonal() == [ZZ(1), ZZ(4)] + A = DM([[1, 2], [3, 4], [5, 6]], ZZ) + assert A.diagonal() == A.to_sparse().diagonal() == [ZZ(1), ZZ(4)] + A = DM([[1, 2, 3], [4, 5, 6]], ZZ) + assert A.diagonal() == A.to_sparse().diagonal() == [ZZ(1), ZZ(5)] + + +def test_DomainMatrix_rank(): + A = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)], [QQ(6), QQ(8)]], (3, 2), QQ) + assert A.rank() == 2 + + +def test_DomainMatrix_add(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + B = DomainMatrix([[ZZ(2), ZZ(4)], [ZZ(6), ZZ(8)]], (2, 2), ZZ) + assert A + A == A.add(A) == B + + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + L = [[2, 3], [3, 4]] + raises(TypeError, lambda: A + L) + raises(TypeError, lambda: L + A) + + A1 = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + A2 = DomainMatrix([[ZZ(1), ZZ(2)]], (1, 2), ZZ) + raises(DMShapeError, lambda: A1 + A2) + raises(DMShapeError, lambda: A2 + A1) + raises(DMShapeError, lambda: A1.add(A2)) + raises(DMShapeError, lambda: A2.add(A1)) + + Az = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + Aq = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ) + Asum = DomainMatrix([[QQ(2), QQ(4)], [QQ(6), QQ(8)]], (2, 2), QQ) + assert Az + Aq == Asum + assert Aq + Az == Asum + raises(DMDomainError, lambda: Az.add(Aq)) + raises(DMDomainError, lambda: Aq.add(Az)) + + As = DomainMatrix({0: {1: ZZ(1)}, 1: {0: ZZ(2)}}, (2, 2), ZZ) + Ad = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + + Asd = As + Ad + Ads = Ad + As + assert Asd == DomainMatrix([[1, 3], [5, 4]], (2, 2), ZZ) + assert Asd.rep == DDM([[1, 3], [5, 4]], (2, 2), ZZ).to_dfm_or_ddm() + assert Ads == DomainMatrix([[1, 3], [5, 4]], (2, 2), ZZ) + assert Ads.rep == DDM([[1, 3], [5, 4]], (2, 2), ZZ).to_dfm_or_ddm() + raises(DMFormatError, lambda: As.add(Ad)) + + +def test_DomainMatrix_sub(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + B = DomainMatrix([[ZZ(0), ZZ(0)], [ZZ(0), ZZ(0)]], (2, 2), ZZ) + assert A - A == A.sub(A) == B + + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + L = [[2, 3], [3, 4]] + raises(TypeError, lambda: A - L) + raises(TypeError, lambda: L - A) + + A1 = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + A2 = DomainMatrix([[ZZ(1), ZZ(2)]], (1, 2), ZZ) + raises(DMShapeError, lambda: A1 - A2) + raises(DMShapeError, lambda: A2 - A1) + raises(DMShapeError, lambda: A1.sub(A2)) + raises(DMShapeError, lambda: A2.sub(A1)) + + Az = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + Aq = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ) + Adiff = DomainMatrix([[QQ(0), QQ(0)], [QQ(0), QQ(0)]], (2, 2), QQ) + assert Az - Aq == Adiff + assert Aq - Az == Adiff + raises(DMDomainError, lambda: Az.sub(Aq)) + raises(DMDomainError, lambda: Aq.sub(Az)) + + As = DomainMatrix({0: {1: ZZ(1)}, 1: {0: ZZ(2)}}, (2, 2), ZZ) + Ad = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + + Asd = As - Ad + Ads = Ad - As + assert Asd == DomainMatrix([[-1, -1], [-1, -4]], (2, 2), ZZ) + assert Asd.rep == DDM([[-1, -1], [-1, -4]], (2, 2), ZZ).to_dfm_or_ddm() + assert Asd == -Ads + assert Asd.rep == -Ads.rep + + +def test_DomainMatrix_neg(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + Aneg = DomainMatrix([[ZZ(-1), ZZ(-2)], [ZZ(-3), ZZ(-4)]], (2, 2), ZZ) + assert -A == A.neg() == Aneg + + +def test_DomainMatrix_mul(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + A2 = DomainMatrix([[ZZ(7), ZZ(10)], [ZZ(15), ZZ(22)]], (2, 2), ZZ) + assert A*A == A.matmul(A) == A2 + + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + L = [[1, 2], [3, 4]] + raises(TypeError, lambda: A * L) + raises(TypeError, lambda: L * A) + + Az = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + Aq = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ) + Aprod = DomainMatrix([[QQ(7), QQ(10)], [QQ(15), QQ(22)]], (2, 2), QQ) + assert Az * Aq == Aprod + assert Aq * Az == Aprod + raises(DMDomainError, lambda: Az.matmul(Aq)) + raises(DMDomainError, lambda: Aq.matmul(Az)) + + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + AA = DomainMatrix([[ZZ(2), ZZ(4)], [ZZ(6), ZZ(8)]], (2, 2), ZZ) + x = ZZ(2) + assert A * x == x * A == A.mul(x) == AA + + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + AA = DomainMatrix.zeros((2, 2), ZZ) + x = ZZ(0) + assert A * x == x * A == A.mul(x).to_sparse() == AA + + As = DomainMatrix({0: {1: ZZ(1)}, 1: {0: ZZ(2)}}, (2, 2), ZZ) + Ad = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + + Asd = As * Ad + Ads = Ad * As + assert Asd == DomainMatrix([[3, 4], [2, 4]], (2, 2), ZZ) + assert Asd.rep == DDM([[3, 4], [2, 4]], (2, 2), ZZ).to_dfm_or_ddm() + assert Ads == DomainMatrix([[4, 1], [8, 3]], (2, 2), ZZ) + assert Ads.rep == DDM([[4, 1], [8, 3]], (2, 2), ZZ).to_dfm_or_ddm() + + +def test_DomainMatrix_mul_elementwise(): + A = DomainMatrix([[ZZ(2), ZZ(2)], [ZZ(0), ZZ(0)]], (2, 2), ZZ) + B = DomainMatrix([[ZZ(4), ZZ(0)], [ZZ(3), ZZ(0)]], (2, 2), ZZ) + C = DomainMatrix([[ZZ(8), ZZ(0)], [ZZ(0), ZZ(0)]], (2, 2), ZZ) + assert A.mul_elementwise(B) == C + assert B.mul_elementwise(A) == C + + +def test_DomainMatrix_pow(): + eye = DomainMatrix.eye(2, ZZ) + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + A2 = DomainMatrix([[ZZ(7), ZZ(10)], [ZZ(15), ZZ(22)]], (2, 2), ZZ) + A3 = DomainMatrix([[ZZ(37), ZZ(54)], [ZZ(81), ZZ(118)]], (2, 2), ZZ) + assert A**0 == A.pow(0) == eye + assert A**1 == A.pow(1) == A + assert A**2 == A.pow(2) == A2 + assert A**3 == A.pow(3) == A3 + + raises(TypeError, lambda: A ** Rational(1, 2)) + raises(NotImplementedError, lambda: A ** -1) + raises(NotImplementedError, lambda: A.pow(-1)) + + A = DomainMatrix.zeros((2, 1), ZZ) + raises(DMNonSquareMatrixError, lambda: A ** 1) + + +def test_DomainMatrix_clear_denoms(): + A = DM([[(1,2),(1,3)],[(1,4),(1,5)]], QQ) + + den_Z = DomainScalar(ZZ(60), ZZ) + Anum_Z = DM([[30, 20], [15, 12]], ZZ) + Anum_Q = Anum_Z.convert_to(QQ) + + assert A.clear_denoms() == (den_Z, Anum_Q) + assert A.clear_denoms(convert=True) == (den_Z, Anum_Z) + assert A * den_Z == Anum_Q + assert A == Anum_Q / den_Z + + +def test_DomainMatrix_clear_denoms_rowwise(): + A = DM([[(1,2),(1,3)],[(1,4),(1,5)]], QQ) + + den_Z = DM([[6, 0], [0, 20]], ZZ).to_sparse() + Anum_Z = DM([[3, 2], [5, 4]], ZZ) + Anum_Q = DM([[3, 2], [5, 4]], QQ) + + assert A.clear_denoms_rowwise() == (den_Z, Anum_Q) + assert A.clear_denoms_rowwise(convert=True) == (den_Z, Anum_Z) + assert den_Z * A == Anum_Q + assert A == den_Z.to_field().inv() * Anum_Q + + A = DM([[(1,2),(1,3),0,0],[0,0,0,0], [(1,4),(1,5),(1,6),(1,7)]], QQ) + den_Z = DM([[6, 0, 0], [0, 1, 0], [0, 0, 420]], ZZ).to_sparse() + Anum_Z = DM([[3, 2, 0, 0], [0, 0, 0, 0], [105, 84, 70, 60]], ZZ) + Anum_Q = Anum_Z.convert_to(QQ) + + assert A.clear_denoms_rowwise() == (den_Z, Anum_Q) + assert A.clear_denoms_rowwise(convert=True) == (den_Z, Anum_Z) + assert den_Z * A == Anum_Q + assert A == den_Z.to_field().inv() * Anum_Q + + +def test_DomainMatrix_cancel_denom(): + A = DM([[2, 4], [6, 8]], ZZ) + assert A.cancel_denom(ZZ(1)) == (DM([[2, 4], [6, 8]], ZZ), ZZ(1)) + assert A.cancel_denom(ZZ(3)) == (DM([[2, 4], [6, 8]], ZZ), ZZ(3)) + assert A.cancel_denom(ZZ(4)) == (DM([[1, 2], [3, 4]], ZZ), ZZ(2)) + + A = DM([[1, 2], [3, 4]], ZZ) + assert A.cancel_denom(ZZ(2)) == (A, ZZ(2)) + assert A.cancel_denom(ZZ(-2)) == (-A, ZZ(2)) + + # Test canonicalization of denominator over Gaussian rationals. + A = DM([[1, 2], [3, 4]], QQ_I) + assert A.cancel_denom(QQ_I(0,2)) == (QQ_I(0,-1)*A, QQ_I(2)) + + raises(ZeroDivisionError, lambda: A.cancel_denom(ZZ(0))) + + +def test_DomainMatrix_cancel_denom_elementwise(): + A = DM([[2, 4], [6, 8]], ZZ) + numers, denoms = A.cancel_denom_elementwise(ZZ(1)) + assert numers == DM([[2, 4], [6, 8]], ZZ) + assert denoms == DM([[1, 1], [1, 1]], ZZ) + numers, denoms = A.cancel_denom_elementwise(ZZ(4)) + assert numers == DM([[1, 1], [3, 2]], ZZ) + assert denoms == DM([[2, 1], [2, 1]], ZZ) + + raises(ZeroDivisionError, lambda: A.cancel_denom_elementwise(ZZ(0))) + + +def test_DomainMatrix_content_primitive(): + A = DM([[2, 4], [6, 8]], ZZ) + A_primitive = DM([[1, 2], [3, 4]], ZZ) + A_content = ZZ(2) + assert A.content() == A_content + assert A.primitive() == (A_content, A_primitive) + + +def test_DomainMatrix_scc(): + Ad = DomainMatrix([[ZZ(1), ZZ(2), ZZ(3)], + [ZZ(0), ZZ(1), ZZ(0)], + [ZZ(2), ZZ(0), ZZ(4)]], (3, 3), ZZ) + As = Ad.to_sparse() + Addm = Ad.rep + Asdm = As.rep + for A in [Ad, As, Addm, Asdm]: + assert Ad.scc() == [[1], [0, 2]] + + A = DM([[ZZ(1), ZZ(2), ZZ(3)]], ZZ) + raises(DMNonSquareMatrixError, lambda: A.scc()) + + +def test_DomainMatrix_rref(): + # More tests in test_rref.py + A = DomainMatrix([], (0, 1), QQ) + assert A.rref() == (A, ()) + + A = DomainMatrix([[QQ(1)]], (1, 1), QQ) + assert A.rref() == (A, (0,)) + + A = DomainMatrix([[QQ(0)]], (1, 1), QQ) + assert A.rref() == (A, ()) + + A = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ) + Ar, pivots = A.rref() + assert Ar == DomainMatrix([[QQ(1), QQ(0)], [QQ(0), QQ(1)]], (2, 2), QQ) + assert pivots == (0, 1) + + A = DomainMatrix([[QQ(0), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ) + Ar, pivots = A.rref() + assert Ar == DomainMatrix([[QQ(1), QQ(0)], [QQ(0), QQ(1)]], (2, 2), QQ) + assert pivots == (0, 1) + + A = DomainMatrix([[QQ(0), QQ(2)], [QQ(0), QQ(4)]], (2, 2), QQ) + Ar, pivots = A.rref() + assert Ar == DomainMatrix([[QQ(0), QQ(1)], [QQ(0), QQ(0)]], (2, 2), QQ) + assert pivots == (1,) + + Az = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + Ar, pivots = Az.rref() + assert Ar == DomainMatrix([[QQ(1), QQ(0)], [QQ(0), QQ(1)]], (2, 2), QQ) + assert pivots == (0, 1) + + methods = ('auto', 'GJ', 'FF', 'CD', 'GJ_dense', 'FF_dense', 'CD_dense') + Az = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + for method in methods: + Ar, pivots = Az.rref(method=method) + assert Ar == DomainMatrix([[QQ(1), QQ(0)], [QQ(0), QQ(1)]], (2, 2), QQ) + assert pivots == (0, 1) + + raises(ValueError, lambda: Az.rref(method='foo')) + raises(ValueError, lambda: Az.rref_den(method='foo')) + + +def test_DomainMatrix_columnspace(): + A = DomainMatrix([[QQ(1), QQ(-1), QQ(1)], [QQ(2), QQ(-2), QQ(3)]], (2, 3), QQ) + Acol = DomainMatrix([[QQ(1), QQ(1)], [QQ(2), QQ(3)]], (2, 2), QQ) + assert A.columnspace() == Acol + + Az = DomainMatrix([[ZZ(1), ZZ(-1), ZZ(1)], [ZZ(2), ZZ(-2), ZZ(3)]], (2, 3), ZZ) + raises(DMNotAField, lambda: Az.columnspace()) + + A = DomainMatrix([[QQ(1), QQ(-1), QQ(1)], [QQ(2), QQ(-2), QQ(3)]], (2, 3), QQ, fmt='sparse') + Acol = DomainMatrix({0: {0: QQ(1), 1: QQ(1)}, 1: {0: QQ(2), 1: QQ(3)}}, (2, 2), QQ) + assert A.columnspace() == Acol + + +def test_DomainMatrix_rowspace(): + A = DomainMatrix([[QQ(1), QQ(-1), QQ(1)], [QQ(2), QQ(-2), QQ(3)]], (2, 3), QQ) + assert A.rowspace() == A + + Az = DomainMatrix([[ZZ(1), ZZ(-1), ZZ(1)], [ZZ(2), ZZ(-2), ZZ(3)]], (2, 3), ZZ) + raises(DMNotAField, lambda: Az.rowspace()) + + A = DomainMatrix([[QQ(1), QQ(-1), QQ(1)], [QQ(2), QQ(-2), QQ(3)]], (2, 3), QQ, fmt='sparse') + assert A.rowspace() == A + + +def test_DomainMatrix_nullspace(): + A = DomainMatrix([[QQ(1), QQ(1)], [QQ(1), QQ(1)]], (2, 2), QQ) + Anull = DomainMatrix([[QQ(-1), QQ(1)]], (1, 2), QQ) + assert A.nullspace() == Anull + + A = DomainMatrix([[ZZ(1), ZZ(1)], [ZZ(1), ZZ(1)]], (2, 2), ZZ) + Anull = DomainMatrix([[ZZ(-1), ZZ(1)]], (1, 2), ZZ) + assert A.nullspace() == Anull + + raises(DMNotAField, lambda: A.nullspace(divide_last=True)) + + A = DomainMatrix([[ZZ(2), ZZ(2)], [ZZ(2), ZZ(2)]], (2, 2), ZZ) + Anull = DomainMatrix([[ZZ(-2), ZZ(2)]], (1, 2), ZZ) + + Arref, den, pivots = A.rref_den() + assert den == ZZ(2) + assert Arref.nullspace_from_rref() == Anull + assert Arref.nullspace_from_rref(pivots) == Anull + assert Arref.to_sparse().nullspace_from_rref() == Anull.to_sparse() + assert Arref.to_sparse().nullspace_from_rref(pivots) == Anull.to_sparse() + + +def test_DomainMatrix_solve(): + # XXX: Maybe the _solve method should be changed... + A = DomainMatrix([[QQ(1), QQ(2)], [QQ(2), QQ(4)]], (2, 2), QQ) + b = DomainMatrix([[QQ(1)], [QQ(2)]], (2, 1), QQ) + particular = DomainMatrix([[1, 0]], (1, 2), QQ) + nullspace = DomainMatrix([[-2, 1]], (1, 2), QQ) + assert A._solve(b) == (particular, nullspace) + + b3 = DomainMatrix([[QQ(1)], [QQ(1)], [QQ(1)]], (3, 1), QQ) + raises(DMShapeError, lambda: A._solve(b3)) + + bz = DomainMatrix([[ZZ(1)], [ZZ(1)]], (2, 1), ZZ) + raises(DMNotAField, lambda: A._solve(bz)) + + +def test_DomainMatrix_inv(): + A = DomainMatrix([], (0, 0), QQ) + assert A.inv() == A + + A = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ) + Ainv = DomainMatrix([[QQ(-2), QQ(1)], [QQ(3, 2), QQ(-1, 2)]], (2, 2), QQ) + assert A.inv() == Ainv + + Az = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + raises(DMNotAField, lambda: Az.inv()) + + Ans = DomainMatrix([[QQ(1), QQ(2)]], (1, 2), QQ) + raises(DMNonSquareMatrixError, lambda: Ans.inv()) + + Aninv = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(6)]], (2, 2), QQ) + raises(DMNonInvertibleMatrixError, lambda: Aninv.inv()) + + Z3 = FF(3) + assert DM([[1, 2], [3, 4]], Z3).inv() == DM([[1, 1], [0, 1]], Z3) + + Z6 = FF(6) + raises(DMNotAField, lambda: DM([[1, 2], [3, 4]], Z6).inv()) + + +def test_DomainMatrix_det(): + A = DomainMatrix([], (0, 0), ZZ) + assert A.det() == 1 + + A = DomainMatrix([[1]], (1, 1), ZZ) + assert A.det() == 1 + + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + assert A.det() == ZZ(-2) + + A = DomainMatrix([[ZZ(1), ZZ(2), ZZ(3)], [ZZ(1), ZZ(2), ZZ(4)], [ZZ(1), ZZ(3), ZZ(5)]], (3, 3), ZZ) + assert A.det() == ZZ(-1) + + A = DomainMatrix([[ZZ(1), ZZ(2), ZZ(3)], [ZZ(1), ZZ(2), ZZ(4)], [ZZ(1), ZZ(2), ZZ(5)]], (3, 3), ZZ) + assert A.det() == ZZ(0) + + Ans = DomainMatrix([[QQ(1), QQ(2)]], (1, 2), QQ) + raises(DMNonSquareMatrixError, lambda: Ans.det()) + + A = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ) + assert A.det() == QQ(-2) + + +def test_DomainMatrix_eval_poly(): + dM = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + p = [ZZ(1), ZZ(2), ZZ(3)] + result = DomainMatrix([[ZZ(12), ZZ(14)], [ZZ(21), ZZ(33)]], (2, 2), ZZ) + assert dM.eval_poly(p) == result == p[0]*dM**2 + p[1]*dM + p[2]*dM**0 + assert dM.eval_poly([]) == dM.zeros(dM.shape, dM.domain) + assert dM.eval_poly([ZZ(2)]) == 2*dM.eye(2, dM.domain) + + dM2 = DomainMatrix([[ZZ(1), ZZ(2)]], (1, 2), ZZ) + raises(DMNonSquareMatrixError, lambda: dM2.eval_poly([ZZ(1)])) + + +def test_DomainMatrix_eval_poly_mul(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + b = DomainMatrix([[ZZ(1)], [ZZ(2)]], (2, 1), ZZ) + p = [ZZ(1), ZZ(2), ZZ(3)] + result = DomainMatrix([[ZZ(40)], [ZZ(87)]], (2, 1), ZZ) + assert A.eval_poly_mul(p, b) == result == p[0]*A**2*b + p[1]*A*b + p[2]*b + + dM = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + dM1 = DomainMatrix([[ZZ(1)], [ZZ(2)]], (2, 1), ZZ) + raises(DMNonSquareMatrixError, lambda: dM1.eval_poly_mul([ZZ(1)], b)) + b1 = DomainMatrix([[ZZ(1), ZZ(2)]], (1, 2), ZZ) + raises(DMShapeError, lambda: dM.eval_poly_mul([ZZ(1)], b1)) + bq = DomainMatrix([[QQ(1)], [QQ(2)]], (2, 1), QQ) + raises(DMDomainError, lambda: dM.eval_poly_mul([ZZ(1)], bq)) + + +def _check_solve_den(A, b, xnum, xden): + # Examples for solve_den, solve_den_charpoly, solve_den_rref should use + # this so that all methods and types are tested. + + case1 = (A, xnum, b) + case2 = (A.to_sparse(), xnum.to_sparse(), b.to_sparse()) + + for Ai, xnum_i, b_i in [case1, case2]: + # The key invariant for solve_den: + assert Ai*xnum_i == xden*b_i + + # solve_den_rref can differ at least by a minus sign + answers = [(xnum_i, xden), (-xnum_i, -xden)] + assert Ai.solve_den(b) in answers + assert Ai.solve_den(b, method='rref') in answers + assert Ai.solve_den_rref(b) in answers + + # charpoly can only be used if A is square and guarantees to return the + # actual determinant as a denominator. + m, n = Ai.shape + if m == n: + assert Ai.solve_den(b_i, method='charpoly') == (xnum_i, xden) + assert Ai.solve_den_charpoly(b_i) == (xnum_i, xden) + else: + raises(DMNonSquareMatrixError, lambda: Ai.solve_den_charpoly(b)) + raises(DMNonSquareMatrixError, lambda: Ai.solve_den(b, method='charpoly')) + + +def test_DomainMatrix_solve_den(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + b = DomainMatrix([[ZZ(1)], [ZZ(2)]], (2, 1), ZZ) + result = DomainMatrix([[ZZ(0)], [ZZ(-1)]], (2, 1), ZZ) + den = ZZ(-2) + _check_solve_den(A, b, result, den) + + A = DomainMatrix([ + [ZZ(1), ZZ(2), ZZ(3)], + [ZZ(1), ZZ(2), ZZ(4)], + [ZZ(1), ZZ(3), ZZ(5)]], (3, 3), ZZ) + b = DomainMatrix([[ZZ(1)], [ZZ(2)], [ZZ(3)]], (3, 1), ZZ) + result = DomainMatrix([[ZZ(2)], [ZZ(0)], [ZZ(-1)]], (3, 1), ZZ) + den = ZZ(-1) + _check_solve_den(A, b, result, den) + + A = DomainMatrix([[ZZ(2)], [ZZ(2)]], (2, 1), ZZ) + b = DomainMatrix([[ZZ(3)], [ZZ(3)]], (2, 1), ZZ) + result = DomainMatrix([[ZZ(3)]], (1, 1), ZZ) + den = ZZ(2) + _check_solve_den(A, b, result, den) + + +def test_DomainMatrix_solve_den_charpoly(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + b = DomainMatrix([[ZZ(1)], [ZZ(2)]], (2, 1), ZZ) + A1 = DomainMatrix([[ZZ(1), ZZ(2)]], (1, 2), ZZ) + raises(DMNonSquareMatrixError, lambda: A1.solve_den_charpoly(b)) + b1 = DomainMatrix([[ZZ(1), ZZ(2)]], (1, 2), ZZ) + raises(DMShapeError, lambda: A.solve_den_charpoly(b1)) + bq = DomainMatrix([[QQ(1)], [QQ(2)]], (2, 1), QQ) + raises(DMDomainError, lambda: A.solve_den_charpoly(bq)) + + +def test_DomainMatrix_solve_den_charpoly_check(): + # Test check + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(2), ZZ(4)]], (2, 2), ZZ) + b = DomainMatrix([[ZZ(1)], [ZZ(3)]], (2, 1), ZZ) + raises(DMNonInvertibleMatrixError, lambda: A.solve_den_charpoly(b)) + adjAb = DomainMatrix([[ZZ(-2)], [ZZ(1)]], (2, 1), ZZ) + assert A.adjugate() * b == adjAb + assert A.solve_den_charpoly(b, check=False) == (adjAb, ZZ(0)) + + +def test_DomainMatrix_solve_den_errors(): + A = DomainMatrix([[ZZ(1), ZZ(2)]], (1, 2), ZZ) + b = DomainMatrix([[ZZ(1)], [ZZ(2)]], (2, 1), ZZ) + raises(DMShapeError, lambda: A.solve_den(b)) + raises(DMShapeError, lambda: A.solve_den_rref(b)) + + A = DomainMatrix([[ZZ(1), ZZ(2)]], (1, 2), ZZ) + b = DomainMatrix([[ZZ(1), ZZ(2)]], (1, 2), ZZ) + raises(DMShapeError, lambda: A.solve_den(b)) + raises(DMShapeError, lambda: A.solve_den_rref(b)) + + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + b1 = DomainMatrix([[ZZ(1), ZZ(2)]], (1, 2), ZZ) + raises(DMShapeError, lambda: A.solve_den(b1)) + + A = DomainMatrix([[ZZ(2)]], (1, 1), ZZ) + b = DomainMatrix([[ZZ(2)]], (1, 1), ZZ) + raises(DMBadInputError, lambda: A.solve_den(b1, method='invalid')) + + A = DomainMatrix([[ZZ(1)], [ZZ(2)]], (2, 1), ZZ) + b = DomainMatrix([[ZZ(1)], [ZZ(2)]], (2, 1), ZZ) + raises(DMNonSquareMatrixError, lambda: A.solve_den_charpoly(b)) + + +def test_DomainMatrix_solve_den_rref_underdetermined(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(1), ZZ(2)]], (2, 2), ZZ) + b = DomainMatrix([[ZZ(1)], [ZZ(1)]], (2, 1), ZZ) + raises(DMNonInvertibleMatrixError, lambda: A.solve_den(b)) + raises(DMNonInvertibleMatrixError, lambda: A.solve_den_rref(b)) + + +def test_DomainMatrix_adj_poly_det(): + A = DM([[ZZ(1), ZZ(2), ZZ(3)], + [ZZ(4), ZZ(5), ZZ(6)], + [ZZ(7), ZZ(8), ZZ(9)]], ZZ) + p, detA = A.adj_poly_det() + assert p == [ZZ(1), ZZ(-15), ZZ(-18)] + assert A.adjugate() == p[0]*A**2 + p[1]*A**1 + p[2]*A**0 == A.eval_poly(p) + assert A.det() == detA + + A = DM([[ZZ(1), ZZ(2), ZZ(3)], + [ZZ(7), ZZ(8), ZZ(9)]], ZZ) + raises(DMNonSquareMatrixError, lambda: A.adj_poly_det()) + + +def test_DomainMatrix_inv_den(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + den = ZZ(-2) + result = DomainMatrix([[ZZ(4), ZZ(-2)], [ZZ(-3), ZZ(1)]], (2, 2), ZZ) + assert A.inv_den() == (result, den) + + +def test_DomainMatrix_adjugate(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + result = DomainMatrix([[ZZ(4), ZZ(-2)], [ZZ(-3), ZZ(1)]], (2, 2), ZZ) + assert A.adjugate() == result + + +def test_DomainMatrix_adj_det(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + adjA = DomainMatrix([[ZZ(4), ZZ(-2)], [ZZ(-3), ZZ(1)]], (2, 2), ZZ) + assert A.adj_det() == (adjA, ZZ(-2)) + + +def test_DomainMatrix_lu(): + A = DomainMatrix([], (0, 0), QQ) + assert A.lu() == (A, A, []) + + A = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ) + L = DomainMatrix([[QQ(1), QQ(0)], [QQ(3), QQ(1)]], (2, 2), QQ) + U = DomainMatrix([[QQ(1), QQ(2)], [QQ(0), QQ(-2)]], (2, 2), QQ) + swaps = [] + assert A.lu() == (L, U, swaps) + + A = DomainMatrix([[QQ(0), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ) + L = DomainMatrix([[QQ(1), QQ(0)], [QQ(0), QQ(1)]], (2, 2), QQ) + U = DomainMatrix([[QQ(3), QQ(4)], [QQ(0), QQ(2)]], (2, 2), QQ) + swaps = [(0, 1)] + assert A.lu() == (L, U, swaps) + + A = DomainMatrix([[QQ(1), QQ(2)], [QQ(2), QQ(4)]], (2, 2), QQ) + L = DomainMatrix([[QQ(1), QQ(0)], [QQ(2), QQ(1)]], (2, 2), QQ) + U = DomainMatrix([[QQ(1), QQ(2)], [QQ(0), QQ(0)]], (2, 2), QQ) + swaps = [] + assert A.lu() == (L, U, swaps) + + A = DomainMatrix([[QQ(0), QQ(2)], [QQ(0), QQ(4)]], (2, 2), QQ) + L = DomainMatrix([[QQ(1), QQ(0)], [QQ(0), QQ(1)]], (2, 2), QQ) + U = DomainMatrix([[QQ(0), QQ(2)], [QQ(0), QQ(4)]], (2, 2), QQ) + swaps = [] + assert A.lu() == (L, U, swaps) + + A = DomainMatrix([[QQ(1), QQ(2), QQ(3)], [QQ(4), QQ(5), QQ(6)]], (2, 3), QQ) + L = DomainMatrix([[QQ(1), QQ(0)], [QQ(4), QQ(1)]], (2, 2), QQ) + U = DomainMatrix([[QQ(1), QQ(2), QQ(3)], [QQ(0), QQ(-3), QQ(-6)]], (2, 3), QQ) + swaps = [] + assert A.lu() == (L, U, swaps) + + A = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)], [QQ(5), QQ(6)]], (3, 2), QQ) + L = DomainMatrix([ + [QQ(1), QQ(0), QQ(0)], + [QQ(3), QQ(1), QQ(0)], + [QQ(5), QQ(2), QQ(1)]], (3, 3), QQ) + U = DomainMatrix([[QQ(1), QQ(2)], [QQ(0), QQ(-2)], [QQ(0), QQ(0)]], (3, 2), QQ) + swaps = [] + assert A.lu() == (L, U, swaps) + + A = [[1, 0, 0, 0], [0, 0, 0, 0], [0, 0, 1, 1], [0, 0, 1, 2]] + L = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 1, 1]] + U = [[1, 0, 0, 0], [0, 0, 0, 0], [0, 0, 1, 1], [0, 0, 0, 1]] + to_dom = lambda rows, dom: [[dom(e) for e in row] for row in rows] + A = DomainMatrix(to_dom(A, QQ), (4, 4), QQ) + L = DomainMatrix(to_dom(L, QQ), (4, 4), QQ) + U = DomainMatrix(to_dom(U, QQ), (4, 4), QQ) + assert A.lu() == (L, U, []) + + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + raises(DMNotAField, lambda: A.lu()) + + +def test_DomainMatrix_lu_solve(): + # Base case + A = b = x = DomainMatrix([], (0, 0), QQ) + assert A.lu_solve(b) == x + + # Basic example + A = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ) + b = DomainMatrix([[QQ(1)], [QQ(2)]], (2, 1), QQ) + x = DomainMatrix([[QQ(0)], [QQ(1, 2)]], (2, 1), QQ) + assert A.lu_solve(b) == x + + # Example with swaps + A = DomainMatrix([[QQ(0), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ) + b = DomainMatrix([[QQ(1)], [QQ(2)]], (2, 1), QQ) + x = DomainMatrix([[QQ(0)], [QQ(1, 2)]], (2, 1), QQ) + assert A.lu_solve(b) == x + + # Non-invertible + A = DomainMatrix([[QQ(1), QQ(2)], [QQ(2), QQ(4)]], (2, 2), QQ) + b = DomainMatrix([[QQ(1)], [QQ(2)]], (2, 1), QQ) + raises(DMNonInvertibleMatrixError, lambda: A.lu_solve(b)) + + # Overdetermined, consistent + A = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)], [QQ(5), QQ(6)]], (3, 2), QQ) + b = DomainMatrix([[QQ(1)], [QQ(2)], [QQ(3)]], (3, 1), QQ) + x = DomainMatrix([[QQ(0)], [QQ(1, 2)]], (2, 1), QQ) + assert A.lu_solve(b) == x + + # Overdetermined, inconsistent + A = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)], [QQ(5), QQ(6)]], (3, 2), QQ) + b = DomainMatrix([[QQ(1)], [QQ(2)], [QQ(4)]], (3, 1), QQ) + raises(DMNonInvertibleMatrixError, lambda: A.lu_solve(b)) + + # Underdetermined + A = DomainMatrix([[QQ(1), QQ(2)]], (1, 2), QQ) + b = DomainMatrix([[QQ(1)]], (1, 1), QQ) + raises(NotImplementedError, lambda: A.lu_solve(b)) + + # Non-field + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + b = DomainMatrix([[ZZ(1)], [ZZ(2)]], (2, 1), ZZ) + raises(DMNotAField, lambda: A.lu_solve(b)) + + # Shape mismatch + A = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ) + b = DomainMatrix([[QQ(1), QQ(2)]], (1, 2), QQ) + raises(DMShapeError, lambda: A.lu_solve(b)) + + +def test_DomainMatrix_charpoly(): + A = DomainMatrix([], (0, 0), ZZ) + p = [ZZ(1)] + assert A.charpoly() == p + assert A.to_sparse().charpoly() == p + + A = DomainMatrix([[1]], (1, 1), ZZ) + p = [ZZ(1), ZZ(-1)] + assert A.charpoly() == p + assert A.to_sparse().charpoly() == p + + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + p = [ZZ(1), ZZ(-5), ZZ(-2)] + assert A.charpoly() == p + assert A.to_sparse().charpoly() == p + + A = DomainMatrix([[ZZ(1), ZZ(2), ZZ(3)], [ZZ(4), ZZ(5), ZZ(6)], [ZZ(7), ZZ(8), ZZ(9)]], (3, 3), ZZ) + p = [ZZ(1), ZZ(-15), ZZ(-18), ZZ(0)] + assert A.charpoly() == p + assert A.to_sparse().charpoly() == p + + A = DomainMatrix([[ZZ(0), ZZ(1), ZZ(0)], + [ZZ(1), ZZ(0), ZZ(1)], + [ZZ(0), ZZ(1), ZZ(0)]], (3, 3), ZZ) + p = [ZZ(1), ZZ(0), ZZ(-2), ZZ(0)] + assert A.charpoly() == p + assert A.to_sparse().charpoly() == p + + A = DM([[17, 0, 30, 0, 0, 0, 0, 0, 0, 0], + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [69, 0, 0, 0, 0, 86, 0, 0, 0, 0], + [23, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [ 0, 0, 0, 13, 0, 0, 0, 0, 0, 0], + [ 0, 0, 0, 0, 0, 0, 0, 32, 0, 0], + [ 0, 0, 0, 0, 37, 67, 0, 0, 0, 0], + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], ZZ) + p = ZZ.map([1, -17, -2070, 0, -771420, 0, 0, 0, 0, 0, 0]) + assert A.charpoly() == p + assert A.to_sparse().charpoly() == p + + Ans = DomainMatrix([[QQ(1), QQ(2)]], (1, 2), QQ) + raises(DMNonSquareMatrixError, lambda: Ans.charpoly()) + + +def test_DomainMatrix_charpoly_factor_list(): + A = DomainMatrix([], (0, 0), ZZ) + assert A.charpoly_factor_list() == [] + + A = DM([[1]], ZZ) + assert A.charpoly_factor_list() == [ + ([ZZ(1), ZZ(-1)], 1) + ] + + A = DM([[1, 2], [3, 4]], ZZ) + assert A.charpoly_factor_list() == [ + ([ZZ(1), ZZ(-5), ZZ(-2)], 1) + ] + + A = DM([[1, 2, 0], [3, 4, 0], [0, 0, 1]], ZZ) + assert A.charpoly_factor_list() == [ + ([ZZ(1), ZZ(-1)], 1), + ([ZZ(1), ZZ(-5), ZZ(-2)], 1) + ] + + +def test_DomainMatrix_eye(): + A = DomainMatrix.eye(3, QQ) + assert A.rep == SDM.eye((3, 3), QQ) + assert A.shape == (3, 3) + assert A.domain == QQ + + +def test_DomainMatrix_zeros(): + A = DomainMatrix.zeros((1, 2), QQ) + assert A.rep == SDM.zeros((1, 2), QQ) + assert A.shape == (1, 2) + assert A.domain == QQ + + +def test_DomainMatrix_ones(): + A = DomainMatrix.ones((2, 3), QQ) + if GROUND_TYPES != 'flint': + assert A.rep == DDM.ones((2, 3), QQ) + else: + assert A.rep == SDM.ones((2, 3), QQ).to_dfm() + assert A.shape == (2, 3) + assert A.domain == QQ + + +def test_DomainMatrix_diag(): + A = DomainMatrix({0:{0:ZZ(2)}, 1:{1:ZZ(3)}}, (2, 2), ZZ) + assert DomainMatrix.diag([ZZ(2), ZZ(3)], ZZ) == A + + A = DomainMatrix({0:{0:ZZ(2)}, 1:{1:ZZ(3)}}, (3, 4), ZZ) + assert DomainMatrix.diag([ZZ(2), ZZ(3)], ZZ, (3, 4)) == A + + +def test_DomainMatrix_hstack(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + B = DomainMatrix([[ZZ(5), ZZ(6)], [ZZ(7), ZZ(8)]], (2, 2), ZZ) + C = DomainMatrix([[ZZ(9), ZZ(10)], [ZZ(11), ZZ(12)]], (2, 2), ZZ) + + AB = DomainMatrix([ + [ZZ(1), ZZ(2), ZZ(5), ZZ(6)], + [ZZ(3), ZZ(4), ZZ(7), ZZ(8)]], (2, 4), ZZ) + ABC = DomainMatrix([ + [ZZ(1), ZZ(2), ZZ(5), ZZ(6), ZZ(9), ZZ(10)], + [ZZ(3), ZZ(4), ZZ(7), ZZ(8), ZZ(11), ZZ(12)]], (2, 6), ZZ) + assert A.hstack(B) == AB + assert A.hstack(B, C) == ABC + + +def test_DomainMatrix_vstack(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + B = DomainMatrix([[ZZ(5), ZZ(6)], [ZZ(7), ZZ(8)]], (2, 2), ZZ) + C = DomainMatrix([[ZZ(9), ZZ(10)], [ZZ(11), ZZ(12)]], (2, 2), ZZ) + + AB = DomainMatrix([ + [ZZ(1), ZZ(2)], + [ZZ(3), ZZ(4)], + [ZZ(5), ZZ(6)], + [ZZ(7), ZZ(8)]], (4, 2), ZZ) + ABC = DomainMatrix([ + [ZZ(1), ZZ(2)], + [ZZ(3), ZZ(4)], + [ZZ(5), ZZ(6)], + [ZZ(7), ZZ(8)], + [ZZ(9), ZZ(10)], + [ZZ(11), ZZ(12)]], (6, 2), ZZ) + assert A.vstack(B) == AB + assert A.vstack(B, C) == ABC + + +def test_DomainMatrix_applyfunc(): + A = DomainMatrix([[ZZ(1), ZZ(2)]], (1, 2), ZZ) + B = DomainMatrix([[ZZ(2), ZZ(4)]], (1, 2), ZZ) + assert A.applyfunc(lambda x: 2*x) == B + + +def test_DomainMatrix_scalarmul(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + lamda = DomainScalar(QQ(3)/QQ(2), QQ) + assert A * lamda == DomainMatrix([[QQ(3, 2), QQ(3)], [QQ(9, 2), QQ(6)]], (2, 2), QQ) + assert A * 2 == DomainMatrix([[ZZ(2), ZZ(4)], [ZZ(6), ZZ(8)]], (2, 2), ZZ) + assert 2 * A == DomainMatrix([[ZZ(2), ZZ(4)], [ZZ(6), ZZ(8)]], (2, 2), ZZ) + assert A * DomainScalar(ZZ(0), ZZ) == DomainMatrix({}, (2, 2), ZZ) + assert A * DomainScalar(ZZ(1), ZZ) == A + + raises(TypeError, lambda: A * 1.5) + + +def test_DomainMatrix_truediv(): + A = DomainMatrix.from_Matrix(Matrix([[1, 2], [3, 4]])) + lamda = DomainScalar(QQ(3)/QQ(2), QQ) + assert A / lamda == DomainMatrix({0: {0: QQ(2, 3), 1: QQ(4, 3)}, 1: {0: QQ(2), 1: QQ(8, 3)}}, (2, 2), QQ) + b = DomainScalar(ZZ(1), ZZ) + assert A / b == DomainMatrix({0: {0: QQ(1), 1: QQ(2)}, 1: {0: QQ(3), 1: QQ(4)}}, (2, 2), QQ) + + assert A / 1 == DomainMatrix({0: {0: QQ(1), 1: QQ(2)}, 1: {0: QQ(3), 1: QQ(4)}}, (2, 2), QQ) + assert A / 2 == DomainMatrix({0: {0: QQ(1, 2), 1: QQ(1)}, 1: {0: QQ(3, 2), 1: QQ(2)}}, (2, 2), QQ) + + raises(ZeroDivisionError, lambda: A / 0) + raises(TypeError, lambda: A / 1.5) + raises(ZeroDivisionError, lambda: A / DomainScalar(ZZ(0), ZZ)) + + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + assert A.to_field() / 2 == DomainMatrix([[QQ(1, 2), QQ(1)], [QQ(3, 2), QQ(2)]], (2, 2), QQ) + assert A / 2 == DomainMatrix([[QQ(1, 2), QQ(1)], [QQ(3, 2), QQ(2)]], (2, 2), QQ) + assert A.to_field() / QQ(2,3) == DomainMatrix([[QQ(3, 2), QQ(3)], [QQ(9, 2), QQ(6)]], (2, 2), QQ) + + +def test_DomainMatrix_getitem(): + dM = DomainMatrix([ + [ZZ(1), ZZ(2), ZZ(3)], + [ZZ(4), ZZ(5), ZZ(6)], + [ZZ(7), ZZ(8), ZZ(9)]], (3, 3), ZZ) + + assert dM[1:,:-2] == DomainMatrix([[ZZ(4)], [ZZ(7)]], (2, 1), ZZ) + assert dM[2,:-2] == DomainMatrix([[ZZ(7)]], (1, 1), ZZ) + assert dM[:-2,:-2] == DomainMatrix([[ZZ(1)]], (1, 1), ZZ) + assert dM[:-1,0:2] == DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(4), ZZ(5)]], (2, 2), ZZ) + assert dM[:, -1] == DomainMatrix([[ZZ(3)], [ZZ(6)], [ZZ(9)]], (3, 1), ZZ) + assert dM[-1, :] == DomainMatrix([[ZZ(7), ZZ(8), ZZ(9)]], (1, 3), ZZ) + assert dM[::-1, :] == DomainMatrix([ + [ZZ(7), ZZ(8), ZZ(9)], + [ZZ(4), ZZ(5), ZZ(6)], + [ZZ(1), ZZ(2), ZZ(3)]], (3, 3), ZZ) + + raises(IndexError, lambda: dM[4, :-2]) + raises(IndexError, lambda: dM[:-2, 4]) + + assert dM[1, 2] == DomainScalar(ZZ(6), ZZ) + assert dM[-2, 2] == DomainScalar(ZZ(6), ZZ) + assert dM[1, -2] == DomainScalar(ZZ(5), ZZ) + assert dM[-1, -3] == DomainScalar(ZZ(7), ZZ) + + raises(IndexError, lambda: dM[3, 3]) + raises(IndexError, lambda: dM[1, 4]) + raises(IndexError, lambda: dM[-1, -4]) + + dM = DomainMatrix({0: {0: ZZ(1)}}, (10, 10), ZZ) + assert dM[5, 5] == DomainScalar(ZZ(0), ZZ) + assert dM[0, 0] == DomainScalar(ZZ(1), ZZ) + + dM = DomainMatrix({1: {0: 1}}, (2,1), ZZ) + assert dM[0:, 0] == DomainMatrix({1: {0: 1}}, (2, 1), ZZ) + raises(IndexError, lambda: dM[3, 0]) + + dM = DomainMatrix({2: {2: ZZ(1)}, 4: {4: ZZ(1)}}, (5, 5), ZZ) + assert dM[:2,:2] == DomainMatrix({}, (2, 2), ZZ) + assert dM[2:,2:] == DomainMatrix({0: {0: 1}, 2: {2: 1}}, (3, 3), ZZ) + assert dM[3:,3:] == DomainMatrix({1: {1: 1}}, (2, 2), ZZ) + assert dM[2:, 6:] == DomainMatrix({}, (3, 0), ZZ) + + +def test_DomainMatrix_getitem_sympy(): + dM = DomainMatrix({2: {2: ZZ(2)}, 4: {4: ZZ(1)}}, (5, 5), ZZ) + val1 = dM.getitem_sympy(0, 0) + assert val1 is S.Zero + val2 = dM.getitem_sympy(2, 2) + assert val2 == 2 and isinstance(val2, Integer) + + +def test_DomainMatrix_extract(): + dM1 = DomainMatrix([ + [ZZ(1), ZZ(2), ZZ(3)], + [ZZ(4), ZZ(5), ZZ(6)], + [ZZ(7), ZZ(8), ZZ(9)]], (3, 3), ZZ) + dM2 = DomainMatrix([ + [ZZ(1), ZZ(3)], + [ZZ(7), ZZ(9)]], (2, 2), ZZ) + assert dM1.extract([0, 2], [0, 2]) == dM2 + assert dM1.to_sparse().extract([0, 2], [0, 2]) == dM2.to_sparse() + assert dM1.extract([0, -1], [0, -1]) == dM2 + assert dM1.to_sparse().extract([0, -1], [0, -1]) == dM2.to_sparse() + + dM3 = DomainMatrix([ + [ZZ(1), ZZ(2), ZZ(2)], + [ZZ(4), ZZ(5), ZZ(5)], + [ZZ(4), ZZ(5), ZZ(5)]], (3, 3), ZZ) + assert dM1.extract([0, 1, 1], [0, 1, 1]) == dM3 + assert dM1.to_sparse().extract([0, 1, 1], [0, 1, 1]) == dM3.to_sparse() + + empty = [ + ([], [], (0, 0)), + ([1], [], (1, 0)), + ([], [1], (0, 1)), + ] + for rows, cols, size in empty: + assert dM1.extract(rows, cols) == DomainMatrix.zeros(size, ZZ).to_dense() + assert dM1.to_sparse().extract(rows, cols) == DomainMatrix.zeros(size, ZZ) + + dM = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + bad_indices = [([2], [0]), ([0], [2]), ([-3], [0]), ([0], [-3])] + for rows, cols in bad_indices: + raises(IndexError, lambda: dM.extract(rows, cols)) + raises(IndexError, lambda: dM.to_sparse().extract(rows, cols)) + + +def test_DomainMatrix_setitem(): + dM = DomainMatrix({2: {2: ZZ(1)}, 4: {4: ZZ(1)}}, (5, 5), ZZ) + dM[2, 2] = ZZ(2) + assert dM == DomainMatrix({2: {2: ZZ(2)}, 4: {4: ZZ(1)}}, (5, 5), ZZ) + def setitem(i, j, val): + dM[i, j] = val + raises(TypeError, lambda: setitem(2, 2, QQ(1, 2))) + raises(NotImplementedError, lambda: setitem(slice(1, 2), 2, ZZ(1))) + + +def test_DomainMatrix_pickling(): + import pickle + dM = DomainMatrix({2: {2: ZZ(1)}, 4: {4: ZZ(1)}}, (5, 5), ZZ) + assert pickle.loads(pickle.dumps(dM)) == dM + dM = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + assert pickle.loads(pickle.dumps(dM)) == dM + + +def test_DomainMatrix_fflu(): + A = DM([[1, 2], [3, 4]], ZZ) + P, L, D, U = A.fflu() + assert P.shape == A.shape + assert L.shape == A.shape + assert D.shape == A.shape + assert U.shape == A.shape + assert P == DM([[1, 0], [0, 1]], ZZ) + assert L == DM([[1, 0], [3, -2]], ZZ) + assert D == DM([[1, 0], [0, -2]], ZZ) + assert U == DM([[1, 2], [0, -2]], ZZ) + di, d = D.inv_den() + assert P.matmul(A).rmul(d) == L.matmul(di).matmul(U) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_domainscalar.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_domainscalar.py new file mode 100644 index 0000000000000000000000000000000000000000..8c507caf079cc62ba23ba171a50d0d27c98eb6d9 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_domainscalar.py @@ -0,0 +1,153 @@ +from sympy.testing.pytest import raises + +from sympy.core.symbol import S +from sympy.polys import ZZ, QQ +from sympy.polys.matrices.domainscalar import DomainScalar +from sympy.polys.matrices.domainmatrix import DomainMatrix + + +def test_DomainScalar___new__(): + raises(TypeError, lambda: DomainScalar(ZZ(1), QQ)) + raises(TypeError, lambda: DomainScalar(ZZ(1), 1)) + + +def test_DomainScalar_new(): + A = DomainScalar(ZZ(1), ZZ) + B = A.new(ZZ(4), ZZ) + assert B == DomainScalar(ZZ(4), ZZ) + + +def test_DomainScalar_repr(): + A = DomainScalar(ZZ(1), ZZ) + assert repr(A) in {'1', 'mpz(1)'} + + +def test_DomainScalar_from_sympy(): + expr = S(1) + B = DomainScalar.from_sympy(expr) + assert B == DomainScalar(ZZ(1), ZZ) + + +def test_DomainScalar_to_sympy(): + B = DomainScalar(ZZ(1), ZZ) + expr = B.to_sympy() + assert expr.is_Integer and expr == 1 + + +def test_DomainScalar_to_domain(): + A = DomainScalar(ZZ(1), ZZ) + B = A.to_domain(QQ) + assert B == DomainScalar(QQ(1), QQ) + + +def test_DomainScalar_convert_to(): + A = DomainScalar(ZZ(1), ZZ) + B = A.convert_to(QQ) + assert B == DomainScalar(QQ(1), QQ) + + +def test_DomainScalar_unify(): + A = DomainScalar(ZZ(1), ZZ) + B = DomainScalar(QQ(2), QQ) + A, B = A.unify(B) + assert A.domain == B.domain == QQ + + +def test_DomainScalar_add(): + A = DomainScalar(ZZ(1), ZZ) + B = DomainScalar(QQ(2), QQ) + assert A + B == DomainScalar(QQ(3), QQ) + + raises(TypeError, lambda: A + 1.5) + +def test_DomainScalar_sub(): + A = DomainScalar(ZZ(1), ZZ) + B = DomainScalar(QQ(2), QQ) + assert A - B == DomainScalar(QQ(-1), QQ) + + raises(TypeError, lambda: A - 1.5) + +def test_DomainScalar_mul(): + A = DomainScalar(ZZ(1), ZZ) + B = DomainScalar(QQ(2), QQ) + dm = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + assert A * B == DomainScalar(QQ(2), QQ) + assert A * dm == dm + assert B * 2 == DomainScalar(QQ(4), QQ) + + raises(TypeError, lambda: A * 1.5) + + +def test_DomainScalar_floordiv(): + A = DomainScalar(ZZ(-5), ZZ) + B = DomainScalar(QQ(2), QQ) + assert A // B == DomainScalar(QQ(-5, 2), QQ) + C = DomainScalar(ZZ(2), ZZ) + assert A // C == DomainScalar(ZZ(-3), ZZ) + + raises(TypeError, lambda: A // 1.5) + + +def test_DomainScalar_mod(): + A = DomainScalar(ZZ(5), ZZ) + B = DomainScalar(QQ(2), QQ) + assert A % B == DomainScalar(QQ(0), QQ) + C = DomainScalar(ZZ(2), ZZ) + assert A % C == DomainScalar(ZZ(1), ZZ) + + raises(TypeError, lambda: A % 1.5) + + +def test_DomainScalar_divmod(): + A = DomainScalar(ZZ(5), ZZ) + B = DomainScalar(QQ(2), QQ) + assert divmod(A, B) == (DomainScalar(QQ(5, 2), QQ), DomainScalar(QQ(0), QQ)) + C = DomainScalar(ZZ(2), ZZ) + assert divmod(A, C) == (DomainScalar(ZZ(2), ZZ), DomainScalar(ZZ(1), ZZ)) + + raises(TypeError, lambda: divmod(A, 1.5)) + + +def test_DomainScalar_pow(): + A = DomainScalar(ZZ(-5), ZZ) + B = A**(2) + assert B == DomainScalar(ZZ(25), ZZ) + + raises(TypeError, lambda: A**(1.5)) + + +def test_DomainScalar_pos(): + A = DomainScalar(QQ(2), QQ) + B = DomainScalar(QQ(2), QQ) + assert +A == B + + +def test_DomainScalar_neg(): + A = DomainScalar(QQ(2), QQ) + B = DomainScalar(QQ(-2), QQ) + assert -A == B + + +def test_DomainScalar_eq(): + A = DomainScalar(QQ(2), QQ) + assert A == A + B = DomainScalar(ZZ(-5), ZZ) + assert A != B + C = DomainScalar(ZZ(2), ZZ) + assert A != C + D = [1] + assert A != D + + +def test_DomainScalar_isZero(): + A = DomainScalar(ZZ(0), ZZ) + assert A.is_zero() == True + B = DomainScalar(ZZ(1), ZZ) + assert B.is_zero() == False + + +def test_DomainScalar_isOne(): + A = DomainScalar(ZZ(1), ZZ) + assert A.is_one() == True + B = DomainScalar(ZZ(0), ZZ) + assert B.is_one() == False diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_eigen.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_eigen.py new file mode 100644 index 0000000000000000000000000000000000000000..70482eab686d5b4e1c45d552f5eccb5bdaa9e1ed --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_eigen.py @@ -0,0 +1,90 @@ +""" +Tests for the sympy.polys.matrices.eigen module +""" + +from sympy.core.singleton import S +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.matrices.dense import Matrix + +from sympy.polys.agca.extensions import FiniteExtension +from sympy.polys.domains import QQ +from sympy.polys.polytools import Poly +from sympy.polys.rootoftools import CRootOf +from sympy.polys.matrices.domainmatrix import DomainMatrix + +from sympy.polys.matrices.eigen import dom_eigenvects, dom_eigenvects_to_sympy + + +def test_dom_eigenvects_rational(): + # Rational eigenvalues + A = DomainMatrix([[QQ(1), QQ(2)], [QQ(1), QQ(2)]], (2, 2), QQ) + rational_eigenvects = [ + (QQ, QQ(3), 1, DomainMatrix([[QQ(1), QQ(1)]], (1, 2), QQ)), + (QQ, QQ(0), 1, DomainMatrix([[QQ(-2), QQ(1)]], (1, 2), QQ)), + ] + assert dom_eigenvects(A) == (rational_eigenvects, []) + + # Test converting to Expr: + sympy_eigenvects = [ + (S(3), 1, [Matrix([1, 1])]), + (S(0), 1, [Matrix([-2, 1])]), + ] + assert dom_eigenvects_to_sympy(rational_eigenvects, [], Matrix) == sympy_eigenvects + + +def test_dom_eigenvects_algebraic(): + # Algebraic eigenvalues + A = DomainMatrix([[QQ(1), QQ(2)], [QQ(3), QQ(4)]], (2, 2), QQ) + Avects = dom_eigenvects(A) + + # Extract the dummy to build the expected result: + lamda = Avects[1][0][1].gens[0] + irreducible = Poly(lamda**2 - 5*lamda - 2, lamda, domain=QQ) + K = FiniteExtension(irreducible) + KK = K.from_sympy + algebraic_eigenvects = [ + (K, irreducible, 1, DomainMatrix([[KK((lamda-4)/3), KK(1)]], (1, 2), K)), + ] + assert Avects == ([], algebraic_eigenvects) + + # Test converting to Expr: + sympy_eigenvects = [ + (S(5)/2 - sqrt(33)/2, 1, [Matrix([[-sqrt(33)/6 - S(1)/2], [1]])]), + (S(5)/2 + sqrt(33)/2, 1, [Matrix([[-S(1)/2 + sqrt(33)/6], [1]])]), + ] + assert dom_eigenvects_to_sympy([], algebraic_eigenvects, Matrix) == sympy_eigenvects + + +def test_dom_eigenvects_rootof(): + # Algebraic eigenvalues + A = DomainMatrix([ + [0, 0, 0, 0, -1], + [1, 0, 0, 0, 1], + [0, 1, 0, 0, 0], + [0, 0, 1, 0, 0], + [0, 0, 0, 1, 0]], (5, 5), QQ) + Avects = dom_eigenvects(A) + + # Extract the dummy to build the expected result: + lamda = Avects[1][0][1].gens[0] + irreducible = Poly(lamda**5 - lamda + 1, lamda, domain=QQ) + K = FiniteExtension(irreducible) + KK = K.from_sympy + algebraic_eigenvects = [ + (K, irreducible, 1, + DomainMatrix([ + [KK(lamda**4-1), KK(lamda**3), KK(lamda**2), KK(lamda), KK(1)] + ], (1, 5), K)), + ] + assert Avects == ([], algebraic_eigenvects) + + # Test converting to Expr (slow): + l0, l1, l2, l3, l4 = [CRootOf(lamda**5 - lamda + 1, i) for i in range(5)] + sympy_eigenvects = [ + (l0, 1, [Matrix([-1 + l0**4, l0**3, l0**2, l0, 1])]), + (l1, 1, [Matrix([-1 + l1**4, l1**3, l1**2, l1, 1])]), + (l2, 1, [Matrix([-1 + l2**4, l2**3, l2**2, l2, 1])]), + (l3, 1, [Matrix([-1 + l3**4, l3**3, l3**2, l3, 1])]), + (l4, 1, [Matrix([-1 + l4**4, l4**3, l4**2, l4, 1])]), + ] + assert dom_eigenvects_to_sympy([], algebraic_eigenvects, Matrix) == sympy_eigenvects diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_fflu.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_fflu.py new file mode 100644 index 0000000000000000000000000000000000000000..0a4676ce0c3ee2d495b7011ddc48db8c8c40648b --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_fflu.py @@ -0,0 +1,301 @@ +from sympy.polys.matrices import DomainMatrix, DM +from sympy.polys.domains import ZZ, QQ +from sympy import Matrix +import pytest + + +FFLU_EXAMPLES = [ + ( + 'zz_2x3', + DM([[1, 2, 3], [4, 5, 6]], ZZ), + DM([[1, 0], [0, 1]], ZZ), + DM([[1, 0], [4, -3]], ZZ), + DM([[1, 0], [0, -3]], ZZ), + DM([[1, 2, 3], [0, -3, -6]], ZZ), + ), + + ( + 'zz_2x2', + DM([[4, 3], [6, 3]], ZZ), + DM([[1, 0], [0, 1]], ZZ), + DM([[1, 0], [6, -6]], ZZ), + DM([[4, 0], [0, -3]], ZZ), + DM([[4, 3], [0, -3]], ZZ), + ), + + ( + 'zz_3x2', + DM([[1, 2], [3, 4], [5, 6]], ZZ), + DM([[1, 0, 0], [0, 1, 0], [0, 0, 1]], ZZ), + DM([[1, 0, 0], [3, 1, 0], [5, 2, 1]], ZZ), + DM([[1, 0], [0, -2]], ZZ), + DM([[1, 2], [0, -2], [0, 0]], ZZ), + ), + + ( + 'zz_3x3', + DM([[1, 2, 3], [4, 5, 6], [7, 8, 9]], ZZ), + DM([[1, 0, 0], [0, 1, 0], [0, 0, 1]], ZZ), + DM([[1, 0, 0], [4, 1, 0], [7, 2, 1]], ZZ), + DM([[1, 0, 0], [0, -3, 0], [0, 0, 0]], ZZ), + DM([[1, 2, 3], [0, -3, -6], [0, 0, 0]], ZZ), + ), + + ( + 'zz_zero', + DM([[0, 0, 0], [0, 0, 0], [0, 0, 0]], ZZ), + DM([[1, 0, 0], [0, 1, 0], [0, 0, 1]], ZZ), + DM([[1, 0, 0], [0, 1, 0], [0, 0, 1]], ZZ), + DM([[0, 0, 0], [0, 0, 0], [0, 0, 0]], ZZ), + DM([[0, 0, 0], [0, 0, 0], [0, 0, 0]], ZZ), + ), + + ( + 'zz_empty', + DM([], ZZ), + DM([], ZZ), + DM([], ZZ), + DM([], ZZ), + DM([], ZZ), + ), + + ( + 'zz_empty_0x2', + DomainMatrix([], (0, 2), ZZ), + DomainMatrix([], (0, 0), ZZ), + DomainMatrix([], (0, 0), ZZ), + DomainMatrix([], (0, 0), ZZ), + DomainMatrix([], (0, 2), ZZ) + ), + + ( + + 'zz_empty_2x0', + DomainMatrix([[], []], (2, 0), ZZ), + DomainMatrix.eye((2, 2), ZZ), + DomainMatrix.eye((2, 2), ZZ), + DomainMatrix.eye((2, 2), ZZ), + DomainMatrix([[], []], (2, 0), ZZ) + + ), + + ( + 'zz_negative', + DM([[-1, -2], [-3, -4]], ZZ), + DM([[1, 0], [0, 1]], ZZ), + DM([[-1, 0], [-3, -2]], ZZ), + DM([[-1, 0], [0, 2]], ZZ), + DM([[-1, -2], [0, -2]], ZZ), + ), + + ( + 'zz_mixed_signs', + DM([[1, -2], [-3, 4]], ZZ), + DM([[1, 0], [0, 1]], ZZ), + DM([[1, 0], [-3, 1]], ZZ), + DM([[1, 0], [0, -2]], ZZ), + DM([[1, -2], [0, -2]], ZZ), + ), + + ( + 'zz_upper_triangular', + DM([[1, 2, 3], [0, 4, 5], [0, 0, 6]], ZZ), + DM([[1, 0, 0], [0, 1, 0], [0, 0, 1]], ZZ), + DM([[1, 0, 0], [0, 4, 0], [0, 0, 24]], ZZ), + DM([[1, 0, 0], [0, 4, 0], [0, 0, 96]], ZZ), + DM([[1, 2, 3], [0, 4, 5], [0, 0, 24]], ZZ), + ), + + ( + 'zz_lower_triangular', + DM([[1, 0, 0], [2, 3, 0], [4, 5, 6]], ZZ), + DM([[1, 0, 0], [0, 1, 0], [0, 0, 1]], ZZ), + DM([[1, 0, 0], [2, 3, 0], [4, 5, 18]], ZZ), + DM([[1, 0, 0], [0, 3, 0], [0, 0, 54]], ZZ), + DM([[1, 0, 0], [0, 3, 0], [0, 0, 18]], ZZ), + ), + + ( + 'zz_diagonal', + DM([[2, 0, 0], [0, 3, 0], [0, 0, 4]], ZZ), + DM([[1, 0, 0], [0, 1, 0], [0, 0, 1]], ZZ), + DM([[2, 0, 0], [0, 6, 0], [0, 0, 24]], ZZ), + DM([[2, 0, 0], [0, 12, 0], [0, 0, 144]], ZZ), + DM([[2, 0, 0], [0, 6, 0], [0, 0, 24]], ZZ) + + ), + + ( + 'rank_deficient_3x3', + DM([[1, 2, 3], [2, 4, 6], [3, 6, 9]], ZZ), + DM([[1, 0, 0], [0, 1, 0], [0, 0, 1]], ZZ), + DM([[1, 0, 0], [2, 1, 0], [3, 0, 1]], ZZ), + DM([[1, 0, 0], [0, 0, 0], [0, 0, 0]], ZZ), + DM([[1, 2, 3], [0, 0, 0], [0, 0, 0]], ZZ), + ), + + ( + 'zz_1x1', + DM([[5]], ZZ), + DM([[1]], ZZ), + DM([[5]], ZZ), + DM([[5]], ZZ), + DM([[5]], ZZ), + ), + + ( + 'zz_nx1_2rows', + DM([[81], [54]], ZZ), + DM([[1, 0], [0, 1]], ZZ), + DM([[81, 0], [54, 81]], ZZ), + DM([[81, 0], [0, 81]], ZZ), + DM([[81], [0]], ZZ), + ), + + ( + 'zz_nx2_3rows', + DM([[2, 7], [7, 45], [25, 84]], ZZ), + DM([[1, 0, 0], [0, 1, 0], [0, 0, 1]], ZZ), + DM([[2, 0, 0], [7, 82, 0], [25, 41, 41]], ZZ), + DM([[2, 0, 0], [0, 82, 0], [0, 0, 41]], ZZ), + DM([[2, 7], [0, 82], [0, 0]], ZZ), + ), + + ( + + 'zz_1x2', + DM([[0, 28]], ZZ), + DM([[1]], ZZ), + DM([[28]], ZZ), + DM([[28]], ZZ), + DM([[0, 28]], ZZ) + ), + + ( + 'zz_nx3_4rows', + DM([[84, 30, 9], [20, 59, 13], [53, 46, 81], [63, 48, 29]], ZZ), + DM([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]], ZZ), + DM([[84, 0, 0, 0], [20, 365904, 0, 0], [53, 303411, 303411, 0], [63, 303411, 303411, 303411]], ZZ), + DM([[84, 0, 0, 0], [0, 365904, 0, 0], [0, 0, 1321658316, 0], [0, 0, 0, 303411]], ZZ), + DM([[84, 30, 9], [0, 365904, 13], [0, 0, 1321658316], [0, 0, 0]], ZZ), + ), + + ( + 'fflu_row_swap', + DM([[0, 1, 2], [3, 4, 5], [6, 7, 8]], ZZ), + DM([[0, 1, 0], [1, 0, 0], [0, 0, 1]], ZZ), + DM([[3, 0, 0], [0, 3, 0], [6, -3, 1]], ZZ), + DM([[3, 0, 0], [0, 9, 0], [0, 0, 3]], ZZ), + DM([[3, 4, 5], [0, 3, 6], [0, 0, 0]], ZZ) + ), +] + + +def _check_fflu(A, P, L, D, U): + P_field = P.to_field().to_dense() + L_field = L.to_field().to_dense() + D_field = D.to_field().to_dense() + U_field = U.to_field().to_dense() + m, n = A.shape + assert P_field.shape == (m, m) + assert L_field.shape == (m, m) + assert D_field.shape == (m, m) + assert U_field.shape == (m, n) + assert L_field.is_lower + assert D_field.is_diagonal + di, d = D.inv_den() + assert P.matmul(A).rmul(d) == L.matmul(di).matmul(U) + assert U_field.is_upper + + +def _to_DM(A, ans): + if isinstance(A, DomainMatrix): + return A + elif isinstance(A, Matrix): + return A.to_DM(ans.domain) + return DomainMatrix(A.to_list(), A.shape, A.domain) + + +def _check_fflu_result(result, A, P_ans, L_ans, D_ans, U_ans): + P, L, D, U = result + P = _to_DM(P, P_ans) + L = _to_DM(L, L_ans) + D = _to_DM(D, D_ans) + U = _to_DM(U, U_ans) + A = _to_DM(A, P_ans) + m, n = A.shape + assert P.shape == (m, m) + assert L.shape == (m, m) + assert D.shape == (m, m) + assert U.shape == (m, n) + assert L.is_lower + assert D.is_diagonal + di, d = D.inv_den() + assert P.matmul(A).rmul(d) == L.matmul(di).matmul(U) + assert U.is_upper + + +@pytest.mark.parametrize('name, A, P_ans, L_ans, D_ans, U_ans', FFLU_EXAMPLES) +def test_dm_dense_fflu(name, A, P_ans, L_ans, D_ans, U_ans): + A = A.to_dense() + _check_fflu_result(A.fflu(), A, P_ans, L_ans, D_ans, U_ans) + + +@pytest.mark.parametrize('name, A, P_ans, L_ans, D_ans, U_ans', FFLU_EXAMPLES) +def test_dm_sparse_fflu(name, A, P_ans, L_ans, D_ans, U_ans): + A = A.to_sparse() + _check_fflu_result(A.fflu(), A, P_ans, L_ans, D_ans, U_ans) + + +@pytest.mark.parametrize('name, A, P_ans, L_ans, D_ans, U_ans', FFLU_EXAMPLES) +def test_ddm_fflu(name, A, P_ans, L_ans, D_ans, U_ans): + A = A.to_ddm() + _check_fflu_result(A.fflu(), A, P_ans, L_ans, D_ans, U_ans) + + +@pytest.mark.parametrize('name, A, P_ans, L_ans, D_ans, U_ans', FFLU_EXAMPLES) +def test_sdm_fflu(name, A, P_ans, L_ans, D_ans, U_ans): + A = A.to_sdm() + _check_fflu_result(A.fflu(), A, P_ans, L_ans, D_ans, U_ans) + + +@pytest.mark.parametrize('name, A, P_ans, L_ans, D_ans, U_ans', FFLU_EXAMPLES) +def test_dfm_fflu(name, A, P_ans, L_ans, D_ans, U_ans): + pytest.importorskip('flint') + if A.domain not in (ZZ, QQ) and not A.domain.is_FF: + pytest.skip("Domain not supported by DFM") + A = A.to_dfm() + _check_fflu_result(A.fflu(), A, P_ans, L_ans, D_ans, U_ans) + + +def test_fflu_empty_matrix(): + A = DomainMatrix([], (0, 0), ZZ) + P, L, D, U = A.fflu() + assert P.shape == (0, 0) + assert L.shape == (0, 0) + assert D.shape == (0, 0) + assert U.shape == (0, 0) + + +def test_fflu_properties(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]], (2, 2), ZZ) + P, L, D, U = A.fflu() + assert P.shape == (2, 2) + assert L.shape == (2, 2) + assert D.shape == (2, 2) + assert U.shape == (2, 2) + assert L.is_lower + assert U.is_upper + assert D.is_diagonal + di, d = D.inv_den() + assert P.matmul(A).rmul(d) == L.matmul(di).matmul(U) + + +def test_fflu_rank_deficient(): + A = DomainMatrix([[ZZ(1), ZZ(2)], [ZZ(2), ZZ(4)]], (2, 2), ZZ) + P, L, D, U = A.fflu() + assert P.shape == (2, 2) + assert L.shape == (2, 2) + assert D.shape == (2, 2) + assert U.shape == (2, 2) + assert U.getitem_sympy(1, 1) == 0 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_inverse.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_inverse.py new file mode 100644 index 0000000000000000000000000000000000000000..47c82799324518bd7d1cc2405ade0aa0a5a4f6e9 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_inverse.py @@ -0,0 +1,193 @@ +from sympy import ZZ, Matrix +from sympy.polys.matrices import DM, DomainMatrix +from sympy.polys.matrices.dense import ddm_iinv +from sympy.polys.matrices.exceptions import DMNonInvertibleMatrixError +from sympy.matrices.exceptions import NonInvertibleMatrixError + +import pytest +from sympy.testing.pytest import raises +from sympy.core.numbers import all_close + +from sympy.abc import x + + +# Examples are given as adjugate matrix and determinant adj_det should match +# these exactly but inv_den only matches after cancel_denom. + + +INVERSE_EXAMPLES = [ + + ( + 'zz_1', + DomainMatrix([], (0, 0), ZZ), + DomainMatrix([], (0, 0), ZZ), + ZZ(1), + ), + + ( + 'zz_2', + DM([[2]], ZZ), + DM([[1]], ZZ), + ZZ(2), + ), + + ( + 'zz_3', + DM([[2, 0], + [0, 2]], ZZ), + DM([[2, 0], + [0, 2]], ZZ), + ZZ(4), + ), + + ( + 'zz_4', + DM([[1, 2], + [3, 4]], ZZ), + DM([[ 4, -2], + [-3, 1]], ZZ), + ZZ(-2), + ), + + ( + 'zz_5', + DM([[2, 2, 0], + [0, 2, 2], + [0, 0, 2]], ZZ), + DM([[4, -4, 4], + [0, 4, -4], + [0, 0, 4]], ZZ), + ZZ(8), + ), + + ( + 'zz_6', + DM([[1, 2, 3], + [4, 5, 6], + [7, 8, 9]], ZZ), + DM([[-3, 6, -3], + [ 6, -12, 6], + [-3, 6, -3]], ZZ), + ZZ(0), + ), +] + + +@pytest.mark.parametrize('name, A, A_inv, den', INVERSE_EXAMPLES) +def test_Matrix_inv(name, A, A_inv, den): + + def _check(**kwargs): + if den != 0: + assert A.inv(**kwargs) == A_inv + else: + raises(NonInvertibleMatrixError, lambda: A.inv(**kwargs)) + + K = A.domain + A = A.to_Matrix() + A_inv = A_inv.to_Matrix() / K.to_sympy(den) + _check() + for method in ['GE', 'LU', 'ADJ', 'CH', 'LDL', 'QR']: + _check(method=method) + + +@pytest.mark.parametrize('name, A, A_inv, den', INVERSE_EXAMPLES) +def test_dm_inv_den(name, A, A_inv, den): + if den != 0: + A_inv_f, den_f = A.inv_den() + assert A_inv_f.cancel_denom(den_f) == A_inv.cancel_denom(den) + else: + raises(DMNonInvertibleMatrixError, lambda: A.inv_den()) + + +@pytest.mark.parametrize('name, A, A_inv, den', INVERSE_EXAMPLES) +def test_dm_inv(name, A, A_inv, den): + A = A.to_field() + if den != 0: + A_inv = A_inv.to_field() / den + assert A.inv() == A_inv + else: + raises(DMNonInvertibleMatrixError, lambda: A.inv()) + + +@pytest.mark.parametrize('name, A, A_inv, den', INVERSE_EXAMPLES) +def test_ddm_inv(name, A, A_inv, den): + A = A.to_field().to_ddm() + if den != 0: + A_inv = (A_inv.to_field() / den).to_ddm() + assert A.inv() == A_inv + else: + raises(DMNonInvertibleMatrixError, lambda: A.inv()) + + +@pytest.mark.parametrize('name, A, A_inv, den', INVERSE_EXAMPLES) +def test_sdm_inv(name, A, A_inv, den): + A = A.to_field().to_sdm() + if den != 0: + A_inv = (A_inv.to_field() / den).to_sdm() + assert A.inv() == A_inv + else: + raises(DMNonInvertibleMatrixError, lambda: A.inv()) + + +@pytest.mark.parametrize('name, A, A_inv, den', INVERSE_EXAMPLES) +def test_dense_ddm_iinv(name, A, A_inv, den): + A = A.to_field().to_ddm().copy() + K = A.domain + A_result = A.copy() + if den != 0: + A_inv = (A_inv.to_field() / den).to_ddm() + ddm_iinv(A_result, A, K) + assert A_result == A_inv + else: + raises(DMNonInvertibleMatrixError, lambda: ddm_iinv(A_result, A, K)) + + +@pytest.mark.parametrize('name, A, A_inv, den', INVERSE_EXAMPLES) +def test_Matrix_adjugate(name, A, A_inv, den): + A = A.to_Matrix() + A_inv = A_inv.to_Matrix() + assert A.adjugate() == A_inv + for method in ["bareiss", "berkowitz", "bird", "laplace", "lu"]: + assert A.adjugate(method=method) == A_inv + + +@pytest.mark.parametrize('name, A, A_inv, den', INVERSE_EXAMPLES) +def test_dm_adj_det(name, A, A_inv, den): + assert A.adj_det() == (A_inv, den) + + +def test_inverse_inexact(): + + M = Matrix([[x-0.3, -0.06, -0.22], + [-0.46, x-0.48, -0.41], + [-0.14, -0.39, x-0.64]]) + + Mn = Matrix([[1.0*x**2 - 1.12*x + 0.1473, 0.06*x + 0.0474, 0.22*x - 0.081], + [0.46*x - 0.237, 1.0*x**2 - 0.94*x + 0.1612, 0.41*x - 0.0218], + [0.14*x + 0.1122, 0.39*x - 0.1086, 1.0*x**2 - 0.78*x + 0.1164]]) + + d = 1.0*x**3 - 1.42*x**2 + 0.4249*x - 0.0546540000000002 + + Mi = Mn / d + + M_dm = M.to_DM() + M_dmd = M_dm.to_dense() + M_dm_num, M_dm_den = M_dm.inv_den() + M_dmd_num, M_dmd_den = M_dmd.inv_den() + + # XXX: We don't check M_dm().to_field().inv() which currently uses division + # and produces a more complicate result from gcd cancellation failing. + # DomainMatrix.inv() over RR(x) should be changed to clear denominators and + # use DomainMatrix.inv_den(). + + Minvs = [ + M.inv(), + (M_dm_num.to_field() / M_dm_den).to_Matrix(), + (M_dmd_num.to_field() / M_dmd_den).to_Matrix(), + M_dm_num.to_Matrix() / M_dm_den.as_expr(), + M_dmd_num.to_Matrix() / M_dmd_den.as_expr(), + ] + + for Minv in Minvs: + for Mi1, Mi2 in zip(Minv.flat(), Mi.flat()): + assert all_close(Mi2, Mi1) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_linsolve.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_linsolve.py new file mode 100644 index 0000000000000000000000000000000000000000..25300ef2cb4792e4424c9c15c0bbbc313ce062e6 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_linsolve.py @@ -0,0 +1,112 @@ +# +# test_linsolve.py +# +# Test the internal implementation of linsolve. +# + +from sympy.testing.pytest import raises + +from sympy.core.numbers import I +from sympy.core.relational import Eq +from sympy.core.singleton import S +from sympy.abc import x, y, z + +from sympy.polys.matrices.linsolve import _linsolve +from sympy.polys.solvers import PolyNonlinearError + + +def test__linsolve(): + assert _linsolve([], [x]) == {x:x} + assert _linsolve([S.Zero], [x]) == {x:x} + assert _linsolve([x-1,x-2], [x]) is None + assert _linsolve([x-1], [x]) == {x:1} + assert _linsolve([x-1, y], [x, y]) == {x:1, y:S.Zero} + assert _linsolve([2*I], [x]) is None + raises(PolyNonlinearError, lambda: _linsolve([x*(1 + x)], [x])) + + +def test__linsolve_float(): + + # This should give the exact answer: + eqs = [ + y - x, + y - 0.0216 * x + ] + # Should _linsolve return floats here? + sol = {x:0, y:0} + assert _linsolve(eqs, (x, y)) == sol + + # Other cases should be close to eps + + def all_close(sol1, sol2, eps=1e-15): + close = lambda a, b: abs(a - b) < eps + assert sol1.keys() == sol2.keys() + return all(close(sol1[s], sol2[s]) for s in sol1) + + eqs = [ + 0.8*x + 0.8*z + 0.2, + 0.9*x + 0.7*y + 0.2*z + 0.9, + 0.7*x + 0.2*y + 0.2*z + 0.5 + ] + sol_exact = {x:-29/42, y:-11/21, z:37/84} + sol_linsolve = _linsolve(eqs, [x,y,z]) + assert all_close(sol_exact, sol_linsolve) + + eqs = [ + 0.9*x + 0.3*y + 0.4*z + 0.6, + 0.6*x + 0.9*y + 0.1*z + 0.7, + 0.4*x + 0.6*y + 0.9*z + 0.5 + ] + sol_exact = {x:-88/175, y:-46/105, z:-1/25} + sol_linsolve = _linsolve(eqs, [x,y,z]) + assert all_close(sol_exact, sol_linsolve) + + eqs = [ + 0.4*x + 0.3*y + 0.6*z + 0.7, + 0.4*x + 0.3*y + 0.9*z + 0.9, + 0.7*x + 0.9*y, + ] + sol_exact = {x:-9/5, y:7/5, z:-2/3} + sol_linsolve = _linsolve(eqs, [x,y,z]) + assert all_close(sol_exact, sol_linsolve) + + eqs = [ + x*(0.7 + 0.6*I) + y*(0.4 + 0.7*I) + z*(0.9 + 0.1*I) + 0.5, + 0.2*I*x + 0.2*I*y + z*(0.9 + 0.2*I) + 0.1, + x*(0.9 + 0.7*I) + y*(0.9 + 0.7*I) + z*(0.9 + 0.4*I) + 0.4, + ] + sol_exact = { + x:-6157/7995 - 411/5330*I, + y:8519/15990 + 1784/7995*I, + z:-34/533 + 107/1599*I, + } + sol_linsolve = _linsolve(eqs, [x,y,z]) + assert all_close(sol_exact, sol_linsolve) + + # XXX: This system for x and y over RR(z) is problematic. + # + # eqs = [ + # x*(0.2*z + 0.9) + y*(0.5*z + 0.8) + 0.6, + # 0.1*x*z + y*(0.1*z + 0.6) + 0.9, + # ] + # + # linsolve(eqs, [x, y]) + # The solution for x comes out as + # + # -3.9e-5*z**2 - 3.6e-5*z - 8.67361737988404e-20 + # x = ---------------------------------------------- + # 3.0e-6*z**3 - 1.3e-5*z**2 - 5.4e-5*z + # + # The 8e-20 in the numerator should be zero which would allow z to cancel + # from top and bottom. It should be possible to avoid this somehow because + # the inverse of the matrix only has a quadratic factor (the determinant) + # in the denominator. + + +def test__linsolve_deprecated(): + raises(PolyNonlinearError, lambda: + _linsolve([Eq(x**2, x**2 + y)], [x, y])) + raises(PolyNonlinearError, lambda: + _linsolve([(x + y)**2 - x**2], [x])) + raises(PolyNonlinearError, lambda: + _linsolve([Eq((x + y)**2, x**2)], [x])) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_lll.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_lll.py new file mode 100644 index 0000000000000000000000000000000000000000..2cf91a00703532f02d763656d6117018fbc496cf --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_lll.py @@ -0,0 +1,145 @@ +from sympy.polys.domains import ZZ, QQ +from sympy.polys.matrices import DM +from sympy.polys.matrices.domainmatrix import DomainMatrix +from sympy.polys.matrices.exceptions import DMRankError, DMValueError, DMShapeError, DMDomainError +from sympy.polys.matrices.lll import _ddm_lll, ddm_lll, ddm_lll_transform +from sympy.testing.pytest import raises + + +def test_lll(): + normal_test_data = [ + ( + DM([[1, 0, 0, 0, -20160], + [0, 1, 0, 0, 33768], + [0, 0, 1, 0, 39578], + [0, 0, 0, 1, 47757]], ZZ), + DM([[10, -3, -2, 8, -4], + [3, -9, 8, 1, -11], + [-3, 13, -9, -3, -9], + [-12, -7, -11, 9, -1]], ZZ) + ), + ( + DM([[20, 52, 3456], + [14, 31, -1], + [34, -442, 0]], ZZ), + DM([[14, 31, -1], + [188, -101, -11], + [236, 13, 3443]], ZZ) + ), + ( + DM([[34, -1, -86, 12], + [-54, 34, 55, 678], + [23, 3498, 234, 6783], + [87, 49, 665, 11]], ZZ), + DM([[34, -1, -86, 12], + [291, 43, 149, 83], + [-54, 34, 55, 678], + [-189, 3077, -184, -223]], ZZ) + ) + ] + delta = QQ(5, 6) + for basis_dm, reduced_dm in normal_test_data: + reduced = _ddm_lll(basis_dm.rep.to_ddm(), delta=delta)[0] + assert reduced == reduced_dm.rep.to_ddm() + + reduced = ddm_lll(basis_dm.rep.to_ddm(), delta=delta) + assert reduced == reduced_dm.rep.to_ddm() + + reduced, transform = _ddm_lll(basis_dm.rep.to_ddm(), delta=delta, return_transform=True) + assert reduced == reduced_dm.rep.to_ddm() + assert transform.matmul(basis_dm.rep.to_ddm()) == reduced_dm.rep.to_ddm() + + reduced, transform = ddm_lll_transform(basis_dm.rep.to_ddm(), delta=delta) + assert reduced == reduced_dm.rep.to_ddm() + assert transform.matmul(basis_dm.rep.to_ddm()) == reduced_dm.rep.to_ddm() + + reduced = basis_dm.rep.lll(delta=delta) + assert reduced == reduced_dm.rep + + reduced, transform = basis_dm.rep.lll_transform(delta=delta) + assert reduced == reduced_dm.rep + assert transform.matmul(basis_dm.rep) == reduced_dm.rep + + reduced = basis_dm.rep.to_sdm().lll(delta=delta) + assert reduced == reduced_dm.rep.to_sdm() + + reduced, transform = basis_dm.rep.to_sdm().lll_transform(delta=delta) + assert reduced == reduced_dm.rep.to_sdm() + assert transform.matmul(basis_dm.rep.to_sdm()) == reduced_dm.rep.to_sdm() + + reduced = basis_dm.lll(delta=delta) + assert reduced == reduced_dm + + reduced, transform = basis_dm.lll_transform(delta=delta) + assert reduced == reduced_dm + assert transform.matmul(basis_dm) == reduced_dm + + +def test_lll_linear_dependent(): + linear_dependent_test_data = [ + DM([[0, -1, -2, -3], + [1, 0, -1, -2], + [2, 1, 0, -1], + [3, 2, 1, 0]], ZZ), + DM([[1, 0, 0, 1], + [0, 1, 0, 1], + [0, 0, 1, 1], + [1, 2, 3, 6]], ZZ), + DM([[3, -5, 1], + [4, 6, 0], + [10, -4, 2]], ZZ) + ] + for not_basis in linear_dependent_test_data: + raises(DMRankError, lambda: _ddm_lll(not_basis.rep.to_ddm())) + raises(DMRankError, lambda: ddm_lll(not_basis.rep.to_ddm())) + raises(DMRankError, lambda: not_basis.rep.lll()) + raises(DMRankError, lambda: not_basis.rep.to_sdm().lll()) + raises(DMRankError, lambda: not_basis.lll()) + raises(DMRankError, lambda: _ddm_lll(not_basis.rep.to_ddm(), return_transform=True)) + raises(DMRankError, lambda: ddm_lll_transform(not_basis.rep.to_ddm())) + raises(DMRankError, lambda: not_basis.rep.lll_transform()) + raises(DMRankError, lambda: not_basis.rep.to_sdm().lll_transform()) + raises(DMRankError, lambda: not_basis.lll_transform()) + + +def test_lll_wrong_delta(): + dummy_matrix = DomainMatrix.ones((3, 3), ZZ) + for wrong_delta in [QQ(-1, 4), QQ(0, 1), QQ(1, 4), QQ(1, 1), QQ(100, 1)]: + raises(DMValueError, lambda: _ddm_lll(dummy_matrix.rep, delta=wrong_delta)) + raises(DMValueError, lambda: ddm_lll(dummy_matrix.rep, delta=wrong_delta)) + raises(DMValueError, lambda: dummy_matrix.rep.lll(delta=wrong_delta)) + raises(DMValueError, lambda: dummy_matrix.rep.to_sdm().lll(delta=wrong_delta)) + raises(DMValueError, lambda: dummy_matrix.lll(delta=wrong_delta)) + raises(DMValueError, lambda: _ddm_lll(dummy_matrix.rep, delta=wrong_delta, return_transform=True)) + raises(DMValueError, lambda: ddm_lll_transform(dummy_matrix.rep, delta=wrong_delta)) + raises(DMValueError, lambda: dummy_matrix.rep.lll_transform(delta=wrong_delta)) + raises(DMValueError, lambda: dummy_matrix.rep.to_sdm().lll_transform(delta=wrong_delta)) + raises(DMValueError, lambda: dummy_matrix.lll_transform(delta=wrong_delta)) + + +def test_lll_wrong_shape(): + wrong_shape_matrix = DomainMatrix.ones((4, 3), ZZ) + raises(DMShapeError, lambda: _ddm_lll(wrong_shape_matrix.rep)) + raises(DMShapeError, lambda: ddm_lll(wrong_shape_matrix.rep)) + raises(DMShapeError, lambda: wrong_shape_matrix.rep.lll()) + raises(DMShapeError, lambda: wrong_shape_matrix.rep.to_sdm().lll()) + raises(DMShapeError, lambda: wrong_shape_matrix.lll()) + raises(DMShapeError, lambda: _ddm_lll(wrong_shape_matrix.rep, return_transform=True)) + raises(DMShapeError, lambda: ddm_lll_transform(wrong_shape_matrix.rep)) + raises(DMShapeError, lambda: wrong_shape_matrix.rep.lll_transform()) + raises(DMShapeError, lambda: wrong_shape_matrix.rep.to_sdm().lll_transform()) + raises(DMShapeError, lambda: wrong_shape_matrix.lll_transform()) + + +def test_lll_wrong_domain(): + wrong_domain_matrix = DomainMatrix.ones((3, 3), QQ) + raises(DMDomainError, lambda: _ddm_lll(wrong_domain_matrix.rep)) + raises(DMDomainError, lambda: ddm_lll(wrong_domain_matrix.rep)) + raises(DMDomainError, lambda: wrong_domain_matrix.rep.lll()) + raises(DMDomainError, lambda: wrong_domain_matrix.rep.to_sdm().lll()) + raises(DMDomainError, lambda: wrong_domain_matrix.lll()) + raises(DMDomainError, lambda: _ddm_lll(wrong_domain_matrix.rep, return_transform=True)) + raises(DMDomainError, lambda: ddm_lll_transform(wrong_domain_matrix.rep)) + raises(DMDomainError, lambda: wrong_domain_matrix.rep.lll_transform()) + raises(DMDomainError, lambda: wrong_domain_matrix.rep.to_sdm().lll_transform()) + raises(DMDomainError, lambda: wrong_domain_matrix.lll_transform()) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_normalforms.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_normalforms.py new file mode 100644 index 0000000000000000000000000000000000000000..542d9064aea204759158578a4bfbbf5acbb06db3 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_normalforms.py @@ -0,0 +1,156 @@ +from sympy.testing.pytest import raises + +from sympy.core.symbol import Symbol +from sympy.polys.matrices.normalforms import ( + invariant_factors, + smith_normal_form, + smith_normal_decomp, + is_smith_normal_form, + hermite_normal_form, + _hermite_normal_form, + _hermite_normal_form_modulo_D +) +from sympy.polys.domains import ZZ, QQ +from sympy.polys.matrices import DomainMatrix, DM +from sympy.polys.matrices.exceptions import DMDomainError, DMShapeError + + +def test_is_smith_normal_form(): + + snf_examples = [ + DM([[0, 0], [0, 0]], ZZ), + DM([[1, 0], [0, 0]], ZZ), + DM([[1, 0], [0, 1]], ZZ), + DM([[1, 0], [0, 2]], ZZ), + ] + + non_snf_examples = [ + DM([[0, 1], [0, 0]], ZZ), + DM([[0, 0], [0, 1]], ZZ), + DM([[2, 0], [0, 3]], ZZ), + ] + + for m in snf_examples: + assert is_smith_normal_form(m) is True + + for m in non_snf_examples: + assert is_smith_normal_form(m) is False + + +def test_smith_normal(): + + m = DM([ + [12, 6, 4, 8], + [3, 9, 6, 12], + [2, 16, 14, 28], + [20, 10, 10, 20]], ZZ) + + smf = DM([ + [1, 0, 0, 0], + [0, 10, 0, 0], + [0, 0, 30, 0], + [0, 0, 0, 0]], ZZ) + + s = DM([ + [0, 1, -1, 0], + [1, -4, 0, 0], + [0, -2, 3, 0], + [-2, 2, -1, 1]], ZZ) + + t = DM([ + [1, 1, 10, 0], + [0, -1, -2, 0], + [0, 1, 3, -2], + [0, 0, 0, 1]], ZZ) + + assert smith_normal_form(m).to_dense() == smf + assert smith_normal_decomp(m) == (smf, s, t) + assert is_smith_normal_form(smf) + assert smf == s * m * t + + m00 = DomainMatrix.zeros((0, 0), ZZ).to_dense() + m01 = DomainMatrix.zeros((0, 1), ZZ).to_dense() + m10 = DomainMatrix.zeros((1, 0), ZZ).to_dense() + i11 = DM([[1]], ZZ) + + assert smith_normal_form(m00) == m00.to_sparse() + assert smith_normal_form(m01) == m01.to_sparse() + assert smith_normal_form(m10) == m10.to_sparse() + assert smith_normal_form(i11) == i11.to_sparse() + + assert smith_normal_decomp(m00) == (m00, m00, m00) + assert smith_normal_decomp(m01) == (m01, m00, i11) + assert smith_normal_decomp(m10) == (m10, i11, m00) + assert smith_normal_decomp(i11) == (i11, i11, i11) + + x = Symbol('x') + m = DM([[x-1, 1, -1], + [ 0, x, -1], + [ 0, -1, x]], QQ[x]) + dx = m.domain.gens[0] + assert invariant_factors(m) == (1, dx-1, dx**2-1) + + zr = DomainMatrix([], (0, 2), ZZ) + zc = DomainMatrix([[], []], (2, 0), ZZ) + assert smith_normal_form(zr).to_dense() == zr + assert smith_normal_form(zc).to_dense() == zc + + assert smith_normal_form(DM([[2, 4]], ZZ)).to_dense() == DM([[2, 0]], ZZ) + assert smith_normal_form(DM([[0, -2]], ZZ)).to_dense() == DM([[2, 0]], ZZ) + assert smith_normal_form(DM([[0], [-2]], ZZ)).to_dense() == DM([[2], [0]], ZZ) + + assert smith_normal_decomp(DM([[0, -2]], ZZ)) == ( + DM([[2, 0]], ZZ), DM([[-1]], ZZ), DM([[0, 1], [1, 0]], ZZ) + ) + assert smith_normal_decomp(DM([[0], [-2]], ZZ)) == ( + DM([[2], [0]], ZZ), DM([[0, -1], [1, 0]], ZZ), DM([[1]], ZZ) + ) + + m = DM([[3, 0, 0, 0], [0, 0, 0, 0], [0, 0, 2, 0]], ZZ) + snf = DM([[1, 0, 0, 0], [0, 6, 0, 0], [0, 0, 0, 0]], ZZ) + s = DM([[1, 0, 1], [2, 0, 3], [0, 1, 0]], ZZ) + t = DM([[1, -2, 0, 0], [0, 0, 0, 1], [-1, 3, 0, 0], [0, 0, 1, 0]], ZZ) + + assert smith_normal_form(m).to_dense() == snf + assert smith_normal_decomp(m) == (snf, s, t) + assert is_smith_normal_form(snf) + assert snf == s * m * t + + raises(ValueError, lambda: smith_normal_form(DM([[1]], ZZ[x]))) + + +def test_hermite_normal(): + m = DM([[2, 7, 17, 29, 41], [3, 11, 19, 31, 43], [5, 13, 23, 37, 47]], ZZ) + hnf = DM([[1, 0, 0], [0, 2, 1], [0, 0, 1]], ZZ) + assert hermite_normal_form(m) == hnf + assert hermite_normal_form(m, D=ZZ(2)) == hnf + assert hermite_normal_form(m, D=ZZ(2), check_rank=True) == hnf + + m = m.transpose() + hnf = DM([[37, 0, 19], [222, -6, 113], [48, 0, 25], [0, 2, 1], [0, 0, 1]], ZZ) + assert hermite_normal_form(m) == hnf + raises(DMShapeError, lambda: _hermite_normal_form_modulo_D(m, ZZ(96))) + raises(DMDomainError, lambda: _hermite_normal_form_modulo_D(m, QQ(96))) + + m = DM([[8, 28, 68, 116, 164], [3, 11, 19, 31, 43], [5, 13, 23, 37, 47]], ZZ) + hnf = DM([[4, 0, 0], [0, 2, 1], [0, 0, 1]], ZZ) + assert hermite_normal_form(m) == hnf + assert hermite_normal_form(m, D=ZZ(8)) == hnf + assert hermite_normal_form(m, D=ZZ(8), check_rank=True) == hnf + + m = DM([[10, 8, 6, 30, 2], [45, 36, 27, 18, 9], [5, 4, 3, 2, 1]], ZZ) + hnf = DM([[26, 2], [0, 9], [0, 1]], ZZ) + assert hermite_normal_form(m) == hnf + + m = DM([[2, 7], [0, 0], [0, 0]], ZZ) + hnf = DM([[1], [0], [0]], ZZ) + assert hermite_normal_form(m) == hnf + + m = DM([[-2, 1], [0, 1]], ZZ) + hnf = DM([[2, 1], [0, 1]], ZZ) + assert hermite_normal_form(m) == hnf + + m = DomainMatrix([[QQ(1)]], (1, 1), QQ) + raises(DMDomainError, lambda: hermite_normal_form(m)) + raises(DMDomainError, lambda: _hermite_normal_form(m)) + raises(DMDomainError, lambda: _hermite_normal_form_modulo_D(m, ZZ(1))) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_nullspace.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_nullspace.py new file mode 100644 index 0000000000000000000000000000000000000000..dbb025b7dc9dff31bc97d86e175147ffede5a7e3 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_nullspace.py @@ -0,0 +1,209 @@ +from sympy import ZZ, Matrix +from sympy.polys.matrices import DM, DomainMatrix +from sympy.polys.matrices.ddm import DDM +from sympy.polys.matrices.sdm import SDM + +import pytest + +zeros = lambda shape, K: DomainMatrix.zeros(shape, K).to_dense() +eye = lambda n, K: DomainMatrix.eye(n, K).to_dense() + + +# +# DomainMatrix.nullspace can have a divided answer or can return an undivided +# uncanonical answer. The uncanonical answer is not unique but we can make it +# unique by making it primitive (remove gcd). The tests here all show the +# primitive form. We test two things: +# +# A.nullspace().primitive()[1] == answer. +# A.nullspace(divide_last=True) == _divide_last(answer). +# +# The nullspace as returned by DomainMatrix and related classes is the +# transpose of the nullspace as returned by Matrix. Matrix returns a list of +# of column vectors whereas DomainMatrix returns a matrix whose rows are the +# nullspace vectors. +# + + +NULLSPACE_EXAMPLES = [ + + ( + 'zz_1', + DM([[ 1, 2, 3]], ZZ), + DM([[-2, 1, 0], + [-3, 0, 1]], ZZ), + ), + + ( + 'zz_2', + zeros((0, 0), ZZ), + zeros((0, 0), ZZ), + ), + + ( + 'zz_3', + zeros((2, 0), ZZ), + zeros((0, 0), ZZ), + ), + + ( + 'zz_4', + zeros((0, 2), ZZ), + eye(2, ZZ), + ), + + ( + 'zz_5', + zeros((2, 2), ZZ), + eye(2, ZZ), + ), + + ( + 'zz_6', + DM([[1, 2], + [3, 4]], ZZ), + zeros((0, 2), ZZ), + ), + + ( + 'zz_7', + DM([[1, 1], + [1, 1]], ZZ), + DM([[-1, 1]], ZZ), + ), + + ( + 'zz_8', + DM([[1], + [1]], ZZ), + zeros((0, 1), ZZ), + ), + + ( + 'zz_9', + DM([[1, 1]], ZZ), + DM([[-1, 1]], ZZ), + ), + + ( + 'zz_10', + DM([[0, 0, 0, 0, 0, 1, 0, 0, 0, 0], + [1, 0, 0, 0, 0, 0, 1, 0, 0, 0], + [0, 1, 0, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 0, 1, 0, 0, 0, 0, 1, 0], + [0, 0, 0, 0, 1, 0, 0, 0, 0, 1]], ZZ), + DM([[ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], + [-1, 0, 0, 0, 0, 0, 1, 0, 0, 0], + [ 0, -1, 0, 0, 0, 0, 0, 1, 0, 0], + [ 0, 0, 0, -1, 0, 0, 0, 0, 1, 0], + [ 0, 0, 0, 0, -1, 0, 0, 0, 0, 1]], ZZ), + ), + +] + + +def _to_DM(A, ans): + """Convert the answer to DomainMatrix.""" + if isinstance(A, DomainMatrix): + return A.to_dense() + elif isinstance(A, DDM): + return DomainMatrix(list(A), A.shape, A.domain).to_dense() + elif isinstance(A, SDM): + return DomainMatrix(dict(A), A.shape, A.domain).to_dense() + else: + assert False # pragma: no cover + + +def _divide_last(null): + """Normalize the nullspace by the rightmost non-zero entry.""" + null = null.to_field() + + if null.is_zero_matrix: + return null + + rows = [] + for i in range(null.shape[0]): + for j in reversed(range(null.shape[1])): + if null[i, j]: + rows.append(null[i, :] / null[i, j]) + break + else: + assert False # pragma: no cover + + return DomainMatrix.vstack(*rows) + + +def _check_primitive(null, null_ans): + """Check that the primitive of the answer matches.""" + null = _to_DM(null, null_ans) + cont, null_prim = null.primitive() + assert null_prim == null_ans + + +def _check_divided(null, null_ans): + """Check the divided answer.""" + null = _to_DM(null, null_ans) + null_ans_norm = _divide_last(null_ans) + assert null == null_ans_norm + + +@pytest.mark.parametrize('name, A, A_null', NULLSPACE_EXAMPLES) +def test_Matrix_nullspace(name, A, A_null): + A = A.to_Matrix() + + A_null_cols = A.nullspace() + + # We have to patch up the case where the nullspace is empty + if A_null_cols: + A_null_found = Matrix.hstack(*A_null_cols) + else: + A_null_found = Matrix.zeros(A.cols, 0) + + A_null_found = A_null_found.to_DM().to_field().to_dense() + + # The Matrix result is the transpose of DomainMatrix result. + A_null_found = A_null_found.transpose() + + _check_divided(A_null_found, A_null) + + +@pytest.mark.parametrize('name, A, A_null', NULLSPACE_EXAMPLES) +def test_dm_dense_nullspace(name, A, A_null): + A = A.to_field().to_dense() + A_null_found = A.nullspace(divide_last=True) + _check_divided(A_null_found, A_null) + + +@pytest.mark.parametrize('name, A, A_null', NULLSPACE_EXAMPLES) +def test_dm_sparse_nullspace(name, A, A_null): + A = A.to_field().to_sparse() + A_null_found = A.nullspace(divide_last=True) + _check_divided(A_null_found, A_null) + + +@pytest.mark.parametrize('name, A, A_null', NULLSPACE_EXAMPLES) +def test_ddm_nullspace(name, A, A_null): + A = A.to_field().to_ddm() + A_null_found, _ = A.nullspace() + _check_divided(A_null_found, A_null) + + +@pytest.mark.parametrize('name, A, A_null', NULLSPACE_EXAMPLES) +def test_sdm_nullspace(name, A, A_null): + A = A.to_field().to_sdm() + A_null_found, _ = A.nullspace() + _check_divided(A_null_found, A_null) + + +@pytest.mark.parametrize('name, A, A_null', NULLSPACE_EXAMPLES) +def test_dm_dense_nullspace_fracfree(name, A, A_null): + A = A.to_dense() + A_null_found = A.nullspace() + _check_primitive(A_null_found, A_null) + + +@pytest.mark.parametrize('name, A, A_null', NULLSPACE_EXAMPLES) +def test_dm_sparse_nullspace_fracfree(name, A, A_null): + A = A.to_sparse() + A_null_found = A.nullspace() + _check_primitive(A_null_found, A_null) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_rref.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_rref.py new file mode 100644 index 0000000000000000000000000000000000000000..49def18c8132c0537540163a96bf6cf323c5a85c --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_rref.py @@ -0,0 +1,737 @@ +from sympy import ZZ, QQ, ZZ_I, EX, Matrix, eye, zeros, symbols +from sympy.polys.matrices import DM, DomainMatrix +from sympy.polys.matrices.dense import ddm_irref_den, ddm_irref +from sympy.polys.matrices.ddm import DDM +from sympy.polys.matrices.sdm import SDM, sdm_irref, sdm_rref_den + +import pytest + + +# +# The dense and sparse implementations of rref_den are ddm_irref_den and +# sdm_irref_den. These can give results that differ by some factor and also +# give different results if the order of the rows is changed. The tests below +# show all results on lowest terms as should be returned by cancel_denom. +# +# The EX domain is also a case where the dense and sparse implementations +# can give results in different forms: the results should be equivalent but +# are not canonical because EX does not have a canonical form. +# + + +a, b, c, d = symbols('a, b, c, d') + + +qq_large_1 = DM([ +[ (1,2), (1,3), (1,5), (1,7), (1,11), (1,13), (1,17), (1,19), (1,23), (1,29), (1,31)], +[ (1,37), (1,41), (1,43), (1,47), (1,53), (1,59), (1,61), (1,67), (1,71), (1,73), (1,79)], +[ (1,83), (1,89), (1,97),(1,101),(1,103),(1,107),(1,109),(1,113),(1,127),(1,131),(1,137)], +[(1,139),(1,149),(1,151),(1,157),(1,163),(1,167),(1,173),(1,179),(1,181),(1,191),(1,193)], +[(1,197),(1,199),(1,211),(1,223),(1,227),(1,229),(1,233),(1,239),(1,241),(1,251),(1,257)], +[(1,263),(1,269),(1,271),(1,277),(1,281),(1,283),(1,293),(1,307),(1,311),(1,313),(1,317)], +[(1,331),(1,337),(1,347),(1,349),(1,353),(1,359),(1,367),(1,373),(1,379),(1,383),(1,389)], +[(1,397),(1,401),(1,409),(1,419),(1,421),(1,431),(1,433),(1,439),(1,443),(1,449),(1,457)], +[(1,461),(1,463),(1,467),(1,479),(1,487),(1,491),(1,499),(1,503),(1,509),(1,521),(1,523)], +[(1,541),(1,547),(1,557),(1,563),(1,569),(1,571),(1,577),(1,587),(1,593),(1,599),(1,601)], +[(1,607),(1,613),(1,617),(1,619),(1,631),(1,641),(1,643),(1,647),(1,653),(1,659),(1,661)]], + QQ) + +qq_large_2 = qq_large_1 + 10**100 * DomainMatrix.eye(11, QQ) + + +RREF_EXAMPLES = [ + ( + 'zz_1', + DM([[1, 2, 3]], ZZ), + DM([[1, 2, 3]], ZZ), + ZZ(1), + ), + + ( + 'zz_2', + DomainMatrix([], (0, 0), ZZ), + DomainMatrix([], (0, 0), ZZ), + ZZ(1), + ), + + ( + 'zz_3', + DM([[1, 2], + [3, 4]], ZZ), + DM([[1, 0], + [0, 1]], ZZ), + ZZ(1), + ), + + ( + 'zz_4', + DM([[1, 0], + [3, 4]], ZZ), + DM([[1, 0], + [0, 1]], ZZ), + ZZ(1), + ), + + ( + 'zz_5', + DM([[0, 2], + [3, 4]], ZZ), + DM([[1, 0], + [0, 1]], ZZ), + ZZ(1), + ), + + ( + 'zz_6', + DM([[1, 2, 3], + [4, 5, 6], + [7, 8, 9]], ZZ), + DM([[1, 0, -1], + [0, 1, 2], + [0, 0, 0]], ZZ), + ZZ(1), + ), + + ( + 'zz_7', + DM([[0, 0, 0], + [0, 0, 0], + [1, 0, 0]], ZZ), + DM([[1, 0, 0], + [0, 0, 0], + [0, 0, 0]], ZZ), + ZZ(1), + ), + + ( + 'zz_8', + DM([[0, 0, 0], + [0, 0, 0], + [0, 0, 0]], ZZ), + DM([[0, 0, 0], + [0, 0, 0], + [0, 0, 0]], ZZ), + ZZ(1), + ), + + ( + 'zz_9', + DM([[1, 1, 0], + [0, 0, 2], + [0, 0, 0]], ZZ), + DM([[1, 1, 0], + [0, 0, 1], + [0, 0, 0]], ZZ), + ZZ(1), + ), + + ( + 'zz_10', + DM([[2, 2, 0], + [0, 0, 2], + [0, 0, 0]], ZZ), + DM([[1, 1, 0], + [0, 0, 1], + [0, 0, 0]], ZZ), + ZZ(1), + ), + + ( + 'zz_11', + DM([[2, 2, 0], + [0, 2, 2], + [0, 0, 2]], ZZ), + DM([[1, 0, 0], + [0, 1, 0], + [0, 0, 1]], ZZ), + ZZ(1), + ), + + ( + 'zz_12', + DM([[ 1, 2, 3], + [ 4, 5, 6], + [ 7, 8, 9], + [10, 11, 12]], ZZ), + DM([[1, 0, -1], + [0, 1, 2], + [0, 0, 0], + [0, 0, 0]], ZZ), + ZZ(1), + ), + + ( + 'zz_13', + DM([[ 1, 2, 3], + [ 4, 5, 6], + [ 7, 8, 9], + [10, 11, 13]], ZZ), + DM([[ 1, 0, 0], + [ 0, 1, 0], + [ 0, 0, 1], + [ 0, 0, 0]], ZZ), + ZZ(1), + ), + + ( + 'zz_14', + DM([[1, 2, 4, 3], + [4, 5, 10, 6], + [7, 8, 16, 9]], ZZ), + DM([[1, 0, 0, -1], + [0, 1, 2, 2], + [0, 0, 0, 0]], ZZ), + ZZ(1), + ), + + ( + 'zz_15', + DM([[1, 2, 4, 3], + [4, 5, 10, 6], + [7, 8, 17, 9]], ZZ), + DM([[1, 0, 0, -1], + [0, 1, 0, 2], + [0, 0, 1, 0]], ZZ), + ZZ(1), + ), + + ( + 'zz_16', + DM([[1, 2, 0, 1], + [1, 1, 9, 0]], ZZ), + DM([[1, 0, 18, -1], + [0, 1, -9, 1]], ZZ), + ZZ(1), + ), + + ( + 'zz_17', + DM([[1, 1, 1], + [1, 2, 2]], ZZ), + DM([[1, 0, 0], + [0, 1, 1]], ZZ), + ZZ(1), + ), + + ( + # Here the sparse implementation and dense implementation give very + # different denominators: 4061232 and -1765176. + 'zz_18', + DM([[94, 24, 0, 27, 0], + [79, 0, 0, 0, 0], + [85, 16, 71, 81, 0], + [ 0, 0, 72, 77, 0], + [21, 0, 34, 0, 0]], ZZ), + DM([[ 1, 0, 0, 0, 0], + [ 0, 1, 0, 0, 0], + [ 0, 0, 1, 0, 0], + [ 0, 0, 0, 1, 0], + [ 0, 0, 0, 0, 0]], ZZ), + ZZ(1), + ), + + ( + # Let's have a denominator that cannot be cancelled. + 'zz_19', + DM([[1, 2, 4], + [4, 5, 6]], ZZ), + DM([[3, 0, -8], + [0, 3, 10]], ZZ), + ZZ(3), + ), + + ( + 'zz_20', + DM([[0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 4]], ZZ), + DM([[0, 0, 0, 0, 1], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0]], ZZ), + ZZ(1), + ), + + ( + 'zz_21', + DM([[0, 0, 0, 0, 0, 1, 0, 0, 0, 0], + [1, 0, 0, 0, 0, 0, 1, 0, 0, 0], + [0, 1, 0, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 0, 1, 0, 0, 0, 0, 1, 0], + [0, 0, 0, 0, 1, 0, 0, 0, 0, 1]], ZZ), + DM([[1, 0, 0, 0, 0, 0, 1, 0, 0, 0], + [0, 1, 0, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 0, 1, 0, 0, 0, 0, 1, 0], + [0, 0, 0, 0, 1, 0, 0, 0, 0, 1], + [0, 0, 0, 0, 0, 1, 0, 0, 0, 0]], ZZ), + ZZ(1), + ), + + ( + 'zz_22', + DM([[1, 1, 1, 0, 1], + [1, 1, 0, 1, 0], + [1, 0, 1, 0, 1], + [1, 1, 0, 1, 0], + [1, 0, 0, 0, 0]], ZZ), + DM([[1, 0, 0, 0, 0], + [0, 1, 0, 0, 0], + [0, 0, 1, 0, 1], + [0, 0, 0, 1, 0], + [0, 0, 0, 0, 0]], ZZ), + ZZ(1), + ), + + ( + 'zz_large_1', + DM([ +[ 0, 0, 0, 81, 0, 0, 75, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0], +[ 0, 0, 0, 0, 0, 86, 0, 92, 79, 54, 0, 7, 0, 0, 0, 0, 79, 0, 0, 0], +[89, 54, 81, 0, 0, 20, 0, 0, 0, 0, 0, 0, 51, 0, 94, 0, 0, 77, 0, 0], +[ 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 48, 29, 0, 0, 5, 0, 32, 0], +[ 0, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 11], +[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 43, 0, 0], +[ 0, 0, 0, 0, 0, 38, 91, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 26, 0, 0], +[69, 0, 0, 0, 0, 0, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55], +[ 0, 13, 18, 49, 49, 88, 0, 0, 35, 54, 0, 0, 51, 0, 0, 0, 0, 0, 0, 87], +[ 0, 0, 0, 0, 31, 0, 40, 0, 0, 0, 0, 0, 0, 50, 0, 0, 0, 0, 88, 0], +[ 0, 0, 0, 0, 0, 0, 0, 0, 98, 0, 0, 0, 15, 53, 0, 92, 0, 0, 0, 0], +[ 0, 0, 0, 95, 0, 0, 0, 36, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 73, 19], +[ 0, 65, 14, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 0, 0, 0, 34, 0, 0], +[ 0, 0, 0, 16, 39, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0], +[ 0, 17, 0, 0, 0, 99, 84, 13, 50, 84, 0, 0, 0, 0, 95, 0, 43, 33, 20, 0], +[79, 0, 17, 52, 99, 12, 69, 0, 98, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0], +[ 0, 0, 0, 82, 0, 44, 0, 0, 0, 97, 0, 0, 0, 0, 0, 10, 0, 0, 31, 0], +[ 0, 0, 21, 0, 67, 0, 0, 0, 0, 0, 4, 0, 50, 0, 0, 0, 33, 0, 0, 0], +[ 0, 0, 0, 0, 9, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8], +[ 0, 77, 0, 0, 0, 0, 0, 0, 0, 0, 34, 93, 0, 0, 0, 0, 47, 0, 0, 0]], + ZZ), + DM([[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]], ZZ), + ZZ(1), + ), + + ( + 'zz_large_2', + DM([ +[ 0, 0, 0, 0, 50, 0, 6, 81, 0, 1, 86, 0, 0, 98, 82, 94, 4, 0, 0, 29], +[ 0, 44, 43, 0, 62, 0, 0, 0, 60, 0, 0, 0, 0, 71, 9, 0, 57, 41, 0, 93], +[ 0, 0, 28, 0, 74, 89, 42, 0, 28, 0, 6, 0, 0, 0, 44, 0, 0, 0, 77, 19], +[ 0, 21, 82, 0, 30, 88, 0, 89, 68, 0, 0, 0, 79, 41, 0, 0, 99, 0, 0, 0], +[31, 0, 0, 0, 19, 64, 0, 0, 79, 0, 5, 0, 72, 10, 60, 32, 64, 59, 0, 24], +[ 0, 0, 0, 0, 0, 57, 0, 94, 0, 83, 20, 0, 0, 9, 31, 0, 49, 26, 58, 0], +[ 0, 65, 56, 31, 64, 0, 0, 0, 0, 0, 0, 52, 85, 0, 0, 0, 0, 51, 0, 0], +[ 0, 35, 0, 0, 0, 69, 0, 0, 64, 0, 0, 0, 0, 70, 0, 0, 90, 0, 75, 76], +[69, 7, 0, 90, 0, 0, 84, 0, 47, 69, 19, 20, 42, 0, 0, 32, 71, 35, 0, 0], +[39, 0, 90, 0, 0, 4, 85, 0, 0, 55, 0, 0, 0, 35, 67, 40, 0, 40, 0, 77], +[98, 63, 0, 71, 0, 50, 0, 2, 61, 0, 38, 0, 0, 0, 0, 75, 0, 40, 33, 56], +[ 0, 73, 0, 64, 0, 38, 0, 35, 61, 0, 0, 52, 0, 7, 0, 51, 0, 0, 0, 34], +[ 0, 0, 28, 0, 34, 5, 63, 45, 14, 42, 60, 16, 76, 54, 99, 0, 28, 30, 0, 0], +[58, 37, 14, 0, 0, 0, 94, 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 8, 90, 53], +[86, 74, 94, 0, 49, 10, 60, 0, 40, 18, 0, 0, 0, 31, 60, 24, 0, 1, 0, 29], +[53, 0, 0, 97, 0, 0, 58, 0, 0, 39, 44, 47, 0, 0, 0, 12, 50, 0, 0, 11], +[ 4, 0, 92, 10, 28, 0, 0, 89, 0, 0, 18, 54, 23, 39, 0, 2, 0, 48, 0, 92], +[ 0, 0, 90, 77, 95, 33, 0, 0, 49, 22, 39, 0, 0, 0, 0, 0, 0, 40, 0, 0], +[96, 0, 0, 0, 0, 38, 86, 0, 22, 76, 0, 0, 0, 0, 83, 88, 95, 65, 72, 0], +[81, 65, 0, 4, 60, 0, 19, 0, 0, 68, 0, 0, 89, 0, 67, 22, 0, 0, 55, 33]], + ZZ), + DM([ +[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], +[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], +[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], +[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], +[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], +[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], +[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], +[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], +[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], +[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], +[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0], +[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], +[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], +[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0], +[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], +[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], +[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0], +[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0], +[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0], +[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]], + ZZ), + ZZ(1), + ), + + ( + 'zz_large_3', + DM([ +[62,35,89,58,22,47,30,28,52,72,17,56,80,26,64,21,10,35,24,42,96,32,23,50,92,37,76,94,63,66], +[20,47,96,34,10,98,19,6,29,2,19,92,61,94,38,41,32,9,5,94,31,58,27,41,72,85,61,62,40,46], +[69,26,35,68,25,52,94,13,38,65,81,10,29,15,5,4,13,99,85,0,80,51,60,60,26,77,85,2,87,25], +[99,58,69,15,52,12,18,7,27,56,12,54,21,92,38,95,33,83,28,1,44,8,29,84,92,12,2,25,46,46], +[93,13,55,48,35,87,24,40,23,35,25,32,0,19,0,85,4,79,26,11,46,75,7,96,76,11,7,57,99,75], +[128,85,26,51,161,173,77,78,85,103,123,58,91,147,38,91,161,36,123,81,102,25,75,59,17,150,112,65,77,143], +[15,59,61,82,12,83,34,8,94,71,66,7,91,21,48,69,26,12,64,38,97,87,38,15,51,33,93,43,66,89], +[74,74,53,39,69,90,41,80,32,66,40,83,87,87,61,38,12,80,24,49,37,90,19,33,56,0,46,57,56,60], +[82,11,0,25,56,58,39,49,92,93,80,38,19,62,33,85,19,61,14,30,45,91,97,34,97,53,92,28,33,43], +[83,79,41,16,95,35,53,45,26,4,71,76,61,69,69,72,87,92,59,72,54,11,22,83,8,57,77,55,19,22], +[49,34,13,31,72,77,52,70,46,41,37,6,42,66,35,6,75,33,62,57,30,14,26,31,9,95,89,13,12,90], +[29,3,49,30,51,32,77,41,38,50,16,1,87,81,93,88,58,91,83,0,38,67,29,64,60,84,5,60,23,28], +[79,51,13,20,89,96,25,8,39,62,86,52,49,81,3,85,86,3,61,24,72,11,49,28,8,55,23,52,65,53], +[96,86,73,20,41,20,37,18,10,61,85,24,40,83,69,41,4,92,23,99,64,33,18,36,32,56,60,98,39,24], +[32,62,47,80,51,66,17,1,9,30,65,75,75,88,99,92,64,53,53,86,38,51,41,14,35,18,39,25,26,32], +[39,21,8,16,33,6,35,85,75,62,43,34,18,68,71,28,32,18,12,0,81,53,1,99,3,5,45,99,35,33], +[19,95,89,45,75,94,92,5,84,93,34,17,50,56,79,98,68,82,65,81,51,90,5,95,33,71,46,61,14,7], +[53,92,8,49,67,84,21,79,49,95,66,48,36,14,62,97,26,45,58,31,83,48,11,89,67,72,91,34,56,89], +[56,76,99,92,40,8,0,16,15,48,35,72,91,46,81,14,86,60,51,7,33,12,53,78,48,21,3,89,15,79], +[81,43,33,49,6,49,36,32,57,74,87,91,17,37,31,17,67,1,40,38,69,8,3,48,59,37,64,97,11,3], +[98,48,77,16,2,48,57,38,63,59,79,35,16,71,60,86,71,41,14,76,80,97,77,69,4,58,22,55,26,73], +[80,47,78,44,31,48,47,29,29,62,19,21,17,24,19,3,53,93,97,57,13,54,12,10,77,66,60,75,32,21], +[86,63,2,13,71,38,86,23,18,15,91,65,77,65,9,92,50,0,17,42,99,80,99,27,10,99,92,9,87,84], +[66,27,72,13,13,15,72,75,39,3,14,71,15,68,10,19,49,54,11,29,47,20,63,13,97,47,24,62,16,96], +[42,63,83,60,49,68,9,53,75,87,40,25,12,63,0,12,0,95,46,46,55,25,89,1,51,1,1,96,80,52], +[35,9,97,13,86,39,66,48,41,57,23,38,11,9,35,72,88,13,41,60,10,64,71,23,1,5,23,57,6,19], +[70,61,5,50,72,60,77,13,41,94,1,45,52,22,99,47,27,18,99,42,16,48,26,9,88,77,10,94,11,92], +[55,68,58,2,72,56,81,52,79,37,1,40,21,46,27,60,37,13,97,42,85,98,69,60,76,44,42,46,29,73], +[73,0,43,17,89,97,45,2,68,14,55,60,95,2,74,85,88,68,93,76,38,76,2,51,45,76,50,79,56,18], +[72,58,41,39,24,80,23,79,44,7,98,75,30,6,85,60,20,58,77,71,90,51,38,80,30,15,33,10,82,8]], + ZZ), + Matrix([ + [eye(29) * 2028539767964472550625641331179545072876560857886207583101, + Matrix([ 4260575808093245475167216057435155595594339172099000182569, + 169148395880755256182802335904188369274227936894862744452, + 4915975976683942569102447281579134986891620721539038348914, + 6113916866367364958834844982578214901958429746875633283248, + 5585689617819894460378537031623265659753379011388162534838, + 359776822829880747716695359574308645968094838905181892423, + -2800926112141776386671436511182421432449325232461665113305, + 941642292388230001722444876624818265766384442910688463158, + 3648811843256146649321864698600908938933015862008642023935, + -4104526163246702252932955226754097174212129127510547462419, + -704814955438106792441896903238080197619233342348191408078, + 1640882266829725529929398131287244562048075707575030019335, + -4068330845192910563212155694231438198040299927120544468520, + 136589038308366497790495711534532612862715724187671166593, + 2544937011460702462290799932536905731142196510605191645593, + 755591839174293940486133926192300657264122907519174116472, + -3683838489869297144348089243628436188645897133242795965021, + -522207137101161299969706310062775465103537953077871128403, + -2260451796032703984456606059649402832441331339246756656334, + -6476809325293587953616004856993300606040336446656916663680, + 3521944238996782387785653800944972787867472610035040989081, + 2270762115788407950241944504104975551914297395787473242379, + -3259947194628712441902262570532921252128444706733549251156, + -5624569821491886970999097239695637132075823246850431083557, + -3262698255682055804320585332902837076064075936601504555698, + 5786719943788937667411185880136324396357603606944869545501, + -955257841973865996077323863289453200904051299086000660036, + -1294235552446355326174641248209752679127075717918392702116, + -3718353510747301598130831152458342785269166356215331448279, + ]),], + [zeros(1, 29), zeros(1, 1)], + ]).to_DM().to_dense(), + ZZ(2028539767964472550625641331179545072876560857886207583101), + ), + + + ( + 'qq_1', + DM([[(1,2), 0], [0, 2]], QQ), + DM([[1, 0], [0, 1]], QQ), + QQ(1), + ), + + ( + # Standard square case + 'qq_2', + DM([[0, 1], + [1, 1]], QQ), + DM([[1, 0], + [0, 1]], QQ), + QQ(1), + ), + + ( + # m < n case + 'qq_3', + DM([[1, 2, 1], + [3, 4, 1]], QQ), + DM([[1, 0, -1], + [0, 1, 1]], QQ), + QQ(1), + ), + + ( + # same m < n but reversed + 'qq_4', + DM([[3, 4, 1], + [1, 2, 1]], QQ), + DM([[1, 0, -1], + [0, 1, 1]], QQ), + QQ(1), + ), + + ( + # m > n case + 'qq_5', + DM([[1, 0], + [1, 3], + [0, 1]], QQ), + DM([[1, 0], + [0, 1], + [0, 0]], QQ), + QQ(1), + ), + + ( + # Example with missing pivot + 'qq_6', + DM([[1, 0, 1], + [3, 0, 1]], QQ), + DM([[1, 0, 0], + [0, 0, 1]], QQ), + QQ(1), + ), + + ( + # This is intended to trigger the threshold where we give up on + # clearing denominators. + 'qq_large_1', + qq_large_1, + DomainMatrix.eye(11, QQ).to_dense(), + QQ(1), + ), + + ( + # This is intended to trigger the threshold where we use rref_den over + # QQ. + 'qq_large_2', + qq_large_2, + DomainMatrix.eye(11, QQ).to_dense(), + QQ(1), + ), + + ( + # Example with missing pivot and no replacement + + # This example is just enough to show a different result from the dense + # and sparse versions of the algorithm: + # + # >>> A = Matrix([[0, 1], [0, 2], [1, 0]]) + # >>> A.to_DM().to_sparse().rref_den()[0].to_Matrix() + # Matrix([ + # [1, 0], + # [0, 1], + # [0, 0]]) + # >>> A.to_DM().to_dense().rref_den()[0].to_Matrix() + # Matrix([ + # [2, 0], + # [0, 2], + # [0, 0]]) + # + 'qq_7', + DM([[0, 1], + [0, 2], + [1, 0]], QQ), + DM([[1, 0], + [0, 1], + [0, 0]], QQ), + QQ(1), + ), + + ( + # Gaussian integers + 'zz_i_1', + DM([[(0,1), 1, 1], + [ 1, 1, 1]], ZZ_I), + DM([[1, 0, 0], + [0, 1, 1]], ZZ_I), + ZZ_I(1), + ), + + ( + # EX: test_issue_23718 + 'EX_1', + DM([ + [a, b, 1], + [c, d, 1]], EX), + DM([[a*d - b*c, 0, -b + d], + [ 0, a*d - b*c, a - c]], EX), + EX(a*d - b*c), + ), + +] + + +def _to_DM(A, ans): + """Convert the answer to DomainMatrix.""" + if isinstance(A, DomainMatrix): + return A.to_dense() + elif isinstance(A, Matrix): + return A.to_DM(ans.domain).to_dense() + + if not (hasattr(A, 'shape') and hasattr(A, 'domain')): + shape, domain = ans.shape, ans.domain + else: + shape, domain = A.shape, A.domain + + if isinstance(A, (DDM, list)): + return DomainMatrix(list(A), shape, domain).to_dense() + elif isinstance(A, (SDM, dict)): + return DomainMatrix(dict(A), shape, domain).to_dense() + else: + assert False # pragma: no cover + + +def _pivots(A_rref): + """Return the pivots from the rref of A.""" + return tuple(sorted(map(min, A_rref.to_sdm().values()))) + + +def _check_cancel(result, rref_ans, den_ans): + """Check the cancelled result.""" + rref, den, pivots = result + if isinstance(rref, (DDM, SDM, list, dict)): + assert type(pivots) is list + pivots = tuple(pivots) + rref = _to_DM(rref, rref_ans) + rref2, den2 = rref.cancel_denom(den) + assert rref2 == rref_ans + assert den2 == den_ans + assert pivots == _pivots(rref) + + +def _check_divide(result, rref_ans, den_ans): + """Check the divided result.""" + rref, pivots = result + if isinstance(rref, (DDM, SDM, list, dict)): + assert type(pivots) is list + pivots = tuple(pivots) + rref_ans = rref_ans.to_field() / den_ans + rref = _to_DM(rref, rref_ans) + assert rref == rref_ans + assert _pivots(rref) == pivots + + +@pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES) +def test_Matrix_rref(name, A, A_rref, den): + K = A.domain + A = A.to_Matrix() + A_rref_found, pivots = A.rref() + if K.is_EX: + A_rref_found = A_rref_found.expand() + _check_divide((A_rref_found, pivots), A_rref, den) + + +@pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES) +def test_dm_dense_rref(name, A, A_rref, den): + A = A.to_field() + _check_divide(A.rref(), A_rref, den) + + +@pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES) +def test_dm_dense_rref_den(name, A, A_rref, den): + _check_cancel(A.rref_den(), A_rref, den) + + +@pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES) +def test_dm_sparse_rref(name, A, A_rref, den): + A = A.to_field().to_sparse() + _check_divide(A.rref(), A_rref, den) + + +@pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES) +def test_dm_sparse_rref_den(name, A, A_rref, den): + A = A.to_sparse() + _check_cancel(A.rref_den(), A_rref, den) + + +@pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES) +def test_dm_sparse_rref_den_keep_domain(name, A, A_rref, den): + A = A.to_sparse() + A_rref_f, den_f, pivots_f = A.rref_den(keep_domain=False) + A_rref_f = A_rref_f.to_field() / den_f + _check_divide((A_rref_f, pivots_f), A_rref, den) + + +@pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES) +def test_dm_sparse_rref_den_keep_domain_CD(name, A, A_rref, den): + A = A.to_sparse() + A_rref_f, den_f, pivots_f = A.rref_den(keep_domain=False, method='CD') + A_rref_f = A_rref_f.to_field() / den_f + _check_divide((A_rref_f, pivots_f), A_rref, den) + + +@pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES) +def test_dm_sparse_rref_den_keep_domain_GJ(name, A, A_rref, den): + A = A.to_sparse() + A_rref_f, den_f, pivots_f = A.rref_den(keep_domain=False, method='GJ') + A_rref_f = A_rref_f.to_field() / den_f + _check_divide((A_rref_f, pivots_f), A_rref, den) + + +@pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES) +def test_ddm_rref_den(name, A, A_rref, den): + A = A.to_ddm() + _check_cancel(A.rref_den(), A_rref, den) + + +@pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES) +def test_sdm_rref_den(name, A, A_rref, den): + A = A.to_sdm() + _check_cancel(A.rref_den(), A_rref, den) + + +@pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES) +def test_ddm_rref(name, A, A_rref, den): + A = A.to_field().to_ddm() + _check_divide(A.rref(), A_rref, den) + + +@pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES) +def test_sdm_rref(name, A, A_rref, den): + A = A.to_field().to_sdm() + _check_divide(A.rref(), A_rref, den) + + +@pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES) +def test_ddm_irref(name, A, A_rref, den): + A = A.to_field().to_ddm().copy() + pivots_found = ddm_irref(A) + _check_divide((A, pivots_found), A_rref, den) + + +@pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES) +def test_ddm_irref_den(name, A, A_rref, den): + A = A.to_ddm().copy() + (den_found, pivots_found) = ddm_irref_den(A, A.domain) + result = (A, den_found, pivots_found) + _check_cancel(result, A_rref, den) + + +@pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES) +def test_sparse_sdm_rref(name, A, A_rref, den): + A = A.to_field().to_sdm() + _check_divide(sdm_irref(A)[:2], A_rref, den) + + +@pytest.mark.parametrize('name, A, A_rref, den', RREF_EXAMPLES) +def test_sparse_sdm_rref_den(name, A, A_rref, den): + A = A.to_sdm().copy() + K = A.domain + _check_cancel(sdm_rref_den(A, K), A_rref, den) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_sdm.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_sdm.py new file mode 100644 index 0000000000000000000000000000000000000000..cd7e5d460a1b2d44279a2a1772cc901f80ca733e --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_sdm.py @@ -0,0 +1,428 @@ +""" +Tests for the basic functionality of the SDM class. +""" + +from itertools import product + +from sympy.core.singleton import S +from sympy.external.gmpy import GROUND_TYPES +from sympy.testing.pytest import raises + +from sympy.polys.domains import QQ, ZZ, EXRAW +from sympy.polys.matrices.sdm import SDM +from sympy.polys.matrices.ddm import DDM +from sympy.polys.matrices.exceptions import (DMBadInputError, DMDomainError, + DMShapeError) + + +def test_SDM(): + A = SDM({0:{0:ZZ(1)}}, (2, 2), ZZ) + assert A.domain == ZZ + assert A.shape == (2, 2) + assert dict(A) == {0:{0:ZZ(1)}} + + raises(DMBadInputError, lambda: SDM({5:{1:ZZ(0)}}, (2, 2), ZZ)) + raises(DMBadInputError, lambda: SDM({0:{5:ZZ(0)}}, (2, 2), ZZ)) + + +def test_DDM_str(): + sdm = SDM({0:{0:ZZ(1)}, 1:{1:ZZ(1)}}, (2, 2), ZZ) + assert str(sdm) == '{0: {0: 1}, 1: {1: 1}}' + if GROUND_TYPES == 'gmpy': # pragma: no cover + assert repr(sdm) == 'SDM({0: {0: mpz(1)}, 1: {1: mpz(1)}}, (2, 2), ZZ)' + else: # pragma: no cover + assert repr(sdm) == 'SDM({0: {0: 1}, 1: {1: 1}}, (2, 2), ZZ)' + + +def test_SDM_new(): + A = SDM({0:{0:ZZ(1)}}, (2, 2), ZZ) + B = A.new({}, (2, 2), ZZ) + assert B == SDM({}, (2, 2), ZZ) + + +def test_SDM_copy(): + A = SDM({0:{0:ZZ(1)}}, (2, 2), ZZ) + B = A.copy() + assert A == B + A[0][0] = ZZ(2) + assert A != B + + +def test_SDM_from_list(): + A = SDM.from_list([[ZZ(0), ZZ(1)], [ZZ(1), ZZ(0)]], (2, 2), ZZ) + assert A == SDM({0:{1:ZZ(1)}, 1:{0:ZZ(1)}}, (2, 2), ZZ) + + raises(DMBadInputError, lambda: SDM.from_list([[ZZ(0)], [ZZ(0), ZZ(1)]], (2, 2), ZZ)) + raises(DMBadInputError, lambda: SDM.from_list([[ZZ(0), ZZ(1)]], (2, 2), ZZ)) + + +def test_SDM_to_list(): + A = SDM({0:{1: ZZ(1)}}, (2, 2), ZZ) + assert A.to_list() == [[ZZ(0), ZZ(1)], [ZZ(0), ZZ(0)]] + + A = SDM({}, (0, 2), ZZ) + assert A.to_list() == [] + + A = SDM({}, (2, 0), ZZ) + assert A.to_list() == [[], []] + + +def test_SDM_to_list_flat(): + A = SDM({0:{1: ZZ(1)}}, (2, 2), ZZ) + assert A.to_list_flat() == [ZZ(0), ZZ(1), ZZ(0), ZZ(0)] + + +def test_SDM_to_dok(): + A = SDM({0:{1: ZZ(1)}}, (2, 2), ZZ) + assert A.to_dok() == {(0, 1): ZZ(1)} + + +def test_SDM_from_ddm(): + A = DDM([[ZZ(1), ZZ(0)], [ZZ(1), ZZ(0)]], (2, 2), ZZ) + B = SDM.from_ddm(A) + assert B.domain == ZZ + assert B.shape == (2, 2) + assert dict(B) == {0:{0:ZZ(1)}, 1:{0:ZZ(1)}} + + +def test_SDM_to_ddm(): + A = SDM({0:{1: ZZ(1)}}, (2, 2), ZZ) + B = DDM([[ZZ(0), ZZ(1)], [ZZ(0), ZZ(0)]], (2, 2), ZZ) + assert A.to_ddm() == B + + +def test_SDM_to_sdm(): + A = SDM({0:{1: ZZ(1)}}, (2, 2), ZZ) + assert A.to_sdm() == A + + +def test_SDM_getitem(): + A = SDM({0:{1:ZZ(1)}}, (2, 2), ZZ) + assert A.getitem(0, 0) == ZZ.zero + assert A.getitem(0, 1) == ZZ.one + assert A.getitem(1, 0) == ZZ.zero + assert A.getitem(-2, -2) == ZZ.zero + assert A.getitem(-2, -1) == ZZ.one + assert A.getitem(-1, -2) == ZZ.zero + raises(IndexError, lambda: A.getitem(2, 0)) + raises(IndexError, lambda: A.getitem(0, 2)) + + +def test_SDM_setitem(): + A = SDM({0:{1:ZZ(1)}}, (2, 2), ZZ) + A.setitem(0, 0, ZZ(1)) + assert A == SDM({0:{0:ZZ(1), 1:ZZ(1)}}, (2, 2), ZZ) + A.setitem(1, 0, ZZ(1)) + assert A == SDM({0:{0:ZZ(1), 1:ZZ(1)}, 1:{0:ZZ(1)}}, (2, 2), ZZ) + A.setitem(1, 0, ZZ(0)) + assert A == SDM({0:{0:ZZ(1), 1:ZZ(1)}}, (2, 2), ZZ) + # Repeat the above test so that this time the row is empty + A.setitem(1, 0, ZZ(0)) + assert A == SDM({0:{0:ZZ(1), 1:ZZ(1)}}, (2, 2), ZZ) + A.setitem(0, 0, ZZ(0)) + assert A == SDM({0:{1:ZZ(1)}}, (2, 2), ZZ) + # This time the row is there but column is empty + A.setitem(0, 0, ZZ(0)) + assert A == SDM({0:{1:ZZ(1)}}, (2, 2), ZZ) + raises(IndexError, lambda: A.setitem(2, 0, ZZ(1))) + raises(IndexError, lambda: A.setitem(0, 2, ZZ(1))) + + +def test_SDM_extract_slice(): + A = SDM({0:{0:ZZ(1), 1:ZZ(2)}, 1:{0:ZZ(3), 1:ZZ(4)}}, (2, 2), ZZ) + B = A.extract_slice(slice(1, 2), slice(1, 2)) + assert B == SDM({0:{0:ZZ(4)}}, (1, 1), ZZ) + + +def test_SDM_extract(): + A = SDM({0:{0:ZZ(1), 1:ZZ(2)}, 1:{0:ZZ(3), 1:ZZ(4)}}, (2, 2), ZZ) + B = A.extract([1], [1]) + assert B == SDM({0:{0:ZZ(4)}}, (1, 1), ZZ) + B = A.extract([1, 0], [1, 0]) + assert B == SDM({0:{0:ZZ(4), 1:ZZ(3)}, 1:{0:ZZ(2), 1:ZZ(1)}}, (2, 2), ZZ) + B = A.extract([1, 1], [1, 1]) + assert B == SDM({0:{0:ZZ(4), 1:ZZ(4)}, 1:{0:ZZ(4), 1:ZZ(4)}}, (2, 2), ZZ) + B = A.extract([-1], [-1]) + assert B == SDM({0:{0:ZZ(4)}}, (1, 1), ZZ) + + A = SDM({}, (2, 2), ZZ) + B = A.extract([0, 1, 0], [0, 0]) + assert B == SDM({}, (3, 2), ZZ) + + A = SDM({0:{0:ZZ(1), 1:ZZ(2)}, 1:{0:ZZ(3), 1:ZZ(4)}}, (2, 2), ZZ) + assert A.extract([], []) == SDM.zeros((0, 0), ZZ) + assert A.extract([1], []) == SDM.zeros((1, 0), ZZ) + assert A.extract([], [1]) == SDM.zeros((0, 1), ZZ) + + raises(IndexError, lambda: A.extract([2], [0])) + raises(IndexError, lambda: A.extract([0], [2])) + raises(IndexError, lambda: A.extract([-3], [0])) + raises(IndexError, lambda: A.extract([0], [-3])) + + +def test_SDM_zeros(): + A = SDM.zeros((2, 2), ZZ) + assert A.domain == ZZ + assert A.shape == (2, 2) + assert dict(A) == {} + +def test_SDM_ones(): + A = SDM.ones((1, 2), QQ) + assert A.domain == QQ + assert A.shape == (1, 2) + assert dict(A) == {0:{0:QQ(1), 1:QQ(1)}} + +def test_SDM_eye(): + A = SDM.eye((2, 2), ZZ) + assert A.domain == ZZ + assert A.shape == (2, 2) + assert dict(A) == {0:{0:ZZ(1)}, 1:{1:ZZ(1)}} + + +def test_SDM_diag(): + A = SDM.diag([ZZ(1), ZZ(2)], ZZ, (2, 3)) + assert A == SDM({0:{0:ZZ(1)}, 1:{1:ZZ(2)}}, (2, 3), ZZ) + + +def test_SDM_transpose(): + A = SDM({0:{0:ZZ(1), 1:ZZ(2)}, 1:{0:ZZ(3), 1:ZZ(4)}}, (2, 2), ZZ) + B = SDM({0:{0:ZZ(1), 1:ZZ(3)}, 1:{0:ZZ(2), 1:ZZ(4)}}, (2, 2), ZZ) + assert A.transpose() == B + + A = SDM({0:{1:ZZ(2)}}, (2, 2), ZZ) + B = SDM({1:{0:ZZ(2)}}, (2, 2), ZZ) + assert A.transpose() == B + + A = SDM({0:{1:ZZ(2)}}, (1, 2), ZZ) + B = SDM({1:{0:ZZ(2)}}, (2, 1), ZZ) + assert A.transpose() == B + + +def test_SDM_mul(): + A = SDM({0:{0:ZZ(2)}}, (2, 2), ZZ) + B = SDM({0:{0:ZZ(4)}}, (2, 2), ZZ) + assert A*ZZ(2) == B + assert ZZ(2)*A == B + + raises(TypeError, lambda: A*QQ(1, 2)) + raises(TypeError, lambda: QQ(1, 2)*A) + + +def test_SDM_mul_elementwise(): + A = SDM({0:{0:ZZ(2), 1:ZZ(2)}}, (2, 2), ZZ) + B = SDM({0:{0:ZZ(4)}, 1:{0:ZZ(3)}}, (2, 2), ZZ) + C = SDM({0:{0:ZZ(8)}}, (2, 2), ZZ) + assert A.mul_elementwise(B) == C + assert B.mul_elementwise(A) == C + + Aq = A.convert_to(QQ) + A1 = SDM({0:{0:ZZ(1)}}, (1, 1), ZZ) + + raises(DMDomainError, lambda: Aq.mul_elementwise(B)) + raises(DMShapeError, lambda: A1.mul_elementwise(B)) + + +def test_SDM_matmul(): + A = SDM({0:{0:ZZ(2)}}, (2, 2), ZZ) + B = SDM({0:{0:ZZ(4)}}, (2, 2), ZZ) + assert A.matmul(A) == A*A == B + + C = SDM({0:{0:ZZ(2)}}, (2, 2), QQ) + raises(DMDomainError, lambda: A.matmul(C)) + + A = SDM({0:{0:ZZ(1), 1:ZZ(2)}, 1:{0:ZZ(3), 1:ZZ(4)}}, (2, 2), ZZ) + B = SDM({0:{0:ZZ(7), 1:ZZ(10)}, 1:{0:ZZ(15), 1:ZZ(22)}}, (2, 2), ZZ) + assert A.matmul(A) == A*A == B + + A22 = SDM({0:{0:ZZ(4)}}, (2, 2), ZZ) + A32 = SDM({0:{0:ZZ(2)}}, (3, 2), ZZ) + A23 = SDM({0:{0:ZZ(4)}}, (2, 3), ZZ) + A33 = SDM({0:{0:ZZ(8)}}, (3, 3), ZZ) + A22 = SDM({0:{0:ZZ(8)}}, (2, 2), ZZ) + assert A32.matmul(A23) == A33 + assert A23.matmul(A32) == A22 + # XXX: @ not supported by SDM... + #assert A32.matmul(A23) == A32 @ A23 == A33 + #assert A23.matmul(A32) == A23 @ A32 == A22 + #raises(DMShapeError, lambda: A23 @ A22) + raises(DMShapeError, lambda: A23.matmul(A22)) + + A = SDM({0: {0: ZZ(-1), 1: ZZ(1)}}, (1, 2), ZZ) + B = SDM({0: {0: ZZ(-1)}, 1: {0: ZZ(-1)}}, (2, 1), ZZ) + assert A.matmul(B) == A*B == SDM({}, (1, 1), ZZ) + + +def test_matmul_exraw(): + + def dm(d): + result = {} + for i, row in d.items(): + row = {j:val for j, val in row.items() if val} + if row: + result[i] = row + return SDM(result, (2, 2), EXRAW) + + values = [S.NegativeInfinity, S.NegativeOne, S.Zero, S.One, S.Infinity] + for a, b, c, d in product(*[values]*4): + Ad = dm({0: {0:a, 1:b}, 1: {0:c, 1:d}}) + Ad2 = dm({0: {0:a*a + b*c, 1:a*b + b*d}, 1:{0:c*a + d*c, 1: c*b + d*d}}) + assert Ad * Ad == Ad2 + + +def test_SDM_add(): + A = SDM({0:{1:ZZ(1)}, 1:{0:ZZ(2), 1:ZZ(3)}}, (2, 2), ZZ) + B = SDM({0:{0:ZZ(1)}, 1:{0:ZZ(-2), 1:ZZ(3)}}, (2, 2), ZZ) + C = SDM({0:{0:ZZ(1), 1:ZZ(1)}, 1:{1:ZZ(6)}}, (2, 2), ZZ) + assert A.add(B) == B.add(A) == A + B == B + A == C + + A = SDM({0:{1:ZZ(1)}}, (2, 2), ZZ) + B = SDM({0:{0:ZZ(1)}, 1:{0:ZZ(-2), 1:ZZ(3)}}, (2, 2), ZZ) + C = SDM({0:{0:ZZ(1), 1:ZZ(1)}, 1:{0:ZZ(-2), 1:ZZ(3)}}, (2, 2), ZZ) + assert A.add(B) == B.add(A) == A + B == B + A == C + + raises(TypeError, lambda: A + []) + + +def test_SDM_sub(): + A = SDM({0:{1:ZZ(1)}, 1:{0:ZZ(2), 1:ZZ(3)}}, (2, 2), ZZ) + B = SDM({0:{0:ZZ(1)}, 1:{0:ZZ(-2), 1:ZZ(3)}}, (2, 2), ZZ) + C = SDM({0:{0:ZZ(-1), 1:ZZ(1)}, 1:{0:ZZ(4)}}, (2, 2), ZZ) + assert A.sub(B) == A - B == C + + raises(TypeError, lambda: A - []) + + +def test_SDM_neg(): + A = SDM({0:{1:ZZ(1)}, 1:{0:ZZ(2), 1:ZZ(3)}}, (2, 2), ZZ) + B = SDM({0:{1:ZZ(-1)}, 1:{0:ZZ(-2), 1:ZZ(-3)}}, (2, 2), ZZ) + assert A.neg() == -A == B + + +def test_SDM_convert_to(): + A = SDM({0:{1:ZZ(1)}, 1:{0:ZZ(2), 1:ZZ(3)}}, (2, 2), ZZ) + B = SDM({0:{1:QQ(1)}, 1:{0:QQ(2), 1:QQ(3)}}, (2, 2), QQ) + C = A.convert_to(QQ) + assert C == B + assert C.domain == QQ + + D = A.convert_to(ZZ) + assert D == A + assert D.domain == ZZ + + +def test_SDM_hstack(): + A = SDM({0:{1:ZZ(1)}}, (2, 2), ZZ) + B = SDM({1:{1:ZZ(1)}}, (2, 2), ZZ) + AA = SDM({0:{1:ZZ(1), 3:ZZ(1)}}, (2, 4), ZZ) + AB = SDM({0:{1:ZZ(1)}, 1:{3:ZZ(1)}}, (2, 4), ZZ) + assert SDM.hstack(A) == A + assert SDM.hstack(A, A) == AA + assert SDM.hstack(A, B) == AB + + +def test_SDM_vstack(): + A = SDM({0:{1:ZZ(1)}}, (2, 2), ZZ) + B = SDM({1:{1:ZZ(1)}}, (2, 2), ZZ) + AA = SDM({0:{1:ZZ(1)}, 2:{1:ZZ(1)}}, (4, 2), ZZ) + AB = SDM({0:{1:ZZ(1)}, 3:{1:ZZ(1)}}, (4, 2), ZZ) + assert SDM.vstack(A) == A + assert SDM.vstack(A, A) == AA + assert SDM.vstack(A, B) == AB + + +def test_SDM_applyfunc(): + A = SDM({0:{1:ZZ(1)}}, (2, 2), ZZ) + B = SDM({0:{1:ZZ(2)}}, (2, 2), ZZ) + assert A.applyfunc(lambda x: 2*x, ZZ) == B + + +def test_SDM_inv(): + A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(3), 1:QQ(4)}}, (2, 2), QQ) + B = SDM({0:{0:QQ(-2), 1:QQ(1)}, 1:{0:QQ(3, 2), 1:QQ(-1, 2)}}, (2, 2), QQ) + assert A.inv() == B + + +def test_SDM_det(): + A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(3), 1:QQ(4)}}, (2, 2), QQ) + assert A.det() == QQ(-2) + + +def test_SDM_lu(): + A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(3), 1:QQ(4)}}, (2, 2), QQ) + L = SDM({0:{0:QQ(1)}, 1:{0:QQ(3), 1:QQ(1)}}, (2, 2), QQ) + #U = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(3), 1:QQ(-2)}}, (2, 2), QQ) + #swaps = [] + # This doesn't quite work. U has some nonzero elements in the lower part. + #assert A.lu() == (L, U, swaps) + assert A.lu()[0] == L + + +def test_SDM_lu_solve(): + A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(3), 1:QQ(4)}}, (2, 2), QQ) + b = SDM({0:{0:QQ(1)}, 1:{0:QQ(2)}}, (2, 1), QQ) + x = SDM({1:{0:QQ(1, 2)}}, (2, 1), QQ) + assert A.matmul(x) == b + assert A.lu_solve(b) == x + + +def test_SDM_charpoly(): + A = SDM({0:{0:ZZ(1), 1:ZZ(2)}, 1:{0:ZZ(3), 1:ZZ(4)}}, (2, 2), ZZ) + assert A.charpoly() == [ZZ(1), ZZ(-5), ZZ(-2)] + + +def test_SDM_nullspace(): + # More tests are in test_nullspace.py + A = SDM({0:{0:QQ(1), 1:QQ(1)}}, (2, 2), QQ) + assert A.nullspace()[0] == SDM({0:{0:QQ(-1), 1:QQ(1)}}, (1, 2), QQ) + + +def test_SDM_rref(): + # More tests are in test_rref.py + + A = SDM({0:{0:QQ(1), 1:QQ(2)}, + 1:{0:QQ(3), 1:QQ(4)}}, (2, 2), QQ) + A_rref = SDM({0:{0:QQ(1)}, 1:{1:QQ(1)}}, (2, 2), QQ) + assert A.rref() == (A_rref, [0, 1]) + + A = SDM({0: {0: QQ(1), 1: QQ(2), 2: QQ(2)}, + 1: {0: QQ(3), 2: QQ(4)}}, (2, 3), ZZ) + A_rref = SDM({0: {0: QQ(1,1), 2: QQ(4,3)}, + 1: {1: QQ(1,1), 2: QQ(1,3)}}, (2, 3), QQ) + assert A.rref() == (A_rref, [0, 1]) + + +def test_SDM_particular(): + A = SDM({0:{0:QQ(1)}}, (2, 2), QQ) + Apart = SDM.zeros((1, 2), QQ) + assert A.particular() == Apart + + +def test_SDM_is_zero_matrix(): + A = SDM({0: {0: QQ(1)}}, (2, 2), QQ) + Azero = SDM.zeros((1, 2), QQ) + assert A.is_zero_matrix() is False + assert Azero.is_zero_matrix() is True + + +def test_SDM_is_upper(): + A = SDM({0: {0: QQ(1), 1: QQ(2), 2: QQ(3), 3: QQ(4)}, + 1: {1: QQ(5), 2: QQ(6), 3: QQ(7)}, + 2: {2: QQ(8), 3: QQ(9)}}, (3, 4), QQ) + B = SDM({0: {0: QQ(1), 1: QQ(2), 2: QQ(3), 3: QQ(4)}, + 1: {1: QQ(5), 2: QQ(6), 3: QQ(7)}, + 2: {1: QQ(7), 2: QQ(8), 3: QQ(9)}}, (3, 4), QQ) + assert A.is_upper() is True + assert B.is_upper() is False + + +def test_SDM_is_lower(): + A = SDM({0: {0: QQ(1), 1: QQ(2), 2: QQ(3), 3: QQ(4)}, + 1: {1: QQ(5), 2: QQ(6), 3: QQ(7)}, + 2: {2: QQ(8), 3: QQ(9)}}, (3, 4), QQ + ).transpose() + B = SDM({0: {0: QQ(1), 1: QQ(2), 2: QQ(3), 3: QQ(4)}, + 1: {1: QQ(5), 2: QQ(6), 3: QQ(7)}, + 2: {1: QQ(7), 2: QQ(8), 3: QQ(9)}}, (3, 4), QQ + ).transpose() + assert A.is_lower() is True + assert B.is_lower() is False diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_xxm.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_xxm.py new file mode 100644 index 0000000000000000000000000000000000000000..628d66d15f5db82718231ba8f89bc0dadd393594 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/polys/matrices/tests/test_xxm.py @@ -0,0 +1,1023 @@ +# +# Test basic features of DDM, SDM and DFM. +# +# These three types are supposed to be interchangeable, so we should use the +# same tests for all of them for the most part. +# +# The tests here cover the basic part of the interface that the three types +# should expose and that DomainMatrix should mostly rely on. +# +# More in-depth tests of the heavier algorithms like rref etc should go in +# their own test files. +# +# Any new methods added to the DDM, SDM or DFM classes should be tested here +# and added to all classes. +# + +from sympy.external.gmpy import GROUND_TYPES + +from sympy import ZZ, QQ, GF, ZZ_I, symbols + +from sympy.polys.matrices.exceptions import ( + DMBadInputError, + DMDomainError, + DMNonSquareMatrixError, + DMNonInvertibleMatrixError, + DMShapeError, +) + +from sympy.polys.matrices.domainmatrix import DM, DomainMatrix, DDM, SDM, DFM + +from sympy.testing.pytest import raises, skip +import pytest + + +def test_XXM_constructors(): + """Test the DDM, etc constructors.""" + + lol = [ + [ZZ(1), ZZ(2)], + [ZZ(3), ZZ(4)], + [ZZ(5), ZZ(6)], + ] + dod = { + 0: {0: ZZ(1), 1: ZZ(2)}, + 1: {0: ZZ(3), 1: ZZ(4)}, + 2: {0: ZZ(5), 1: ZZ(6)}, + } + + lol_0x0 = [] + lol_0x2 = [] + lol_2x0 = [[], []] + dod_0x0 = {} + dod_0x2 = {} + dod_2x0 = {} + + lol_bad = [ + [ZZ(1), ZZ(2)], + [ZZ(3), ZZ(4)], + [ZZ(5), ZZ(6), ZZ(7)], + ] + dod_bad = { + 0: {0: ZZ(1), 1: ZZ(2)}, + 1: {0: ZZ(3), 1: ZZ(4)}, + 2: {0: ZZ(5), 1: ZZ(6), 2: ZZ(7)}, + } + + XDM_dense = [DDM] + XDM_sparse = [SDM] + + if GROUND_TYPES == 'flint': + XDM_dense.append(DFM) + + for XDM in XDM_dense: + + A = XDM(lol, (3, 2), ZZ) + assert A.rows == 3 + assert A.cols == 2 + assert A.domain == ZZ + assert A.shape == (3, 2) + if XDM is not DFM: + assert ZZ.of_type(A[0][0]) is True + else: + assert ZZ.of_type(A.rep[0, 0]) is True + + Adm = DomainMatrix(lol, (3, 2), ZZ) + if XDM is DFM: + assert Adm.rep == A + assert Adm.rep.to_ddm() != A + elif GROUND_TYPES == 'flint': + assert Adm.rep.to_ddm() == A + assert Adm.rep != A + else: + assert Adm.rep == A + assert Adm.rep.to_ddm() == A + + assert XDM(lol_0x0, (0, 0), ZZ).shape == (0, 0) + assert XDM(lol_0x2, (0, 2), ZZ).shape == (0, 2) + assert XDM(lol_2x0, (2, 0), ZZ).shape == (2, 0) + raises(DMBadInputError, lambda: XDM(lol, (2, 3), ZZ)) + raises(DMBadInputError, lambda: XDM(lol_bad, (3, 2), ZZ)) + raises(DMBadInputError, lambda: XDM(dod, (3, 2), ZZ)) + + for XDM in XDM_sparse: + + A = XDM(dod, (3, 2), ZZ) + assert A.rows == 3 + assert A.cols == 2 + assert A.domain == ZZ + assert A.shape == (3, 2) + assert ZZ.of_type(A[0][0]) is True + + assert DomainMatrix(dod, (3, 2), ZZ).rep == A + + assert XDM(dod_0x0, (0, 0), ZZ).shape == (0, 0) + assert XDM(dod_0x2, (0, 2), ZZ).shape == (0, 2) + assert XDM(dod_2x0, (2, 0), ZZ).shape == (2, 0) + raises(DMBadInputError, lambda: XDM(dod, (2, 3), ZZ)) + raises(DMBadInputError, lambda: XDM(lol, (3, 2), ZZ)) + raises(DMBadInputError, lambda: XDM(dod_bad, (3, 2), ZZ)) + + raises(DMBadInputError, lambda: DomainMatrix(lol, (2, 3), ZZ)) + raises(DMBadInputError, lambda: DomainMatrix(lol_bad, (3, 2), ZZ)) + raises(DMBadInputError, lambda: DomainMatrix(dod_bad, (3, 2), ZZ)) + + +def test_XXM_eq(): + """Test equality for DDM, SDM, DFM and DomainMatrix.""" + + lol1 = [[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]] + dod1 = {0: {0: ZZ(1), 1: ZZ(2)}, 1: {0: ZZ(3), 1: ZZ(4)}} + + lol2 = [[ZZ(1), ZZ(2)], [ZZ(3), ZZ(5)]] + dod2 = {0: {0: ZZ(1), 1: ZZ(2)}, 1: {0: ZZ(3), 1: ZZ(5)}} + + A1_ddm = DDM(lol1, (2, 2), ZZ) + A1_sdm = SDM(dod1, (2, 2), ZZ) + A1_dm_d = DomainMatrix(lol1, (2, 2), ZZ) + A1_dm_s = DomainMatrix(dod1, (2, 2), ZZ) + + A2_ddm = DDM(lol2, (2, 2), ZZ) + A2_sdm = SDM(dod2, (2, 2), ZZ) + A2_dm_d = DomainMatrix(lol2, (2, 2), ZZ) + A2_dm_s = DomainMatrix(dod2, (2, 2), ZZ) + + A1_all = [A1_ddm, A1_sdm, A1_dm_d, A1_dm_s] + A2_all = [A2_ddm, A2_sdm, A2_dm_d, A2_dm_s] + + if GROUND_TYPES == 'flint': + + A1_dfm = DFM([[1, 2], [3, 4]], (2, 2), ZZ) + A2_dfm = DFM([[1, 2], [3, 5]], (2, 2), ZZ) + + A1_all.append(A1_dfm) + A2_all.append(A2_dfm) + + for n, An in enumerate(A1_all): + for m, Am in enumerate(A1_all): + if n == m: + assert (An == Am) is True + assert (An != Am) is False + else: + assert (An == Am) is False + assert (An != Am) is True + + for n, An in enumerate(A2_all): + for m, Am in enumerate(A2_all): + if n == m: + assert (An == Am) is True + assert (An != Am) is False + else: + assert (An == Am) is False + assert (An != Am) is True + + for n, A1 in enumerate(A1_all): + for m, A2 in enumerate(A2_all): + assert (A1 == A2) is False + assert (A1 != A2) is True + + +def test_to_XXM(): + """Test to_ddm etc. for DDM, SDM, DFM and DomainMatrix.""" + + lol = [[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]] + dod = {0: {0: ZZ(1), 1: ZZ(2)}, 1: {0: ZZ(3), 1: ZZ(4)}} + + A_ddm = DDM(lol, (2, 2), ZZ) + A_sdm = SDM(dod, (2, 2), ZZ) + A_dm_d = DomainMatrix(lol, (2, 2), ZZ) + A_dm_s = DomainMatrix(dod, (2, 2), ZZ) + + A_all = [A_ddm, A_sdm, A_dm_d, A_dm_s] + + if GROUND_TYPES == 'flint': + A_dfm = DFM(lol, (2, 2), ZZ) + A_all.append(A_dfm) + + for A in A_all: + assert A.to_ddm() == A_ddm + assert A.to_sdm() == A_sdm + if GROUND_TYPES != 'flint': + raises(NotImplementedError, lambda: A.to_dfm()) + assert A.to_dfm_or_ddm() == A_ddm + + # Add e.g. DDM.to_DM()? + # assert A.to_DM() == A_dm + + if GROUND_TYPES == 'flint': + for A in A_all: + assert A.to_dfm() == A_dfm + for K in [ZZ, QQ, GF(5), ZZ_I]: + if isinstance(A, DFM) and not DFM._supports_domain(K): + raises(NotImplementedError, lambda: A.convert_to(K)) + else: + A_K = A.convert_to(K) + if DFM._supports_domain(K): + A_dfm_K = A_dfm.convert_to(K) + assert A_K.to_dfm() == A_dfm_K + assert A_K.to_dfm_or_ddm() == A_dfm_K + else: + raises(NotImplementedError, lambda: A_K.to_dfm()) + assert A_K.to_dfm_or_ddm() == A_ddm.convert_to(K) + + +def test_DFM_domains(): + """Test which domains are supported by DFM.""" + + x, y = symbols('x, y') + + if GROUND_TYPES in ('python', 'gmpy'): + + supported = [] + flint_funcs = {} + not_supported = [ZZ, QQ, GF(5), QQ[x], QQ[x,y]] + + elif GROUND_TYPES == 'flint': + + import flint + supported = [ZZ, QQ] + flint_funcs = { + ZZ: flint.fmpz_mat, + QQ: flint.fmpq_mat, + GF(5): None, + } + not_supported = [ + # Other domains could be supported but not implemented as matrices + # in python-flint: + QQ[x], + QQ[x,y], + QQ.frac_field(x,y), + # Others would potentially never be supported by python-flint: + ZZ_I, + ] + + else: + assert False, "Unknown GROUND_TYPES: %s" % GROUND_TYPES + + for domain in supported: + assert DFM._supports_domain(domain) is True + if flint_funcs[domain] is not None: + assert DFM._get_flint_func(domain) == flint_funcs[domain] + for domain in not_supported: + assert DFM._supports_domain(domain) is False + raises(NotImplementedError, lambda: DFM._get_flint_func(domain)) + + +def _DM(lol, typ, K): + """Make a DM of type typ over K from lol.""" + A = DM(lol, K) + + if typ == 'DDM': + return A.to_ddm() + elif typ == 'SDM': + return A.to_sdm() + elif typ == 'DFM': + if GROUND_TYPES != 'flint': + skip("DFM not supported in this ground type") + return A.to_dfm() + else: + assert False, "Unknown type %s" % typ + + +def _DMZ(lol, typ): + """Make a DM of type typ over ZZ from lol.""" + return _DM(lol, typ, ZZ) + + +def _DMQ(lol, typ): + """Make a DM of type typ over QQ from lol.""" + return _DM(lol, typ, QQ) + + +def DM_ddm(lol, K): + """Make a DDM over K from lol.""" + return _DM(lol, 'DDM', K) + + +def DM_sdm(lol, K): + """Make a SDM over K from lol.""" + return _DM(lol, 'SDM', K) + + +def DM_dfm(lol, K): + """Make a DFM over K from lol.""" + return _DM(lol, 'DFM', K) + + +def DMZ_ddm(lol): + """Make a DDM from lol.""" + return _DMZ(lol, 'DDM') + + +def DMZ_sdm(lol): + """Make a SDM from lol.""" + return _DMZ(lol, 'SDM') + + +def DMZ_dfm(lol): + """Make a DFM from lol.""" + return _DMZ(lol, 'DFM') + + +def DMQ_ddm(lol): + """Make a DDM from lol.""" + return _DMQ(lol, 'DDM') + + +def DMQ_sdm(lol): + """Make a SDM from lol.""" + return _DMQ(lol, 'SDM') + + +def DMQ_dfm(lol): + """Make a DFM from lol.""" + return _DMQ(lol, 'DFM') + + +DM_all = [DM_ddm, DM_sdm, DM_dfm] +DMZ_all = [DMZ_ddm, DMZ_sdm, DMZ_dfm] +DMQ_all = [DMQ_ddm, DMQ_sdm, DMQ_dfm] + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XDM_getitem(DM): + """Test getitem for DDM, etc.""" + + lol = [[0, 1], [2, 0]] + A = DM(lol) + m, n = A.shape + + indices = [-3, -2, -1, 0, 1, 2] + + for i in indices: + for j in indices: + if -2 <= i < m and -2 <= j < n: + assert A.getitem(i, j) == ZZ(lol[i][j]) + else: + raises(IndexError, lambda: A.getitem(i, j)) + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XDM_setitem(DM): + """Test setitem for DDM, etc.""" + + A = DM([[0, 1, 2], [3, 4, 5]]) + + A.setitem(0, 0, ZZ(6)) + assert A == DM([[6, 1, 2], [3, 4, 5]]) + + A.setitem(0, 1, ZZ(7)) + assert A == DM([[6, 7, 2], [3, 4, 5]]) + + A.setitem(0, 2, ZZ(8)) + assert A == DM([[6, 7, 8], [3, 4, 5]]) + + A.setitem(0, -1, ZZ(9)) + assert A == DM([[6, 7, 9], [3, 4, 5]]) + + A.setitem(0, -2, ZZ(10)) + assert A == DM([[6, 10, 9], [3, 4, 5]]) + + A.setitem(0, -3, ZZ(11)) + assert A == DM([[11, 10, 9], [3, 4, 5]]) + + raises(IndexError, lambda: A.setitem(0, 3, ZZ(12))) + raises(IndexError, lambda: A.setitem(0, -4, ZZ(13))) + + A.setitem(1, 0, ZZ(14)) + assert A == DM([[11, 10, 9], [14, 4, 5]]) + + A.setitem(1, 1, ZZ(15)) + assert A == DM([[11, 10, 9], [14, 15, 5]]) + + A.setitem(-1, 1, ZZ(16)) + assert A == DM([[11, 10, 9], [14, 16, 5]]) + + A.setitem(-2, 1, ZZ(17)) + assert A == DM([[11, 17, 9], [14, 16, 5]]) + + raises(IndexError, lambda: A.setitem(2, 0, ZZ(18))) + raises(IndexError, lambda: A.setitem(-3, 0, ZZ(19))) + + A.setitem(1, 2, ZZ(0)) + assert A == DM([[11, 17, 9], [14, 16, 0]]) + + A.setitem(1, -2, ZZ(0)) + assert A == DM([[11, 17, 9], [14, 0, 0]]) + + A.setitem(1, -3, ZZ(0)) + assert A == DM([[11, 17, 9], [0, 0, 0]]) + + A.setitem(0, 0, ZZ(0)) + assert A == DM([[0, 17, 9], [0, 0, 0]]) + + A.setitem(0, -1, ZZ(0)) + assert A == DM([[0, 17, 0], [0, 0, 0]]) + + A.setitem(0, 0, ZZ(0)) + assert A == DM([[0, 17, 0], [0, 0, 0]]) + + A.setitem(0, -2, ZZ(0)) + assert A == DM([[0, 0, 0], [0, 0, 0]]) + + A.setitem(0, -3, ZZ(1)) + assert A == DM([[1, 0, 0], [0, 0, 0]]) + + +class _Sliced: + def __getitem__(self, item): + return item + + +_slice = _Sliced() + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_extract_slice(DM): + A = DM([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + assert A.extract_slice(*_slice[:,:]) == A + assert A.extract_slice(*_slice[1:,:]) == DM([[4, 5, 6], [7, 8, 9]]) + assert A.extract_slice(*_slice[1:,1:]) == DM([[5, 6], [8, 9]]) + assert A.extract_slice(*_slice[1:,:-1]) == DM([[4, 5], [7, 8]]) + assert A.extract_slice(*_slice[1:,:-1:2]) == DM([[4], [7]]) + assert A.extract_slice(*_slice[:,::2]) == DM([[1, 3], [4, 6], [7, 9]]) + assert A.extract_slice(*_slice[::2,:]) == DM([[1, 2, 3], [7, 8, 9]]) + assert A.extract_slice(*_slice[::2,::2]) == DM([[1, 3], [7, 9]]) + assert A.extract_slice(*_slice[::2,::-2]) == DM([[3, 1], [9, 7]]) + assert A.extract_slice(*_slice[::-2,::2]) == DM([[7, 9], [1, 3]]) + assert A.extract_slice(*_slice[::-2,::-2]) == DM([[9, 7], [3, 1]]) + assert A.extract_slice(*_slice[:,::-1]) == DM([[3, 2, 1], [6, 5, 4], [9, 8, 7]]) + assert A.extract_slice(*_slice[::-1,:]) == DM([[7, 8, 9], [4, 5, 6], [1, 2, 3]]) + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_extract(DM): + + A = DM([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + + assert A.extract([0, 1, 2], [0, 1, 2]) == A + assert A.extract([1, 2], [1, 2]) == DM([[5, 6], [8, 9]]) + assert A.extract([1, 2], [0, 1]) == DM([[4, 5], [7, 8]]) + assert A.extract([1, 2], [0, 2]) == DM([[4, 6], [7, 9]]) + assert A.extract([1, 2], [0]) == DM([[4], [7]]) + assert A.extract([1, 2], []) == DM([[1]]).zeros((2, 0), ZZ) + assert A.extract([], [0, 1, 2]) == DM([[1]]).zeros((0, 3), ZZ) + + raises(IndexError, lambda: A.extract([1, 2], [0, 3])) + raises(IndexError, lambda: A.extract([1, 2], [0, -4])) + raises(IndexError, lambda: A.extract([3, 1], [0, 1])) + raises(IndexError, lambda: A.extract([-4, 2], [3, 1])) + + B = DM([[0, 0, 0], [0, 0, 0], [0, 0, 0]]) + assert B.extract([1, 2], [1, 2]) == DM([[0, 0], [0, 0]]) + + +def test_XXM_str(): + + A = DomainMatrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]], (3, 3), ZZ) + + assert str(A) == \ + 'DomainMatrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]], (3, 3), ZZ)' + assert str(A.to_ddm()) == \ + '[[1, 2, 3], [4, 5, 6], [7, 8, 9]]' + assert str(A.to_sdm()) == \ + '{0: {0: 1, 1: 2, 2: 3}, 1: {0: 4, 1: 5, 2: 6}, 2: {0: 7, 1: 8, 2: 9}}' + + assert repr(A) == \ + 'DomainMatrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]], (3, 3), ZZ)' + assert repr(A.to_ddm()) == \ + 'DDM([[1, 2, 3], [4, 5, 6], [7, 8, 9]], (3, 3), ZZ)' + assert repr(A.to_sdm()) == \ + 'SDM({0: {0: 1, 1: 2, 2: 3}, 1: {0: 4, 1: 5, 2: 6}, 2: {0: 7, 1: 8, 2: 9}}, (3, 3), ZZ)' + + B = DomainMatrix({0: {0: ZZ(1), 1: ZZ(2)}, 1: {0: ZZ(3)}}, (2, 2), ZZ) + + assert str(B) == \ + 'DomainMatrix({0: {0: 1, 1: 2}, 1: {0: 3}}, (2, 2), ZZ)' + assert str(B.to_ddm()) == \ + '[[1, 2], [3, 0]]' + assert str(B.to_sdm()) == \ + '{0: {0: 1, 1: 2}, 1: {0: 3}}' + + assert repr(B) == \ + 'DomainMatrix({0: {0: 1, 1: 2}, 1: {0: 3}}, (2, 2), ZZ)' + + if GROUND_TYPES != 'gmpy': + assert repr(B.to_ddm()) == \ + 'DDM([[1, 2], [3, 0]], (2, 2), ZZ)' + assert repr(B.to_sdm()) == \ + 'SDM({0: {0: 1, 1: 2}, 1: {0: 3}}, (2, 2), ZZ)' + else: + assert repr(B.to_ddm()) == \ + 'DDM([[mpz(1), mpz(2)], [mpz(3), mpz(0)]], (2, 2), ZZ)' + assert repr(B.to_sdm()) == \ + 'SDM({0: {0: mpz(1), 1: mpz(2)}, 1: {0: mpz(3)}}, (2, 2), ZZ)' + + if GROUND_TYPES == 'flint': + + assert str(A.to_dfm()) == \ + '[[1, 2, 3], [4, 5, 6], [7, 8, 9]]' + assert str(B.to_dfm()) == \ + '[[1, 2], [3, 0]]' + + assert repr(A.to_dfm()) == \ + 'DFM([[1, 2, 3], [4, 5, 6], [7, 8, 9]], (3, 3), ZZ)' + assert repr(B.to_dfm()) == \ + 'DFM([[1, 2], [3, 0]], (2, 2), ZZ)' + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_from_list(DM): + T = type(DM([[0]])) + + lol = [[1, 2, 4], [4, 5, 6]] + lol_ZZ = [[ZZ(1), ZZ(2), ZZ(4)], [ZZ(4), ZZ(5), ZZ(6)]] + lol_ZZ_bad = [[ZZ(1), ZZ(2), ZZ(4)], [ZZ(4), ZZ(5), ZZ(6), ZZ(7)]] + + assert T.from_list(lol_ZZ, (2, 3), ZZ) == DM(lol) + raises(DMBadInputError, lambda: T.from_list(lol_ZZ_bad, (3, 2), ZZ)) + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_to_list(DM): + lol = [[1, 2, 4], [4, 5, 6]] + assert DM(lol).to_list() == [[ZZ(1), ZZ(2), ZZ(4)], [ZZ(4), ZZ(5), ZZ(6)]] + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_to_list_flat(DM): + lol = [[1, 2, 4], [4, 5, 6]] + assert DM(lol).to_list_flat() == [ZZ(1), ZZ(2), ZZ(4), ZZ(4), ZZ(5), ZZ(6)] + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_from_list_flat(DM): + T = type(DM([[0]])) + flat = [ZZ(1), ZZ(2), ZZ(4), ZZ(4), ZZ(5), ZZ(6)] + assert T.from_list_flat(flat, (2, 3), ZZ) == DM([[1, 2, 4], [4, 5, 6]]) + raises(DMBadInputError, lambda: T.from_list_flat(flat, (3, 3), ZZ)) + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_to_flat_nz(DM): + M = DM([[1, 2, 0], [0, 0, 0], [0, 0, 3]]) + elements = [ZZ(1), ZZ(2), ZZ(3)] + indices = ((0, 0), (0, 1), (2, 2)) + assert M.to_flat_nz() == (elements, (indices, M.shape)) + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_from_flat_nz(DM): + T = type(DM([[0]])) + elements = [ZZ(1), ZZ(2), ZZ(3)] + indices = ((0, 0), (0, 1), (2, 2)) + data = (indices, (3, 3)) + result = DM([[1, 2, 0], [0, 0, 0], [0, 0, 3]]) + assert T.from_flat_nz(elements, data, ZZ) == result + raises(DMBadInputError, lambda: T.from_flat_nz(elements, (indices, (2, 3)), ZZ)) + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_to_dod(DM): + dod = {0: {0: ZZ(1), 2: ZZ(4)}, 1: {0: ZZ(4), 1: ZZ(5), 2: ZZ(6)}} + assert DM([[1, 0, 4], [4, 5, 6]]).to_dod() == dod + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_from_dod(DM): + T = type(DM([[0]])) + dod = {0: {0: ZZ(1), 2: ZZ(4)}, 1: {0: ZZ(4), 1: ZZ(5), 2: ZZ(6)}} + assert T.from_dod(dod, (2, 3), ZZ) == DM([[1, 0, 4], [4, 5, 6]]) + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_to_dok(DM): + dod = {(0, 0): ZZ(1), (0, 2): ZZ(4), + (1, 0): ZZ(4), (1, 1): ZZ(5), (1, 2): ZZ(6)} + assert DM([[1, 0, 4], [4, 5, 6]]).to_dok() == dod + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_from_dok(DM): + T = type(DM([[0]])) + dod = {(0, 0): ZZ(1), (0, 2): ZZ(4), + (1, 0): ZZ(4), (1, 1): ZZ(5), (1, 2): ZZ(6)} + assert T.from_dok(dod, (2, 3), ZZ) == DM([[1, 0, 4], [4, 5, 6]]) + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_iter_values(DM): + values = [ZZ(1), ZZ(4), ZZ(4), ZZ(5), ZZ(6)] + assert sorted(DM([[1, 0, 4], [4, 5, 6]]).iter_values()) == values + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_iter_items(DM): + items = [((0, 0), ZZ(1)), ((0, 2), ZZ(4)), + ((1, 0), ZZ(4)), ((1, 1), ZZ(5)), ((1, 2), ZZ(6))] + assert sorted(DM([[1, 0, 4], [4, 5, 6]]).iter_items()) == items + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_from_ddm(DM): + T = type(DM([[0]])) + ddm = DDM([[1, 2, 4], [4, 5, 6]], (2, 3), ZZ) + assert T.from_ddm(ddm) == DM([[1, 2, 4], [4, 5, 6]]) + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_zeros(DM): + T = type(DM([[0]])) + assert T.zeros((2, 3), ZZ) == DM([[0, 0, 0], [0, 0, 0]]) + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_ones(DM): + T = type(DM([[0]])) + assert T.ones((2, 3), ZZ) == DM([[1, 1, 1], [1, 1, 1]]) + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_eye(DM): + T = type(DM([[0]])) + assert T.eye(3, ZZ) == DM([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) + assert T.eye((3, 2), ZZ) == DM([[1, 0], [0, 1], [0, 0]]) + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_diag(DM): + T = type(DM([[0]])) + assert T.diag([1, 2, 3], ZZ) == DM([[1, 0, 0], [0, 2, 0], [0, 0, 3]]) + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_transpose(DM): + A = DM([[1, 2, 3], [4, 5, 6]]) + assert A.transpose() == DM([[1, 4], [2, 5], [3, 6]]) + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_add(DM): + A = DM([[1, 2, 3], [4, 5, 6]]) + B = DM([[1, 2, 3], [4, 5, 6]]) + C = DM([[2, 4, 6], [8, 10, 12]]) + assert A.add(B) == C + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_sub(DM): + A = DM([[1, 2, 3], [4, 5, 6]]) + B = DM([[1, 2, 3], [4, 5, 6]]) + C = DM([[0, 0, 0], [0, 0, 0]]) + assert A.sub(B) == C + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_mul(DM): + A = DM([[1, 2, 3], [4, 5, 6]]) + b = ZZ(2) + assert A.mul(b) == DM([[2, 4, 6], [8, 10, 12]]) + assert A.rmul(b) == DM([[2, 4, 6], [8, 10, 12]]) + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_matmul(DM): + A = DM([[1, 2, 3], [4, 5, 6]]) + B = DM([[1, 2], [3, 4], [5, 6]]) + C = DM([[22, 28], [49, 64]]) + assert A.matmul(B) == C + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_mul_elementwise(DM): + A = DM([[1, 2, 3], [4, 5, 6]]) + B = DM([[1, 2, 3], [4, 5, 6]]) + C = DM([[1, 4, 9], [16, 25, 36]]) + assert A.mul_elementwise(B) == C + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_neg(DM): + A = DM([[1, 2, 3], [4, 5, 6]]) + C = DM([[-1, -2, -3], [-4, -5, -6]]) + assert A.neg() == C + + +@pytest.mark.parametrize('DM', DM_all) +def test_XXM_convert_to(DM): + A = DM([[1, 2, 3], [4, 5, 6]], ZZ) + B = DM([[1, 2, 3], [4, 5, 6]], QQ) + assert A.convert_to(QQ) == B + assert B.convert_to(ZZ) == A + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_scc(DM): + A = DM([ + [0, 1, 0, 0, 0, 0], + [1, 0, 0, 0, 0, 0], + [0, 0, 1, 0, 0, 0], + [0, 0, 0, 1, 0, 1], + [0, 0, 0, 0, 1, 0], + [0, 0, 0, 1, 0, 1]]) + assert A.scc() == [[0, 1], [2], [3, 5], [4]] + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_hstack(DM): + A = DM([[1, 2, 3], [4, 5, 6]]) + B = DM([[7, 8], [9, 10]]) + C = DM([[1, 2, 3, 7, 8], [4, 5, 6, 9, 10]]) + ABC = DM([[1, 2, 3, 7, 8, 1, 2, 3, 7, 8], + [4, 5, 6, 9, 10, 4, 5, 6, 9, 10]]) + assert A.hstack(B) == C + assert A.hstack(B, C) == ABC + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_vstack(DM): + A = DM([[1, 2, 3], [4, 5, 6]]) + B = DM([[7, 8, 9]]) + C = DM([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + ABC = DM([[1, 2, 3], [4, 5, 6], [7, 8, 9], [1, 2, 3], [4, 5, 6], [7, 8, 9]]) + assert A.vstack(B) == C + assert A.vstack(B, C) == ABC + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_applyfunc(DM): + A = DM([[1, 2, 3], [4, 5, 6]]) + B = DM([[2, 4, 6], [8, 10, 12]]) + assert A.applyfunc(lambda x: 2*x, ZZ) == B + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_is_upper(DM): + assert DM([[1, 2, 3], [0, 5, 6]]).is_upper() is True + assert DM([[1, 2, 3], [4, 5, 6]]).is_upper() is False + assert DM([]).is_upper() is True + assert DM([[], []]).is_upper() is True + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_is_lower(DM): + assert DM([[1, 0, 0], [4, 5, 0]]).is_lower() is True + assert DM([[1, 2, 3], [4, 5, 6]]).is_lower() is False + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_is_diagonal(DM): + assert DM([[1, 0, 0], [0, 5, 0]]).is_diagonal() is True + assert DM([[1, 2, 3], [4, 5, 6]]).is_diagonal() is False + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_diagonal(DM): + assert DM([[1, 0, 0], [0, 5, 0]]).diagonal() == [1, 5] + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_is_zero_matrix(DM): + assert DM([[0, 0, 0], [0, 0, 0]]).is_zero_matrix() is True + assert DM([[1, 0, 0], [0, 0, 0]]).is_zero_matrix() is False + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_det_ZZ(DM): + assert DM([[1, 2, 3], [4, 5, 6], [7, 8, 9]]).det() == 0 + assert DM([[1, 2, 3], [4, 5, 6], [7, 8, 10]]).det() == -3 + + +@pytest.mark.parametrize('DM', DMQ_all) +def test_XXM_det_QQ(DM): + dM1 = DM([[(1,2), (2,3)], [(3,4), (4,5)]]) + assert dM1.det() == QQ(-1,10) + + +@pytest.mark.parametrize('DM', DMQ_all) +def test_XXM_inv_QQ(DM): + dM1 = DM([[(1,2), (2,3)], [(3,4), (4,5)]]) + dM2 = DM([[(-8,1), (20,3)], [(15,2), (-5,1)]]) + assert dM1.inv() == dM2 + assert dM1.matmul(dM2) == DM([[1, 0], [0, 1]]) + + dM3 = DM([[(1,2), (2,3)], [(1,4), (1,3)]]) + raises(DMNonInvertibleMatrixError, lambda: dM3.inv()) + + dM4 = DM([[(1,2), (2,3), (3,4)], [(1,4), (1,3), (1,2)]]) + raises(DMNonSquareMatrixError, lambda: dM4.inv()) + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_inv_ZZ(DM): + dM1 = DM([[1, 2, 3], [4, 5, 6], [7, 8, 10]]) + # XXX: Maybe this should return a DM over QQ instead? + # XXX: Handle unimodular matrices? + raises(DMDomainError, lambda: dM1.inv()) + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_charpoly_ZZ(DM): + dM1 = DM([[1, 2, 3], [4, 5, 6], [7, 8, 10]]) + assert dM1.charpoly() == [1, -16, -12, 3] + + +@pytest.mark.parametrize('DM', DMQ_all) +def test_XXM_charpoly_QQ(DM): + dM1 = DM([[(1,2), (2,3)], [(3,4), (4,5)]]) + assert dM1.charpoly() == [QQ(1,1), QQ(-13,10), QQ(-1,10)] + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_lu_solve_ZZ(DM): + dM1 = DM([[1, 2, 3], [4, 5, 6], [7, 8, 10]]) + dM2 = DM([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) + raises(DMDomainError, lambda: dM1.lu_solve(dM2)) + + +@pytest.mark.parametrize('DM', DMQ_all) +def test_XXM_lu_solve_QQ(DM): + dM1 = DM([[1, 2, 3], [4, 5, 6], [7, 8, 10]]) + dM2 = DM([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) + dM3 = DM([[(-2,3),(-4,3),(1,1)],[(-2,3),(11,3),(-2,1)],[(1,1),(-2,1),(1,1)]]) + assert dM1.lu_solve(dM2) == dM3 == dM1.inv() + + dM4 = DM([[1, 2, 3], [4, 5, 6]]) + dM5 = DM([[1, 0], [0, 1], [0, 0]]) + raises(DMShapeError, lambda: dM4.lu_solve(dM5)) + + +@pytest.mark.parametrize('DM', DMQ_all) +def test_XXM_nullspace_QQ(DM): + dM1 = DM([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + # XXX: Change the signature to just return the nullspace. Possibly + # returning the rank or nullity makes sense but the list of nonpivots is + # not useful. + assert dM1.nullspace() == (DM([[1, -2, 1]]), [2]) + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_lll(DM): + M = DM([[1, 2, 3], [4, 5, 20]]) + M_lll = DM([[1, 2, 3], [-1, -5, 5]]) + T = DM([[1, 0], [-5, 1]]) + assert M.lll() == M_lll + assert M.lll_transform() == (M_lll, T) + assert T.matmul(M) == M_lll + + +@pytest.mark.parametrize('DM', DMQ_all) +def test_XXM_qr_mixed_signs(DM): + lol = [[QQ(1), QQ(-2)], [QQ(-3), QQ(4)]] + A = DM(lol) + Q, R = A.qr() + assert Q.matmul(R) == A + assert (Q.transpose().matmul(Q)).is_diagonal + assert R.is_upper + + +@pytest.mark.parametrize('DM', DMQ_all) +def test_XXM_qr_large_matrix(DM): + lol = [[QQ(i + j) for j in range(10)] for i in range(10)] + A = DM(lol) + Q, R = A.qr() + assert Q.matmul(R) == A + assert (Q.transpose().matmul(Q)).is_diagonal + assert R.is_upper + + +@pytest.mark.parametrize('DM', DMQ_all) +def test_XXM_qr_identity_matrix(DM): + T = type(DM([[0]])) + A = T.eye(3, QQ) + Q, R = A.qr() + assert Q == A + assert R == A + assert (Q.transpose().matmul(Q)).is_diagonal + assert R.is_upper + assert Q.shape == (3, 3) + assert R.shape == (3, 3) + + +@pytest.mark.parametrize('DM', DMQ_all) +def test_XXM_qr_square_matrix(DM): + lol = [[QQ(3), QQ(1)], [QQ(4), QQ(3)]] + A = DM(lol) + Q, R = A.qr() + assert Q.matmul(R) == A + assert (Q.transpose().matmul(Q)).is_diagonal + assert R.is_upper + + +@pytest.mark.parametrize('DM', DMQ_all) +def test_XXM_qr_matrix_with_zero_columns(DM): + lol = [[QQ(3), QQ(0)], [QQ(4), QQ(0)]] + A = DM(lol) + Q, R = A.qr() + assert Q.matmul(R) == A + assert (Q.transpose().matmul(Q)).is_diagonal + assert R.is_upper + + +@pytest.mark.parametrize('DM', DMQ_all) +def test_XXM_qr_linearly_dependent_columns(DM): + lol = [[QQ(1), QQ(2)], [QQ(2), QQ(4)]] + A = DM(lol) + Q, R = A.qr() + assert Q.matmul(R) == A + assert (Q.transpose().matmul(Q)).is_diagonal + assert R.is_upper + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_qr_non_field(DM): + lol = [[ZZ(3), ZZ(1)], [ZZ(4), ZZ(3)]] + A = DM(lol) + with pytest.raises(DMDomainError): + A.qr() + + +@pytest.mark.parametrize('DM', DMQ_all) +def test_XXM_qr_field(DM): + lol = [[QQ(3), QQ(1)], [QQ(4), QQ(3)]] + A = DM(lol) + Q, R = A.qr() + assert Q.matmul(R) == A + assert (Q.transpose().matmul(Q)).is_diagonal + assert R.is_upper + + +@pytest.mark.parametrize('DM', DMQ_all) +def test_XXM_qr_tall_matrix(DM): + lol = [[QQ(1), QQ(2)], [QQ(3), QQ(4)], [QQ(5), QQ(6)]] + A = DM(lol) + Q, R = A.qr() + assert Q.matmul(R) == A + assert (Q.transpose().matmul(Q)).is_diagonal + assert R.is_upper + + +@pytest.mark.parametrize('DM', DMQ_all) +def test_XXM_qr_wide_matrix(DM): + lol = [[QQ(1), QQ(2), QQ(3)], [QQ(4), QQ(5), QQ(6)]] + A = DM(lol) + Q, R = A.qr() + assert Q.matmul(R) == A + assert (Q.transpose().matmul(Q)).is_diagonal + assert R.is_upper + + +@pytest.mark.parametrize('DM', DMQ_all) +def test_XXM_qr_empty_matrix_0x0(DM): + T = type(DM([[0]])) + A = T.zeros((0, 0), QQ) + Q, R = A.qr() + assert Q.matmul(R).shape == A.shape + assert (Q.transpose().matmul(Q)).is_diagonal + assert R.is_upper + assert Q.shape == (0, 0) + assert R.shape == (0, 0) + + +@pytest.mark.parametrize('DM', DMQ_all) +def test_XXM_qr_empty_matrix_2x0(DM): + T = type(DM([[0]])) + A = T.zeros((2, 0), QQ) + Q, R = A.qr() + assert Q.matmul(R).shape == A.shape + assert (Q.transpose().matmul(Q)).is_diagonal + assert R.is_upper + assert Q.shape == (2, 0) + assert R.shape == (0, 0) + + +@pytest.mark.parametrize('DM', DMQ_all) +def test_XXM_qr_empty_matrix_0x2(DM): + T = type(DM([[0]])) + A = T.zeros((0, 2), QQ) + Q, R = A.qr() + assert Q.matmul(R).shape == A.shape + assert (Q.transpose().matmul(Q)).is_diagonal + assert R.is_upper + assert Q.shape == (0, 0) + assert R.shape == (0, 2) + + +@pytest.mark.parametrize('DM', DMZ_all) +def test_XXM_fflu(DM): + A = DM([[1, 2], [3, 4]]) + P, L, D, U = A.fflu() + A_field = A.convert_to(QQ) + P_field = P.convert_to(QQ) + L_field = L.convert_to(QQ) + D_field = D.convert_to(QQ) + U_field = U.convert_to(QQ) + assert P.shape == A.shape + assert L.shape == A.shape + assert D.shape == A.shape + assert U.shape == A.shape + assert P == DM([[1, 0], [0, 1]]) + assert L == DM([[1, 0], [3, -2]]) + assert D == DM([[1, 0], [0, -2]]) + assert U == DM([[1, 2], [0, -2]]) + assert L_field.matmul(D_field.inv()).matmul(U_field) == P_field.matmul(A_field) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..955d50525adbdeebf1819ddd57bf54a713874822 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/aesaracode.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/aesaracode.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c016a2028a896dffe48593994ca030c2bf4ca104 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/aesaracode.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/c.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/c.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..afacc7ac373ef30e5ebb19a3a80d2442620902bf Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/c.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/codeprinter.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/codeprinter.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e337aa693e35dcd0a01173f6415f2aca6146c06b Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/codeprinter.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/conventions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/conventions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d92e62d2050dc7aaed12ccccc349e38ca244d6e6 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/conventions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/cxx.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/cxx.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..870406a5263f40692870774cf0bbdf56ef95170e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/cxx.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/defaults.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/defaults.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..026d5f2a39eb2eda1c975280a5c13712bcf6404f Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/defaults.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/dot.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/dot.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f77764af856b17bc5f6e1faed7746f20d0c9a301 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/dot.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/fortran.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/fortran.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..60e5e22bca4ec01c1322c1b42daa34522ece318a Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/fortran.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/glsl.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/glsl.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7a770179c71986cad98ef5bcfe6f2725b95fc45f Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/glsl.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/gtk.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/gtk.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8d40199de44f1c0b110c8027435262f4893bd63d Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/gtk.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/jscode.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/jscode.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..60586d8c5a52ab00d6786e6e68cf42ded74c92b4 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/jscode.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/julia.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/julia.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c57c7dcb44c8d84247ced6c382d9a5f67773e35e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/julia.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/lambdarepr.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/lambdarepr.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4c2de5caa334cb975ef7a71c54a3c87eee241c10 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/lambdarepr.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/llvmjitcode.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/llvmjitcode.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..95b1add94015858f8b32a3efc990e5feaa69d574 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/llvmjitcode.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/maple.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/maple.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ff48d5c165318602424f42687cf9baa53029771c Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/maple.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/mathematica.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/mathematica.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..86ca5bf899bb471d94218e55993a558dc9457cac Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/mathematica.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/numpy.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/numpy.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..af71a7bd1969b8809711a0d51a66e25b71bc0315 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/numpy.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/octave.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/octave.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7bcc06667c0fd75a979ca651dfa4715d538b6d15 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/octave.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/precedence.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/precedence.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..db440832661021fe3e315b1042dab0b13d0fad88 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/precedence.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/preview.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/preview.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b0a705eb5e856e28c6cd743457d13d62539d092e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/preview.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/printer.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/printer.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c8f1dc9ed6daa1d417a15742a4d27dcdd3d97974 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/printer.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/pycode.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/pycode.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6c499f9bb5ee65cdeee4bb16a7b822178d5a3571 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/pycode.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/python.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/python.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..906c2a8d305201578f343bc1a56428433377e252 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/python.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/pytorch.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/pytorch.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..331aafc5312dac10658852e79f48564bc45bca44 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/pytorch.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/rcode.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/rcode.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a68d5a3a30abbae21d31a5682cf5db522da963fd Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/rcode.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/repr.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/repr.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f475a7a13bf97118feb4291ae0c4302574959189 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/repr.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/rust.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/rust.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bfa02e369c34fb34b60533ccd64bcd0b849c10aa Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/rust.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/smtlib.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/smtlib.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..62c2e23a3dbbd99c5cc7c60eb4dbe045588bdadd Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/smtlib.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/str.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/str.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9629e54eda31b781e96cc54e48178b81e576c81d Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/str.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/tableform.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/tableform.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..da52ebb567df4e820852279cf26a8020d8baad7c Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/tableform.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/tensorflow.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/tensorflow.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..32af9fc35acd37bb6f0b049ab40674a5227eb8eb Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/tensorflow.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/theanocode.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/theanocode.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..779bdf0613b9e754e215f8ae351bf26cc30bdc03 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/theanocode.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/tree.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/tree.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..537f36aa185995a3c659db8276e01e09b830f025 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/__pycache__/tree.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..cbabc649152a3c353a37225d342064634fbb5805 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/__init__.py @@ -0,0 +1,12 @@ +"""ASCII-ART 2D pretty-printer""" + +from .pretty import (pretty, pretty_print, pprint, pprint_use_unicode, + pprint_try_use_unicode, pager_print) + +# if unicode output is available -- let's use it +pprint_try_use_unicode() + +__all__ = [ + 'pretty', 'pretty_print', 'pprint', 'pprint_use_unicode', + 'pprint_try_use_unicode', 'pager_print', +] diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cad2a28570bafd6992f02794501b111db8f360b5 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/__pycache__/pretty_symbology.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/__pycache__/pretty_symbology.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d1c4a72c9af7b7581985129fff81b3e634530d9f Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/__pycache__/pretty_symbology.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/__pycache__/stringpict.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/__pycache__/stringpict.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fb1ecc70509382eaa7963155ae1a6be509386a3f Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/__pycache__/stringpict.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/pretty.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/pretty.py new file mode 100644 index 0000000000000000000000000000000000000000..b945f009119b24fc95e8452d91359957baba26a8 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/pretty.py @@ -0,0 +1,2937 @@ +import itertools + +from sympy.core import S +from sympy.core.add import Add +from sympy.core.containers import Tuple +from sympy.core.function import Function +from sympy.core.mul import Mul +from sympy.core.numbers import Number, Rational +from sympy.core.power import Pow +from sympy.core.sorting import default_sort_key +from sympy.core.symbol import Symbol +from sympy.core.sympify import SympifyError +from sympy.printing.conventions import requires_partial +from sympy.printing.precedence import PRECEDENCE, precedence, precedence_traditional +from sympy.printing.printer import Printer, print_function +from sympy.printing.str import sstr +from sympy.utilities.iterables import has_variety +from sympy.utilities.exceptions import sympy_deprecation_warning + +from sympy.printing.pretty.stringpict import prettyForm, stringPict +from sympy.printing.pretty.pretty_symbology import hobj, vobj, xobj, \ + xsym, pretty_symbol, pretty_atom, pretty_use_unicode, greek_unicode, U, \ + pretty_try_use_unicode, annotated, is_subscriptable_in_unicode, center_pad, root as nth_root + +# rename for usage from outside +pprint_use_unicode = pretty_use_unicode +pprint_try_use_unicode = pretty_try_use_unicode + + +class PrettyPrinter(Printer): + """Printer, which converts an expression into 2D ASCII-art figure.""" + printmethod = "_pretty" + + _default_settings = { + "order": None, + "full_prec": "auto", + "use_unicode": None, + "wrap_line": True, + "num_columns": None, + "use_unicode_sqrt_char": True, + "root_notation": True, + "mat_symbol_style": "plain", + "imaginary_unit": "i", + "perm_cyclic": True + } + + def __init__(self, settings=None): + Printer.__init__(self, settings) + + if not isinstance(self._settings['imaginary_unit'], str): + raise TypeError("'imaginary_unit' must a string, not {}".format(self._settings['imaginary_unit'])) + elif self._settings['imaginary_unit'] not in ("i", "j"): + raise ValueError("'imaginary_unit' must be either 'i' or 'j', not '{}'".format(self._settings['imaginary_unit'])) + + def emptyPrinter(self, expr): + return prettyForm(str(expr)) + + @property + def _use_unicode(self): + if self._settings['use_unicode']: + return True + else: + return pretty_use_unicode() + + def doprint(self, expr): + return self._print(expr).render(**self._settings) + + # empty op so _print(stringPict) returns the same + def _print_stringPict(self, e): + return e + + def _print_basestring(self, e): + return prettyForm(e) + + def _print_atan2(self, e): + pform = prettyForm(*self._print_seq(e.args).parens()) + pform = prettyForm(*pform.left('atan2')) + return pform + + def _print_Symbol(self, e, bold_name=False): + symb = pretty_symbol(e.name, bold_name) + return prettyForm(symb) + _print_RandomSymbol = _print_Symbol + def _print_MatrixSymbol(self, e): + return self._print_Symbol(e, self._settings['mat_symbol_style'] == "bold") + + def _print_Float(self, e): + # we will use StrPrinter's Float printer, but we need to handle the + # full_prec ourselves, according to the self._print_level + full_prec = self._settings["full_prec"] + if full_prec == "auto": + full_prec = self._print_level == 1 + return prettyForm(sstr(e, full_prec=full_prec)) + + def _print_Cross(self, e): + vec1 = e._expr1 + vec2 = e._expr2 + pform = self._print(vec2) + pform = prettyForm(*pform.left('(')) + pform = prettyForm(*pform.right(')')) + pform = prettyForm(*pform.left(self._print(U('MULTIPLICATION SIGN')))) + pform = prettyForm(*pform.left(')')) + pform = prettyForm(*pform.left(self._print(vec1))) + pform = prettyForm(*pform.left('(')) + return pform + + def _print_Curl(self, e): + vec = e._expr + pform = self._print(vec) + pform = prettyForm(*pform.left('(')) + pform = prettyForm(*pform.right(')')) + pform = prettyForm(*pform.left(self._print(U('MULTIPLICATION SIGN')))) + pform = prettyForm(*pform.left(self._print(U('NABLA')))) + return pform + + def _print_Divergence(self, e): + vec = e._expr + pform = self._print(vec) + pform = prettyForm(*pform.left('(')) + pform = prettyForm(*pform.right(')')) + pform = prettyForm(*pform.left(self._print(U('DOT OPERATOR')))) + pform = prettyForm(*pform.left(self._print(U('NABLA')))) + return pform + + def _print_Dot(self, e): + vec1 = e._expr1 + vec2 = e._expr2 + pform = self._print(vec2) + pform = prettyForm(*pform.left('(')) + pform = prettyForm(*pform.right(')')) + pform = prettyForm(*pform.left(self._print(U('DOT OPERATOR')))) + pform = prettyForm(*pform.left(')')) + pform = prettyForm(*pform.left(self._print(vec1))) + pform = prettyForm(*pform.left('(')) + return pform + + def _print_Gradient(self, e): + func = e._expr + pform = self._print(func) + pform = prettyForm(*pform.left('(')) + pform = prettyForm(*pform.right(')')) + pform = prettyForm(*pform.left(self._print(U('NABLA')))) + return pform + + def _print_Laplacian(self, e): + func = e._expr + pform = self._print(func) + pform = prettyForm(*pform.left('(')) + pform = prettyForm(*pform.right(')')) + pform = prettyForm(*pform.left(self._print(U('INCREMENT')))) + return pform + + def _print_Atom(self, e): + try: + # print atoms like Exp1 or Pi + return prettyForm(pretty_atom(e.__class__.__name__, printer=self)) + except KeyError: + return self.emptyPrinter(e) + + # Infinity inherits from Number, so we have to override _print_XXX order + _print_Infinity = _print_Atom + _print_NegativeInfinity = _print_Atom + _print_EmptySet = _print_Atom + _print_Naturals = _print_Atom + _print_Naturals0 = _print_Atom + _print_Integers = _print_Atom + _print_Rationals = _print_Atom + _print_Complexes = _print_Atom + + _print_EmptySequence = _print_Atom + + def _print_Reals(self, e): + if self._use_unicode: + return self._print_Atom(e) + else: + inf_list = ['-oo', 'oo'] + return self._print_seq(inf_list, '(', ')') + + def _print_subfactorial(self, e): + x = e.args[0] + pform = self._print(x) + # Add parentheses if needed + if not ((x.is_Integer and x.is_nonnegative) or x.is_Symbol): + pform = prettyForm(*pform.parens()) + pform = prettyForm(*pform.left('!')) + return pform + + def _print_factorial(self, e): + x = e.args[0] + pform = self._print(x) + # Add parentheses if needed + if not ((x.is_Integer and x.is_nonnegative) or x.is_Symbol): + pform = prettyForm(*pform.parens()) + pform = prettyForm(*pform.right('!')) + return pform + + def _print_factorial2(self, e): + x = e.args[0] + pform = self._print(x) + # Add parentheses if needed + if not ((x.is_Integer and x.is_nonnegative) or x.is_Symbol): + pform = prettyForm(*pform.parens()) + pform = prettyForm(*pform.right('!!')) + return pform + + def _print_binomial(self, e): + n, k = e.args + + n_pform = self._print(n) + k_pform = self._print(k) + + bar = ' '*max(n_pform.width(), k_pform.width()) + + pform = prettyForm(*k_pform.above(bar)) + pform = prettyForm(*pform.above(n_pform)) + pform = prettyForm(*pform.parens('(', ')')) + + pform.baseline = (pform.baseline + 1)//2 + + return pform + + def _print_Relational(self, e): + op = prettyForm(' ' + xsym(e.rel_op) + ' ') + + l = self._print(e.lhs) + r = self._print(e.rhs) + pform = prettyForm(*stringPict.next(l, op, r), binding=prettyForm.OPEN) + return pform + + def _print_Not(self, e): + from sympy.logic.boolalg import (Equivalent, Implies) + if self._use_unicode: + arg = e.args[0] + pform = self._print(arg) + if isinstance(arg, Equivalent): + return self._print_Equivalent(arg, altchar=pretty_atom('NotEquiv')) + if isinstance(arg, Implies): + return self._print_Implies(arg, altchar=pretty_atom('NotArrow')) + + if arg.is_Boolean and not arg.is_Not: + pform = prettyForm(*pform.parens()) + + return prettyForm(*pform.left(pretty_atom('Not'))) + else: + return self._print_Function(e) + + def __print_Boolean(self, e, char, sort=True): + args = e.args + if sort: + args = sorted(e.args, key=default_sort_key) + arg = args[0] + pform = self._print(arg) + + if arg.is_Boolean and not arg.is_Not: + pform = prettyForm(*pform.parens()) + + for arg in args[1:]: + pform_arg = self._print(arg) + + if arg.is_Boolean and not arg.is_Not: + pform_arg = prettyForm(*pform_arg.parens()) + + pform = prettyForm(*pform.right(' %s ' % char)) + pform = prettyForm(*pform.right(pform_arg)) + + return pform + + def _print_And(self, e): + if self._use_unicode: + return self.__print_Boolean(e, pretty_atom('And')) + else: + return self._print_Function(e, sort=True) + + def _print_Or(self, e): + if self._use_unicode: + return self.__print_Boolean(e, pretty_atom('Or')) + else: + return self._print_Function(e, sort=True) + + def _print_Xor(self, e): + if self._use_unicode: + return self.__print_Boolean(e, pretty_atom("Xor")) + else: + return self._print_Function(e, sort=True) + + def _print_Nand(self, e): + if self._use_unicode: + return self.__print_Boolean(e, pretty_atom('Nand')) + else: + return self._print_Function(e, sort=True) + + def _print_Nor(self, e): + if self._use_unicode: + return self.__print_Boolean(e, pretty_atom('Nor')) + else: + return self._print_Function(e, sort=True) + + def _print_Implies(self, e, altchar=None): + if self._use_unicode: + return self.__print_Boolean(e, altchar or pretty_atom('Arrow'), sort=False) + else: + return self._print_Function(e) + + def _print_Equivalent(self, e, altchar=None): + if self._use_unicode: + return self.__print_Boolean(e, altchar or pretty_atom('Equiv')) + else: + return self._print_Function(e, sort=True) + + def _print_conjugate(self, e): + pform = self._print(e.args[0]) + return prettyForm( *pform.above( hobj('_', pform.width())) ) + + def _print_Abs(self, e): + pform = self._print(e.args[0]) + pform = prettyForm(*pform.parens('|', '|')) + return pform + + def _print_floor(self, e): + if self._use_unicode: + pform = self._print(e.args[0]) + pform = prettyForm(*pform.parens('lfloor', 'rfloor')) + return pform + else: + return self._print_Function(e) + + def _print_ceiling(self, e): + if self._use_unicode: + pform = self._print(e.args[0]) + pform = prettyForm(*pform.parens('lceil', 'rceil')) + return pform + else: + return self._print_Function(e) + + def _print_Derivative(self, deriv): + if requires_partial(deriv.expr) and self._use_unicode: + deriv_symbol = U('PARTIAL DIFFERENTIAL') + else: + deriv_symbol = r'd' + x = None + count_total_deriv = 0 + + for sym, num in reversed(deriv.variable_count): + s = self._print(sym) + ds = prettyForm(*s.left(deriv_symbol)) + count_total_deriv += num + + if (not num.is_Integer) or (num > 1): + ds = ds**prettyForm(str(num)) + + if x is None: + x = ds + else: + x = prettyForm(*x.right(' ')) + x = prettyForm(*x.right(ds)) + + f = prettyForm( + binding=prettyForm.FUNC, *self._print(deriv.expr).parens()) + + pform = prettyForm(deriv_symbol) + + if (count_total_deriv > 1) != False: + pform = pform**prettyForm(str(count_total_deriv)) + + pform = prettyForm(*pform.below(stringPict.LINE, x)) + pform.baseline = pform.baseline + 1 + pform = prettyForm(*stringPict.next(pform, f)) + pform.binding = prettyForm.MUL + + return pform + + def _print_Cycle(self, dc): + from sympy.combinatorics.permutations import Permutation, Cycle + # for Empty Cycle + if dc == Cycle(): + cyc = stringPict('') + return prettyForm(*cyc.parens()) + + dc_list = Permutation(dc.list()).cyclic_form + # for Identity Cycle + if dc_list == []: + cyc = self._print(dc.size - 1) + return prettyForm(*cyc.parens()) + + cyc = stringPict('') + for i in dc_list: + l = self._print(str(tuple(i)).replace(',', '')) + cyc = prettyForm(*cyc.right(l)) + return cyc + + def _print_Permutation(self, expr): + from sympy.combinatorics.permutations import Permutation, Cycle + + perm_cyclic = Permutation.print_cyclic + if perm_cyclic is not None: + sympy_deprecation_warning( + f""" + Setting Permutation.print_cyclic is deprecated. Instead use + init_printing(perm_cyclic={perm_cyclic}). + """, + deprecated_since_version="1.6", + active_deprecations_target="deprecated-permutation-print_cyclic", + stacklevel=7, + ) + else: + perm_cyclic = self._settings.get("perm_cyclic", True) + + if perm_cyclic: + return self._print_Cycle(Cycle(expr)) + + lower = expr.array_form + upper = list(range(len(lower))) + + result = stringPict('') + first = True + for u, l in zip(upper, lower): + s1 = self._print(u) + s2 = self._print(l) + col = prettyForm(*s1.below(s2)) + if first: + first = False + else: + col = prettyForm(*col.left(" ")) + result = prettyForm(*result.right(col)) + return prettyForm(*result.parens()) + + + def _print_Integral(self, integral): + f = integral.function + + # Add parentheses if arg involves addition of terms and + # create a pretty form for the argument + prettyF = self._print(f) + # XXX generalize parens + if f.is_Add: + prettyF = prettyForm(*prettyF.parens()) + + # dx dy dz ... + arg = prettyF + for x in integral.limits: + prettyArg = self._print(x[0]) + # XXX qparens (parens if needs-parens) + if prettyArg.width() > 1: + prettyArg = prettyForm(*prettyArg.parens()) + + arg = prettyForm(*arg.right(' d', prettyArg)) + + # \int \int \int ... + firstterm = True + s = None + for lim in integral.limits: + # Create bar based on the height of the argument + h = arg.height() + H = h + 2 + + # XXX hack! + ascii_mode = not self._use_unicode + if ascii_mode: + H += 2 + + vint = vobj('int', H) + + # Construct the pretty form with the integral sign and the argument + pform = prettyForm(vint) + pform.baseline = arg.baseline + ( + H - h)//2 # covering the whole argument + + if len(lim) > 1: + # Create pretty forms for endpoints, if definite integral. + # Do not print empty endpoints. + if len(lim) == 2: + prettyA = prettyForm("") + prettyB = self._print(lim[1]) + if len(lim) == 3: + prettyA = self._print(lim[1]) + prettyB = self._print(lim[2]) + + if ascii_mode: # XXX hack + # Add spacing so that endpoint can more easily be + # identified with the correct integral sign + spc = max(1, 3 - prettyB.width()) + prettyB = prettyForm(*prettyB.left(' ' * spc)) + + spc = max(1, 4 - prettyA.width()) + prettyA = prettyForm(*prettyA.right(' ' * spc)) + + pform = prettyForm(*pform.above(prettyB)) + pform = prettyForm(*pform.below(prettyA)) + + if not ascii_mode: # XXX hack + pform = prettyForm(*pform.right(' ')) + + if firstterm: + s = pform # first term + firstterm = False + else: + s = prettyForm(*s.left(pform)) + + pform = prettyForm(*arg.left(s)) + pform.binding = prettyForm.MUL + return pform + + def _print_Product(self, expr): + func = expr.term + pretty_func = self._print(func) + + horizontal_chr = xobj('_', 1) + corner_chr = xobj('_', 1) + vertical_chr = xobj('|', 1) + + if self._use_unicode: + # use unicode corners + horizontal_chr = xobj('-', 1) + corner_chr = xobj('UpTack', 1) + + func_height = pretty_func.height() + + first = True + max_upper = 0 + sign_height = 0 + + for lim in expr.limits: + pretty_lower, pretty_upper = self.__print_SumProduct_Limits(lim) + + width = (func_height + 2) * 5 // 3 - 2 + sign_lines = [horizontal_chr + corner_chr + (horizontal_chr * (width-2)) + corner_chr + horizontal_chr] + for _ in range(func_height + 1): + sign_lines.append(' ' + vertical_chr + (' ' * (width-2)) + vertical_chr + ' ') + + pretty_sign = stringPict('') + pretty_sign = prettyForm(*pretty_sign.stack(*sign_lines)) + + + max_upper = max(max_upper, pretty_upper.height()) + + if first: + sign_height = pretty_sign.height() + + pretty_sign = prettyForm(*pretty_sign.above(pretty_upper)) + pretty_sign = prettyForm(*pretty_sign.below(pretty_lower)) + + if first: + pretty_func.baseline = 0 + first = False + + height = pretty_sign.height() + padding = stringPict('') + padding = prettyForm(*padding.stack(*[' ']*(height - 1))) + pretty_sign = prettyForm(*pretty_sign.right(padding)) + + pretty_func = prettyForm(*pretty_sign.right(pretty_func)) + + pretty_func.baseline = max_upper + sign_height//2 + pretty_func.binding = prettyForm.MUL + return pretty_func + + def __print_SumProduct_Limits(self, lim): + def print_start(lhs, rhs): + op = prettyForm(' ' + xsym("==") + ' ') + l = self._print(lhs) + r = self._print(rhs) + pform = prettyForm(*stringPict.next(l, op, r)) + return pform + + prettyUpper = self._print(lim[2]) + prettyLower = print_start(lim[0], lim[1]) + return prettyLower, prettyUpper + + def _print_Sum(self, expr): + ascii_mode = not self._use_unicode + + def asum(hrequired, lower, upper, use_ascii): + def adjust(s, wid=None, how='<^>'): + if not wid or len(s) > wid: + return s + need = wid - len(s) + if how in ('<^>', "<") or how not in list('<^>'): + return s + ' '*need + half = need//2 + lead = ' '*half + if how == ">": + return " "*need + s + return lead + s + ' '*(need - len(lead)) + + h = max(hrequired, 2) + d = h//2 + w = d + 1 + more = hrequired % 2 + + lines = [] + if use_ascii: + lines.append("_"*(w) + ' ') + lines.append(r"\%s`" % (' '*(w - 1))) + for i in range(1, d): + lines.append('%s\\%s' % (' '*i, ' '*(w - i))) + if more: + lines.append('%s)%s' % (' '*(d), ' '*(w - d))) + for i in reversed(range(1, d)): + lines.append('%s/%s' % (' '*i, ' '*(w - i))) + lines.append("/" + "_"*(w - 1) + ',') + return d, h + more, lines, more + else: + w = w + more + d = d + more + vsum = vobj('sum', 4) + lines.append("_"*(w)) + for i in range(0, d): + lines.append('%s%s%s' % (' '*i, vsum[2], ' '*(w - i - 1))) + for i in reversed(range(0, d)): + lines.append('%s%s%s' % (' '*i, vsum[4], ' '*(w - i - 1))) + lines.append(vsum[8]*(w)) + return d, h + 2*more, lines, more + + f = expr.function + + prettyF = self._print(f) + + if f.is_Add: # add parens + prettyF = prettyForm(*prettyF.parens()) + + H = prettyF.height() + 2 + + # \sum \sum \sum ... + first = True + max_upper = 0 + sign_height = 0 + + for lim in expr.limits: + prettyLower, prettyUpper = self.__print_SumProduct_Limits(lim) + + max_upper = max(max_upper, prettyUpper.height()) + + # Create sum sign based on the height of the argument + d, h, slines, adjustment = asum( + H, prettyLower.width(), prettyUpper.width(), ascii_mode) + prettySign = stringPict('') + prettySign = prettyForm(*prettySign.stack(*slines)) + + if first: + sign_height = prettySign.height() + + prettySign = prettyForm(*prettySign.above(prettyUpper)) + prettySign = prettyForm(*prettySign.below(prettyLower)) + + if first: + # change F baseline so it centers on the sign + prettyF.baseline -= d - (prettyF.height()//2 - + prettyF.baseline) + first = False + + # put padding to the right + pad = stringPict('') + pad = prettyForm(*pad.stack(*[' ']*h)) + prettySign = prettyForm(*prettySign.right(pad)) + # put the present prettyF to the right + prettyF = prettyForm(*prettySign.right(prettyF)) + + # adjust baseline of ascii mode sigma with an odd height so that it is + # exactly through the center + ascii_adjustment = ascii_mode if not adjustment else 0 + prettyF.baseline = max_upper + sign_height//2 + ascii_adjustment + + prettyF.binding = prettyForm.MUL + return prettyF + + def _print_Limit(self, l): + e, z, z0, dir = l.args + + E = self._print(e) + if precedence(e) <= PRECEDENCE["Mul"]: + E = prettyForm(*E.parens('(', ')')) + Lim = prettyForm('lim') + + LimArg = self._print(z) + if self._use_unicode: + LimArg = prettyForm(*LimArg.right(f"{xobj('-', 1)}{pretty_atom('Arrow')}")) + else: + LimArg = prettyForm(*LimArg.right('->')) + LimArg = prettyForm(*LimArg.right(self._print(z0))) + + if str(dir) == '+-' or z0 in (S.Infinity, S.NegativeInfinity): + dir = "" + else: + if self._use_unicode: + dir = pretty_atom('SuperscriptPlus') if str(dir) == "+" else pretty_atom('SuperscriptMinus') + + LimArg = prettyForm(*LimArg.right(self._print(dir))) + + Lim = prettyForm(*Lim.below(LimArg)) + Lim = prettyForm(*Lim.right(E), binding=prettyForm.MUL) + + return Lim + + def _print_matrix_contents(self, e): + """ + This method factors out what is essentially grid printing. + """ + M = e # matrix + Ms = {} # i,j -> pretty(M[i,j]) + for i in range(M.rows): + for j in range(M.cols): + Ms[i, j] = self._print(M[i, j]) + + # h- and v- spacers + hsep = 2 + vsep = 1 + + # max width for columns + maxw = [-1] * M.cols + + for j in range(M.cols): + maxw[j] = max([Ms[i, j].width() for i in range(M.rows)] or [0]) + + # drawing result + D = None + + for i in range(M.rows): + + D_row = None + for j in range(M.cols): + s = Ms[i, j] + + # reshape s to maxw + # XXX this should be generalized, and go to stringPict.reshape ? + assert s.width() <= maxw[j] + + # hcenter it, +0.5 to the right 2 + # ( it's better to align formula starts for say 0 and r ) + # XXX this is not good in all cases -- maybe introduce vbaseline? + left, right = center_pad(s.width(), maxw[j]) + + s = prettyForm(*s.right(right)) + s = prettyForm(*s.left(left)) + + # we don't need vcenter cells -- this is automatically done in + # a pretty way because when their baselines are taking into + # account in .right() + + if D_row is None: + D_row = s # first box in a row + continue + + D_row = prettyForm(*D_row.right(' '*hsep)) # h-spacer + D_row = prettyForm(*D_row.right(s)) + + if D is None: + D = D_row # first row in a picture + continue + + # v-spacer + for _ in range(vsep): + D = prettyForm(*D.below(' ')) + + D = prettyForm(*D.below(D_row)) + + if D is None: + D = prettyForm('') # Empty Matrix + + return D + + def _print_MatrixBase(self, e, lparens='[', rparens=']'): + D = self._print_matrix_contents(e) + D.baseline = D.height()//2 + D = prettyForm(*D.parens(lparens, rparens)) + return D + + def _print_Determinant(self, e): + mat = e.arg + if mat.is_MatrixExpr: + from sympy.matrices.expressions.blockmatrix import BlockMatrix + if isinstance(mat, BlockMatrix): + return self._print_MatrixBase(mat.blocks, lparens='|', rparens='|') + D = self._print(mat) + D.baseline = D.height()//2 + return prettyForm(*D.parens('|', '|')) + else: + return self._print_MatrixBase(mat, lparens='|', rparens='|') + + def _print_TensorProduct(self, expr): + # This should somehow share the code with _print_WedgeProduct: + if self._use_unicode: + circled_times = "\u2297" + else: + circled_times = ".*" + return self._print_seq(expr.args, None, None, circled_times, + parenthesize=lambda x: precedence_traditional(x) <= PRECEDENCE["Mul"]) + + def _print_WedgeProduct(self, expr): + # This should somehow share the code with _print_TensorProduct: + if self._use_unicode: + wedge_symbol = "\u2227" + else: + wedge_symbol = '/\\' + return self._print_seq(expr.args, None, None, wedge_symbol, + parenthesize=lambda x: precedence_traditional(x) <= PRECEDENCE["Mul"]) + + def _print_Trace(self, e): + D = self._print(e.arg) + D = prettyForm(*D.parens('(',')')) + D.baseline = D.height()//2 + D = prettyForm(*D.left('\n'*(0) + 'tr')) + return D + + + def _print_MatrixElement(self, expr): + from sympy.matrices import MatrixSymbol + if (isinstance(expr.parent, MatrixSymbol) + and expr.i.is_number and expr.j.is_number): + return self._print( + Symbol(expr.parent.name + '_%d%d' % (expr.i, expr.j))) + else: + prettyFunc = self._print(expr.parent) + prettyFunc = prettyForm(*prettyFunc.parens()) + prettyIndices = self._print_seq((expr.i, expr.j), delimiter=', ' + ).parens(left='[', right=']')[0] + pform = prettyForm(binding=prettyForm.FUNC, + *stringPict.next(prettyFunc, prettyIndices)) + + # store pform parts so it can be reassembled e.g. when powered + pform.prettyFunc = prettyFunc + pform.prettyArgs = prettyIndices + + return pform + + + def _print_MatrixSlice(self, m): + # XXX works only for applied functions + from sympy.matrices import MatrixSymbol + prettyFunc = self._print(m.parent) + if not isinstance(m.parent, MatrixSymbol): + prettyFunc = prettyForm(*prettyFunc.parens()) + def ppslice(x, dim): + x = list(x) + if x[2] == 1: + del x[2] + if x[0] == 0: + x[0] = '' + if x[1] == dim: + x[1] = '' + return prettyForm(*self._print_seq(x, delimiter=':')) + prettyArgs = self._print_seq((ppslice(m.rowslice, m.parent.rows), + ppslice(m.colslice, m.parent.cols)), delimiter=', ').parens(left='[', right=']')[0] + + pform = prettyForm( + binding=prettyForm.FUNC, *stringPict.next(prettyFunc, prettyArgs)) + + # store pform parts so it can be reassembled e.g. when powered + pform.prettyFunc = prettyFunc + pform.prettyArgs = prettyArgs + + return pform + + def _print_Transpose(self, expr): + mat = expr.arg + pform = self._print(mat) + from sympy.matrices import MatrixSymbol, BlockMatrix + if (not isinstance(mat, MatrixSymbol) and + not isinstance(mat, BlockMatrix) and mat.is_MatrixExpr): + pform = prettyForm(*pform.parens()) + pform = pform**(prettyForm('T')) + return pform + + def _print_Adjoint(self, expr): + mat = expr.arg + pform = self._print(mat) + if self._use_unicode: + dag = prettyForm(pretty_atom('Dagger')) + else: + dag = prettyForm('+') + from sympy.matrices import MatrixSymbol, BlockMatrix + if (not isinstance(mat, MatrixSymbol) and + not isinstance(mat, BlockMatrix) and mat.is_MatrixExpr): + pform = prettyForm(*pform.parens()) + pform = pform**dag + return pform + + def _print_BlockMatrix(self, B): + if B.blocks.shape == (1, 1): + return self._print(B.blocks[0, 0]) + return self._print(B.blocks) + + def _print_MatAdd(self, expr): + s = None + for item in expr.args: + pform = self._print(item) + if s is None: + s = pform # First element + else: + coeff = item.as_coeff_mmul()[0] + if S(coeff).could_extract_minus_sign(): + s = prettyForm(*stringPict.next(s, ' ')) + pform = self._print(item) + else: + s = prettyForm(*stringPict.next(s, ' + ')) + s = prettyForm(*stringPict.next(s, pform)) + + return s + + def _print_MatMul(self, expr): + args = list(expr.args) + from sympy.matrices.expressions.hadamard import HadamardProduct + from sympy.matrices.expressions.kronecker import KroneckerProduct + from sympy.matrices.expressions.matadd import MatAdd + for i, a in enumerate(args): + if (isinstance(a, (Add, MatAdd, HadamardProduct, KroneckerProduct)) + and len(expr.args) > 1): + args[i] = prettyForm(*self._print(a).parens()) + else: + args[i] = self._print(a) + + return prettyForm.__mul__(*args) + + def _print_Identity(self, expr): + if self._use_unicode: + return prettyForm(pretty_atom('IdentityMatrix')) + else: + return prettyForm('I') + + def _print_ZeroMatrix(self, expr): + if self._use_unicode: + return prettyForm(pretty_atom('ZeroMatrix')) + else: + return prettyForm('0') + + def _print_OneMatrix(self, expr): + if self._use_unicode: + return prettyForm(pretty_atom("OneMatrix")) + else: + return prettyForm('1') + + def _print_DotProduct(self, expr): + args = list(expr.args) + + for i, a in enumerate(args): + args[i] = self._print(a) + return prettyForm.__mul__(*args) + + def _print_MatPow(self, expr): + pform = self._print(expr.base) + from sympy.matrices import MatrixSymbol + if not isinstance(expr.base, MatrixSymbol) and expr.base.is_MatrixExpr: + pform = prettyForm(*pform.parens()) + pform = pform**(self._print(expr.exp)) + return pform + + def _print_HadamardProduct(self, expr): + from sympy.matrices.expressions.hadamard import HadamardProduct + from sympy.matrices.expressions.matadd import MatAdd + from sympy.matrices.expressions.matmul import MatMul + if self._use_unicode: + delim = pretty_atom('Ring') + else: + delim = '.*' + return self._print_seq(expr.args, None, None, delim, + parenthesize=lambda x: isinstance(x, (MatAdd, MatMul, HadamardProduct))) + + def _print_HadamardPower(self, expr): + # from sympy import MatAdd, MatMul + if self._use_unicode: + circ = pretty_atom('Ring') + else: + circ = self._print('.') + pretty_base = self._print(expr.base) + pretty_exp = self._print(expr.exp) + if precedence(expr.exp) < PRECEDENCE["Mul"]: + pretty_exp = prettyForm(*pretty_exp.parens()) + pretty_circ_exp = prettyForm( + binding=prettyForm.LINE, + *stringPict.next(circ, pretty_exp) + ) + return pretty_base**pretty_circ_exp + + def _print_KroneckerProduct(self, expr): + from sympy.matrices.expressions.matadd import MatAdd + from sympy.matrices.expressions.matmul import MatMul + if self._use_unicode: + delim = f" {pretty_atom('TensorProduct')} " + else: + delim = ' x ' + return self._print_seq(expr.args, None, None, delim, + parenthesize=lambda x: isinstance(x, (MatAdd, MatMul))) + + def _print_FunctionMatrix(self, X): + D = self._print(X.lamda.expr) + D = prettyForm(*D.parens('[', ']')) + return D + + def _print_TransferFunction(self, expr): + if not expr.num == 1: + num, den = expr.num, expr.den + res = Mul(num, Pow(den, -1, evaluate=False), evaluate=False) + return self._print_Mul(res) + else: + return self._print(1)/self._print(expr.den) + + def _print_Series(self, expr): + args = list(expr.args) + for i, a in enumerate(expr.args): + args[i] = prettyForm(*self._print(a).parens()) + return prettyForm.__mul__(*args) + + def _print_MIMOSeries(self, expr): + from sympy.physics.control.lti import MIMOParallel + args = list(expr.args) + pretty_args = [] + for a in reversed(args): + if (isinstance(a, MIMOParallel) and len(expr.args) > 1): + expression = self._print(a) + expression.baseline = expression.height()//2 + pretty_args.append(prettyForm(*expression.parens())) + else: + expression = self._print(a) + expression.baseline = expression.height()//2 + pretty_args.append(expression) + return prettyForm.__mul__(*pretty_args) + + def _print_Parallel(self, expr): + s = None + for item in expr.args: + pform = self._print(item) + if s is None: + s = pform # First element + else: + s = prettyForm(*stringPict.next(s)) + s.baseline = s.height()//2 + s = prettyForm(*stringPict.next(s, ' + ')) + s = prettyForm(*stringPict.next(s, pform)) + return s + + def _print_MIMOParallel(self, expr): + from sympy.physics.control.lti import TransferFunctionMatrix + s = None + for item in expr.args: + pform = self._print(item) + if s is None: + s = pform # First element + else: + s = prettyForm(*stringPict.next(s)) + s.baseline = s.height()//2 + s = prettyForm(*stringPict.next(s, ' + ')) + if isinstance(item, TransferFunctionMatrix): + s.baseline = s.height() - 1 + s = prettyForm(*stringPict.next(s, pform)) + # s.baseline = s.height()//2 + return s + + def _print_Feedback(self, expr): + from sympy.physics.control import TransferFunction, Series + + num, tf = expr.sys1, TransferFunction(1, 1, expr.var) + num_arg_list = list(num.args) if isinstance(num, Series) else [num] + den_arg_list = list(expr.sys2.args) if \ + isinstance(expr.sys2, Series) else [expr.sys2] + + if isinstance(num, Series) and isinstance(expr.sys2, Series): + den = Series(*num_arg_list, *den_arg_list) + elif isinstance(num, Series) and isinstance(expr.sys2, TransferFunction): + if expr.sys2 == tf: + den = Series(*num_arg_list) + else: + den = Series(*num_arg_list, expr.sys2) + elif isinstance(num, TransferFunction) and isinstance(expr.sys2, Series): + if num == tf: + den = Series(*den_arg_list) + else: + den = Series(num, *den_arg_list) + else: + if num == tf: + den = Series(*den_arg_list) + elif expr.sys2 == tf: + den = Series(*num_arg_list) + else: + den = Series(*num_arg_list, *den_arg_list) + + denom = prettyForm(*stringPict.next(self._print(tf))) + denom.baseline = denom.height()//2 + denom = prettyForm(*stringPict.next(denom, ' + ')) if expr.sign == -1 \ + else prettyForm(*stringPict.next(denom, ' - ')) + denom = prettyForm(*stringPict.next(denom, self._print(den))) + + return self._print(num)/denom + + def _print_MIMOFeedback(self, expr): + from sympy.physics.control import MIMOSeries, TransferFunctionMatrix + + inv_mat = self._print(MIMOSeries(expr.sys2, expr.sys1)) + plant = self._print(expr.sys1) + _feedback = prettyForm(*stringPict.next(inv_mat)) + _feedback = prettyForm(*stringPict.right("I + ", _feedback)) if expr.sign == -1 \ + else prettyForm(*stringPict.right("I - ", _feedback)) + _feedback = prettyForm(*stringPict.parens(_feedback)) + _feedback.baseline = 0 + _feedback = prettyForm(*stringPict.right(_feedback, '-1 ')) + _feedback.baseline = _feedback.height()//2 + _feedback = prettyForm.__mul__(_feedback, prettyForm(" ")) + if isinstance(expr.sys1, TransferFunctionMatrix): + _feedback.baseline = _feedback.height() - 1 + _feedback = prettyForm(*stringPict.next(_feedback, plant)) + return _feedback + + def _print_TransferFunctionMatrix(self, expr): + mat = self._print(expr._expr_mat) + mat.baseline = mat.height() - 1 + subscript = greek_unicode['tau'] if self._use_unicode else r'{t}' + mat = prettyForm(*mat.right(subscript)) + return mat + + def _print_StateSpace(self, expr): + from sympy.matrices.expressions.blockmatrix import BlockMatrix + A = expr._A + B = expr._B + C = expr._C + D = expr._D + mat = BlockMatrix([[A, B], [C, D]]) + return self._print(mat.blocks) + + def _print_BasisDependent(self, expr): + from sympy.vector import Vector + + if not self._use_unicode: + raise NotImplementedError("ASCII pretty printing of BasisDependent is not implemented") + + if expr == expr.zero: + return prettyForm(expr.zero._pretty_form) + o1 = [] + vectstrs = [] + if isinstance(expr, Vector): + items = expr.separate().items() + else: + items = [(0, expr)] + for system, vect in items: + inneritems = list(vect.components.items()) + inneritems.sort(key = lambda x: x[0].__str__()) + for k, v in inneritems: + #if the coef of the basis vector is 1 + #we skip the 1 + if v == 1: + o1.append("" + + k._pretty_form) + #Same for -1 + elif v == -1: + o1.append("(-1) " + + k._pretty_form) + #For a general expr + else: + #We always wrap the measure numbers in + #parentheses + arg_str = self._print( + v).parens()[0] + + o1.append(arg_str + ' ' + k._pretty_form) + vectstrs.append(k._pretty_form) + + #outstr = u("").join(o1) + if o1[0].startswith(" + "): + o1[0] = o1[0][3:] + elif o1[0].startswith(" "): + o1[0] = o1[0][1:] + #Fixing the newlines + lengths = [] + strs = [''] + flag = [] + for i, partstr in enumerate(o1): + flag.append(0) + # XXX: What is this hack? + if '\n' in partstr: + tempstr = partstr + tempstr = tempstr.replace(vectstrs[i], '') + if xobj(')_ext', 1) in tempstr: # If scalar is a fraction + for paren in range(len(tempstr)): + flag[i] = 1 + if tempstr[paren] == xobj(')_ext', 1) and tempstr[paren + 1] == '\n': + # We want to place the vector string after all the right parentheses, because + # otherwise, the vector will be in the middle of the string + tempstr = tempstr[:paren] + xobj(')_ext', 1)\ + + ' ' + vectstrs[i] + tempstr[paren + 1:] + break + elif xobj(')_lower_hook', 1) in tempstr: + # We want to place the vector string after all the right parentheses, because + # otherwise, the vector will be in the middle of the string. For this reason, + # we insert the vector string at the rightmost index. + index = tempstr.rfind(xobj(')_lower_hook', 1)) + if index != -1: # then this character was found in this string + flag[i] = 1 + tempstr = tempstr[:index] + xobj(')_lower_hook', 1)\ + + ' ' + vectstrs[i] + tempstr[index + 1:] + o1[i] = tempstr + + o1 = [x.split('\n') for x in o1] + n_newlines = max(len(x) for x in o1) # Width of part in its pretty form + + if 1 in flag: # If there was a fractional scalar + for i, parts in enumerate(o1): + if len(parts) == 1: # If part has no newline + parts.insert(0, ' ' * (len(parts[0]))) + flag[i] = 1 + + for i, parts in enumerate(o1): + lengths.append(len(parts[flag[i]])) + for j in range(n_newlines): + if j+1 <= len(parts): + if j >= len(strs): + strs.append(' ' * (sum(lengths[:-1]) + + 3*(len(lengths)-1))) + if j == flag[i]: + strs[flag[i]] += parts[flag[i]] + ' + ' + else: + strs[j] += parts[j] + ' '*(lengths[-1] - + len(parts[j])+ + 3) + else: + if j >= len(strs): + strs.append(' ' * (sum(lengths[:-1]) + + 3*(len(lengths)-1))) + strs[j] += ' '*(lengths[-1]+3) + + return prettyForm('\n'.join([s[:-3] for s in strs])) + + def _print_NDimArray(self, expr): + from sympy.matrices.immutable import ImmutableMatrix + + if expr.rank() == 0: + return self._print(expr[()]) + + level_str = [[]] + [[] for i in range(expr.rank())] + shape_ranges = [list(range(i)) for i in expr.shape] + # leave eventual matrix elements unflattened + mat = lambda x: ImmutableMatrix(x, evaluate=False) + for outer_i in itertools.product(*shape_ranges): + level_str[-1].append(expr[outer_i]) + even = True + for back_outer_i in range(expr.rank()-1, -1, -1): + if len(level_str[back_outer_i+1]) < expr.shape[back_outer_i]: + break + if even: + level_str[back_outer_i].append(level_str[back_outer_i+1]) + else: + level_str[back_outer_i].append(mat( + level_str[back_outer_i+1])) + if len(level_str[back_outer_i + 1]) == 1: + level_str[back_outer_i][-1] = mat( + [[level_str[back_outer_i][-1]]]) + even = not even + level_str[back_outer_i+1] = [] + + out_expr = level_str[0][0] + if expr.rank() % 2 == 1: + out_expr = mat([out_expr]) + + return self._print(out_expr) + + def _printer_tensor_indices(self, name, indices, index_map={}): + center = stringPict(name) + top = stringPict(" "*center.width()) + bot = stringPict(" "*center.width()) + + last_valence = None + prev_map = None + + for index in indices: + indpic = self._print(index.args[0]) + if ((index in index_map) or prev_map) and last_valence == index.is_up: + if index.is_up: + top = prettyForm(*stringPict.next(top, ",")) + else: + bot = prettyForm(*stringPict.next(bot, ",")) + if index in index_map: + indpic = prettyForm(*stringPict.next(indpic, "=")) + indpic = prettyForm(*stringPict.next(indpic, self._print(index_map[index]))) + prev_map = True + else: + prev_map = False + if index.is_up: + top = stringPict(*top.right(indpic)) + center = stringPict(*center.right(" "*indpic.width())) + bot = stringPict(*bot.right(" "*indpic.width())) + else: + bot = stringPict(*bot.right(indpic)) + center = stringPict(*center.right(" "*indpic.width())) + top = stringPict(*top.right(" "*indpic.width())) + last_valence = index.is_up + + pict = prettyForm(*center.above(top)) + pict = prettyForm(*pict.below(bot)) + return pict + + def _print_Tensor(self, expr): + name = expr.args[0].name + indices = expr.get_indices() + return self._printer_tensor_indices(name, indices) + + def _print_TensorElement(self, expr): + name = expr.expr.args[0].name + indices = expr.expr.get_indices() + index_map = expr.index_map + return self._printer_tensor_indices(name, indices, index_map) + + def _print_TensMul(self, expr): + sign, args = expr._get_args_for_traditional_printer() + args = [ + prettyForm(*self._print(i).parens()) if + precedence_traditional(i) < PRECEDENCE["Mul"] else self._print(i) + for i in args + ] + pform = prettyForm.__mul__(*args) + if sign: + return prettyForm(*pform.left(sign)) + else: + return pform + + def _print_TensAdd(self, expr): + args = [ + prettyForm(*self._print(i).parens()) if + precedence_traditional(i) < PRECEDENCE["Mul"] else self._print(i) + for i in expr.args + ] + return prettyForm.__add__(*args) + + def _print_TensorIndex(self, expr): + sym = expr.args[0] + if not expr.is_up: + sym = -sym + return self._print(sym) + + def _print_PartialDerivative(self, deriv): + if self._use_unicode: + deriv_symbol = U('PARTIAL DIFFERENTIAL') + else: + deriv_symbol = r'd' + x = None + + for variable in reversed(deriv.variables): + s = self._print(variable) + ds = prettyForm(*s.left(deriv_symbol)) + + if x is None: + x = ds + else: + x = prettyForm(*x.right(' ')) + x = prettyForm(*x.right(ds)) + + f = prettyForm( + binding=prettyForm.FUNC, *self._print(deriv.expr).parens()) + + pform = prettyForm(deriv_symbol) + + if len(deriv.variables) > 1: + pform = pform**self._print(len(deriv.variables)) + + pform = prettyForm(*pform.below(stringPict.LINE, x)) + pform.baseline = pform.baseline + 1 + pform = prettyForm(*stringPict.next(pform, f)) + pform.binding = prettyForm.MUL + + return pform + + def _print_Piecewise(self, pexpr): + + P = {} + for n, ec in enumerate(pexpr.args): + P[n, 0] = self._print(ec.expr) + if ec.cond == True: + P[n, 1] = prettyForm('otherwise') + else: + P[n, 1] = prettyForm( + *prettyForm('for ').right(self._print(ec.cond))) + hsep = 2 + vsep = 1 + len_args = len(pexpr.args) + + # max widths + maxw = [max(P[i, j].width() for i in range(len_args)) + for j in range(2)] + + # FIXME: Refactor this code and matrix into some tabular environment. + # drawing result + D = None + + for i in range(len_args): + D_row = None + for j in range(2): + p = P[i, j] + assert p.width() <= maxw[j] + + wdelta = maxw[j] - p.width() + wleft = wdelta // 2 + wright = wdelta - wleft + + p = prettyForm(*p.right(' '*wright)) + p = prettyForm(*p.left(' '*wleft)) + + if D_row is None: + D_row = p + continue + + D_row = prettyForm(*D_row.right(' '*hsep)) # h-spacer + D_row = prettyForm(*D_row.right(p)) + if D is None: + D = D_row # first row in a picture + continue + + # v-spacer + for _ in range(vsep): + D = prettyForm(*D.below(' ')) + + D = prettyForm(*D.below(D_row)) + + D = prettyForm(*D.parens('{', '')) + D.baseline = D.height()//2 + D.binding = prettyForm.OPEN + return D + + def _print_ITE(self, ite): + from sympy.functions.elementary.piecewise import Piecewise + return self._print(ite.rewrite(Piecewise)) + + def _hprint_vec(self, v): + D = None + + for a in v: + p = a + if D is None: + D = p + else: + D = prettyForm(*D.right(', ')) + D = prettyForm(*D.right(p)) + if D is None: + D = stringPict(' ') + + return D + + def _hprint_vseparator(self, p1, p2, left=None, right=None, delimiter='', ifascii_nougly=False): + if ifascii_nougly and not self._use_unicode: + return self._print_seq((p1, '|', p2), left=left, right=right, + delimiter=delimiter, ifascii_nougly=True) + tmp = self._print_seq((p1, p2,), left=left, right=right, delimiter=delimiter) + sep = stringPict(vobj('|', tmp.height()), baseline=tmp.baseline) + return self._print_seq((p1, sep, p2), left=left, right=right, + delimiter=delimiter) + + def _print_hyper(self, e): + # FIXME refactor Matrix, Piecewise, and this into a tabular environment + ap = [self._print(a) for a in e.ap] + bq = [self._print(b) for b in e.bq] + + P = self._print(e.argument) + P.baseline = P.height()//2 + + # Drawing result - first create the ap, bq vectors + D = None + for v in [ap, bq]: + D_row = self._hprint_vec(v) + if D is None: + D = D_row # first row in a picture + else: + D = prettyForm(*D.below(' ')) + D = prettyForm(*D.below(D_row)) + + # make sure that the argument `z' is centred vertically + D.baseline = D.height()//2 + + # insert horizontal separator + P = prettyForm(*P.left(' ')) + D = prettyForm(*D.right(' ')) + + # insert separating `|` + D = self._hprint_vseparator(D, P) + + # add parens + D = prettyForm(*D.parens('(', ')')) + + # create the F symbol + above = D.height()//2 - 1 + below = D.height() - above - 1 + + sz, t, b, add, img = annotated('F') + F = prettyForm('\n' * (above - t) + img + '\n' * (below - b), + baseline=above + sz) + add = (sz + 1)//2 + + F = prettyForm(*F.left(self._print(len(e.ap)))) + F = prettyForm(*F.right(self._print(len(e.bq)))) + F.baseline = above + add + + D = prettyForm(*F.right(' ', D)) + + return D + + def _print_meijerg(self, e): + # FIXME refactor Matrix, Piecewise, and this into a tabular environment + + v = {} + v[(0, 0)] = [self._print(a) for a in e.an] + v[(0, 1)] = [self._print(a) for a in e.aother] + v[(1, 0)] = [self._print(b) for b in e.bm] + v[(1, 1)] = [self._print(b) for b in e.bother] + + P = self._print(e.argument) + P.baseline = P.height()//2 + + vp = {} + for idx in v: + vp[idx] = self._hprint_vec(v[idx]) + + for i in range(2): + maxw = max(vp[(0, i)].width(), vp[(1, i)].width()) + for j in range(2): + s = vp[(j, i)] + left = (maxw - s.width()) // 2 + right = maxw - left - s.width() + s = prettyForm(*s.left(' ' * left)) + s = prettyForm(*s.right(' ' * right)) + vp[(j, i)] = s + + D1 = prettyForm(*vp[(0, 0)].right(' ', vp[(0, 1)])) + D1 = prettyForm(*D1.below(' ')) + D2 = prettyForm(*vp[(1, 0)].right(' ', vp[(1, 1)])) + D = prettyForm(*D1.below(D2)) + + # make sure that the argument `z' is centred vertically + D.baseline = D.height()//2 + + # insert horizontal separator + P = prettyForm(*P.left(' ')) + D = prettyForm(*D.right(' ')) + + # insert separating `|` + D = self._hprint_vseparator(D, P) + + # add parens + D = prettyForm(*D.parens('(', ')')) + + # create the G symbol + above = D.height()//2 - 1 + below = D.height() - above - 1 + + sz, t, b, add, img = annotated('G') + F = prettyForm('\n' * (above - t) + img + '\n' * (below - b), + baseline=above + sz) + + pp = self._print(len(e.ap)) + pq = self._print(len(e.bq)) + pm = self._print(len(e.bm)) + pn = self._print(len(e.an)) + + def adjust(p1, p2): + diff = p1.width() - p2.width() + if diff == 0: + return p1, p2 + elif diff > 0: + return p1, prettyForm(*p2.left(' '*diff)) + else: + return prettyForm(*p1.left(' '*-diff)), p2 + pp, pm = adjust(pp, pm) + pq, pn = adjust(pq, pn) + pu = prettyForm(*pm.right(', ', pn)) + pl = prettyForm(*pp.right(', ', pq)) + + ht = F.baseline - above - 2 + if ht > 0: + pu = prettyForm(*pu.below('\n'*ht)) + p = prettyForm(*pu.below(pl)) + + F.baseline = above + F = prettyForm(*F.right(p)) + + F.baseline = above + add + + D = prettyForm(*F.right(' ', D)) + + return D + + def _print_ExpBase(self, e): + # TODO should exp_polar be printed differently? + # what about exp_polar(0), exp_polar(1)? + base = prettyForm(pretty_atom('Exp1', 'e')) + return base ** self._print(e.args[0]) + + def _print_Exp1(self, e): + return prettyForm(pretty_atom('Exp1', 'e')) + + def _print_Function(self, e, sort=False, func_name=None, left='(', + right=')'): + # optional argument func_name for supplying custom names + # XXX works only for applied functions + return self._helper_print_function(e.func, e.args, sort=sort, func_name=func_name, left=left, right=right) + + def _print_mathieuc(self, e): + return self._print_Function(e, func_name='C') + + def _print_mathieus(self, e): + return self._print_Function(e, func_name='S') + + def _print_mathieucprime(self, e): + return self._print_Function(e, func_name="C'") + + def _print_mathieusprime(self, e): + return self._print_Function(e, func_name="S'") + + def _helper_print_function(self, func, args, sort=False, func_name=None, + delimiter=', ', elementwise=False, left='(', + right=')'): + if sort: + args = sorted(args, key=default_sort_key) + + if not func_name and hasattr(func, "__name__"): + func_name = func.__name__ + + if func_name: + prettyFunc = self._print(Symbol(func_name)) + else: + prettyFunc = prettyForm(*self._print(func).parens()) + + if elementwise: + if self._use_unicode: + circ = pretty_atom('Modifier Letter Low Ring') + else: + circ = '.' + circ = self._print(circ) + prettyFunc = prettyForm( + binding=prettyForm.LINE, + *stringPict.next(prettyFunc, circ) + ) + + prettyArgs = prettyForm(*self._print_seq(args, delimiter=delimiter).parens( + left=left, right=right)) + + pform = prettyForm( + binding=prettyForm.FUNC, *stringPict.next(prettyFunc, prettyArgs)) + + # store pform parts so it can be reassembled e.g. when powered + pform.prettyFunc = prettyFunc + pform.prettyArgs = prettyArgs + + return pform + + def _print_ElementwiseApplyFunction(self, e): + func = e.function + arg = e.expr + args = [arg] + return self._helper_print_function(func, args, delimiter="", elementwise=True) + + @property + def _special_function_classes(self): + from sympy.functions.special.tensor_functions import KroneckerDelta + from sympy.functions.special.gamma_functions import gamma, lowergamma + from sympy.functions.special.zeta_functions import lerchphi + from sympy.functions.special.beta_functions import beta + from sympy.functions.special.delta_functions import DiracDelta + from sympy.functions.special.error_functions import Chi + return {KroneckerDelta: [greek_unicode['delta'], 'delta'], + gamma: [greek_unicode['Gamma'], 'Gamma'], + lerchphi: [greek_unicode['Phi'], 'lerchphi'], + lowergamma: [greek_unicode['gamma'], 'gamma'], + beta: [greek_unicode['Beta'], 'B'], + DiracDelta: [greek_unicode['delta'], 'delta'], + Chi: ['Chi', 'Chi']} + + def _print_FunctionClass(self, expr): + for cls in self._special_function_classes: + if issubclass(expr, cls) and expr.__name__ == cls.__name__: + if self._use_unicode: + return prettyForm(self._special_function_classes[cls][0]) + else: + return prettyForm(self._special_function_classes[cls][1]) + func_name = expr.__name__ + return prettyForm(pretty_symbol(func_name)) + + def _print_GeometryEntity(self, expr): + # GeometryEntity is based on Tuple but should not print like a Tuple + return self.emptyPrinter(expr) + + def _print_polylog(self, e): + subscript = self._print(e.args[0]) + if self._use_unicode and is_subscriptable_in_unicode(subscript): + return self._print_Function(Function('Li_%s' % subscript)(e.args[1])) + return self._print_Function(e) + + def _print_lerchphi(self, e): + func_name = greek_unicode['Phi'] if self._use_unicode else 'lerchphi' + return self._print_Function(e, func_name=func_name) + + def _print_dirichlet_eta(self, e): + func_name = greek_unicode['eta'] if self._use_unicode else 'dirichlet_eta' + return self._print_Function(e, func_name=func_name) + + def _print_Heaviside(self, e): + func_name = greek_unicode['theta'] if self._use_unicode else 'Heaviside' + if e.args[1] is S.Half: + pform = prettyForm(*self._print(e.args[0]).parens()) + pform = prettyForm(*pform.left(func_name)) + return pform + else: + return self._print_Function(e, func_name=func_name) + + def _print_fresnels(self, e): + return self._print_Function(e, func_name="S") + + def _print_fresnelc(self, e): + return self._print_Function(e, func_name="C") + + def _print_airyai(self, e): + return self._print_Function(e, func_name="Ai") + + def _print_airybi(self, e): + return self._print_Function(e, func_name="Bi") + + def _print_airyaiprime(self, e): + return self._print_Function(e, func_name="Ai'") + + def _print_airybiprime(self, e): + return self._print_Function(e, func_name="Bi'") + + def _print_LambertW(self, e): + return self._print_Function(e, func_name="W") + + def _print_Covariance(self, e): + return self._print_Function(e, func_name="Cov") + + def _print_Variance(self, e): + return self._print_Function(e, func_name="Var") + + def _print_Probability(self, e): + return self._print_Function(e, func_name="P") + + def _print_Expectation(self, e): + return self._print_Function(e, func_name="E", left='[', right=']') + + def _print_Lambda(self, e): + expr = e.expr + sig = e.signature + if self._use_unicode: + arrow = f" {pretty_atom('ArrowFromBar')} " + else: + arrow = " -> " + if len(sig) == 1 and sig[0].is_symbol: + sig = sig[0] + var_form = self._print(sig) + + return prettyForm(*stringPict.next(var_form, arrow, self._print(expr)), binding=8) + + def _print_Order(self, expr): + pform = self._print(expr.expr) + if (expr.point and any(p != S.Zero for p in expr.point)) or \ + len(expr.variables) > 1: + pform = prettyForm(*pform.right("; ")) + if len(expr.variables) > 1: + pform = prettyForm(*pform.right(self._print(expr.variables))) + elif len(expr.variables): + pform = prettyForm(*pform.right(self._print(expr.variables[0]))) + if self._use_unicode: + pform = prettyForm(*pform.right(f" {pretty_atom('Arrow')} ")) + else: + pform = prettyForm(*pform.right(" -> ")) + if len(expr.point) > 1: + pform = prettyForm(*pform.right(self._print(expr.point))) + else: + pform = prettyForm(*pform.right(self._print(expr.point[0]))) + pform = prettyForm(*pform.parens()) + pform = prettyForm(*pform.left("O")) + return pform + + def _print_SingularityFunction(self, e): + if self._use_unicode: + shift = self._print(e.args[0]-e.args[1]) + n = self._print(e.args[2]) + base = prettyForm("<") + base = prettyForm(*base.right(shift)) + base = prettyForm(*base.right(">")) + pform = base**n + return pform + else: + n = self._print(e.args[2]) + shift = self._print(e.args[0]-e.args[1]) + base = self._print_seq(shift, "<", ">", ' ') + return base**n + + def _print_beta(self, e): + func_name = greek_unicode['Beta'] if self._use_unicode else 'B' + return self._print_Function(e, func_name=func_name) + + def _print_betainc(self, e): + func_name = "B'" + return self._print_Function(e, func_name=func_name) + + def _print_betainc_regularized(self, e): + func_name = 'I' + return self._print_Function(e, func_name=func_name) + + def _print_gamma(self, e): + func_name = greek_unicode['Gamma'] if self._use_unicode else 'Gamma' + return self._print_Function(e, func_name=func_name) + + def _print_uppergamma(self, e): + func_name = greek_unicode['Gamma'] if self._use_unicode else 'Gamma' + return self._print_Function(e, func_name=func_name) + + def _print_lowergamma(self, e): + func_name = greek_unicode['gamma'] if self._use_unicode else 'lowergamma' + return self._print_Function(e, func_name=func_name) + + def _print_DiracDelta(self, e): + if self._use_unicode: + if len(e.args) == 2: + a = prettyForm(greek_unicode['delta']) + b = self._print(e.args[1]) + b = prettyForm(*b.parens()) + c = self._print(e.args[0]) + c = prettyForm(*c.parens()) + pform = a**b + pform = prettyForm(*pform.right(' ')) + pform = prettyForm(*pform.right(c)) + return pform + pform = self._print(e.args[0]) + pform = prettyForm(*pform.parens()) + pform = prettyForm(*pform.left(greek_unicode['delta'])) + return pform + else: + return self._print_Function(e) + + def _print_expint(self, e): + subscript = self._print(e.args[0]) + if self._use_unicode and is_subscriptable_in_unicode(subscript): + return self._print_Function(Function('E_%s' % subscript)(e.args[1])) + return self._print_Function(e) + + def _print_Chi(self, e): + # This needs a special case since otherwise it comes out as greek + # letter chi... + prettyFunc = prettyForm("Chi") + prettyArgs = prettyForm(*self._print_seq(e.args).parens()) + + pform = prettyForm( + binding=prettyForm.FUNC, *stringPict.next(prettyFunc, prettyArgs)) + + # store pform parts so it can be reassembled e.g. when powered + pform.prettyFunc = prettyFunc + pform.prettyArgs = prettyArgs + + return pform + + def _print_elliptic_e(self, e): + pforma0 = self._print(e.args[0]) + if len(e.args) == 1: + pform = pforma0 + else: + pforma1 = self._print(e.args[1]) + pform = self._hprint_vseparator(pforma0, pforma1) + pform = prettyForm(*pform.parens()) + pform = prettyForm(*pform.left('E')) + return pform + + def _print_elliptic_k(self, e): + pform = self._print(e.args[0]) + pform = prettyForm(*pform.parens()) + pform = prettyForm(*pform.left('K')) + return pform + + def _print_elliptic_f(self, e): + pforma0 = self._print(e.args[0]) + pforma1 = self._print(e.args[1]) + pform = self._hprint_vseparator(pforma0, pforma1) + pform = prettyForm(*pform.parens()) + pform = prettyForm(*pform.left('F')) + return pform + + def _print_elliptic_pi(self, e): + name = greek_unicode['Pi'] if self._use_unicode else 'Pi' + pforma0 = self._print(e.args[0]) + pforma1 = self._print(e.args[1]) + if len(e.args) == 2: + pform = self._hprint_vseparator(pforma0, pforma1) + else: + pforma2 = self._print(e.args[2]) + pforma = self._hprint_vseparator(pforma1, pforma2, ifascii_nougly=False) + pforma = prettyForm(*pforma.left('; ')) + pform = prettyForm(*pforma.left(pforma0)) + pform = prettyForm(*pform.parens()) + pform = prettyForm(*pform.left(name)) + return pform + + def _print_GoldenRatio(self, expr): + if self._use_unicode: + return prettyForm(pretty_symbol('phi')) + return self._print(Symbol("GoldenRatio")) + + def _print_EulerGamma(self, expr): + if self._use_unicode: + return prettyForm(pretty_symbol('gamma')) + return self._print(Symbol("EulerGamma")) + + def _print_Catalan(self, expr): + return self._print(Symbol("G")) + + def _print_Mod(self, expr): + pform = self._print(expr.args[0]) + if pform.binding > prettyForm.MUL: + pform = prettyForm(*pform.parens()) + pform = prettyForm(*pform.right(' mod ')) + pform = prettyForm(*pform.right(self._print(expr.args[1]))) + pform.binding = prettyForm.OPEN + return pform + + def _print_Add(self, expr, order=None): + terms = self._as_ordered_terms(expr, order=order) + pforms, indices = [], [] + + def pretty_negative(pform, index): + """Prepend a minus sign to a pretty form. """ + #TODO: Move this code to prettyForm + if index == 0: + if pform.height() > 1: + pform_neg = '- ' + else: + pform_neg = '-' + else: + pform_neg = ' - ' + + if (pform.binding > prettyForm.NEG + or pform.binding == prettyForm.ADD): + p = stringPict(*pform.parens()) + else: + p = pform + p = stringPict.next(pform_neg, p) + # Lower the binding to NEG, even if it was higher. Otherwise, it + # will print as a + ( - (b)), instead of a - (b). + return prettyForm(binding=prettyForm.NEG, *p) + + for i, term in enumerate(terms): + if term.is_Mul and term.could_extract_minus_sign(): + coeff, other = term.as_coeff_mul(rational=False) + if coeff == -1: + negterm = Mul(*other, evaluate=False) + else: + negterm = Mul(-coeff, *other, evaluate=False) + pform = self._print(negterm) + pforms.append(pretty_negative(pform, i)) + elif term.is_Rational and term.q > 1: + pforms.append(None) + indices.append(i) + elif term.is_Number and term < 0: + pform = self._print(-term) + pforms.append(pretty_negative(pform, i)) + elif term.is_Relational: + pforms.append(prettyForm(*self._print(term).parens())) + else: + pforms.append(self._print(term)) + + if indices: + large = True + + for pform in pforms: + if pform is not None and pform.height() > 1: + break + else: + large = False + + for i in indices: + term, negative = terms[i], False + + if term < 0: + term, negative = -term, True + + if large: + pform = prettyForm(str(term.p))/prettyForm(str(term.q)) + else: + pform = self._print(term) + + if negative: + pform = pretty_negative(pform, i) + + pforms[i] = pform + + return prettyForm.__add__(*pforms) + + def _print_Mul(self, product): + from sympy.physics.units import Quantity + + # Check for unevaluated Mul. In this case we need to make sure the + # identities are visible, multiple Rational factors are not combined + # etc so we display in a straight-forward form that fully preserves all + # args and their order. + args = product.args + if args[0] is S.One or any(isinstance(arg, Number) for arg in args[1:]): + strargs = list(map(self._print, args)) + # XXX: This is a hack to work around the fact that + # prettyForm.__mul__ absorbs a leading -1 in the args. Probably it + # would be better to fix this in prettyForm.__mul__ instead. + negone = strargs[0] == '-1' + if negone: + strargs[0] = prettyForm('1', 0, 0) + obj = prettyForm.__mul__(*strargs) + if negone: + obj = prettyForm('-' + obj.s, obj.baseline, obj.binding) + return obj + + a = [] # items in the numerator + b = [] # items that are in the denominator (if any) + + if self.order not in ('old', 'none'): + args = product.as_ordered_factors() + else: + args = list(product.args) + + # If quantities are present append them at the back + args = sorted(args, key=lambda x: isinstance(x, Quantity) or + (isinstance(x, Pow) and isinstance(x.base, Quantity))) + + # Gather terms for numerator/denominator + for item in args: + if item.is_commutative and item.is_Pow and item.exp.is_Rational and item.exp.is_negative: + if item.exp != -1: + b.append(Pow(item.base, -item.exp, evaluate=False)) + else: + b.append(Pow(item.base, -item.exp)) + elif item.is_Rational and item is not S.Infinity: + if item.p != 1: + a.append( Rational(item.p) ) + if item.q != 1: + b.append( Rational(item.q) ) + else: + a.append(item) + + # Convert to pretty forms. Parentheses are added by `__mul__`. + a = [self._print(ai) for ai in a] + b = [self._print(bi) for bi in b] + + # Construct a pretty form + if len(b) == 0: + return prettyForm.__mul__(*a) + else: + if len(a) == 0: + a.append( self._print(S.One) ) + return prettyForm.__mul__(*a)/prettyForm.__mul__(*b) + + # A helper function for _print_Pow to print x**(1/n) + def _print_nth_root(self, base, root): + bpretty = self._print(base) + + # In very simple cases, use a single-char root sign + if (self._settings['use_unicode_sqrt_char'] and self._use_unicode + and root == 2 and bpretty.height() == 1 + and (bpretty.width() == 1 + or (base.is_Integer and base.is_nonnegative))): + return prettyForm(*bpretty.left(nth_root[2])) + + # Construct root sign, start with the \/ shape + _zZ = xobj('/', 1) + rootsign = xobj('\\', 1) + _zZ + # Constructing the number to put on root + rpretty = self._print(root) + # roots look bad if they are not a single line + if rpretty.height() != 1: + return self._print(base)**self._print(1/root) + # If power is half, no number should appear on top of root sign + exp = '' if root == 2 else str(rpretty).ljust(2) + if len(exp) > 2: + rootsign = ' '*(len(exp) - 2) + rootsign + # Stack the exponent + rootsign = stringPict(exp + '\n' + rootsign) + rootsign.baseline = 0 + # Diagonal: length is one less than height of base + linelength = bpretty.height() - 1 + diagonal = stringPict('\n'.join( + ' '*(linelength - i - 1) + _zZ + ' '*i + for i in range(linelength) + )) + # Put baseline just below lowest line: next to exp + diagonal.baseline = linelength - 1 + # Make the root symbol + rootsign = prettyForm(*rootsign.right(diagonal)) + # Det the baseline to match contents to fix the height + # but if the height of bpretty is one, the rootsign must be one higher + rootsign.baseline = max(1, bpretty.baseline) + #build result + s = prettyForm(hobj('_', 2 + bpretty.width())) + s = prettyForm(*bpretty.above(s)) + s = prettyForm(*s.left(rootsign)) + return s + + def _print_Pow(self, power): + from sympy.simplify.simplify import fraction + b, e = power.as_base_exp() + if power.is_commutative: + if e is S.NegativeOne: + return prettyForm("1")/self._print(b) + n, d = fraction(e) + if n is S.One and d.is_Atom and not e.is_Integer and (e.is_Rational or d.is_Symbol) \ + and self._settings['root_notation']: + return self._print_nth_root(b, d) + if e.is_Rational and e < 0: + return prettyForm("1")/self._print(Pow(b, -e, evaluate=False)) + + if b.is_Relational: + return prettyForm(*self._print(b).parens()).__pow__(self._print(e)) + + return self._print(b)**self._print(e) + + def _print_UnevaluatedExpr(self, expr): + return self._print(expr.args[0]) + + def __print_numer_denom(self, p, q): + if q == 1: + if p < 0: + return prettyForm(str(p), binding=prettyForm.NEG) + else: + return prettyForm(str(p)) + elif abs(p) >= 10 and abs(q) >= 10: + # If more than one digit in numer and denom, print larger fraction + if p < 0: + return prettyForm(str(p), binding=prettyForm.NEG)/prettyForm(str(q)) + # Old printing method: + #pform = prettyForm(str(-p))/prettyForm(str(q)) + #return prettyForm(binding=prettyForm.NEG, *pform.left('- ')) + else: + return prettyForm(str(p))/prettyForm(str(q)) + else: + return None + + def _print_Rational(self, expr): + result = self.__print_numer_denom(expr.p, expr.q) + + if result is not None: + return result + else: + return self.emptyPrinter(expr) + + def _print_Fraction(self, expr): + result = self.__print_numer_denom(expr.numerator, expr.denominator) + + if result is not None: + return result + else: + return self.emptyPrinter(expr) + + def _print_ProductSet(self, p): + if len(p.sets) >= 1 and not has_variety(p.sets): + return self._print(p.sets[0]) ** self._print(len(p.sets)) + else: + prod_char = pretty_atom('Multiplication') if self._use_unicode else 'x' + return self._print_seq(p.sets, None, None, ' %s ' % prod_char, + parenthesize=lambda set: set.is_Union or + set.is_Intersection or set.is_ProductSet) + + def _print_FiniteSet(self, s): + items = sorted(s.args, key=default_sort_key) + return self._print_seq(items, '{', '}', ', ' ) + + def _print_Range(self, s): + + if self._use_unicode: + dots = pretty_atom('Dots') + else: + dots = '...' + + if s.start.is_infinite and s.stop.is_infinite: + if s.step.is_positive: + printset = dots, -1, 0, 1, dots + else: + printset = dots, 1, 0, -1, dots + elif s.start.is_infinite: + printset = dots, s[-1] - s.step, s[-1] + elif s.stop.is_infinite: + it = iter(s) + printset = next(it), next(it), dots + elif len(s) > 4: + it = iter(s) + printset = next(it), next(it), dots, s[-1] + else: + printset = tuple(s) + + return self._print_seq(printset, '{', '}', ', ' ) + + def _print_Interval(self, i): + if i.start == i.end: + return self._print_seq(i.args[:1], '{', '}') + + else: + if i.left_open: + left = '(' + else: + left = '[' + + if i.right_open: + right = ')' + else: + right = ']' + + return self._print_seq(i.args[:2], left, right) + + def _print_AccumulationBounds(self, i): + left = '<' + right = '>' + + return self._print_seq(i.args[:2], left, right) + + def _print_Intersection(self, u): + + delimiter = ' %s ' % pretty_atom('Intersection', 'n') + + return self._print_seq(u.args, None, None, delimiter, + parenthesize=lambda set: set.is_ProductSet or + set.is_Union or set.is_Complement) + + def _print_Union(self, u): + + union_delimiter = ' %s ' % pretty_atom('Union', 'U') + + return self._print_seq(u.args, None, None, union_delimiter, + parenthesize=lambda set: set.is_ProductSet or + set.is_Intersection or set.is_Complement) + + def _print_SymmetricDifference(self, u): + if not self._use_unicode: + raise NotImplementedError("ASCII pretty printing of SymmetricDifference is not implemented") + + sym_delimeter = ' %s ' % pretty_atom('SymmetricDifference') + + return self._print_seq(u.args, None, None, sym_delimeter) + + def _print_Complement(self, u): + + delimiter = r' \ ' + + return self._print_seq(u.args, None, None, delimiter, + parenthesize=lambda set: set.is_ProductSet or set.is_Intersection + or set.is_Union) + + def _print_ImageSet(self, ts): + if self._use_unicode: + inn = pretty_atom("SmallElementOf") + else: + inn = 'in' + fun = ts.lamda + sets = ts.base_sets + signature = fun.signature + expr = self._print(fun.expr) + + # TODO: the stuff to the left of the | and the stuff to the right of + # the | should have independent baselines, that way something like + # ImageSet(Lambda(x, 1/x**2), S.Naturals) prints the "x in N" part + # centered on the right instead of aligned with the fraction bar on + # the left. The same also applies to ConditionSet and ComplexRegion + if len(signature) == 1: + S = self._print_seq((signature[0], inn, sets[0]), + delimiter=' ') + return self._hprint_vseparator(expr, S, + left='{', right='}', + ifascii_nougly=True, delimiter=' ') + else: + pargs = tuple(j for var, setv in zip(signature, sets) for j in + (var, ' ', inn, ' ', setv, ", ")) + S = self._print_seq(pargs[:-1], delimiter='') + return self._hprint_vseparator(expr, S, + left='{', right='}', + ifascii_nougly=True, delimiter=' ') + + def _print_ConditionSet(self, ts): + if self._use_unicode: + inn = pretty_atom('SmallElementOf') + # using _and because and is a keyword and it is bad practice to + # overwrite them + _and = pretty_atom('And') + else: + inn = 'in' + _and = 'and' + + variables = self._print_seq(Tuple(ts.sym)) + as_expr = getattr(ts.condition, 'as_expr', None) + if as_expr is not None: + cond = self._print(ts.condition.as_expr()) + else: + cond = self._print(ts.condition) + if self._use_unicode: + cond = self._print(cond) + cond = prettyForm(*cond.parens()) + + if ts.base_set is S.UniversalSet: + return self._hprint_vseparator(variables, cond, left="{", + right="}", ifascii_nougly=True, + delimiter=' ') + + base = self._print(ts.base_set) + C = self._print_seq((variables, inn, base, _and, cond), + delimiter=' ') + return self._hprint_vseparator(variables, C, left="{", right="}", + ifascii_nougly=True, delimiter=' ') + + def _print_ComplexRegion(self, ts): + if self._use_unicode: + inn = pretty_atom('SmallElementOf') + else: + inn = 'in' + variables = self._print_seq(ts.variables) + expr = self._print(ts.expr) + prodsets = self._print(ts.sets) + + C = self._print_seq((variables, inn, prodsets), + delimiter=' ') + return self._hprint_vseparator(expr, C, left="{", right="}", + ifascii_nougly=True, delimiter=' ') + + def _print_Contains(self, e): + var, set = e.args + if self._use_unicode: + el = f" {pretty_atom('ElementOf')} " + return prettyForm(*stringPict.next(self._print(var), + el, self._print(set)), binding=8) + else: + return prettyForm(sstr(e)) + + def _print_FourierSeries(self, s): + if s.an.formula is S.Zero and s.bn.formula is S.Zero: + return self._print(s.a0) + if self._use_unicode: + dots = pretty_atom('Dots') + else: + dots = '...' + return self._print_Add(s.truncate()) + self._print(dots) + + def _print_FormalPowerSeries(self, s): + return self._print_Add(s.infinite) + + def _print_SetExpr(self, se): + pretty_set = prettyForm(*self._print(se.set).parens()) + pretty_name = self._print(Symbol("SetExpr")) + return prettyForm(*pretty_name.right(pretty_set)) + + def _print_SeqFormula(self, s): + if self._use_unicode: + dots = pretty_atom('Dots') + else: + dots = '...' + + if len(s.start.free_symbols) > 0 or len(s.stop.free_symbols) > 0: + raise NotImplementedError("Pretty printing of sequences with symbolic bound not implemented") + + if s.start is S.NegativeInfinity: + stop = s.stop + printset = (dots, s.coeff(stop - 3), s.coeff(stop - 2), + s.coeff(stop - 1), s.coeff(stop)) + elif s.stop is S.Infinity or s.length > 4: + printset = s[:4] + printset.append(dots) + printset = tuple(printset) + else: + printset = tuple(s) + return self._print_list(printset) + + _print_SeqPer = _print_SeqFormula + _print_SeqAdd = _print_SeqFormula + _print_SeqMul = _print_SeqFormula + + def _print_seq(self, seq, left=None, right=None, delimiter=', ', + parenthesize=lambda x: False, ifascii_nougly=True): + + pforms = [] + for item in seq: + pform = self._print(item) + if parenthesize(item): + pform = prettyForm(*pform.parens()) + if pforms: + pforms.append(delimiter) + pforms.append(pform) + + if not pforms: + s = stringPict('') + else: + s = prettyForm(*stringPict.next(*pforms)) + + s = prettyForm(*s.parens(left, right, ifascii_nougly=ifascii_nougly)) + return s + + def join(self, delimiter, args): + pform = None + + for arg in args: + if pform is None: + pform = arg + else: + pform = prettyForm(*pform.right(delimiter)) + pform = prettyForm(*pform.right(arg)) + + if pform is None: + return prettyForm("") + else: + return pform + + def _print_list(self, l): + return self._print_seq(l, '[', ']') + + def _print_tuple(self, t): + if len(t) == 1: + ptuple = prettyForm(*stringPict.next(self._print(t[0]), ',')) + return prettyForm(*ptuple.parens('(', ')', ifascii_nougly=True)) + else: + return self._print_seq(t, '(', ')') + + def _print_Tuple(self, expr): + return self._print_tuple(expr) + + def _print_dict(self, d): + keys = sorted(d.keys(), key=default_sort_key) + items = [] + + for k in keys: + K = self._print(k) + V = self._print(d[k]) + s = prettyForm(*stringPict.next(K, ': ', V)) + + items.append(s) + + return self._print_seq(items, '{', '}') + + def _print_Dict(self, d): + return self._print_dict(d) + + def _print_set(self, s): + if not s: + return prettyForm('set()') + items = sorted(s, key=default_sort_key) + pretty = self._print_seq(items) + pretty = prettyForm(*pretty.parens('{', '}', ifascii_nougly=True)) + return pretty + + def _print_frozenset(self, s): + if not s: + return prettyForm('frozenset()') + items = sorted(s, key=default_sort_key) + pretty = self._print_seq(items) + pretty = prettyForm(*pretty.parens('{', '}', ifascii_nougly=True)) + pretty = prettyForm(*pretty.parens('(', ')', ifascii_nougly=True)) + pretty = prettyForm(*stringPict.next(type(s).__name__, pretty)) + return pretty + + def _print_UniversalSet(self, s): + if self._use_unicode: + return prettyForm(pretty_atom('Universe')) + else: + return prettyForm('UniversalSet') + + def _print_PolyRing(self, ring): + return prettyForm(sstr(ring)) + + def _print_FracField(self, field): + return prettyForm(sstr(field)) + + def _print_FreeGroupElement(self, elm): + return prettyForm(str(elm)) + + def _print_PolyElement(self, poly): + return prettyForm(sstr(poly)) + + def _print_FracElement(self, frac): + return prettyForm(sstr(frac)) + + def _print_AlgebraicNumber(self, expr): + if expr.is_aliased: + return self._print(expr.as_poly().as_expr()) + else: + return self._print(expr.as_expr()) + + def _print_ComplexRootOf(self, expr): + args = [self._print_Add(expr.expr, order='lex'), expr.index] + pform = prettyForm(*self._print_seq(args).parens()) + pform = prettyForm(*pform.left('CRootOf')) + return pform + + def _print_RootSum(self, expr): + args = [self._print_Add(expr.expr, order='lex')] + + if expr.fun is not S.IdentityFunction: + args.append(self._print(expr.fun)) + + pform = prettyForm(*self._print_seq(args).parens()) + pform = prettyForm(*pform.left('RootSum')) + + return pform + + def _print_FiniteField(self, expr): + if self._use_unicode: + form = f"{pretty_atom('Integers')}_%d" + else: + form = 'GF(%d)' + + return prettyForm(pretty_symbol(form % expr.mod)) + + def _print_IntegerRing(self, expr): + if self._use_unicode: + return prettyForm(pretty_atom('Integers')) + else: + return prettyForm('ZZ') + + def _print_RationalField(self, expr): + if self._use_unicode: + return prettyForm(pretty_atom('Rationals')) + else: + return prettyForm('QQ') + + def _print_RealField(self, domain): + if self._use_unicode: + prefix = pretty_atom("Reals") + else: + prefix = 'RR' + + if domain.has_default_precision: + return prettyForm(prefix) + else: + return self._print(pretty_symbol(prefix + "_" + str(domain.precision))) + + def _print_ComplexField(self, domain): + if self._use_unicode: + prefix = pretty_atom('Complexes') + else: + prefix = 'CC' + + if domain.has_default_precision: + return prettyForm(prefix) + else: + return self._print(pretty_symbol(prefix + "_" + str(domain.precision))) + + def _print_PolynomialRing(self, expr): + args = list(expr.symbols) + + if not expr.order.is_default: + order = prettyForm(*prettyForm("order=").right(self._print(expr.order))) + args.append(order) + + pform = self._print_seq(args, '[', ']') + pform = prettyForm(*pform.left(self._print(expr.domain))) + + return pform + + def _print_FractionField(self, expr): + args = list(expr.symbols) + + if not expr.order.is_default: + order = prettyForm(*prettyForm("order=").right(self._print(expr.order))) + args.append(order) + + pform = self._print_seq(args, '(', ')') + pform = prettyForm(*pform.left(self._print(expr.domain))) + + return pform + + def _print_PolynomialRingBase(self, expr): + g = expr.symbols + if str(expr.order) != str(expr.default_order): + g = g + ("order=" + str(expr.order),) + pform = self._print_seq(g, '[', ']') + pform = prettyForm(*pform.left(self._print(expr.domain))) + + return pform + + def _print_GroebnerBasis(self, basis): + exprs = [ self._print_Add(arg, order=basis.order) + for arg in basis.exprs ] + exprs = prettyForm(*self.join(", ", exprs).parens(left="[", right="]")) + + gens = [ self._print(gen) for gen in basis.gens ] + + domain = prettyForm( + *prettyForm("domain=").right(self._print(basis.domain))) + order = prettyForm( + *prettyForm("order=").right(self._print(basis.order))) + + pform = self.join(", ", [exprs] + gens + [domain, order]) + + pform = prettyForm(*pform.parens()) + pform = prettyForm(*pform.left(basis.__class__.__name__)) + + return pform + + def _print_Subs(self, e): + pform = self._print(e.expr) + pform = prettyForm(*pform.parens()) + + h = pform.height() if pform.height() > 1 else 2 + rvert = stringPict(vobj('|', h), baseline=pform.baseline) + pform = prettyForm(*pform.right(rvert)) + + b = pform.baseline + pform.baseline = pform.height() - 1 + pform = prettyForm(*pform.right(self._print_seq([ + self._print_seq((self._print(v[0]), xsym('=='), self._print(v[1])), + delimiter='') for v in zip(e.variables, e.point) ]))) + + pform.baseline = b + return pform + + def _print_number_function(self, e, name): + # Print name_arg[0] for one argument or name_arg[0](arg[1]) + # for more than one argument + pform = prettyForm(name) + arg = self._print(e.args[0]) + pform_arg = prettyForm(" "*arg.width()) + pform_arg = prettyForm(*pform_arg.below(arg)) + pform = prettyForm(*pform.right(pform_arg)) + if len(e.args) == 1: + return pform + m, x = e.args + # TODO: copy-pasted from _print_Function: can we do better? + prettyFunc = pform + prettyArgs = prettyForm(*self._print_seq([x]).parens()) + pform = prettyForm( + binding=prettyForm.FUNC, *stringPict.next(prettyFunc, prettyArgs)) + pform.prettyFunc = prettyFunc + pform.prettyArgs = prettyArgs + return pform + + def _print_euler(self, e): + return self._print_number_function(e, "E") + + def _print_catalan(self, e): + return self._print_number_function(e, "C") + + def _print_bernoulli(self, e): + return self._print_number_function(e, "B") + + _print_bell = _print_bernoulli + + def _print_lucas(self, e): + return self._print_number_function(e, "L") + + def _print_fibonacci(self, e): + return self._print_number_function(e, "F") + + def _print_tribonacci(self, e): + return self._print_number_function(e, "T") + + def _print_stieltjes(self, e): + if self._use_unicode: + return self._print_number_function(e, greek_unicode['gamma']) + else: + return self._print_number_function(e, "stieltjes") + + def _print_KroneckerDelta(self, e): + pform = self._print(e.args[0]) + pform = prettyForm(*pform.right(prettyForm(','))) + pform = prettyForm(*pform.right(self._print(e.args[1]))) + if self._use_unicode: + a = stringPict(pretty_symbol('delta')) + else: + a = stringPict('d') + b = pform + top = stringPict(*b.left(' '*a.width())) + bot = stringPict(*a.right(' '*b.width())) + return prettyForm(binding=prettyForm.POW, *bot.below(top)) + + def _print_RandomDomain(self, d): + if hasattr(d, 'as_boolean'): + pform = self._print('Domain: ') + pform = prettyForm(*pform.right(self._print(d.as_boolean()))) + return pform + elif hasattr(d, 'set'): + pform = self._print('Domain: ') + pform = prettyForm(*pform.right(self._print(d.symbols))) + pform = prettyForm(*pform.right(self._print(' in '))) + pform = prettyForm(*pform.right(self._print(d.set))) + return pform + elif hasattr(d, 'symbols'): + pform = self._print('Domain on ') + pform = prettyForm(*pform.right(self._print(d.symbols))) + return pform + else: + return self._print(None) + + def _print_DMP(self, p): + try: + if p.ring is not None: + # TODO incorporate order + return self._print(p.ring.to_sympy(p)) + except SympifyError: + pass + return self._print(repr(p)) + + def _print_DMF(self, p): + return self._print_DMP(p) + + def _print_Object(self, object): + return self._print(pretty_symbol(object.name)) + + def _print_Morphism(self, morphism): + arrow = xsym("-->") + + domain = self._print(morphism.domain) + codomain = self._print(morphism.codomain) + tail = domain.right(arrow, codomain)[0] + + return prettyForm(tail) + + def _print_NamedMorphism(self, morphism): + pretty_name = self._print(pretty_symbol(morphism.name)) + pretty_morphism = self._print_Morphism(morphism) + return prettyForm(pretty_name.right(":", pretty_morphism)[0]) + + def _print_IdentityMorphism(self, morphism): + from sympy.categories import NamedMorphism + return self._print_NamedMorphism( + NamedMorphism(morphism.domain, morphism.codomain, "id")) + + def _print_CompositeMorphism(self, morphism): + + circle = xsym(".") + + # All components of the morphism have names and it is thus + # possible to build the name of the composite. + component_names_list = [pretty_symbol(component.name) for + component in morphism.components] + component_names_list.reverse() + component_names = circle.join(component_names_list) + ":" + + pretty_name = self._print(component_names) + pretty_morphism = self._print_Morphism(morphism) + return prettyForm(pretty_name.right(pretty_morphism)[0]) + + def _print_Category(self, category): + return self._print(pretty_symbol(category.name)) + + def _print_Diagram(self, diagram): + if not diagram.premises: + # This is an empty diagram. + return self._print(S.EmptySet) + + pretty_result = self._print(diagram.premises) + if diagram.conclusions: + results_arrow = " %s " % xsym("==>") + + pretty_conclusions = self._print(diagram.conclusions)[0] + pretty_result = pretty_result.right( + results_arrow, pretty_conclusions) + + return prettyForm(pretty_result[0]) + + def _print_DiagramGrid(self, grid): + from sympy.matrices import Matrix + matrix = Matrix([[grid[i, j] if grid[i, j] else Symbol(" ") + for j in range(grid.width)] + for i in range(grid.height)]) + return self._print_matrix_contents(matrix) + + def _print_FreeModuleElement(self, m): + # Print as row vector for convenience, for now. + return self._print_seq(m, '[', ']') + + def _print_SubModule(self, M): + gens = [[M.ring.to_sympy(g) for g in gen] for gen in M.gens] + return self._print_seq(gens, '<', '>') + + def _print_FreeModule(self, M): + return self._print(M.ring)**self._print(M.rank) + + def _print_ModuleImplementedIdeal(self, M): + sym = M.ring.to_sympy + return self._print_seq([sym(x) for [x] in M._module.gens], '<', '>') + + def _print_QuotientRing(self, R): + return self._print(R.ring) / self._print(R.base_ideal) + + def _print_QuotientRingElement(self, R): + return self._print(R.ring.to_sympy(R)) + self._print(R.ring.base_ideal) + + def _print_QuotientModuleElement(self, m): + return self._print(m.data) + self._print(m.module.killed_module) + + def _print_QuotientModule(self, M): + return self._print(M.base) / self._print(M.killed_module) + + def _print_MatrixHomomorphism(self, h): + matrix = self._print(h._sympy_matrix()) + matrix.baseline = matrix.height() // 2 + pform = prettyForm(*matrix.right(' : ', self._print(h.domain), + ' %s> ' % hobj('-', 2), self._print(h.codomain))) + return pform + + def _print_Manifold(self, manifold): + return self._print(manifold.name) + + def _print_Patch(self, patch): + return self._print(patch.name) + + def _print_CoordSystem(self, coords): + return self._print(coords.name) + + def _print_BaseScalarField(self, field): + string = field._coord_sys.symbols[field._index].name + return self._print(pretty_symbol(string)) + + def _print_BaseVectorField(self, field): + s = U('PARTIAL DIFFERENTIAL') + '_' + field._coord_sys.symbols[field._index].name + return self._print(pretty_symbol(s)) + + def _print_Differential(self, diff): + if self._use_unicode: + d = pretty_atom('Differential') + else: + d = 'd' + field = diff._form_field + if hasattr(field, '_coord_sys'): + string = field._coord_sys.symbols[field._index].name + return self._print(d + ' ' + pretty_symbol(string)) + else: + pform = self._print(field) + pform = prettyForm(*pform.parens()) + return prettyForm(*pform.left(d)) + + def _print_Tr(self, p): + #TODO: Handle indices + pform = self._print(p.args[0]) + pform = prettyForm(*pform.left('%s(' % (p.__class__.__name__))) + pform = prettyForm(*pform.right(')')) + return pform + + def _print_primenu(self, e): + pform = self._print(e.args[0]) + pform = prettyForm(*pform.parens()) + if self._use_unicode: + pform = prettyForm(*pform.left(greek_unicode['nu'])) + else: + pform = prettyForm(*pform.left('nu')) + return pform + + def _print_primeomega(self, e): + pform = self._print(e.args[0]) + pform = prettyForm(*pform.parens()) + if self._use_unicode: + pform = prettyForm(*pform.left(greek_unicode['Omega'])) + else: + pform = prettyForm(*pform.left('Omega')) + return pform + + def _print_Quantity(self, e): + if e.name.name == 'degree': + if self._use_unicode: + pform = self._print(pretty_atom('Degree')) + else: + pform = self._print(chr(176)) + return pform + else: + return self.emptyPrinter(e) + + def _print_AssignmentBase(self, e): + + op = prettyForm(' ' + xsym(e.op) + ' ') + + l = self._print(e.lhs) + r = self._print(e.rhs) + pform = prettyForm(*stringPict.next(l, op, r)) + return pform + + def _print_Str(self, s): + return self._print(s.name) + + +@print_function(PrettyPrinter) +def pretty(expr, **settings): + """Returns a string containing the prettified form of expr. + + For information on keyword arguments see pretty_print function. + + """ + pp = PrettyPrinter(settings) + + # XXX: this is an ugly hack, but at least it works + use_unicode = pp._settings['use_unicode'] + uflag = pretty_use_unicode(use_unicode) + + try: + return pp.doprint(expr) + finally: + pretty_use_unicode(uflag) + + +def pretty_print(expr, **kwargs): + """Prints expr in pretty form. + + pprint is just a shortcut for this function. + + Parameters + ========== + + expr : expression + The expression to print. + + wrap_line : bool, optional (default=True) + Line wrapping enabled/disabled. + + num_columns : int or None, optional (default=None) + Number of columns before line breaking (default to None which reads + the terminal width), useful when using SymPy without terminal. + + use_unicode : bool or None, optional (default=None) + Use unicode characters, such as the Greek letter pi instead of + the string pi. + + full_prec : bool or string, optional (default="auto") + Use full precision. + + order : bool or string, optional (default=None) + Set to 'none' for long expressions if slow; default is None. + + use_unicode_sqrt_char : bool, optional (default=True) + Use compact single-character square root symbol (when unambiguous). + + root_notation : bool, optional (default=True) + Set to 'False' for printing exponents of the form 1/n in fractional form. + By default exponent is printed in root form. + + mat_symbol_style : string, optional (default="plain") + Set to "bold" for printing MatrixSymbols using a bold mathematical symbol face. + By default the standard face is used. + + imaginary_unit : string, optional (default="i") + Letter to use for imaginary unit when use_unicode is True. + Can be "i" (default) or "j". + """ + print(pretty(expr, **kwargs)) + +pprint = pretty_print + + +def pager_print(expr, **settings): + """Prints expr using the pager, in pretty form. + + This invokes a pager command using pydoc. Lines are not wrapped + automatically. This routine is meant to be used with a pager that allows + sideways scrolling, like ``less -S``. + + Parameters are the same as for ``pretty_print``. If you wish to wrap lines, + pass ``num_columns=None`` to auto-detect the width of the terminal. + + """ + from pydoc import pager + from locale import getpreferredencoding + if 'num_columns' not in settings: + settings['num_columns'] = 500000 # disable line wrap + pager(pretty(expr, **settings).encode(getpreferredencoding())) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/pretty_symbology.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/pretty_symbology.py new file mode 100644 index 0000000000000000000000000000000000000000..bdb6ec556c6ed7b15dfcddcfc3da189102d5395b --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/pretty_symbology.py @@ -0,0 +1,731 @@ +"""Symbolic primitives + unicode/ASCII abstraction for pretty.py""" + +import sys +import warnings +from string import ascii_lowercase, ascii_uppercase +import unicodedata + +unicode_warnings = '' + +def U(name): + """ + Get a unicode character by name or, None if not found. + + This exists because older versions of Python use older unicode databases. + """ + try: + return unicodedata.lookup(name) + except KeyError: + global unicode_warnings + unicode_warnings += 'No \'%s\' in unicodedata\n' % name + return None + +from sympy.printing.conventions import split_super_sub +from sympy.core.alphabets import greeks +from sympy.utilities.exceptions import sympy_deprecation_warning + +# prefix conventions when constructing tables +# L - LATIN i +# G - GREEK beta +# D - DIGIT 0 +# S - SYMBOL + + + +__all__ = ['greek_unicode', 'sub', 'sup', 'xsym', 'vobj', 'hobj', 'pretty_symbol', + 'annotated', 'center_pad', 'center'] + + +_use_unicode = False + + +def pretty_use_unicode(flag=None): + """Set whether pretty-printer should use unicode by default""" + global _use_unicode, unicode_warnings + if flag is None: + return _use_unicode + + if flag and unicode_warnings: + # print warnings (if any) on first unicode usage + warnings.warn(unicode_warnings) + unicode_warnings = '' + + use_unicode_prev = _use_unicode + _use_unicode = flag + return use_unicode_prev + + +def pretty_try_use_unicode(): + """See if unicode output is available and leverage it if possible""" + + encoding = getattr(sys.stdout, 'encoding', None) + + # this happens when e.g. stdout is redirected through a pipe, or is + # e.g. a cStringIO.StringO + if encoding is None: + return # sys.stdout has no encoding + + symbols = [] + + # see if we can represent greek alphabet + symbols += greek_unicode.values() + + # and atoms + symbols += atoms_table.values() + + for s in symbols: + if s is None: + return # common symbols not present! + + try: + s.encode(encoding) + except UnicodeEncodeError: + return + + # all the characters were present and encodable + pretty_use_unicode(True) + + +def xstr(*args): + sympy_deprecation_warning( + """ + The sympy.printing.pretty.pretty_symbology.xstr() function is + deprecated. Use str() instead. + """, + deprecated_since_version="1.7", + active_deprecations_target="deprecated-pretty-printing-functions" + ) + return str(*args) + +# GREEK +g = lambda l: U('GREEK SMALL LETTER %s' % l.upper()) +G = lambda l: U('GREEK CAPITAL LETTER %s' % l.upper()) + +greek_letters = list(greeks) # make a copy +# deal with Unicode's funny spelling of lambda +greek_letters[greek_letters.index('lambda')] = 'lamda' + +# {} greek letter -> (g,G) +greek_unicode = {L: g(L) for L in greek_letters} +greek_unicode.update((L[0].upper() + L[1:], G(L)) for L in greek_letters) + +# aliases +greek_unicode['lambda'] = greek_unicode['lamda'] +greek_unicode['Lambda'] = greek_unicode['Lamda'] +greek_unicode['varsigma'] = '\N{GREEK SMALL LETTER FINAL SIGMA}' + +# BOLD +b = lambda l: U('MATHEMATICAL BOLD SMALL %s' % l.upper()) +B = lambda l: U('MATHEMATICAL BOLD CAPITAL %s' % l.upper()) + +bold_unicode = {l: b(l) for l in ascii_lowercase} +bold_unicode.update((L, B(L)) for L in ascii_uppercase) + +# GREEK BOLD +gb = lambda l: U('MATHEMATICAL BOLD SMALL %s' % l.upper()) +GB = lambda l: U('MATHEMATICAL BOLD CAPITAL %s' % l.upper()) + +greek_bold_letters = list(greeks) # make a copy, not strictly required here +# deal with Unicode's funny spelling of lambda +greek_bold_letters[greek_bold_letters.index('lambda')] = 'lamda' + +# {} greek letter -> (g,G) +greek_bold_unicode = {L: g(L) for L in greek_bold_letters} +greek_bold_unicode.update((L[0].upper() + L[1:], G(L)) for L in greek_bold_letters) +greek_bold_unicode['lambda'] = greek_unicode['lamda'] +greek_bold_unicode['Lambda'] = greek_unicode['Lamda'] +greek_bold_unicode['varsigma'] = '\N{MATHEMATICAL BOLD SMALL FINAL SIGMA}' + +digit_2txt = { + '0': 'ZERO', + '1': 'ONE', + '2': 'TWO', + '3': 'THREE', + '4': 'FOUR', + '5': 'FIVE', + '6': 'SIX', + '7': 'SEVEN', + '8': 'EIGHT', + '9': 'NINE', +} + +symb_2txt = { + '+': 'PLUS SIGN', + '-': 'MINUS', + '=': 'EQUALS SIGN', + '(': 'LEFT PARENTHESIS', + ')': 'RIGHT PARENTHESIS', + '[': 'LEFT SQUARE BRACKET', + ']': 'RIGHT SQUARE BRACKET', + '{': 'LEFT CURLY BRACKET', + '}': 'RIGHT CURLY BRACKET', + + # non-std + '{}': 'CURLY BRACKET', + 'sum': 'SUMMATION', + 'int': 'INTEGRAL', +} + +# SUBSCRIPT & SUPERSCRIPT +LSUB = lambda letter: U('LATIN SUBSCRIPT SMALL LETTER %s' % letter.upper()) +GSUB = lambda letter: U('GREEK SUBSCRIPT SMALL LETTER %s' % letter.upper()) +DSUB = lambda digit: U('SUBSCRIPT %s' % digit_2txt[digit]) +SSUB = lambda symb: U('SUBSCRIPT %s' % symb_2txt[symb]) + +LSUP = lambda letter: U('SUPERSCRIPT LATIN SMALL LETTER %s' % letter.upper()) +DSUP = lambda digit: U('SUPERSCRIPT %s' % digit_2txt[digit]) +SSUP = lambda symb: U('SUPERSCRIPT %s' % symb_2txt[symb]) + +sub = {} # symb -> subscript symbol +sup = {} # symb -> superscript symbol + +# latin subscripts +for l in 'aeioruvxhklmnpst': + sub[l] = LSUB(l) + +for l in 'in': + sup[l] = LSUP(l) + +for gl in ['beta', 'gamma', 'rho', 'phi', 'chi']: + sub[gl] = GSUB(gl) + +for d in [str(i) for i in range(10)]: + sub[d] = DSUB(d) + sup[d] = DSUP(d) + +for s in '+-=()': + sub[s] = SSUB(s) + sup[s] = SSUP(s) + +# Variable modifiers +# TODO: Make brackets adjust to height of contents +modifier_dict = { + # Accents + 'mathring': lambda s: center_accent(s, '\N{COMBINING RING ABOVE}'), + 'ddddot': lambda s: center_accent(s, '\N{COMBINING FOUR DOTS ABOVE}'), + 'dddot': lambda s: center_accent(s, '\N{COMBINING THREE DOTS ABOVE}'), + 'ddot': lambda s: center_accent(s, '\N{COMBINING DIAERESIS}'), + 'dot': lambda s: center_accent(s, '\N{COMBINING DOT ABOVE}'), + 'check': lambda s: center_accent(s, '\N{COMBINING CARON}'), + 'breve': lambda s: center_accent(s, '\N{COMBINING BREVE}'), + 'acute': lambda s: center_accent(s, '\N{COMBINING ACUTE ACCENT}'), + 'grave': lambda s: center_accent(s, '\N{COMBINING GRAVE ACCENT}'), + 'tilde': lambda s: center_accent(s, '\N{COMBINING TILDE}'), + 'hat': lambda s: center_accent(s, '\N{COMBINING CIRCUMFLEX ACCENT}'), + 'bar': lambda s: center_accent(s, '\N{COMBINING OVERLINE}'), + 'vec': lambda s: center_accent(s, '\N{COMBINING RIGHT ARROW ABOVE}'), + 'prime': lambda s: s+'\N{PRIME}', + 'prm': lambda s: s+'\N{PRIME}', + # # Faces -- these are here for some compatibility with latex printing + # 'bold': lambda s: s, + # 'bm': lambda s: s, + # 'cal': lambda s: s, + # 'scr': lambda s: s, + # 'frak': lambda s: s, + # Brackets + 'norm': lambda s: '\N{DOUBLE VERTICAL LINE}'+s+'\N{DOUBLE VERTICAL LINE}', + 'avg': lambda s: '\N{MATHEMATICAL LEFT ANGLE BRACKET}'+s+'\N{MATHEMATICAL RIGHT ANGLE BRACKET}', + 'abs': lambda s: '\N{VERTICAL LINE}'+s+'\N{VERTICAL LINE}', + 'mag': lambda s: '\N{VERTICAL LINE}'+s+'\N{VERTICAL LINE}', +} + +# VERTICAL OBJECTS +HUP = lambda symb: U('%s UPPER HOOK' % symb_2txt[symb]) +CUP = lambda symb: U('%s UPPER CORNER' % symb_2txt[symb]) +MID = lambda symb: U('%s MIDDLE PIECE' % symb_2txt[symb]) +EXT = lambda symb: U('%s EXTENSION' % symb_2txt[symb]) +HLO = lambda symb: U('%s LOWER HOOK' % symb_2txt[symb]) +CLO = lambda symb: U('%s LOWER CORNER' % symb_2txt[symb]) +TOP = lambda symb: U('%s TOP' % symb_2txt[symb]) +BOT = lambda symb: U('%s BOTTOM' % symb_2txt[symb]) + +# {} '(' -> (extension, start, end, middle) 1-character +_xobj_unicode = { + + # vertical symbols + # (( ext, top, bot, mid ), c1) + '(': (( EXT('('), HUP('('), HLO('(') ), '('), + ')': (( EXT(')'), HUP(')'), HLO(')') ), ')'), + '[': (( EXT('['), CUP('['), CLO('[') ), '['), + ']': (( EXT(']'), CUP(']'), CLO(']') ), ']'), + '{': (( EXT('{}'), HUP('{'), HLO('{'), MID('{') ), '{'), + '}': (( EXT('{}'), HUP('}'), HLO('}'), MID('}') ), '}'), + '|': U('BOX DRAWINGS LIGHT VERTICAL'), + 'Tee': U('BOX DRAWINGS LIGHT UP AND HORIZONTAL'), + 'UpTack': U('BOX DRAWINGS LIGHT DOWN AND HORIZONTAL'), + 'corner_up_centre' + '(_ext': U('LEFT PARENTHESIS EXTENSION'), + ')_ext': U('RIGHT PARENTHESIS EXTENSION'), + '(_lower_hook': U('LEFT PARENTHESIS LOWER HOOK'), + ')_lower_hook': U('RIGHT PARENTHESIS LOWER HOOK'), + '(_upper_hook': U('LEFT PARENTHESIS UPPER HOOK'), + ')_upper_hook': U('RIGHT PARENTHESIS UPPER HOOK'), + '<': ((U('BOX DRAWINGS LIGHT VERTICAL'), + U('BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT'), + U('BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT')), '<'), + + '>': ((U('BOX DRAWINGS LIGHT VERTICAL'), + U('BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT'), + U('BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT')), '>'), + + 'lfloor': (( EXT('['), EXT('['), CLO('[') ), U('LEFT FLOOR')), + 'rfloor': (( EXT(']'), EXT(']'), CLO(']') ), U('RIGHT FLOOR')), + 'lceil': (( EXT('['), CUP('['), EXT('[') ), U('LEFT CEILING')), + 'rceil': (( EXT(']'), CUP(']'), EXT(']') ), U('RIGHT CEILING')), + + 'int': (( EXT('int'), U('TOP HALF INTEGRAL'), U('BOTTOM HALF INTEGRAL') ), U('INTEGRAL')), + 'sum': (( U('BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT'), '_', U('OVERLINE'), U('BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT')), U('N-ARY SUMMATION')), + + # horizontal objects + #'-': '-', + '-': U('BOX DRAWINGS LIGHT HORIZONTAL'), + '_': U('LOW LINE'), + # We used to use this, but LOW LINE looks better for roots, as it's a + # little lower (i.e., it lines up with the / perfectly. But perhaps this + # one would still be wanted for some cases? + # '_': U('HORIZONTAL SCAN LINE-9'), + + # diagonal objects '\' & '/' ? + '/': U('BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT'), + '\\': U('BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT'), +} + +_xobj_ascii = { + # vertical symbols + # (( ext, top, bot, mid ), c1) + '(': (( '|', '/', '\\' ), '('), + ')': (( '|', '\\', '/' ), ')'), + +# XXX this looks ugly +# '[': (( '|', '-', '-' ), '['), +# ']': (( '|', '-', '-' ), ']'), +# XXX not so ugly :( + '[': (( '[', '[', '[' ), '['), + ']': (( ']', ']', ']' ), ']'), + + '{': (( '|', '/', '\\', '<' ), '{'), + '}': (( '|', '\\', '/', '>' ), '}'), + '|': '|', + + '<': (( '|', '/', '\\' ), '<'), + '>': (( '|', '\\', '/' ), '>'), + + 'int': ( ' | ', ' /', '/ ' ), + + # horizontal objects + '-': '-', + '_': '_', + + # diagonal objects '\' & '/' ? + '/': '/', + '\\': '\\', +} + + +def xobj(symb, length): + """Construct spatial object of given length. + + return: [] of equal-length strings + """ + + if length <= 0: + raise ValueError("Length should be greater than 0") + + # TODO robustify when no unicodedat available + if _use_unicode: + _xobj = _xobj_unicode + else: + _xobj = _xobj_ascii + + vinfo = _xobj[symb] + + c1 = top = bot = mid = None + + if not isinstance(vinfo, tuple): # 1 entry + ext = vinfo + else: + if isinstance(vinfo[0], tuple): # (vlong), c1 + vlong = vinfo[0] + c1 = vinfo[1] + else: # (vlong), c1 + vlong = vinfo + + ext = vlong[0] + + try: + top = vlong[1] + bot = vlong[2] + mid = vlong[3] + except IndexError: + pass + + if c1 is None: + c1 = ext + if top is None: + top = ext + if bot is None: + bot = ext + if mid is not None: + if (length % 2) == 0: + # even height, but we have to print it somehow anyway... + # XXX is it ok? + length += 1 + + else: + mid = ext + + if length == 1: + return c1 + + res = [] + next = (length - 2)//2 + nmid = (length - 2) - next*2 + + res += [top] + res += [ext]*next + res += [mid]*nmid + res += [ext]*next + res += [bot] + + return res + + +def vobj(symb, height): + """Construct vertical object of a given height + + see: xobj + """ + return '\n'.join( xobj(symb, height) ) + + +def hobj(symb, width): + """Construct horizontal object of a given width + + see: xobj + """ + return ''.join( xobj(symb, width) ) + +# RADICAL +# n -> symbol +root = { + 2: U('SQUARE ROOT'), # U('RADICAL SYMBOL BOTTOM') + 3: U('CUBE ROOT'), + 4: U('FOURTH ROOT'), +} + + +# RATIONAL +VF = lambda txt: U('VULGAR FRACTION %s' % txt) + +# (p,q) -> symbol +frac = { + (1, 2): VF('ONE HALF'), + (1, 3): VF('ONE THIRD'), + (2, 3): VF('TWO THIRDS'), + (1, 4): VF('ONE QUARTER'), + (3, 4): VF('THREE QUARTERS'), + (1, 5): VF('ONE FIFTH'), + (2, 5): VF('TWO FIFTHS'), + (3, 5): VF('THREE FIFTHS'), + (4, 5): VF('FOUR FIFTHS'), + (1, 6): VF('ONE SIXTH'), + (5, 6): VF('FIVE SIXTHS'), + (1, 8): VF('ONE EIGHTH'), + (3, 8): VF('THREE EIGHTHS'), + (5, 8): VF('FIVE EIGHTHS'), + (7, 8): VF('SEVEN EIGHTHS'), +} + + +# atom symbols +_xsym = { + '==': ('=', '='), + '<': ('<', '<'), + '>': ('>', '>'), + '<=': ('<=', U('LESS-THAN OR EQUAL TO')), + '>=': ('>=', U('GREATER-THAN OR EQUAL TO')), + '!=': ('!=', U('NOT EQUAL TO')), + ':=': (':=', ':='), + '+=': ('+=', '+='), + '-=': ('-=', '-='), + '*=': ('*=', '*='), + '/=': ('/=', '/='), + '%=': ('%=', '%='), + '*': ('*', U('DOT OPERATOR')), + '-->': ('-->', U('EM DASH') + U('EM DASH') + + U('BLACK RIGHT-POINTING TRIANGLE') if U('EM DASH') + and U('BLACK RIGHT-POINTING TRIANGLE') else None), + '==>': ('==>', U('BOX DRAWINGS DOUBLE HORIZONTAL') + + U('BOX DRAWINGS DOUBLE HORIZONTAL') + + U('BLACK RIGHT-POINTING TRIANGLE') if + U('BOX DRAWINGS DOUBLE HORIZONTAL') and + U('BOX DRAWINGS DOUBLE HORIZONTAL') and + U('BLACK RIGHT-POINTING TRIANGLE') else None), + '.': ('*', U('RING OPERATOR')), +} + + +def xsym(sym): + """get symbology for a 'character'""" + op = _xsym[sym] + + if _use_unicode: + return op[1] + else: + return op[0] + + +# SYMBOLS + +atoms_table = { + # class how-to-display + 'Exp1': U('SCRIPT SMALL E'), + 'Pi': U('GREEK SMALL LETTER PI'), + 'Infinity': U('INFINITY'), + 'NegativeInfinity': U('INFINITY') and ('-' + U('INFINITY')), # XXX what to do here + #'ImaginaryUnit': U('GREEK SMALL LETTER IOTA'), + #'ImaginaryUnit': U('MATHEMATICAL ITALIC SMALL I'), + 'ImaginaryUnit': U('DOUBLE-STRUCK ITALIC SMALL I'), + 'EmptySet': U('EMPTY SET'), + 'Naturals': U('DOUBLE-STRUCK CAPITAL N'), + 'Naturals0': (U('DOUBLE-STRUCK CAPITAL N') and + (U('DOUBLE-STRUCK CAPITAL N') + + U('SUBSCRIPT ZERO'))), + 'Integers': U('DOUBLE-STRUCK CAPITAL Z'), + 'Rationals': U('DOUBLE-STRUCK CAPITAL Q'), + 'Reals': U('DOUBLE-STRUCK CAPITAL R'), + 'Complexes': U('DOUBLE-STRUCK CAPITAL C'), + 'Universe': U('MATHEMATICAL DOUBLE-STRUCK CAPITAL U'), + 'IdentityMatrix': U('MATHEMATICAL DOUBLE-STRUCK CAPITAL I'), + 'ZeroMatrix': U('MATHEMATICAL DOUBLE-STRUCK DIGIT ZERO'), + 'OneMatrix': U('MATHEMATICAL DOUBLE-STRUCK DIGIT ONE'), + 'Differential': U('DOUBLE-STRUCK ITALIC SMALL D'), + 'Union': U('UNION'), + 'ElementOf': U('ELEMENT OF'), + 'SmallElementOf': U('SMALL ELEMENT OF'), + 'SymmetricDifference': U('INCREMENT'), + 'Intersection': U('INTERSECTION'), + 'Ring': U('RING OPERATOR'), + 'Multiplication': U('MULTIPLICATION SIGN'), + 'TensorProduct': U('N-ARY CIRCLED TIMES OPERATOR'), + 'Dots': U('HORIZONTAL ELLIPSIS'), + 'Modifier Letter Low Ring':U('Modifier Letter Low Ring'), + 'EmptySequence': 'EmptySequence', + 'SuperscriptPlus': U('SUPERSCRIPT PLUS SIGN'), + 'SuperscriptMinus': U('SUPERSCRIPT MINUS'), + 'Dagger': U('DAGGER'), + 'Degree': U('DEGREE SIGN'), + #Logic Symbols + 'And': U('LOGICAL AND'), + 'Or': U('LOGICAL OR'), + 'Not': U('NOT SIGN'), + 'Nor': U('NOR'), + 'Nand': U('NAND'), + 'Xor': U('XOR'), + 'Equiv': U('LEFT RIGHT DOUBLE ARROW'), + 'NotEquiv': U('LEFT RIGHT DOUBLE ARROW WITH STROKE'), + 'Implies': U('LEFT RIGHT DOUBLE ARROW'), + 'NotImplies': U('LEFT RIGHT DOUBLE ARROW WITH STROKE'), + 'Arrow': U('RIGHTWARDS ARROW'), + 'ArrowFromBar': U('RIGHTWARDS ARROW FROM BAR'), + 'NotArrow': U('RIGHTWARDS ARROW WITH STROKE'), + 'Tautology': U('BOX DRAWINGS LIGHT UP AND HORIZONTAL'), + 'Contradiction': U('BOX DRAWINGS LIGHT DOWN AND HORIZONTAL') +} + + +def pretty_atom(atom_name, default=None, printer=None): + """return pretty representation of an atom""" + if _use_unicode: + if printer is not None and atom_name == 'ImaginaryUnit' and printer._settings['imaginary_unit'] == 'j': + return U('DOUBLE-STRUCK ITALIC SMALL J') + else: + return atoms_table[atom_name] + else: + if default is not None: + return default + + raise KeyError('only unicode') # send it default printer + + +def pretty_symbol(symb_name, bold_name=False): + """return pretty representation of a symbol""" + # let's split symb_name into symbol + index + # UC: beta1 + # UC: f_beta + + if not _use_unicode: + return symb_name + + name, sups, subs = split_super_sub(symb_name) + + def translate(s, bold_name) : + if bold_name: + gG = greek_bold_unicode.get(s) + else: + gG = greek_unicode.get(s) + if gG is not None: + return gG + for key in sorted(modifier_dict.keys(), key=lambda k:len(k), reverse=True) : + if s.lower().endswith(key) and len(s)>len(key): + return modifier_dict[key](translate(s[:-len(key)], bold_name)) + if bold_name: + return ''.join([bold_unicode[c] for c in s]) + return s + + name = translate(name, bold_name) + + # Let's prettify sups/subs. If it fails at one of them, pretty sups/subs are + # not used at all. + def pretty_list(l, mapping): + result = [] + for s in l: + pretty = mapping.get(s) + if pretty is None: + try: # match by separate characters + pretty = ''.join([mapping[c] for c in s]) + except (TypeError, KeyError): + return None + result.append(pretty) + return result + + pretty_sups = pretty_list(sups, sup) + if pretty_sups is not None: + pretty_subs = pretty_list(subs, sub) + else: + pretty_subs = None + + # glue the results into one string + if pretty_subs is None: # nice formatting of sups/subs did not work + if subs: + name += '_'+'_'.join([translate(s, bold_name) for s in subs]) + if sups: + name += '__'+'__'.join([translate(s, bold_name) for s in sups]) + return name + else: + sups_result = ' '.join(pretty_sups) + subs_result = ' '.join(pretty_subs) + + return ''.join([name, sups_result, subs_result]) + + +def annotated(letter): + """ + Return a stylised drawing of the letter ``letter``, together with + information on how to put annotations (super- and subscripts to the + left and to the right) on it. + + See pretty.py functions _print_meijerg, _print_hyper on how to use this + information. + """ + ucode_pics = { + 'F': (2, 0, 2, 0, '\N{BOX DRAWINGS LIGHT DOWN AND RIGHT}\N{BOX DRAWINGS LIGHT HORIZONTAL}\n' + '\N{BOX DRAWINGS LIGHT VERTICAL AND RIGHT}\N{BOX DRAWINGS LIGHT HORIZONTAL}\n' + '\N{BOX DRAWINGS LIGHT UP}'), + 'G': (3, 0, 3, 1, '\N{BOX DRAWINGS LIGHT ARC DOWN AND RIGHT}\N{BOX DRAWINGS LIGHT HORIZONTAL}\N{BOX DRAWINGS LIGHT ARC DOWN AND LEFT}\n' + '\N{BOX DRAWINGS LIGHT VERTICAL}\N{BOX DRAWINGS LIGHT RIGHT}\N{BOX DRAWINGS LIGHT DOWN AND LEFT}\n' + '\N{BOX DRAWINGS LIGHT ARC UP AND RIGHT}\N{BOX DRAWINGS LIGHT HORIZONTAL}\N{BOX DRAWINGS LIGHT ARC UP AND LEFT}') + } + ascii_pics = { + 'F': (3, 0, 3, 0, ' _\n|_\n|\n'), + 'G': (3, 0, 3, 1, ' __\n/__\n\\_|') + } + + if _use_unicode: + return ucode_pics[letter] + else: + return ascii_pics[letter] + +_remove_combining = dict.fromkeys(list(range(ord('\N{COMBINING GRAVE ACCENT}'), ord('\N{COMBINING LATIN SMALL LETTER X}'))) + + list(range(ord('\N{COMBINING LEFT HARPOON ABOVE}'), ord('\N{COMBINING ASTERISK ABOVE}')))) + +def is_combining(sym): + """Check whether symbol is a unicode modifier. """ + + return ord(sym) in _remove_combining + + +def center_accent(string, accent): + """ + Returns a string with accent inserted on the middle character. Useful to + put combining accents on symbol names, including multi-character names. + + Parameters + ========== + + string : string + The string to place the accent in. + accent : string + The combining accent to insert + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Combining_character + .. [2] https://en.wikipedia.org/wiki/Combining_Diacritical_Marks + + """ + + # Accent is placed on the previous character, although it may not always look + # like that depending on console + midpoint = len(string) // 2 + 1 + firstpart = string[:midpoint] + secondpart = string[midpoint:] + return firstpart + accent + secondpart + + +def line_width(line): + """Unicode combining symbols (modifiers) are not ever displayed as + separate symbols and thus should not be counted + """ + return len(line.translate(_remove_combining)) + + +def is_subscriptable_in_unicode(subscript): + """ + Checks whether a string is subscriptable in unicode or not. + + Parameters + ========== + + subscript: the string which needs to be checked + + Examples + ======== + + >>> from sympy.printing.pretty.pretty_symbology import is_subscriptable_in_unicode + >>> is_subscriptable_in_unicode('abc') + False + >>> is_subscriptable_in_unicode('123') + True + + """ + return all(character in sub for character in subscript) + + +def center_pad(wstring, wtarget, fillchar=' '): + """ + Return the padding strings necessary to center a string of + wstring characters wide in a wtarget wide space. + + The line_width wstring should always be less or equal to wtarget + or else a ValueError will be raised. + """ + if wstring > wtarget: + raise ValueError('not enough space for string') + wdelta = wtarget - wstring + + wleft = wdelta // 2 # favor left '1 ' + wright = wdelta - wleft + + left = fillchar * wleft + right = fillchar * wright + + return left, right + + +def center(string, width, fillchar=' '): + """Return a centered string of length determined by `line_width` + that uses `fillchar` for padding. + """ + left, right = center_pad(line_width(string), width, fillchar) + return ''.join([left, string, right]) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/stringpict.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/stringpict.py new file mode 100644 index 0000000000000000000000000000000000000000..b6055f09c83b2abbe0c492991aaee4dff5b34f49 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/stringpict.py @@ -0,0 +1,537 @@ +"""Prettyprinter by Jurjen Bos. +(I hate spammers: mail me at pietjepuk314 at the reverse of ku.oc.oohay). +All objects have a method that create a "stringPict", +that can be used in the str method for pretty printing. + +Updates by Jason Gedge (email at cs mun ca) + - terminal_string() method + - minor fixes and changes (mostly to prettyForm) + +TODO: + - Allow left/center/right alignment options for above/below and + top/center/bottom alignment options for left/right +""" + +import shutil + +from .pretty_symbology import hobj, vobj, xsym, xobj, pretty_use_unicode, line_width, center +from sympy.utilities.exceptions import sympy_deprecation_warning + +_GLOBAL_WRAP_LINE = None + +class stringPict: + """An ASCII picture. + The pictures are represented as a list of equal length strings. + """ + #special value for stringPict.below + LINE = 'line' + + def __init__(self, s, baseline=0): + """Initialize from string. + Multiline strings are centered. + """ + self.s = s + #picture is a string that just can be printed + self.picture = stringPict.equalLengths(s.splitlines()) + #baseline is the line number of the "base line" + self.baseline = baseline + self.binding = None + + @staticmethod + def equalLengths(lines): + # empty lines + if not lines: + return [''] + + width = max(line_width(line) for line in lines) + return [center(line, width) for line in lines] + + def height(self): + """The height of the picture in characters.""" + return len(self.picture) + + def width(self): + """The width of the picture in characters.""" + return line_width(self.picture[0]) + + @staticmethod + def next(*args): + """Put a string of stringPicts next to each other. + Returns string, baseline arguments for stringPict. + """ + #convert everything to stringPicts + objects = [] + for arg in args: + if isinstance(arg, str): + arg = stringPict(arg) + objects.append(arg) + + #make a list of pictures, with equal height and baseline + newBaseline = max(obj.baseline for obj in objects) + newHeightBelowBaseline = max( + obj.height() - obj.baseline + for obj in objects) + newHeight = newBaseline + newHeightBelowBaseline + + pictures = [] + for obj in objects: + oneEmptyLine = [' '*obj.width()] + basePadding = newBaseline - obj.baseline + totalPadding = newHeight - obj.height() + pictures.append( + oneEmptyLine * basePadding + + obj.picture + + oneEmptyLine * (totalPadding - basePadding)) + + result = [''.join(lines) for lines in zip(*pictures)] + return '\n'.join(result), newBaseline + + def right(self, *args): + r"""Put pictures next to this one. + Returns string, baseline arguments for stringPict. + (Multiline) strings are allowed, and are given a baseline of 0. + + Examples + ======== + + >>> from sympy.printing.pretty.stringpict import stringPict + >>> print(stringPict("10").right(" + ",stringPict("1\r-\r2",1))[0]) + 1 + 10 + - + 2 + + """ + return stringPict.next(self, *args) + + def left(self, *args): + """Put pictures (left to right) at left. + Returns string, baseline arguments for stringPict. + """ + return stringPict.next(*(args + (self,))) + + @staticmethod + def stack(*args): + """Put pictures on top of each other, + from top to bottom. + Returns string, baseline arguments for stringPict. + The baseline is the baseline of the second picture. + Everything is centered. + Baseline is the baseline of the second picture. + Strings are allowed. + The special value stringPict.LINE is a row of '-' extended to the width. + """ + #convert everything to stringPicts; keep LINE + objects = [] + for arg in args: + if arg is not stringPict.LINE and isinstance(arg, str): + arg = stringPict(arg) + objects.append(arg) + + #compute new width + newWidth = max( + obj.width() + for obj in objects + if obj is not stringPict.LINE) + + lineObj = stringPict(hobj('-', newWidth)) + + #replace LINE with proper lines + for i, obj in enumerate(objects): + if obj is stringPict.LINE: + objects[i] = lineObj + + #stack the pictures, and center the result + newPicture = [center(line, newWidth) for obj in objects for line in obj.picture] + newBaseline = objects[0].height() + objects[1].baseline + return '\n'.join(newPicture), newBaseline + + def below(self, *args): + """Put pictures under this picture. + Returns string, baseline arguments for stringPict. + Baseline is baseline of top picture + + Examples + ======== + + >>> from sympy.printing.pretty.stringpict import stringPict + >>> print(stringPict("x+3").below( + ... stringPict.LINE, '3')[0]) #doctest: +NORMALIZE_WHITESPACE + x+3 + --- + 3 + + """ + s, baseline = stringPict.stack(self, *args) + return s, self.baseline + + def above(self, *args): + """Put pictures above this picture. + Returns string, baseline arguments for stringPict. + Baseline is baseline of bottom picture. + """ + string, baseline = stringPict.stack(*(args + (self,))) + baseline = len(string.splitlines()) - self.height() + self.baseline + return string, baseline + + def parens(self, left='(', right=')', ifascii_nougly=False): + """Put parentheses around self. + Returns string, baseline arguments for stringPict. + + left or right can be None or empty string which means 'no paren from + that side' + """ + h = self.height() + b = self.baseline + + # XXX this is a hack -- ascii parens are ugly! + if ifascii_nougly and not pretty_use_unicode(): + h = 1 + b = 0 + + res = self + + if left: + lparen = stringPict(vobj(left, h), baseline=b) + res = stringPict(*lparen.right(self)) + if right: + rparen = stringPict(vobj(right, h), baseline=b) + res = stringPict(*res.right(rparen)) + + return ('\n'.join(res.picture), res.baseline) + + def leftslash(self): + """Precede object by a slash of the proper size. + """ + # XXX not used anywhere ? + height = max( + self.baseline, + self.height() - 1 - self.baseline)*2 + 1 + slash = '\n'.join( + ' '*(height - i - 1) + xobj('/', 1) + ' '*i + for i in range(height) + ) + return self.left(stringPict(slash, height//2)) + + def root(self, n=None): + """Produce a nice root symbol. + Produces ugly results for big n inserts. + """ + # XXX not used anywhere + # XXX duplicate of root drawing in pretty.py + #put line over expression + result = self.above('_'*self.width()) + #construct right half of root symbol + height = self.height() + slash = '\n'.join( + ' ' * (height - i - 1) + '/' + ' ' * i + for i in range(height) + ) + slash = stringPict(slash, height - 1) + #left half of root symbol + if height > 2: + downline = stringPict('\\ \n \\', 1) + else: + downline = stringPict('\\') + #put n on top, as low as possible + if n is not None and n.width() > downline.width(): + downline = downline.left(' '*(n.width() - downline.width())) + downline = downline.above(n) + #build root symbol + root = downline.right(slash) + #glue it on at the proper height + #normally, the root symbel is as high as self + #which is one less than result + #this moves the root symbol one down + #if the root became higher, the baseline has to grow too + root.baseline = result.baseline - result.height() + root.height() + return result.left(root) + + def render(self, * args, **kwargs): + """Return the string form of self. + + Unless the argument line_break is set to False, it will + break the expression in a form that can be printed + on the terminal without being broken up. + """ + if _GLOBAL_WRAP_LINE is not None: + kwargs["wrap_line"] = _GLOBAL_WRAP_LINE + + if kwargs["wrap_line"] is False: + return "\n".join(self.picture) + + if kwargs["num_columns"] is not None: + # Read the argument num_columns if it is not None + ncols = kwargs["num_columns"] + else: + # Attempt to get a terminal width + ncols = self.terminal_width() + + if ncols <= 0: + ncols = 80 + + # If smaller than the terminal width, no need to correct + if self.width() <= ncols: + return type(self.picture[0])(self) + + """ + Break long-lines in a visually pleasing format. + without overflow indicators | with overflow indicators + | 2 2 3 | | 2 2 3 ↪| + |6*x *y + 4*x*y + | |6*x *y + 4*x*y + ↪| + | | | | + | 3 4 4 | |↪ 3 4 4 | + |4*y*x + x + y | |↪ 4*y*x + x + y | + |a*c*e + a*c*f + a*d | |a*c*e + a*c*f + a*d ↪| + |*e + a*d*f + b*c*e | | | + |+ b*c*f + b*d*e + b | |↪ *e + a*d*f + b*c* ↪| + |*d*f | | | + | | |↪ e + b*c*f + b*d*e ↪| + | | | | + | | |↪ + b*d*f | + """ + + overflow_first = "" + if kwargs["use_unicode"] or pretty_use_unicode(): + overflow_start = "\N{RIGHTWARDS ARROW WITH HOOK} " + overflow_end = " \N{RIGHTWARDS ARROW WITH HOOK}" + else: + overflow_start = "> " + overflow_end = " >" + + def chunks(line): + """Yields consecutive chunks of line_width ncols""" + prefix = overflow_first + width, start = line_width(prefix + overflow_end), 0 + for i, x in enumerate(line): + wx = line_width(x) + # Only flush the screen when the current character overflows. + # This way, combining marks can be appended even when width == ncols. + if width + wx > ncols: + yield prefix + line[start:i] + overflow_end + prefix = overflow_start + width, start = line_width(prefix + overflow_end), i + width += wx + yield prefix + line[start:] + + # Concurrently assemble chunks of all lines into individual screens + pictures = zip(*map(chunks, self.picture)) + + # Join lines of each screen into sub-pictures + pictures = ["\n".join(picture) for picture in pictures] + + # Add spacers between sub-pictures + return "\n\n".join(pictures) + + def terminal_width(self): + """Return the terminal width if possible, otherwise return 0. + """ + size = shutil.get_terminal_size(fallback=(0, 0)) + return size.columns + + def __eq__(self, o): + if isinstance(o, str): + return '\n'.join(self.picture) == o + elif isinstance(o, stringPict): + return o.picture == self.picture + return False + + def __hash__(self): + return super().__hash__() + + def __str__(self): + return '\n'.join(self.picture) + + def __repr__(self): + return "stringPict(%r,%d)" % ('\n'.join(self.picture), self.baseline) + + def __getitem__(self, index): + return self.picture[index] + + def __len__(self): + return len(self.s) + + +class prettyForm(stringPict): + """ + Extension of the stringPict class that knows about basic math applications, + optimizing double minus signs. + + "Binding" is interpreted as follows:: + + ATOM this is an atom: never needs to be parenthesized + FUNC this is a function application: parenthesize if added (?) + DIV this is a division: make wider division if divided + POW this is a power: only parenthesize if exponent + MUL this is a multiplication: parenthesize if powered + ADD this is an addition: parenthesize if multiplied or powered + NEG this is a negative number: optimize if added, parenthesize if + multiplied or powered + OPEN this is an open object: parenthesize if added, multiplied, or + powered (example: Piecewise) + """ + ATOM, FUNC, DIV, POW, MUL, ADD, NEG, OPEN = range(8) + + def __init__(self, s, baseline=0, binding=0, unicode=None): + """Initialize from stringPict and binding power.""" + stringPict.__init__(self, s, baseline) + self.binding = binding + if unicode is not None: + sympy_deprecation_warning( + """ + The unicode argument to prettyForm is deprecated. Only the s + argument (the first positional argument) should be passed. + """, + deprecated_since_version="1.7", + active_deprecations_target="deprecated-pretty-printing-functions") + self._unicode = unicode or s + + @property + def unicode(self): + sympy_deprecation_warning( + """ + The prettyForm.unicode attribute is deprecated. Use the + prettyForm.s attribute instead. + """, + deprecated_since_version="1.7", + active_deprecations_target="deprecated-pretty-printing-functions") + return self._unicode + + # Note: code to handle subtraction is in _print_Add + + def __add__(self, *others): + """Make a pretty addition. + Addition of negative numbers is simplified. + """ + arg = self + if arg.binding > prettyForm.NEG: + arg = stringPict(*arg.parens()) + result = [arg] + for arg in others: + #add parentheses for weak binders + if arg.binding > prettyForm.NEG: + arg = stringPict(*arg.parens()) + #use existing minus sign if available + if arg.binding != prettyForm.NEG: + result.append(' + ') + result.append(arg) + return prettyForm(binding=prettyForm.ADD, *stringPict.next(*result)) + + def __truediv__(self, den, slashed=False): + """Make a pretty division; stacked or slashed. + """ + if slashed: + raise NotImplementedError("Can't do slashed fraction yet") + num = self + if num.binding == prettyForm.DIV: + num = stringPict(*num.parens()) + if den.binding == prettyForm.DIV: + den = stringPict(*den.parens()) + + if num.binding==prettyForm.NEG: + num = num.right(" ")[0] + + return prettyForm(binding=prettyForm.DIV, *stringPict.stack( + num, + stringPict.LINE, + den)) + + def __mul__(self, *others): + """Make a pretty multiplication. + Parentheses are needed around +, - and neg. + """ + quantity = { + 'degree': "\N{DEGREE SIGN}" + } + + if len(others) == 0: + return self # We aren't actually multiplying... So nothing to do here. + + # add parens on args that need them + arg = self + if arg.binding > prettyForm.MUL and arg.binding != prettyForm.NEG: + arg = stringPict(*arg.parens()) + result = [arg] + for arg in others: + if arg.picture[0] not in quantity.values(): + result.append(xsym('*')) + #add parentheses for weak binders + if arg.binding > prettyForm.MUL and arg.binding != prettyForm.NEG: + arg = stringPict(*arg.parens()) + result.append(arg) + + len_res = len(result) + for i in range(len_res): + if i < len_res - 1 and result[i] == '-1' and result[i + 1] == xsym('*'): + # substitute -1 by -, like in -1*x -> -x + result.pop(i) + result.pop(i) + result.insert(i, '-') + if result[0][0] == '-': + # if there is a - sign in front of all + # This test was failing to catch a prettyForm.__mul__(prettyForm("-1", 0, 6)) being negative + bin = prettyForm.NEG + if result[0] == '-': + right = result[1] + if right.picture[right.baseline][0] == '-': + result[0] = '- ' + else: + bin = prettyForm.MUL + return prettyForm(binding=bin, *stringPict.next(*result)) + + def __repr__(self): + return "prettyForm(%r,%d,%d)" % ( + '\n'.join(self.picture), + self.baseline, + self.binding) + + def __pow__(self, b): + """Make a pretty power. + """ + a = self + use_inline_func_form = False + if b.binding == prettyForm.POW: + b = stringPict(*b.parens()) + if a.binding > prettyForm.FUNC: + a = stringPict(*a.parens()) + elif a.binding == prettyForm.FUNC: + # heuristic for when to use inline power + if b.height() > 1: + a = stringPict(*a.parens()) + else: + use_inline_func_form = True + + if use_inline_func_form: + # 2 + # sin + + (x) + b.baseline = a.prettyFunc.baseline + b.height() + func = stringPict(*a.prettyFunc.right(b)) + return prettyForm(*func.right(a.prettyArgs)) + else: + # 2 <-- top + # (x+y) <-- bot + top = stringPict(*b.left(' '*a.width())) + bot = stringPict(*a.right(' '*b.width())) + + return prettyForm(binding=prettyForm.POW, *bot.above(top)) + + simpleFunctions = ["sin", "cos", "tan"] + + @staticmethod + def apply(function, *args): + """Functions of one or more variables. + """ + if function in prettyForm.simpleFunctions: + #simple function: use only space if possible + assert len( + args) == 1, "Simple function %s must have 1 argument" % function + arg = args[0].__pretty__() + if arg.binding <= prettyForm.DIV: + #optimization: no parentheses necessary + return prettyForm(binding=prettyForm.FUNC, *arg.left(function + ' ')) + argumentList = [] + for arg in args: + argumentList.append(',') + argumentList.append(arg.__pretty__()) + argumentList = stringPict(*stringPict.next(*argumentList[1:])) + argumentList = stringPict(*argumentList.parens()) + return prettyForm(binding=prettyForm.ATOM, *argumentList.left(function)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7576c98a89daa185e67e9425c16ffaef0a06118c Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/tests/test_pretty.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/tests/test_pretty.py new file mode 100644 index 0000000000000000000000000000000000000000..1cca79bd1dc5c3ba81483c8fe2e87c35926d1b94 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/pretty/tests/test_pretty.py @@ -0,0 +1,7972 @@ +# -*- coding: utf-8 -*- +from sympy.concrete.products import Product +from sympy.concrete.summations import Sum +from sympy.core.add import Add +from sympy.core.basic import Basic +from sympy.core.containers import (Dict, Tuple) +from sympy.core.function import (Derivative, Function, Lambda, Subs) +from sympy.core.mul import Mul +from sympy.core import (EulerGamma, GoldenRatio, Catalan) +from sympy.core.numbers import (I, Rational, oo, pi) +from sympy.core.power import Pow +from sympy.core.relational import (Eq, Ge, Gt, Le, Lt, Ne) +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.elementary.complexes import conjugate +from sympy.functions.elementary.exponential import LambertW +from sympy.functions.special.bessel import (airyai, airyaiprime, airybi, airybiprime) +from sympy.functions.special.delta_functions import Heaviside +from sympy.functions.special.error_functions import (fresnelc, fresnels) +from sympy.functions.special.singularity_functions import SingularityFunction +from sympy.functions.special.zeta_functions import dirichlet_eta +from sympy.geometry.line import (Ray, Segment) +from sympy.integrals.integrals import Integral +from sympy.logic.boolalg import (And, Equivalent, ITE, Implies, Nand, Nor, Not, Or, Xor) +from sympy.matrices.dense import (Matrix, diag) +from sympy.matrices.expressions.slice import MatrixSlice +from sympy.matrices.expressions.trace import Trace +from sympy.polys.domains.finitefield import FF +from sympy.polys.domains.integerring import ZZ +from sympy.polys.domains.rationalfield import QQ +from sympy.polys.domains.realfield import RR +from sympy.polys.orderings import (grlex, ilex) +from sympy.polys.polytools import groebner +from sympy.polys.rootoftools import (RootSum, rootof) +from sympy.series.formal import fps +from sympy.series.fourier import fourier_series +from sympy.series.limits import Limit +from sympy.series.order import O +from sympy.series.sequences import (SeqAdd, SeqFormula, SeqMul, SeqPer) +from sympy.sets.contains import Contains +from sympy.sets.fancysets import Range +from sympy.sets.sets import (Complement, FiniteSet, Intersection, Interval, Union) +from sympy.codegen.ast import (Assignment, AddAugmentedAssignment, + SubAugmentedAssignment, MulAugmentedAssignment, DivAugmentedAssignment, ModAugmentedAssignment) +from sympy.core.expr import UnevaluatedExpr +from sympy.physics.quantum.trace import Tr + +from sympy.functions import (Abs, Chi, Ci, Ei, KroneckerDelta, + Piecewise, Shi, Si, atan2, beta, binomial, catalan, ceiling, cos, + euler, exp, expint, factorial, factorial2, floor, gamma, hyper, log, + meijerg, sin, sqrt, subfactorial, tan, uppergamma, lerchphi, polylog, + elliptic_k, elliptic_f, elliptic_e, elliptic_pi, DiracDelta, bell, + bernoulli, fibonacci, tribonacci, lucas, stieltjes, mathieuc, mathieus, + mathieusprime, mathieucprime) + +from sympy.matrices import (Adjoint, Inverse, MatrixSymbol, Transpose, + KroneckerProduct, BlockMatrix, OneMatrix, ZeroMatrix) +from sympy.matrices.expressions import hadamard_power + +from sympy.physics import mechanics +from sympy.physics.control.lti import (TransferFunction, Feedback, TransferFunctionMatrix, + Series, Parallel, MIMOSeries, MIMOParallel, MIMOFeedback, StateSpace) +from sympy.physics.units import joule, degree +from sympy.printing.pretty import pprint, pretty as xpretty +from sympy.printing.pretty.pretty_symbology import center_accent, is_combining, center +from sympy.sets.conditionset import ConditionSet + +from sympy.sets import ImageSet, ProductSet +from sympy.sets.setexpr import SetExpr +from sympy.stats.crv_types import Normal +from sympy.stats.symbolic_probability import (Covariance, Expectation, + Probability, Variance) +from sympy.tensor.array import (ImmutableDenseNDimArray, ImmutableSparseNDimArray, + MutableDenseNDimArray, MutableSparseNDimArray, tensorproduct) +from sympy.tensor.functions import TensorProduct +from sympy.tensor.tensor import (TensorIndexType, tensor_indices, TensorHead, + TensorElement, tensor_heads) + +from sympy.testing.pytest import raises, _both_exp_pow, warns_deprecated_sympy + +from sympy.vector import CoordSys3D, Gradient, Curl, Divergence, Dot, Cross, Laplacian + + + +import sympy as sym +class lowergamma(sym.lowergamma): + pass # testing notation inheritance by a subclass with same name + +a, b, c, d, x, y, z, k, n, s, p = symbols('a,b,c,d,x,y,z,k,n,s,p') +f = Function("f") +th = Symbol('theta') +ph = Symbol('phi') + +""" +Expressions whose pretty-printing is tested here: +(A '#' to the right of an expression indicates that its various acceptable +orderings are accounted for by the tests.) + + +BASIC EXPRESSIONS: + +oo +(x**2) +1/x +y*x**-2 +x**Rational(-5,2) +(-2)**x +Pow(3, 1, evaluate=False) +(x**2 + x + 1) # +1-x # +1-2*x # +x/y +-x/y +(x+2)/y # +(1+x)*y #3 +-5*x/(x+10) # correct placement of negative sign +1 - Rational(3,2)*(x+1) +-(-x + 5)*(-x - 2*sqrt(2) + 5) - (-y + 5)*(-y + 5) # issue 5524 + + +ORDERING: + +x**2 + x + 1 +1 - x +1 - 2*x +2*x**4 + y**2 - x**2 + y**3 + + +RELATIONAL: + +Eq(x, y) +Lt(x, y) +Gt(x, y) +Le(x, y) +Ge(x, y) +Ne(x/(y+1), y**2) # + + +RATIONAL NUMBERS: + +y*x**-2 +y**Rational(3,2) * x**Rational(-5,2) +sin(x)**3/tan(x)**2 + + +FUNCTIONS (ABS, CONJ, EXP, FUNCTION BRACES, FACTORIAL, FLOOR, CEILING): + +(2*x + exp(x)) # +Abs(x) +Abs(x/(x**2+1)) # +Abs(1 / (y - Abs(x))) +factorial(n) +factorial(2*n) +subfactorial(n) +subfactorial(2*n) +factorial(factorial(factorial(n))) +factorial(n+1) # +conjugate(x) +conjugate(f(x+1)) # +f(x) +f(x, y) +f(x/(y+1), y) # +f(x**x**x**x**x**x) +sin(x)**2 +conjugate(a+b*I) +conjugate(exp(a+b*I)) +conjugate( f(1 + conjugate(f(x))) ) # +f(x/(y+1), y) # denom of first arg +floor(1 / (y - floor(x))) +ceiling(1 / (y - ceiling(x))) + + +SQRT: + +sqrt(2) +2**Rational(1,3) +2**Rational(1,1000) +sqrt(x**2 + 1) +(1 + sqrt(5))**Rational(1,3) +2**(1/x) +sqrt(2+pi) +(2+(1+x**2)/(2+x))**Rational(1,4)+(1+x**Rational(1,1000))/sqrt(3+x**2) + + +DERIVATIVES: + +Derivative(log(x), x, evaluate=False) +Derivative(log(x), x, evaluate=False) + x # +Derivative(log(x) + x**2, x, y, evaluate=False) +Derivative(2*x*y, y, x, evaluate=False) + x**2 # +beta(alpha).diff(alpha) + + +INTEGRALS: + +Integral(log(x), x) +Integral(x**2, x) +Integral((sin(x))**2 / (tan(x))**2) +Integral(x**(2**x), x) +Integral(x**2, (x,1,2)) +Integral(x**2, (x,Rational(1,2),10)) +Integral(x**2*y**2, x,y) +Integral(x**2, (x, None, 1)) +Integral(x**2, (x, 1, None)) +Integral(sin(th)/cos(ph), (th,0,pi), (ph, 0, 2*pi)) + + +MATRICES: + +Matrix([[x**2+1, 1], [y, x+y]]) # +Matrix([[x/y, y, th], [0, exp(I*k*ph), 1]]) + + +PIECEWISE: + +Piecewise((x,x<1),(x**2,True)) + +ITE: + +ITE(x, y, z) + +SEQUENCES (TUPLES, LISTS, DICTIONARIES): + +() +[] +{} +(1/x,) +[x**2, 1/x, x, y, sin(th)**2/cos(ph)**2] +(x**2, 1/x, x, y, sin(th)**2/cos(ph)**2) +{x: sin(x)} +{1/x: 1/y, x: sin(x)**2} # +[x**2] +(x**2,) +{x**2: 1} + + +LIMITS: + +Limit(x, x, oo) +Limit(x**2, x, 0) +Limit(1/x, x, 0) +Limit(sin(x)/x, x, 0) + + +UNITS: + +joule => kg*m**2/s + + +SUBS: + +Subs(f(x), x, ph**2) +Subs(f(x).diff(x), x, 0) +Subs(f(x).diff(x)/y, (x, y), (0, Rational(1, 2))) + + +ORDER: + +O(1) +O(1/x) +O(x**2 + y**2) + +""" + + +def pretty(expr, order=None): + """ASCII pretty-printing""" + return xpretty(expr, order=order, use_unicode=False, wrap_line=False) + + +def upretty(expr, order=None): + """Unicode pretty-printing""" + return xpretty(expr, order=order, use_unicode=True, wrap_line=False) + + +def test_pretty_ascii_str(): + assert pretty( 'xxx' ) == 'xxx' + assert pretty( "xxx" ) == 'xxx' + assert pretty( 'xxx\'xxx' ) == 'xxx\'xxx' + assert pretty( 'xxx"xxx' ) == 'xxx\"xxx' + assert pretty( 'xxx\"xxx' ) == 'xxx\"xxx' + assert pretty( "xxx'xxx" ) == 'xxx\'xxx' + assert pretty( "xxx\'xxx" ) == 'xxx\'xxx' + assert pretty( "xxx\"xxx" ) == 'xxx\"xxx' + assert pretty( "xxx\"xxx\'xxx" ) == 'xxx"xxx\'xxx' + assert pretty( "xxx\nxxx" ) == 'xxx\nxxx' + + +def test_pretty_unicode_str(): + assert pretty( 'xxx' ) == 'xxx' + assert pretty( 'xxx' ) == 'xxx' + assert pretty( 'xxx\'xxx' ) == 'xxx\'xxx' + assert pretty( 'xxx"xxx' ) == 'xxx\"xxx' + assert pretty( 'xxx\"xxx' ) == 'xxx\"xxx' + assert pretty( "xxx'xxx" ) == 'xxx\'xxx' + assert pretty( "xxx\'xxx" ) == 'xxx\'xxx' + assert pretty( "xxx\"xxx" ) == 'xxx\"xxx' + assert pretty( "xxx\"xxx\'xxx" ) == 'xxx"xxx\'xxx' + assert pretty( "xxx\nxxx" ) == 'xxx\nxxx' + + +def test_upretty_greek(): + assert upretty( oo ) == '∞' + assert upretty( Symbol('alpha^+_1') ) == 'α⁺₁' + assert upretty( Symbol('beta') ) == 'β' + assert upretty(Symbol('lambda')) == 'λ' + + +def test_upretty_multiindex(): + assert upretty( Symbol('beta12') ) == 'β₁₂' + assert upretty( Symbol('Y00') ) == 'Y₀₀' + assert upretty( Symbol('Y_00') ) == 'Y₀₀' + assert upretty( Symbol('F^+-') ) == 'F⁺⁻' + + +def test_upretty_sub_super(): + assert upretty( Symbol('beta_1_2') ) == 'β₁ ₂' + assert upretty( Symbol('beta^1^2') ) == 'β¹ ²' + assert upretty( Symbol('beta_1^2') ) == 'β²₁' + assert upretty( Symbol('beta_10_20') ) == 'β₁₀ ₂₀' + assert upretty( Symbol('beta_ax_gamma^i') ) == 'βⁱₐₓ ᵧ' + assert upretty( Symbol("F^1^2_3_4") ) == 'F¹ ²₃ ₄' + assert upretty( Symbol("F_1_2^3^4") ) == 'F³ ⁴₁ ₂' + assert upretty( Symbol("F_1_2_3_4") ) == 'F₁ ₂ ₃ ₄' + assert upretty( Symbol("F^1^2^3^4") ) == 'F¹ ² ³ ⁴' + + +def test_upretty_subs_missing_in_24(): + assert upretty( Symbol('F_beta') ) == 'Fᵦ' + assert upretty( Symbol('F_gamma') ) == 'Fᵧ' + assert upretty( Symbol('F_rho') ) == 'Fᵨ' + assert upretty( Symbol('F_phi') ) == 'Fᵩ' + assert upretty( Symbol('F_chi') ) == 'Fᵪ' + + assert upretty( Symbol('F_a') ) == 'Fₐ' + assert upretty( Symbol('F_e') ) == 'Fₑ' + assert upretty( Symbol('F_i') ) == 'Fᵢ' + assert upretty( Symbol('F_o') ) == 'Fₒ' + assert upretty( Symbol('F_u') ) == 'Fᵤ' + assert upretty( Symbol('F_r') ) == 'Fᵣ' + assert upretty( Symbol('F_v') ) == 'Fᵥ' + assert upretty( Symbol('F_x') ) == 'Fₓ' + + +def test_missing_in_2X_issue_9047(): + assert upretty( Symbol('F_h') ) == 'Fₕ' + assert upretty( Symbol('F_k') ) == 'Fₖ' + assert upretty( Symbol('F_l') ) == 'Fₗ' + assert upretty( Symbol('F_m') ) == 'Fₘ' + assert upretty( Symbol('F_n') ) == 'Fₙ' + assert upretty( Symbol('F_p') ) == 'Fₚ' + assert upretty( Symbol('F_s') ) == 'Fₛ' + assert upretty( Symbol('F_t') ) == 'Fₜ' + + +def test_upretty_modifiers(): + # Accents + assert upretty( Symbol('Fmathring') ) == 'F̊' + assert upretty( Symbol('Fddddot') ) == 'F⃜' + assert upretty( Symbol('Fdddot') ) == 'F⃛' + assert upretty( Symbol('Fddot') ) == 'F̈' + assert upretty( Symbol('Fdot') ) == 'Ḟ' + assert upretty( Symbol('Fcheck') ) == 'F̌' + assert upretty( Symbol('Fbreve') ) == 'F̆' + assert upretty( Symbol('Facute') ) == 'F́' + assert upretty( Symbol('Fgrave') ) == 'F̀' + assert upretty( Symbol('Ftilde') ) == 'F̃' + assert upretty( Symbol('Fhat') ) == 'F̂' + assert upretty( Symbol('Fbar') ) == 'F̅' + assert upretty( Symbol('Fvec') ) == 'F⃗' + assert upretty( Symbol('Fprime') ) == 'F′' + assert upretty( Symbol('Fprm') ) == 'F′' + # No faces are actually implemented, but test to make sure the modifiers are stripped + assert upretty( Symbol('Fbold') ) == 'Fbold' + assert upretty( Symbol('Fbm') ) == 'Fbm' + assert upretty( Symbol('Fcal') ) == 'Fcal' + assert upretty( Symbol('Fscr') ) == 'Fscr' + assert upretty( Symbol('Ffrak') ) == 'Ffrak' + # Brackets + assert upretty( Symbol('Fnorm') ) == '‖F‖' + assert upretty( Symbol('Favg') ) == '⟨F⟩' + assert upretty( Symbol('Fabs') ) == '|F|' + assert upretty( Symbol('Fmag') ) == '|F|' + # Combinations + assert upretty( Symbol('xvecdot') ) == 'x⃗̇' + assert upretty( Symbol('xDotVec') ) == 'ẋ⃗' + assert upretty( Symbol('xHATNorm') ) == '‖x̂‖' + assert upretty( Symbol('xMathring_yCheckPRM__zbreveAbs') ) == 'x̊_y̌′__|z̆|' + assert upretty( Symbol('alphadothat_nVECDOT__tTildePrime') ) == 'α̇̂_n⃗̇__t̃′' + assert upretty( Symbol('x_dot') ) == 'x_dot' + assert upretty( Symbol('x__dot') ) == 'x__dot' + + +def test_pretty_Cycle(): + from sympy.combinatorics.permutations import Cycle + assert pretty(Cycle(1, 2)) == '(1 2)' + assert pretty(Cycle(2)) == '(2)' + assert pretty(Cycle(1, 3)(4, 5)) == '(1 3)(4 5)' + assert pretty(Cycle()) == '()' + + +def test_pretty_Permutation(): + from sympy.combinatorics.permutations import Permutation + p1 = Permutation(1, 2)(3, 4) + assert xpretty(p1, perm_cyclic=True, use_unicode=True) == "(1 2)(3 4)" + assert xpretty(p1, perm_cyclic=True, use_unicode=False) == "(1 2)(3 4)" + assert xpretty(p1, perm_cyclic=False, use_unicode=True) == \ + '⎛0 1 2 3 4⎞\n'\ + '⎝0 2 1 4 3⎠' + assert xpretty(p1, perm_cyclic=False, use_unicode=False) == \ + "/0 1 2 3 4\\\n"\ + "\\0 2 1 4 3/" + + with warns_deprecated_sympy(): + old_print_cyclic = Permutation.print_cyclic + Permutation.print_cyclic = False + assert xpretty(p1, use_unicode=True) == \ + '⎛0 1 2 3 4⎞\n'\ + '⎝0 2 1 4 3⎠' + assert xpretty(p1, use_unicode=False) == \ + "/0 1 2 3 4\\\n"\ + "\\0 2 1 4 3/" + Permutation.print_cyclic = old_print_cyclic + + +def test_pretty_basic(): + assert pretty( -Rational(1)/2 ) == '-1/2' + assert pretty( -Rational(13)/22 ) == \ +"""\ +-13 \n\ +----\n\ + 22 \ +""" + expr = oo + ascii_str = \ +"""\ +oo\ +""" + ucode_str = \ +"""\ +∞\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = (x**2) + ascii_str = \ +"""\ + 2\n\ +x \ +""" + ucode_str = \ +"""\ + 2\n\ +x \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = 1/x + ascii_str = \ +"""\ +1\n\ +-\n\ +x\ +""" + ucode_str = \ +"""\ +1\n\ +─\n\ +x\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + # not the same as 1/x + expr = x**-1.0 + ascii_str = \ +"""\ + -1.0\n\ +x \ +""" + ucode_str = \ +"""\ + -1.0\n\ +x \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + # see issue #2860 + expr = Pow(S(2), -1.0, evaluate=False) + ascii_str = \ +"""\ + -1.0\n\ +2 \ +""" + ucode_str = \ +"""\ + -1.0\n\ +2 \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = y*x**-2 + ascii_str = \ +"""\ +y \n\ +--\n\ + 2\n\ +x \ +""" + ucode_str = \ +"""\ +y \n\ +──\n\ + 2\n\ +x \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + #see issue #14033 + expr = x**Rational(1, 3) + ascii_str = \ +"""\ + 1/3\n\ +x \ +""" + ucode_str = \ +"""\ + 1/3\n\ +x \ +""" + assert xpretty(expr, use_unicode=False, wrap_line=False,\ + root_notation = False) == ascii_str + assert xpretty(expr, use_unicode=True, wrap_line=False,\ + root_notation = False) == ucode_str + + expr = x**Rational(-5, 2) + ascii_str = \ +"""\ + 1 \n\ +----\n\ + 5/2\n\ +x \ +""" + ucode_str = \ +"""\ + 1 \n\ +────\n\ + 5/2\n\ +x \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = (-2)**x + ascii_str = \ +"""\ + x\n\ +(-2) \ +""" + ucode_str = \ +"""\ + x\n\ +(-2) \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + # See issue 4923 + expr = Pow(3, 1, evaluate=False) + ascii_str = \ +"""\ + 1\n\ +3 \ +""" + ucode_str = \ +"""\ + 1\n\ +3 \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = (x**2 + x + 1) + ascii_str_1 = \ +"""\ + 2\n\ +1 + x + x \ +""" + ascii_str_2 = \ +"""\ + 2 \n\ +x + x + 1\ +""" + ascii_str_3 = \ +"""\ + 2 \n\ +x + 1 + x\ +""" + ucode_str_1 = \ +"""\ + 2\n\ +1 + x + x \ +""" + ucode_str_2 = \ +"""\ + 2 \n\ +x + x + 1\ +""" + ucode_str_3 = \ +"""\ + 2 \n\ +x + 1 + x\ +""" + assert pretty(expr) in [ascii_str_1, ascii_str_2, ascii_str_3] + assert upretty(expr) in [ucode_str_1, ucode_str_2, ucode_str_3] + + expr = 1 - x + ascii_str_1 = \ +"""\ +1 - x\ +""" + ascii_str_2 = \ +"""\ +-x + 1\ +""" + ucode_str_1 = \ +"""\ +1 - x\ +""" + ucode_str_2 = \ +"""\ +-x + 1\ +""" + assert pretty(expr) in [ascii_str_1, ascii_str_2] + assert upretty(expr) in [ucode_str_1, ucode_str_2] + + expr = 1 - 2*x + ascii_str_1 = \ +"""\ +1 - 2*x\ +""" + ascii_str_2 = \ +"""\ +-2*x + 1\ +""" + ucode_str_1 = \ +"""\ +1 - 2⋅x\ +""" + ucode_str_2 = \ +"""\ +-2⋅x + 1\ +""" + assert pretty(expr) in [ascii_str_1, ascii_str_2] + assert upretty(expr) in [ucode_str_1, ucode_str_2] + + expr = x/y + ascii_str = \ +"""\ +x\n\ +-\n\ +y\ +""" + ucode_str = \ +"""\ +x\n\ +─\n\ +y\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = -x/y + ascii_str = \ +"""\ +-x \n\ +---\n\ + y \ +""" + ucode_str = \ +"""\ +-x \n\ +───\n\ + y \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = (x + 2)/y + ascii_str_1 = \ +"""\ +2 + x\n\ +-----\n\ + y \ +""" + ascii_str_2 = \ +"""\ +x + 2\n\ +-----\n\ + y \ +""" + ucode_str_1 = \ +"""\ +2 + x\n\ +─────\n\ + y \ +""" + ucode_str_2 = \ +"""\ +x + 2\n\ +─────\n\ + y \ +""" + assert pretty(expr) in [ascii_str_1, ascii_str_2] + assert upretty(expr) in [ucode_str_1, ucode_str_2] + + expr = (1 + x)*y + ascii_str_1 = \ +"""\ +y*(1 + x)\ +""" + ascii_str_2 = \ +"""\ +(1 + x)*y\ +""" + ascii_str_3 = \ +"""\ +y*(x + 1)\ +""" + ucode_str_1 = \ +"""\ +y⋅(1 + x)\ +""" + ucode_str_2 = \ +"""\ +(1 + x)⋅y\ +""" + ucode_str_3 = \ +"""\ +y⋅(x + 1)\ +""" + assert pretty(expr) in [ascii_str_1, ascii_str_2, ascii_str_3] + assert upretty(expr) in [ucode_str_1, ucode_str_2, ucode_str_3] + + # Test for correct placement of the negative sign + expr = -5*x/(x + 10) + ascii_str_1 = \ +"""\ +-5*x \n\ +------\n\ +10 + x\ +""" + ascii_str_2 = \ +"""\ +-5*x \n\ +------\n\ +x + 10\ +""" + ucode_str_1 = \ +"""\ +-5⋅x \n\ +──────\n\ +10 + x\ +""" + ucode_str_2 = \ +"""\ +-5⋅x \n\ +──────\n\ +x + 10\ +""" + assert pretty(expr) in [ascii_str_1, ascii_str_2] + assert upretty(expr) in [ucode_str_1, ucode_str_2] + + expr = -S.Half - 3*x + ascii_str = \ +"""\ +-3*x - 1/2\ +""" + ucode_str = \ +"""\ +-3⋅x - 1/2\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = S.Half - 3*x + ascii_str = \ +"""\ +1/2 - 3*x\ +""" + ucode_str = \ +"""\ +1/2 - 3⋅x\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = -S.Half - 3*x/2 + ascii_str = \ +"""\ + 3*x 1\n\ +- --- - -\n\ + 2 2\ +""" + ucode_str = \ +"""\ + 3⋅x 1\n\ +- ─── - ─\n\ + 2 2\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = S.Half - 3*x/2 + ascii_str = \ +"""\ +1 3*x\n\ +- - ---\n\ +2 2 \ +""" + ucode_str = \ +"""\ +1 3⋅x\n\ +─ - ───\n\ +2 2 \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + +def test_negative_fractions(): + expr = -x/y + ascii_str =\ +"""\ +-x \n\ +---\n\ + y \ +""" + ucode_str =\ +"""\ +-x \n\ +───\n\ + y \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + expr = -x*z/y + ascii_str =\ +"""\ +-x*z \n\ +-----\n\ + y \ +""" + ucode_str =\ +"""\ +-x⋅z \n\ +─────\n\ + y \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + expr = x**2/y + ascii_str =\ +"""\ + 2\n\ +x \n\ +--\n\ +y \ +""" + ucode_str =\ +"""\ + 2\n\ +x \n\ +──\n\ +y \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + expr = -x**2/y + ascii_str =\ +"""\ + 2 \n\ +-x \n\ +----\n\ + y \ +""" + ucode_str =\ +"""\ + 2 \n\ +-x \n\ +────\n\ + y \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + expr = -x/(y*z) + ascii_str =\ +"""\ +-x \n\ +---\n\ +y*z\ +""" + ucode_str =\ +"""\ +-x \n\ +───\n\ +y⋅z\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + expr = -a/y**2 + ascii_str =\ +"""\ +-a \n\ +---\n\ + 2 \n\ +y \ +""" + ucode_str =\ +"""\ +-a \n\ +───\n\ + 2 \n\ +y \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + expr = y**(-a/b) + ascii_str =\ +"""\ + -a \n\ + ---\n\ + b \n\ +y \ +""" + ucode_str =\ +"""\ + -a \n\ + ───\n\ + b \n\ +y \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + expr = -1/y**2 + ascii_str =\ +"""\ +-1 \n\ +---\n\ + 2 \n\ +y \ +""" + ucode_str =\ +"""\ +-1 \n\ +───\n\ + 2 \n\ +y \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + expr = -10/b**2 + ascii_str =\ +"""\ +-10 \n\ +----\n\ + 2 \n\ + b \ +""" + ucode_str =\ +"""\ +-10 \n\ +────\n\ + 2 \n\ + b \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + expr = Rational(-200, 37) + ascii_str =\ +"""\ +-200 \n\ +-----\n\ + 37 \ +""" + ucode_str =\ +"""\ +-200 \n\ +─────\n\ + 37 \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + +def test_Mul(): + expr = Mul(0, 1, evaluate=False) + assert pretty(expr) == "0*1" + assert upretty(expr) == "0⋅1" + expr = Mul(1, 0, evaluate=False) + assert pretty(expr) == "1*0" + assert upretty(expr) == "1⋅0" + expr = Mul(1, 1, evaluate=False) + assert pretty(expr) == "1*1" + assert upretty(expr) == "1⋅1" + expr = Mul(1, 1, 1, evaluate=False) + assert pretty(expr) == "1*1*1" + assert upretty(expr) == "1⋅1⋅1" + expr = Mul(1, 2, evaluate=False) + assert pretty(expr) == "1*2" + assert upretty(expr) == "1⋅2" + expr = Add(0, 1, evaluate=False) + assert pretty(expr) == "0 + 1" + assert upretty(expr) == "0 + 1" + expr = Mul(1, 1, 2, evaluate=False) + assert pretty(expr) == "1*1*2" + assert upretty(expr) == "1⋅1⋅2" + expr = Add(0, 0, 1, evaluate=False) + assert pretty(expr) == "0 + 0 + 1" + assert upretty(expr) == "0 + 0 + 1" + expr = Mul(1, -1, evaluate=False) + assert pretty(expr) == "1*-1" + assert upretty(expr) == "1⋅-1" + expr = Mul(1.0, x, evaluate=False) + assert pretty(expr) == "1.0*x" + assert upretty(expr) == "1.0⋅x" + expr = Mul(1, 1, 2, 3, x, evaluate=False) + assert pretty(expr) == "1*1*2*3*x" + assert upretty(expr) == "1⋅1⋅2⋅3⋅x" + expr = Mul(-1, 1, evaluate=False) + assert pretty(expr) == "-1*1" + assert upretty(expr) == "-1⋅1" + expr = Mul(4, 3, 2, 1, 0, y, x, evaluate=False) + assert pretty(expr) == "4*3*2*1*0*y*x" + assert upretty(expr) == "4⋅3⋅2⋅1⋅0⋅y⋅x" + expr = Mul(4, 3, 2, 1+z, 0, y, x, evaluate=False) + assert pretty(expr) == "4*3*2*(z + 1)*0*y*x" + assert upretty(expr) == "4⋅3⋅2⋅(z + 1)⋅0⋅y⋅x" + expr = Mul(Rational(2, 3), Rational(5, 7), evaluate=False) + assert pretty(expr) == "2/3*5/7" + assert upretty(expr) == "2/3⋅5/7" + expr = Mul(x + y, Rational(1, 2), evaluate=False) + assert pretty(expr) == "(x + y)*1/2" + assert upretty(expr) == "(x + y)⋅1/2" + expr = Mul(Rational(1, 2), x + y, evaluate=False) + assert pretty(expr) == "x + y\n-----\n 2 " + assert upretty(expr) == "x + y\n─────\n 2 " + expr = Mul(S.One, x + y, evaluate=False) + assert pretty(expr) == "1*(x + y)" + assert upretty(expr) == "1⋅(x + y)" + expr = Mul(x - y, S.One, evaluate=False) + assert pretty(expr) == "(x - y)*1" + assert upretty(expr) == "(x - y)⋅1" + expr = Mul(Rational(1, 2), x - y, S.One, x + y, evaluate=False) + assert pretty(expr) == "1/2*(x - y)*1*(x + y)" + assert upretty(expr) == "1/2⋅(x - y)⋅1⋅(x + y)" + expr = Mul(x + y, Rational(3, 4), S.One, y - z, evaluate=False) + assert pretty(expr) == "(x + y)*3/4*1*(y - z)" + assert upretty(expr) == "(x + y)⋅3/4⋅1⋅(y - z)" + expr = Mul(x + y, Rational(1, 1), Rational(3, 4), Rational(5, 6),evaluate=False) + assert pretty(expr) == "(x + y)*1*3/4*5/6" + assert upretty(expr) == "(x + y)⋅1⋅3/4⋅5/6" + expr = Mul(Rational(3, 4), x + y, S.One, y - z, evaluate=False) + assert pretty(expr) == "3/4*(x + y)*1*(y - z)" + assert upretty(expr) == "3/4⋅(x + y)⋅1⋅(y - z)" + + +def test_issue_5524(): + assert pretty(-(-x + 5)*(-x - 2*sqrt(2) + 5) - (-y + 5)*(-y + 5)) == \ +"""\ + 2 / ___ \\\n\ +- (5 - y) + (x - 5)*\\-x - 2*\\/ 2 + 5/\ +""" + + assert upretty(-(-x + 5)*(-x - 2*sqrt(2) + 5) - (-y + 5)*(-y + 5)) == \ +"""\ + 2 \n\ +- (5 - y) + (x - 5)⋅(-x - 2⋅√2 + 5)\ +""" + + +def test_pretty_ordering(): + assert pretty(x**2 + x + 1, order='lex') == \ +"""\ + 2 \n\ +x + x + 1\ +""" + assert pretty(x**2 + x + 1, order='rev-lex') == \ +"""\ + 2\n\ +1 + x + x \ +""" + assert pretty(1 - x, order='lex') == '-x + 1' + assert pretty(1 - x, order='rev-lex') == '1 - x' + + assert pretty(1 - 2*x, order='lex') == '-2*x + 1' + assert pretty(1 - 2*x, order='rev-lex') == '1 - 2*x' + + f = 2*x**4 + y**2 - x**2 + y**3 + assert pretty(f, order=None) == \ +"""\ + 4 2 3 2\n\ +2*x - x + y + y \ +""" + assert pretty(f, order='lex') == \ +"""\ + 4 2 3 2\n\ +2*x - x + y + y \ +""" + assert pretty(f, order='rev-lex') == \ +"""\ + 2 3 2 4\n\ +y + y - x + 2*x \ +""" + + expr = x - x**3/6 + x**5/120 + O(x**6) + ascii_str = \ +"""\ + 3 5 \n\ + x x / 6\\\n\ +x - -- + --- + O\\x /\n\ + 6 120 \ +""" + ucode_str = \ +"""\ + 3 5 \n\ + x x ⎛ 6⎞\n\ +x - ── + ─── + O⎝x ⎠\n\ + 6 120 \ +""" + assert pretty(expr, order=None) == ascii_str + assert upretty(expr, order=None) == ucode_str + + assert pretty(expr, order='lex') == ascii_str + assert upretty(expr, order='lex') == ucode_str + + assert pretty(expr, order='rev-lex') == ascii_str + assert upretty(expr, order='rev-lex') == ucode_str + + +def test_EulerGamma(): + assert pretty(EulerGamma) == str(EulerGamma) == "EulerGamma" + assert upretty(EulerGamma) == "γ" + + +def test_GoldenRatio(): + assert pretty(GoldenRatio) == str(GoldenRatio) == "GoldenRatio" + assert upretty(GoldenRatio) == "φ" + + +def test_Catalan(): + assert pretty(Catalan) == upretty(Catalan) == "G" + + +def test_pretty_relational(): + expr = Eq(x, y) + ascii_str = \ +"""\ +x = y\ +""" + ucode_str = \ +"""\ +x = y\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Lt(x, y) + ascii_str = \ +"""\ +x < y\ +""" + ucode_str = \ +"""\ +x < y\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Gt(x, y) + ascii_str = \ +"""\ +x > y\ +""" + ucode_str = \ +"""\ +x > y\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Le(x, y) + ascii_str = \ +"""\ +x <= y\ +""" + ucode_str = \ +"""\ +x ≤ y\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Ge(x, y) + ascii_str = \ +"""\ +x >= y\ +""" + ucode_str = \ +"""\ +x ≥ y\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Ne(x/(y + 1), y**2) + ascii_str_1 = \ +"""\ + x 2\n\ +----- != y \n\ +1 + y \ +""" + ascii_str_2 = \ +"""\ + x 2\n\ +----- != y \n\ +y + 1 \ +""" + ucode_str_1 = \ +"""\ + x 2\n\ +───── ≠ y \n\ +1 + y \ +""" + ucode_str_2 = \ +"""\ + x 2\n\ +───── ≠ y \n\ +y + 1 \ +""" + assert pretty(expr) in [ascii_str_1, ascii_str_2] + assert upretty(expr) in [ucode_str_1, ucode_str_2] + + +def test_Assignment(): + expr = Assignment(x, y) + ascii_str = \ +"""\ +x := y\ +""" + ucode_str = \ +"""\ +x := y\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + +def test_AugmentedAssignment(): + expr = AddAugmentedAssignment(x, y) + ascii_str = \ +"""\ +x += y\ +""" + ucode_str = \ +"""\ +x += y\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = SubAugmentedAssignment(x, y) + ascii_str = \ +"""\ +x -= y\ +""" + ucode_str = \ +"""\ +x -= y\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = MulAugmentedAssignment(x, y) + ascii_str = \ +"""\ +x *= y\ +""" + ucode_str = \ +"""\ +x *= y\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = DivAugmentedAssignment(x, y) + ascii_str = \ +"""\ +x /= y\ +""" + ucode_str = \ +"""\ +x /= y\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = ModAugmentedAssignment(x, y) + ascii_str = \ +"""\ +x %= y\ +""" + ucode_str = \ +"""\ +x %= y\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + +def test_pretty_rational(): + expr = y*x**-2 + ascii_str = \ +"""\ +y \n\ +--\n\ + 2\n\ +x \ +""" + ucode_str = \ +"""\ +y \n\ +──\n\ + 2\n\ +x \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = y**Rational(3, 2) * x**Rational(-5, 2) + ascii_str = \ +"""\ + 3/2\n\ +y \n\ +----\n\ + 5/2\n\ +x \ +""" + ucode_str = \ +"""\ + 3/2\n\ +y \n\ +────\n\ + 5/2\n\ +x \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = sin(x)**3/tan(x)**2 + ascii_str = \ +"""\ + 3 \n\ +sin (x)\n\ +-------\n\ + 2 \n\ +tan (x)\ +""" + ucode_str = \ +"""\ + 3 \n\ +sin (x)\n\ +───────\n\ + 2 \n\ +tan (x)\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + +@_both_exp_pow +def test_pretty_functions(): + """Tests for Abs, conjugate, exp, function braces, and factorial.""" + expr = (2*x + exp(x)) + ascii_str_1 = \ +"""\ + x\n\ +2*x + e \ +""" + ascii_str_2 = \ +"""\ + x \n\ +e + 2*x\ +""" + ucode_str_1 = \ +"""\ + x\n\ +2⋅x + ℯ \ +""" + ucode_str_2 = \ +"""\ + x \n\ +ℯ + 2⋅x\ +""" + ucode_str_3 = \ +"""\ + x \n\ +ℯ + 2⋅x\ +""" + assert pretty(expr) in [ascii_str_1, ascii_str_2] + assert upretty(expr) in [ucode_str_1, ucode_str_2, ucode_str_3] + + expr = Abs(x) + ascii_str = \ +"""\ +|x|\ +""" + ucode_str = \ +"""\ +│x│\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Abs(x/(x**2 + 1)) + ascii_str_1 = \ +"""\ +| x |\n\ +|------|\n\ +| 2|\n\ +|1 + x |\ +""" + ascii_str_2 = \ +"""\ +| x |\n\ +|------|\n\ +| 2 |\n\ +|x + 1|\ +""" + ucode_str_1 = \ +"""\ +│ x │\n\ +│──────│\n\ +│ 2│\n\ +│1 + x │\ +""" + ucode_str_2 = \ +"""\ +│ x │\n\ +│──────│\n\ +│ 2 │\n\ +│x + 1│\ +""" + assert pretty(expr) in [ascii_str_1, ascii_str_2] + assert upretty(expr) in [ucode_str_1, ucode_str_2] + + expr = Abs(1 / (y - Abs(x))) + ascii_str = \ +"""\ + 1 \n\ +---------\n\ +|y - |x||\ +""" + ucode_str = \ +"""\ + 1 \n\ +─────────\n\ +│y - │x││\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + n = Symbol('n', integer=True) + expr = factorial(n) + ascii_str = \ +"""\ +n!\ +""" + ucode_str = \ +"""\ +n!\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = factorial(2*n) + ascii_str = \ +"""\ +(2*n)!\ +""" + ucode_str = \ +"""\ +(2⋅n)!\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = factorial(factorial(factorial(n))) + ascii_str = \ +"""\ +((n!)!)!\ +""" + ucode_str = \ +"""\ +((n!)!)!\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = factorial(n + 1) + ascii_str_1 = \ +"""\ +(1 + n)!\ +""" + ascii_str_2 = \ +"""\ +(n + 1)!\ +""" + ucode_str_1 = \ +"""\ +(1 + n)!\ +""" + ucode_str_2 = \ +"""\ +(n + 1)!\ +""" + + assert pretty(expr) in [ascii_str_1, ascii_str_2] + assert upretty(expr) in [ucode_str_1, ucode_str_2] + + expr = subfactorial(n) + ascii_str = \ +"""\ +!n\ +""" + ucode_str = \ +"""\ +!n\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = subfactorial(2*n) + ascii_str = \ +"""\ +!(2*n)\ +""" + ucode_str = \ +"""\ +!(2⋅n)\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + n = Symbol('n', integer=True) + expr = factorial2(n) + ascii_str = \ +"""\ +n!!\ +""" + ucode_str = \ +"""\ +n!!\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = factorial2(2*n) + ascii_str = \ +"""\ +(2*n)!!\ +""" + ucode_str = \ +"""\ +(2⋅n)!!\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = factorial2(factorial2(factorial2(n))) + ascii_str = \ +"""\ +((n!!)!!)!!\ +""" + ucode_str = \ +"""\ +((n!!)!!)!!\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = factorial2(n + 1) + ascii_str_1 = \ +"""\ +(1 + n)!!\ +""" + ascii_str_2 = \ +"""\ +(n + 1)!!\ +""" + ucode_str_1 = \ +"""\ +(1 + n)!!\ +""" + ucode_str_2 = \ +"""\ +(n + 1)!!\ +""" + + assert pretty(expr) in [ascii_str_1, ascii_str_2] + assert upretty(expr) in [ucode_str_1, ucode_str_2] + + expr = 2*binomial(n, k) + ascii_str = \ +"""\ + /n\\\n\ +2*| |\n\ + \\k/\ +""" + ucode_str = \ +"""\ + ⎛n⎞\n\ +2⋅⎜ ⎟\n\ + ⎝k⎠\ +""" + + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = 2*binomial(2*n, k) + ascii_str = \ +"""\ + /2*n\\\n\ +2*| |\n\ + \\ k /\ +""" + ucode_str = \ +"""\ + ⎛2⋅n⎞\n\ +2⋅⎜ ⎟\n\ + ⎝ k ⎠\ +""" + + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = 2*binomial(n**2, k) + ascii_str = \ +"""\ + / 2\\\n\ + |n |\n\ +2*| |\n\ + \\k /\ +""" + ucode_str = \ +"""\ + ⎛ 2⎞\n\ + ⎜n ⎟\n\ +2⋅⎜ ⎟\n\ + ⎝k ⎠\ +""" + + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = catalan(n) + ascii_str = \ +"""\ +C \n\ + n\ +""" + ucode_str = \ +"""\ +C \n\ + n\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = catalan(n) + ascii_str = \ +"""\ +C \n\ + n\ +""" + ucode_str = \ +"""\ +C \n\ + n\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = bell(n) + ascii_str = \ +"""\ +B \n\ + n\ +""" + ucode_str = \ +"""\ +B \n\ + n\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = bernoulli(n) + ascii_str = \ +"""\ +B \n\ + n\ +""" + ucode_str = \ +"""\ +B \n\ + n\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = bernoulli(n, x) + ascii_str = \ +"""\ +B (x)\n\ + n \ +""" + ucode_str = \ +"""\ +B (x)\n\ + n \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = fibonacci(n) + ascii_str = \ +"""\ +F \n\ + n\ +""" + ucode_str = \ +"""\ +F \n\ + n\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = lucas(n) + ascii_str = \ +"""\ +L \n\ + n\ +""" + ucode_str = \ +"""\ +L \n\ + n\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = tribonacci(n) + ascii_str = \ +"""\ +T \n\ + n\ +""" + ucode_str = \ +"""\ +T \n\ + n\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = stieltjes(n) + ascii_str = \ +"""\ +stieltjes \n\ + n\ +""" + ucode_str = \ +"""\ +γ \n\ + n\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = stieltjes(n, x) + ascii_str = \ +"""\ +stieltjes (x)\n\ + n \ +""" + ucode_str = \ +"""\ +γ (x)\n\ + n \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = mathieuc(x, y, z) + ascii_str = 'C(x, y, z)' + ucode_str = 'C(x, y, z)' + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = mathieus(x, y, z) + ascii_str = 'S(x, y, z)' + ucode_str = 'S(x, y, z)' + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = mathieucprime(x, y, z) + ascii_str = "C'(x, y, z)" + ucode_str = "C'(x, y, z)" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = mathieusprime(x, y, z) + ascii_str = "S'(x, y, z)" + ucode_str = "S'(x, y, z)" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = conjugate(x) + ascii_str = \ +"""\ +_\n\ +x\ +""" + ucode_str = \ +"""\ +_\n\ +x\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + f = Function('f') + expr = conjugate(f(x + 1)) + ascii_str_1 = \ +"""\ +________\n\ +f(1 + x)\ +""" + ascii_str_2 = \ +"""\ +________\n\ +f(x + 1)\ +""" + ucode_str_1 = \ +"""\ +________\n\ +f(1 + x)\ +""" + ucode_str_2 = \ +"""\ +________\n\ +f(x + 1)\ +""" + assert pretty(expr) in [ascii_str_1, ascii_str_2] + assert upretty(expr) in [ucode_str_1, ucode_str_2] + + expr = f(x) + ascii_str = \ +"""\ +f(x)\ +""" + ucode_str = \ +"""\ +f(x)\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = f(x, y) + ascii_str = \ +"""\ +f(x, y)\ +""" + ucode_str = \ +"""\ +f(x, y)\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = f(x/(y + 1), y) + ascii_str_1 = \ +"""\ + / x \\\n\ +f|-----, y|\n\ + \\1 + y /\ +""" + ascii_str_2 = \ +"""\ + / x \\\n\ +f|-----, y|\n\ + \\y + 1 /\ +""" + ucode_str_1 = \ +"""\ + ⎛ x ⎞\n\ +f⎜─────, y⎟\n\ + ⎝1 + y ⎠\ +""" + ucode_str_2 = \ +"""\ + ⎛ x ⎞\n\ +f⎜─────, y⎟\n\ + ⎝y + 1 ⎠\ +""" + assert pretty(expr) in [ascii_str_1, ascii_str_2] + assert upretty(expr) in [ucode_str_1, ucode_str_2] + + expr = f(x**x**x**x**x**x) + ascii_str = \ +"""\ + / / / / / x\\\\\\\\\\ + | | | | \\x /|||| + | | | \\x /||| + | | \\x /|| + | \\x /| +f\\x /\ +""" + ucode_str = \ +"""\ + ⎛ ⎛ ⎛ ⎛ ⎛ x⎞⎞⎞⎞⎞ + ⎜ ⎜ ⎜ ⎜ ⎝x ⎠⎟⎟⎟⎟ + ⎜ ⎜ ⎜ ⎝x ⎠⎟⎟⎟ + ⎜ ⎜ ⎝x ⎠⎟⎟ + ⎜ ⎝x ⎠⎟ +f⎝x ⎠\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = sin(x)**2 + ascii_str = \ +"""\ + 2 \n\ +sin (x)\ +""" + ucode_str = \ +"""\ + 2 \n\ +sin (x)\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = conjugate(a + b*I) + ascii_str = \ +"""\ +_ _\n\ +a - I*b\ +""" + ucode_str = \ +"""\ +_ _\n\ +a - ⅈ⋅b\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = conjugate(exp(a + b*I)) + ascii_str = \ +"""\ + _ _\n\ + a - I*b\n\ +e \ +""" + ucode_str = \ +"""\ + _ _\n\ + a - ⅈ⋅b\n\ +ℯ \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = conjugate( f(1 + conjugate(f(x))) ) + ascii_str_1 = \ +"""\ +___________\n\ + / ____\\\n\ +f\\1 + f(x)/\ +""" + ascii_str_2 = \ +"""\ +___________\n\ + /____ \\\n\ +f\\f(x) + 1/\ +""" + ucode_str_1 = \ +"""\ +___________\n\ + ⎛ ____⎞\n\ +f⎝1 + f(x)⎠\ +""" + ucode_str_2 = \ +"""\ +___________\n\ + ⎛____ ⎞\n\ +f⎝f(x) + 1⎠\ +""" + assert pretty(expr) in [ascii_str_1, ascii_str_2] + assert upretty(expr) in [ucode_str_1, ucode_str_2] + + expr = f(x/(y + 1), y) + ascii_str_1 = \ +"""\ + / x \\\n\ +f|-----, y|\n\ + \\1 + y /\ +""" + ascii_str_2 = \ +"""\ + / x \\\n\ +f|-----, y|\n\ + \\y + 1 /\ +""" + ucode_str_1 = \ +"""\ + ⎛ x ⎞\n\ +f⎜─────, y⎟\n\ + ⎝1 + y ⎠\ +""" + ucode_str_2 = \ +"""\ + ⎛ x ⎞\n\ +f⎜─────, y⎟\n\ + ⎝y + 1 ⎠\ +""" + assert pretty(expr) in [ascii_str_1, ascii_str_2] + assert upretty(expr) in [ucode_str_1, ucode_str_2] + + expr = floor(1 / (y - floor(x))) + ascii_str = \ +"""\ + / 1 \\\n\ +floor|------------|\n\ + \\y - floor(x)/\ +""" + ucode_str = \ +"""\ +⎢ 1 ⎥\n\ +⎢───────⎥\n\ +⎣y - ⌊x⌋⎦\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = ceiling(1 / (y - ceiling(x))) + ascii_str = \ +"""\ + / 1 \\\n\ +ceiling|--------------|\n\ + \\y - ceiling(x)/\ +""" + ucode_str = \ +"""\ +⎡ 1 ⎤\n\ +⎢───────⎥\n\ +⎢y - ⌈x⌉⎥\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = euler(n) + ascii_str = \ +"""\ +E \n\ + n\ +""" + ucode_str = \ +"""\ +E \n\ + n\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = euler(1/(1 + 1/(1 + 1/n))) + ascii_str = \ +"""\ +E \n\ + 1 \n\ + ---------\n\ + 1 \n\ + 1 + -----\n\ + 1\n\ + 1 + -\n\ + n\ +""" + + ucode_str = \ +"""\ +E \n\ + 1 \n\ + ─────────\n\ + 1 \n\ + 1 + ─────\n\ + 1\n\ + 1 + ─\n\ + n\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = euler(n, x) + ascii_str = \ +"""\ +E (x)\n\ + n \ +""" + ucode_str = \ +"""\ +E (x)\n\ + n \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = euler(n, x/2) + ascii_str = \ +"""\ + /x\\\n\ +E |-|\n\ + n\\2/\ +""" + ucode_str = \ +"""\ + ⎛x⎞\n\ +E ⎜─⎟\n\ + n⎝2⎠\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + +def test_pretty_sqrt(): + expr = sqrt(2) + ascii_str = \ +"""\ + ___\n\ +\\/ 2 \ +""" + ucode_str = \ +"√2" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = 2**Rational(1, 3) + ascii_str = \ +"""\ +3 ___\n\ +\\/ 2 \ +""" + ucode_str = \ +"""\ +3 ___\n\ +╲╱ 2 \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = 2**Rational(1, 1000) + ascii_str = \ +"""\ +1000___\n\ + \\/ 2 \ +""" + ucode_str = \ +"""\ +1000___\n\ + ╲╱ 2 \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = sqrt(x**2 + 1) + ascii_str = \ +"""\ + ________\n\ + / 2 \n\ +\\/ x + 1 \ +""" + ucode_str = \ +"""\ + ________\n\ + ╱ 2 \n\ +╲╱ x + 1 \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = (1 + sqrt(5))**Rational(1, 3) + ascii_str = \ +"""\ + ___________\n\ +3 / ___ \n\ +\\/ 1 + \\/ 5 \ +""" + ucode_str = \ +"""\ +3 ________\n\ +╲╱ 1 + √5 \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = 2**(1/x) + ascii_str = \ +"""\ +x ___\n\ +\\/ 2 \ +""" + ucode_str = \ +"""\ +x ___\n\ +╲╱ 2 \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = sqrt(2 + pi) + ascii_str = \ +"""\ + ________\n\ +\\/ 2 + pi \ +""" + ucode_str = \ +"""\ + _______\n\ +╲╱ 2 + π \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = (2 + ( + 1 + x**2)/(2 + x))**Rational(1, 4) + (1 + x**Rational(1, 1000))/sqrt(3 + x**2) + ascii_str = \ +"""\ + ____________ \n\ + / 2 1000___ \n\ + / x + 1 \\/ x + 1\n\ +4 / 2 + ------ + -----------\n\ +\\/ x + 2 ________\n\ + / 2 \n\ + \\/ x + 3 \ +""" + ucode_str = \ +"""\ + ____________ \n\ + ╱ 2 1000___ \n\ + ╱ x + 1 ╲╱ x + 1\n\ +4 ╱ 2 + ────── + ───────────\n\ +╲╱ x + 2 ________\n\ + ╱ 2 \n\ + ╲╱ x + 3 \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + +def test_pretty_sqrt_char_knob(): + # See PR #9234. + expr = sqrt(2) + ucode_str1 = \ +"""\ + ___\n\ +╲╱ 2 \ +""" + ucode_str2 = \ +"√2" + assert xpretty(expr, use_unicode=True, + use_unicode_sqrt_char=False) == ucode_str1 + assert xpretty(expr, use_unicode=True, + use_unicode_sqrt_char=True) == ucode_str2 + + +def test_pretty_sqrt_longsymbol_no_sqrt_char(): + # Do not use unicode sqrt char for long symbols (see PR #9234). + expr = sqrt(Symbol('C1')) + ucode_str = \ +"""\ + ____\n\ +╲╱ C₁ \ +""" + assert upretty(expr) == ucode_str + + +def test_pretty_KroneckerDelta(): + x, y = symbols("x, y") + expr = KroneckerDelta(x, y) + ascii_str = \ +"""\ +d \n\ + x,y\ +""" + ucode_str = \ +"""\ +δ \n\ + x,y\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + +def test_pretty_product(): + n, m, k, l = symbols('n m k l') + f = symbols('f', cls=Function) + expr = Product(f((n/3)**2), (n, k**2, l)) + + unicode_str = \ +"""\ + l \n\ +─┬──────┬─ \n\ + │ │ ⎛ 2⎞\n\ + │ │ ⎜n ⎟\n\ + │ │ f⎜──⎟\n\ + │ │ ⎝9 ⎠\n\ + │ │ \n\ + 2 \n\ + n = k """ + ascii_str = \ +"""\ + l \n\ +__________ \n\ + | | / 2\\\n\ + | | |n |\n\ + | | f|--|\n\ + | | \\9 /\n\ + | | \n\ + 2 \n\ + n = k """ + + expr = Product(f((n/3)**2), (n, k**2, l), (l, 1, m)) + + unicode_str = \ +"""\ + m l \n\ +─┬──────┬─ ─┬──────┬─ \n\ + │ │ │ │ ⎛ 2⎞\n\ + │ │ │ │ ⎜n ⎟\n\ + │ │ │ │ f⎜──⎟\n\ + │ │ │ │ ⎝9 ⎠\n\ + │ │ │ │ \n\ + l = 1 2 \n\ + n = k """ + ascii_str = \ +"""\ + m l \n\ +__________ __________ \n\ + | | | | / 2\\\n\ + | | | | |n |\n\ + | | | | f|--|\n\ + | | | | \\9 /\n\ + | | | | \n\ + l = 1 2 \n\ + n = k """ + + assert pretty(expr) == ascii_str + assert upretty(expr) == unicode_str + + +def test_pretty_Lambda(): + # S.IdentityFunction is a special case + expr = Lambda(y, y) + assert pretty(expr) == "x -> x" + assert upretty(expr) == "x ↦ x" + + expr = Lambda(x, x+1) + assert pretty(expr) == "x -> x + 1" + assert upretty(expr) == "x ↦ x + 1" + + expr = Lambda(x, x**2) + ascii_str = \ +"""\ + 2\n\ +x -> x \ +""" + ucode_str = \ +"""\ + 2\n\ +x ↦ x \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Lambda(x, x**2)**2 + ascii_str = \ +"""\ + 2 +/ 2\\ \n\ +\\x -> x / \ +""" + ucode_str = \ +"""\ + 2 +⎛ 2⎞ \n\ +⎝x ↦ x ⎠ \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Lambda((x, y), x) + ascii_str = "(x, y) -> x" + ucode_str = "(x, y) ↦ x" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Lambda((x, y), x**2) + ascii_str = \ +"""\ + 2\n\ +(x, y) -> x \ +""" + ucode_str = \ +"""\ + 2\n\ +(x, y) ↦ x \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Lambda(((x, y),), x**2) + ascii_str = \ +"""\ + 2\n\ +((x, y),) -> x \ +""" + ucode_str = \ +"""\ + 2\n\ +((x, y),) ↦ x \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + +def test_pretty_TransferFunction(): + tf1 = TransferFunction(s - 1, s + 1, s) + assert upretty(tf1) == "s - 1\n─────\ns + 1" + tf2 = TransferFunction(2*s + 1, 3 - p, s) + assert upretty(tf2) == "2⋅s + 1\n───────\n 3 - p " + tf3 = TransferFunction(p, p + 1, p) + assert upretty(tf3) == " p \n─────\np + 1" + + +def test_pretty_Series(): + tf1 = TransferFunction(x + y, x - 2*y, y) + tf2 = TransferFunction(x - y, x + y, y) + tf3 = TransferFunction(x**2 + y, y - x, y) + tf4 = TransferFunction(2, 3, y) + + tfm1 = TransferFunctionMatrix([[tf1, tf2], [tf3, tf4]]) + tfm2 = TransferFunctionMatrix([[tf3], [-tf4]]) + tfm3 = TransferFunctionMatrix([[tf1, -tf2, -tf3], [tf3, -tf4, tf2]]) + tfm4 = TransferFunctionMatrix([[tf1, tf2], [tf3, -tf4], [-tf2, -tf1]]) + tfm5 = TransferFunctionMatrix([[-tf2, -tf1], [tf4, -tf3], [tf1, tf2]]) + + expected1 = \ +"""\ + ⎛ 2 ⎞\n\ +⎛ x + y ⎞ ⎜x + y⎟\n\ +⎜───────⎟⋅⎜──────⎟\n\ +⎝x - 2⋅y⎠ ⎝-x + y⎠\ +""" + expected2 = \ +"""\ +⎛-x + y⎞ ⎛-x - y ⎞\n\ +⎜──────⎟⋅⎜───────⎟\n\ +⎝x + y ⎠ ⎝x - 2⋅y⎠\ +""" + expected3 = \ +"""\ +⎛ 2 ⎞ \n\ +⎜x + y⎟ ⎛ x + y ⎞ ⎛-x - y x - y⎞\n\ +⎜──────⎟⋅⎜───────⎟⋅⎜─────── + ─────⎟\n\ +⎝-x + y⎠ ⎝x - 2⋅y⎠ ⎝x - 2⋅y x + y⎠\ +""" + expected4 = \ +"""\ + ⎛ 2 ⎞\n\ +⎛ x + y x - y⎞ ⎜x - y x + y⎟\n\ +⎜─────── + ─────⎟⋅⎜───── + ──────⎟\n\ +⎝x - 2⋅y x + y⎠ ⎝x + y -x + y⎠\ +""" + expected5 = \ +"""\ +⎡ x + y x - y⎤ ⎡ 2 ⎤ \n\ +⎢─────── ─────⎥ ⎢x + y⎥ \n\ +⎢x - 2⋅y x + y⎥ ⎢──────⎥ \n\ +⎢ ⎥ ⎢-x + y⎥ \n\ +⎢ 2 ⎥ ⋅⎢ ⎥ \n\ +⎢x + y 2 ⎥ ⎢ -2 ⎥ \n\ +⎢────── ─ ⎥ ⎢ ─── ⎥ \n\ +⎣-x + y 3 ⎦τ ⎣ 3 ⎦τ\ +""" + expected6 = \ +"""\ + ⎛⎡ x + y x - y ⎤ ⎡ x - y x + y ⎤ ⎞\n\ + ⎜⎢─────── ───── ⎥ ⎢ ───── ───────⎥ ⎟\n\ +⎡ x + y x - y⎤ ⎡ 2 ⎤ ⎜⎢x - 2⋅y x + y ⎥ ⎢ x + y x - 2⋅y⎥ ⎟\n\ +⎢─────── ─────⎥ ⎢ x + y -x + y - x - y⎥ ⎜⎢ ⎥ ⎢ ⎥ ⎟\n\ +⎢x - 2⋅y x + y⎥ ⎢─────── ────── ────────⎥ ⎜⎢ 2 ⎥ ⎢ 2 ⎥ ⎟\n\ +⎢ ⎥ ⎢x - 2⋅y x + y -x + y ⎥ ⎜⎢x + y -2 ⎥ ⎢ -2 x + y ⎥ ⎟\n\ +⎢ 2 ⎥ ⋅⎢ ⎥ ⋅⎜⎢────── ─── ⎥ + ⎢ ─── ────── ⎥ ⎟\n\ +⎢x + y 2 ⎥ ⎢ 2 ⎥ ⎜⎢-x + y 3 ⎥ ⎢ 3 -x + y ⎥ ⎟\n\ +⎢────── ─ ⎥ ⎢x + y -2 x - y ⎥ ⎜⎢ ⎥ ⎢ ⎥ ⎟\n\ +⎣-x + y 3 ⎦τ ⎢────── ─── ───── ⎥ ⎜⎢-x + y -x - y ⎥ ⎢-x - y -x + y ⎥ ⎟\n\ + ⎣-x + y 3 x + y ⎦τ ⎜⎢────── ───────⎥ ⎢─────── ────── ⎥ ⎟\n\ + ⎝⎣x + y x - 2⋅y⎦τ ⎣x - 2⋅y x + y ⎦τ⎠\ +""" + + assert upretty(Series(tf1, tf3)) == expected1 + assert upretty(Series(-tf2, -tf1)) == expected2 + assert upretty(Series(tf3, tf1, Parallel(-tf1, tf2))) == expected3 + assert upretty(Series(Parallel(tf1, tf2), Parallel(tf2, tf3))) == expected4 + assert upretty(MIMOSeries(tfm2, tfm1)) == expected5 + assert upretty(MIMOSeries(MIMOParallel(tfm4, -tfm5), tfm3, tfm1)) == expected6 + + +def test_pretty_Parallel(): + tf1 = TransferFunction(x + y, x - 2*y, y) + tf2 = TransferFunction(x - y, x + y, y) + tf3 = TransferFunction(x**2 + y, y - x, y) + tf4 = TransferFunction(y**2 - x, x**3 + x, y) + + tfm1 = TransferFunctionMatrix([[tf1, tf2], [tf3, -tf4], [-tf2, -tf1]]) + tfm2 = TransferFunctionMatrix([[-tf2, -tf1], [tf4, -tf3], [tf1, tf2]]) + tfm3 = TransferFunctionMatrix([[-tf1, tf2], [-tf3, tf4], [tf2, tf1]]) + tfm4 = TransferFunctionMatrix([[-tf1, -tf2], [-tf3, -tf4]]) + + expected1 = \ +"""\ + x + y x - y\n\ +─────── + ─────\n\ +x - 2⋅y x + y\ +""" + expected2 = \ +"""\ +-x + y -x - y \n\ +────── + ─────── +x + y x - 2⋅y\ +""" + expected3 = \ +"""\ + 2 \n\ +x + y x + y ⎛-x - y ⎞ ⎛x - y⎞ +────── + ─────── + ⎜───────⎟⋅⎜─────⎟ +-x + y x - 2⋅y ⎝x - 2⋅y⎠ ⎝x + y⎠\ +""" + + expected4 = \ +"""\ + ⎛ 2 ⎞\n\ +⎛ x + y ⎞ ⎛x - y⎞ ⎛x - y⎞ ⎜x + y⎟\n\ +⎜───────⎟⋅⎜─────⎟ + ⎜─────⎟⋅⎜──────⎟\n\ +⎝x - 2⋅y⎠ ⎝x + y⎠ ⎝x + y⎠ ⎝-x + y⎠\ +""" + expected5 = \ +"""\ +⎡ x + y -x + y ⎤ ⎡ x - y x + y ⎤ ⎡ x + y x - y ⎤ \n\ +⎢─────── ────── ⎥ ⎢ ───── ───────⎥ ⎢─────── ───── ⎥ \n\ +⎢x - 2⋅y x + y ⎥ ⎢ x + y x - 2⋅y⎥ ⎢x - 2⋅y x + y ⎥ \n\ +⎢ ⎥ ⎢ ⎥ ⎢ ⎥ \n\ +⎢ 2 2 ⎥ ⎢ 2 2 ⎥ ⎢ 2 2 ⎥ \n\ +⎢x + y x - y ⎥ ⎢x - y x + y ⎥ ⎢x + y x - y ⎥ \n\ +⎢────── ────── ⎥ + ⎢────── ────── ⎥ + ⎢────── ────── ⎥ \n\ +⎢-x + y 3 ⎥ ⎢ 3 -x + y ⎥ ⎢-x + y 3 ⎥ \n\ +⎢ x + x ⎥ ⎢x + x ⎥ ⎢ x + x ⎥ \n\ +⎢ ⎥ ⎢ ⎥ ⎢ ⎥ \n\ +⎢-x + y -x - y ⎥ ⎢-x - y -x + y ⎥ ⎢-x + y -x - y ⎥ \n\ +⎢────── ───────⎥ ⎢─────── ────── ⎥ ⎢────── ───────⎥ \n\ +⎣x + y x - 2⋅y⎦τ ⎣x - 2⋅y x + y ⎦τ ⎣x + y x - 2⋅y⎦τ\ +""" + expected6 = \ +"""\ +⎡ x - y x + y ⎤ ⎡-x + y -x - y ⎤ \n\ +⎢ ───── ───────⎥ ⎢────── ─────── ⎥ \n\ +⎢ x + y x - 2⋅y⎥ ⎡-x - y -x + y⎤ ⎢x + y x - 2⋅y ⎥ \n\ +⎢ ⎥ ⎢─────── ──────⎥ ⎢ ⎥ \n\ +⎢ 2 2 ⎥ ⎢x - 2⋅y x + y ⎥ ⎢ 2 2 ⎥ \n\ +⎢x - y x + y ⎥ ⎢ ⎥ ⎢-x + y - x - y⎥ \n\ +⎢────── ────── ⎥ ⋅⎢ 2 2⎥ + ⎢─────── ────────⎥ \n\ +⎢ 3 -x + y ⎥ ⎢- x - y x - y ⎥ ⎢ 3 -x + y ⎥ \n\ +⎢x + x ⎥ ⎢──────── ──────⎥ ⎢x + x ⎥ \n\ +⎢ ⎥ ⎢ -x + y 3 ⎥ ⎢ ⎥ \n\ +⎢-x - y -x + y ⎥ ⎣ x + x⎦τ ⎢ x + y x - y ⎥ \n\ +⎢─────── ────── ⎥ ⎢─────── ───── ⎥ \n\ +⎣x - 2⋅y x + y ⎦τ ⎣x - 2⋅y x + y ⎦τ\ +""" + assert upretty(Parallel(tf1, tf2)) == expected1 + assert upretty(Parallel(-tf2, -tf1)) == expected2 + assert upretty(Parallel(tf3, tf1, Series(-tf1, tf2))) == expected3 + assert upretty(Parallel(Series(tf1, tf2), Series(tf2, tf3))) == expected4 + assert upretty(MIMOParallel(-tfm3, -tfm2, tfm1)) == expected5 + assert upretty(MIMOParallel(MIMOSeries(tfm4, -tfm2), tfm2)) == expected6 + + +def test_pretty_Feedback(): + tf = TransferFunction(1, 1, y) + tf1 = TransferFunction(x + y, x - 2*y, y) + tf2 = TransferFunction(x - y, x + y, y) + tf3 = TransferFunction(y**2 - 2*y + 1, y + 5, y) + tf4 = TransferFunction(x - 2*y**3, x + y, x) + tf5 = TransferFunction(1 - x, x - y, y) + tf6 = TransferFunction(2, 2, x) + expected1 = \ +"""\ + ⎛1⎞ \n\ + ⎜─⎟ \n\ + ⎝1⎠ \n\ +─────────────\n\ +1 ⎛ x + y ⎞\n\ +─ + ⎜───────⎟\n\ +1 ⎝x - 2⋅y⎠\ +""" + expected2 = \ +"""\ + ⎛1⎞ \n\ + ⎜─⎟ \n\ + ⎝1⎠ \n\ +────────────────────────────────────\n\ + ⎛ 2 ⎞\n\ +1 ⎛x - y⎞ ⎛ x + y ⎞ ⎜y - 2⋅y + 1⎟\n\ +─ + ⎜─────⎟⋅⎜───────⎟⋅⎜────────────⎟\n\ +1 ⎝x + y⎠ ⎝x - 2⋅y⎠ ⎝ y + 5 ⎠\ +""" + expected3 = \ +"""\ + ⎛ x + y ⎞ \n\ + ⎜───────⎟ \n\ + ⎝x - 2⋅y⎠ \n\ +────────────────────────────────────────────\n\ + ⎛ 2 ⎞ \n\ +1 ⎛ x + y ⎞ ⎛x - y⎞ ⎜y - 2⋅y + 1⎟ ⎛1 - x⎞\n\ +─ + ⎜───────⎟⋅⎜─────⎟⋅⎜────────────⎟⋅⎜─────⎟\n\ +1 ⎝x - 2⋅y⎠ ⎝x + y⎠ ⎝ y + 5 ⎠ ⎝x - y⎠\ +""" + expected4 = \ +"""\ + ⎛ x + y ⎞ ⎛x - y⎞ \n\ + ⎜───────⎟⋅⎜─────⎟ \n\ + ⎝x - 2⋅y⎠ ⎝x + y⎠ \n\ +─────────────────────\n\ +1 ⎛ x + y ⎞ ⎛x - y⎞\n\ +─ + ⎜───────⎟⋅⎜─────⎟\n\ +1 ⎝x - 2⋅y⎠ ⎝x + y⎠\ +""" + expected5 = \ +"""\ + ⎛ x + y ⎞ ⎛x - y⎞ \n\ + ⎜───────⎟⋅⎜─────⎟ \n\ + ⎝x - 2⋅y⎠ ⎝x + y⎠ \n\ +─────────────────────────────\n\ +1 ⎛ x + y ⎞ ⎛x - y⎞ ⎛1 - x⎞\n\ +─ + ⎜───────⎟⋅⎜─────⎟⋅⎜─────⎟\n\ +1 ⎝x - 2⋅y⎠ ⎝x + y⎠ ⎝x - y⎠\ +""" + expected6 = \ +"""\ + ⎛ 2 ⎞ \n\ + ⎜y - 2⋅y + 1⎟ ⎛1 - x⎞ \n\ + ⎜────────────⎟⋅⎜─────⎟ \n\ + ⎝ y + 5 ⎠ ⎝x - y⎠ \n\ +────────────────────────────────────────────\n\ + ⎛ 2 ⎞ \n\ +1 ⎜y - 2⋅y + 1⎟ ⎛1 - x⎞ ⎛x - y⎞ ⎛ x + y ⎞\n\ +─ + ⎜────────────⎟⋅⎜─────⎟⋅⎜─────⎟⋅⎜───────⎟\n\ +1 ⎝ y + 5 ⎠ ⎝x - y⎠ ⎝x + y⎠ ⎝x - 2⋅y⎠\ +""" + expected7 = \ +"""\ + ⎛ 3⎞ \n\ + ⎜x - 2⋅y ⎟ \n\ + ⎜────────⎟ \n\ + ⎝ x + y ⎠ \n\ +──────────────────\n\ + ⎛ 3⎞ \n\ +1 ⎜x - 2⋅y ⎟ ⎛2⎞\n\ +─ + ⎜────────⎟⋅⎜─⎟\n\ +1 ⎝ x + y ⎠ ⎝2⎠\ +""" + expected8 = \ +"""\ + ⎛1 - x⎞ \n\ + ⎜─────⎟ \n\ + ⎝x - y⎠ \n\ +───────────\n\ +1 ⎛1 - x⎞\n\ +─ + ⎜─────⎟\n\ +1 ⎝x - y⎠\ +""" + expected9 = \ +"""\ + ⎛ x + y ⎞ ⎛x - y⎞ \n\ + ⎜───────⎟⋅⎜─────⎟ \n\ + ⎝x - 2⋅y⎠ ⎝x + y⎠ \n\ +─────────────────────────────\n\ +1 ⎛ x + y ⎞ ⎛x - y⎞ ⎛1 - x⎞\n\ +─ - ⎜───────⎟⋅⎜─────⎟⋅⎜─────⎟\n\ +1 ⎝x - 2⋅y⎠ ⎝x + y⎠ ⎝x - y⎠\ +""" + expected10 = \ +"""\ + ⎛1 - x⎞ \n\ + ⎜─────⎟ \n\ + ⎝x - y⎠ \n\ +───────────\n\ +1 ⎛1 - x⎞\n\ +─ - ⎜─────⎟\n\ +1 ⎝x - y⎠\ +""" + assert upretty(Feedback(tf, tf1)) == expected1 + assert upretty(Feedback(tf, tf2*tf1*tf3)) == expected2 + assert upretty(Feedback(tf1, tf2*tf3*tf5)) == expected3 + assert upretty(Feedback(tf1*tf2, tf)) == expected4 + assert upretty(Feedback(tf1*tf2, tf5)) == expected5 + assert upretty(Feedback(tf3*tf5, tf2*tf1)) == expected6 + assert upretty(Feedback(tf4, tf6)) == expected7 + assert upretty(Feedback(tf5, tf)) == expected8 + + assert upretty(Feedback(tf1*tf2, tf5, 1)) == expected9 + assert upretty(Feedback(tf5, tf, 1)) == expected10 + + +def test_pretty_MIMOFeedback(): + tf1 = TransferFunction(x + y, x - 2*y, y) + tf2 = TransferFunction(x - y, x + y, y) + tfm_1 = TransferFunctionMatrix([[tf1, tf2], [tf2, tf1]]) + tfm_2 = TransferFunctionMatrix([[tf2, tf1], [tf1, tf2]]) + tfm_3 = TransferFunctionMatrix([[tf1, tf1], [tf2, tf2]]) + + expected1 = \ +"""\ +⎛ ⎡ x + y x - y ⎤ ⎡ x - y x + y ⎤ ⎞-1 ⎡ x + y x - y ⎤ \n\ +⎜ ⎢─────── ───── ⎥ ⎢ ───── ───────⎥ ⎟ ⎢─────── ───── ⎥ \n\ +⎜ ⎢x - 2⋅y x + y ⎥ ⎢ x + y x - 2⋅y⎥ ⎟ ⎢x - 2⋅y x + y ⎥ \n\ +⎜I - ⎢ ⎥ ⋅⎢ ⎥ ⎟ ⋅ ⎢ ⎥ \n\ +⎜ ⎢ x - y x + y ⎥ ⎢ x + y x - y ⎥ ⎟ ⎢ x - y x + y ⎥ \n\ +⎜ ⎢ ───── ───────⎥ ⎢─────── ───── ⎥ ⎟ ⎢ ───── ───────⎥ \n\ +⎝ ⎣ x + y x - 2⋅y⎦τ ⎣x - 2⋅y x + y ⎦τ⎠ ⎣ x + y x - 2⋅y⎦τ\ +""" + expected2 = \ +"""\ +⎛ ⎡ x + y x - y ⎤ ⎡ x - y x + y ⎤ ⎡ x + y x + y ⎤ ⎞-1 ⎡ x + y x - y ⎤ ⎡ x - y x + y ⎤ \n\ +⎜ ⎢─────── ───── ⎥ ⎢ ───── ───────⎥ ⎢─────── ───────⎥ ⎟ ⎢─────── ───── ⎥ ⎢ ───── ───────⎥ \n\ +⎜ ⎢x - 2⋅y x + y ⎥ ⎢ x + y x - 2⋅y⎥ ⎢x - 2⋅y x - 2⋅y⎥ ⎟ ⎢x - 2⋅y x + y ⎥ ⎢ x + y x - 2⋅y⎥ \n\ +⎜I + ⎢ ⎥ ⋅⎢ ⎥ ⋅⎢ ⎥ ⎟ ⋅ ⎢ ⎥ ⋅⎢ ⎥ \n\ +⎜ ⎢ x - y x + y ⎥ ⎢ x + y x - y ⎥ ⎢ x - y x - y ⎥ ⎟ ⎢ x - y x + y ⎥ ⎢ x + y x - y ⎥ \n\ +⎜ ⎢ ───── ───────⎥ ⎢─────── ───── ⎥ ⎢ ───── ───── ⎥ ⎟ ⎢ ───── ───────⎥ ⎢─────── ───── ⎥ \n\ +⎝ ⎣ x + y x - 2⋅y⎦τ ⎣x - 2⋅y x + y ⎦τ ⎣ x + y x + y ⎦τ⎠ ⎣ x + y x - 2⋅y⎦τ ⎣x - 2⋅y x + y ⎦τ\ +""" + + assert upretty(MIMOFeedback(tfm_1, tfm_2, 1)) == \ + expected1 # Positive MIMOFeedback + assert upretty(MIMOFeedback(tfm_1*tfm_2, tfm_3)) == \ + expected2 # Negative MIMOFeedback (Default) + + +def test_pretty_TransferFunctionMatrix(): + tf1 = TransferFunction(x + y, x - 2*y, y) + tf2 = TransferFunction(x - y, x + y, y) + tf3 = TransferFunction(y**2 - 2*y + 1, y + 5, y) + tf4 = TransferFunction(y, x**2 + x + 1, y) + tf5 = TransferFunction(1 - x, x - y, y) + tf6 = TransferFunction(2, 2, y) + expected1 = \ +"""\ +⎡ x + y ⎤ \n\ +⎢───────⎥ \n\ +⎢x - 2⋅y⎥ \n\ +⎢ ⎥ \n\ +⎢ x - y ⎥ \n\ +⎢ ───── ⎥ \n\ +⎣ x + y ⎦τ\ +""" + expected2 = \ +"""\ +⎡ x + y ⎤ \n\ +⎢ ─────── ⎥ \n\ +⎢ x - 2⋅y ⎥ \n\ +⎢ ⎥ \n\ +⎢ x - y ⎥ \n\ +⎢ ───── ⎥ \n\ +⎢ x + y ⎥ \n\ +⎢ ⎥ \n\ +⎢ 2 ⎥ \n\ +⎢- y + 2⋅y - 1⎥ \n\ +⎢──────────────⎥ \n\ +⎣ y + 5 ⎦τ\ +""" + expected3 = \ +"""\ +⎡ x + y x - y ⎤ \n\ +⎢ ─────── ───── ⎥ \n\ +⎢ x - 2⋅y x + y ⎥ \n\ +⎢ ⎥ \n\ +⎢ 2 ⎥ \n\ +⎢y - 2⋅y + 1 y ⎥ \n\ +⎢──────────── ──────────⎥ \n\ +⎢ y + 5 2 ⎥ \n\ +⎢ x + x + 1⎥ \n\ +⎢ ⎥ \n\ +⎢ 1 - x 2 ⎥ \n\ +⎢ ───── ─ ⎥ \n\ +⎣ x - y 2 ⎦τ\ +""" + expected4 = \ +"""\ +⎡ x - y x + y y ⎤ \n\ +⎢ ───── ─────── ──────────⎥ \n\ +⎢ x + y x - 2⋅y 2 ⎥ \n\ +⎢ x + x + 1⎥ \n\ +⎢ ⎥ \n\ +⎢ 2 ⎥ \n\ +⎢- y + 2⋅y - 1 x - 1 -2 ⎥ \n\ +⎢────────────── ───── ─── ⎥ \n\ +⎣ y + 5 x - y 2 ⎦τ\ +""" + expected5 = \ +"""\ +⎡ x + y x - y x + y y ⎤ \n\ +⎢───────⋅───── ─────── ──────────⎥ \n\ +⎢x - 2⋅y x + y x - 2⋅y 2 ⎥ \n\ +⎢ x + x + 1⎥ \n\ +⎢ ⎥ \n\ +⎢ 1 - x 2 x + y -2 ⎥ \n\ +⎢ ───── + ─ ─────── ─── ⎥ \n\ +⎣ x - y 2 x - 2⋅y 2 ⎦τ\ +""" + + assert upretty(TransferFunctionMatrix([[tf1], [tf2]])) == expected1 + assert upretty(TransferFunctionMatrix([[tf1], [tf2], [-tf3]])) == expected2 + assert upretty(TransferFunctionMatrix([[tf1, tf2], [tf3, tf4], [tf5, tf6]])) == expected3 + assert upretty(TransferFunctionMatrix([[tf2, tf1, tf4], [-tf3, -tf5, -tf6]])) == expected4 + assert upretty(TransferFunctionMatrix([[Series(tf2, tf1), tf1, tf4], [Parallel(tf6, tf5), tf1, -tf6]])) == \ + expected5 + + +def test_pretty_StateSpace(): + ss1 = StateSpace(Matrix([a]), Matrix([b]), Matrix([c]), Matrix([d])) + A = Matrix([[0, 1], [1, 0]]) + B = Matrix([1, 0]) + C = Matrix([[0, 1]]) + D = Matrix([0]) + ss2 = StateSpace(A, B, C, D) + ss3 = StateSpace(Matrix([[-1.5, -2], [1, 0]]), + Matrix([[0.5, 0], [0, 1]]), + Matrix([[0, 1], [0, 2]]), + Matrix([[2, 2], [1, 1]])) + + expected1 = \ +"""\ +⎡[a] [b]⎤\n\ +⎢ ⎥\n\ +⎣[c] [d]⎦\ +""" + expected2 = \ +"""\ +⎡⎡0 1⎤ ⎡1⎤⎤\n\ +⎢⎢ ⎥ ⎢ ⎥⎥\n\ +⎢⎣1 0⎦ ⎣0⎦⎥\n\ +⎢ ⎥\n\ +⎣[0 1] [0]⎦\ +""" + expected3 = \ +"""\ +⎡⎡-1.5 -2⎤ ⎡0.5 0⎤⎤\n\ +⎢⎢ ⎥ ⎢ ⎥⎥\n\ +⎢⎣ 1 0 ⎦ ⎣ 0 1⎦⎥\n\ +⎢ ⎥\n\ +⎢ ⎡0 1⎤ ⎡2 2⎤ ⎥\n\ +⎢ ⎢ ⎥ ⎢ ⎥ ⎥\n\ +⎣ ⎣0 2⎦ ⎣1 1⎦ ⎦\ +""" + + assert upretty(ss1) == expected1 + assert upretty(ss2) == expected2 + assert upretty(ss3) == expected3 + +def test_pretty_order(): + expr = O(1) + ascii_str = \ +"""\ +O(1)\ +""" + ucode_str = \ +"""\ +O(1)\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = O(1/x) + ascii_str = \ +"""\ + /1\\\n\ +O|-|\n\ + \\x/\ +""" + ucode_str = \ +"""\ + ⎛1⎞\n\ +O⎜─⎟\n\ + ⎝x⎠\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = O(x**2 + y**2) + ascii_str = \ +"""\ + / 2 2 \\\n\ +O\\x + y ; (x, y) -> (0, 0)/\ +""" + ucode_str = \ +"""\ + ⎛ 2 2 ⎞\n\ +O⎝x + y ; (x, y) → (0, 0)⎠\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = O(1, (x, oo)) + ascii_str = \ +"""\ +O(1; x -> oo)\ +""" + ucode_str = \ +"""\ +O(1; x → ∞)\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = O(1/x, (x, oo)) + ascii_str = \ +"""\ + /1 \\\n\ +O|-; x -> oo|\n\ + \\x /\ +""" + ucode_str = \ +"""\ + ⎛1 ⎞\n\ +O⎜─; x → ∞⎟\n\ + ⎝x ⎠\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = O(x**2 + y**2, (x, oo), (y, oo)) + ascii_str = \ +"""\ + / 2 2 \\\n\ +O\\x + y ; (x, y) -> (oo, oo)/\ +""" + ucode_str = \ +"""\ + ⎛ 2 2 ⎞\n\ +O⎝x + y ; (x, y) → (∞, ∞)⎠\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + +def test_pretty_derivatives(): + # Simple + expr = Derivative(log(x), x, evaluate=False) + ascii_str = \ +"""\ +d \n\ +--(log(x))\n\ +dx \ +""" + ucode_str = \ +"""\ +d \n\ +──(log(x))\n\ +dx \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Derivative(log(x), x, evaluate=False) + x + ascii_str_1 = \ +"""\ + d \n\ +x + --(log(x))\n\ + dx \ +""" + ascii_str_2 = \ +"""\ +d \n\ +--(log(x)) + x\n\ +dx \ +""" + ucode_str_1 = \ +"""\ + d \n\ +x + ──(log(x))\n\ + dx \ +""" + ucode_str_2 = \ +"""\ +d \n\ +──(log(x)) + x\n\ +dx \ +""" + assert pretty(expr) in [ascii_str_1, ascii_str_2] + assert upretty(expr) in [ucode_str_1, ucode_str_2] + + # basic partial derivatives + expr = Derivative(log(x + y) + x, x) + ascii_str_1 = \ +"""\ +d \n\ +--(log(x + y) + x)\n\ +dx \ +""" + ascii_str_2 = \ +"""\ +d \n\ +--(x + log(x + y))\n\ +dx \ +""" + ucode_str_1 = \ +"""\ +∂ \n\ +──(log(x + y) + x)\n\ +∂x \ +""" + ucode_str_2 = \ +"""\ +∂ \n\ +──(x + log(x + y))\n\ +∂x \ +""" + assert pretty(expr) in [ascii_str_1, ascii_str_2] + assert upretty(expr) in [ucode_str_1, ucode_str_2], upretty(expr) + + # Multiple symbols + expr = Derivative(log(x) + x**2, x, y) + ascii_str_1 = \ +"""\ + 2 \n\ + d / 2\\\n\ +-----\\log(x) + x /\n\ +dy dx \ +""" + ascii_str_2 = \ +"""\ + 2 \n\ + d / 2 \\\n\ +-----\\x + log(x)/\n\ +dy dx \ +""" + ascii_str_3 = \ +"""\ + 2 \n\ + d / 2 \\\n\ +-----\\x + log(x)/\n\ +dy dx \ +""" + ucode_str_1 = \ +"""\ + 2 \n\ + d ⎛ 2⎞\n\ +─────⎝log(x) + x ⎠\n\ +dy dx \ +""" + ucode_str_2 = \ +"""\ + 2 \n\ + d ⎛ 2 ⎞\n\ +─────⎝x + log(x)⎠\n\ +dy dx \ +""" + ucode_str_3 = \ +"""\ + 2 \n\ + d ⎛ 2 ⎞\n\ +─────⎝x + log(x)⎠\n\ +dy dx \ +""" + assert pretty(expr) in [ascii_str_1, ascii_str_2, ascii_str_3] + assert upretty(expr) in [ucode_str_1, ucode_str_2, ucode_str_3] + + expr = Derivative(2*x*y, y, x) + x**2 + ascii_str_1 = \ +"""\ + 2 \n\ + d 2\n\ +-----(2*x*y) + x \n\ +dx dy \ +""" + ascii_str_2 = \ +"""\ + 2 \n\ + 2 d \n\ +x + -----(2*x*y)\n\ + dx dy \ +""" + ascii_str_3 = \ +"""\ + 2 \n\ + 2 d \n\ +x + -----(2*x*y)\n\ + dx dy \ +""" + ucode_str_1 = \ +"""\ + 2 \n\ + ∂ 2\n\ +─────(2⋅x⋅y) + x \n\ +∂x ∂y \ +""" + ucode_str_2 = \ +"""\ + 2 \n\ + 2 ∂ \n\ +x + ─────(2⋅x⋅y)\n\ + ∂x ∂y \ +""" + ucode_str_3 = \ +"""\ + 2 \n\ + 2 ∂ \n\ +x + ─────(2⋅x⋅y)\n\ + ∂x ∂y \ +""" + assert pretty(expr) in [ascii_str_1, ascii_str_2, ascii_str_3] + assert upretty(expr) in [ucode_str_1, ucode_str_2, ucode_str_3] + + expr = Derivative(2*x*y, x, x) + ascii_str = \ +"""\ + 2 \n\ +d \n\ +---(2*x*y)\n\ + 2 \n\ +dx \ +""" + ucode_str = \ +"""\ + 2 \n\ +∂ \n\ +───(2⋅x⋅y)\n\ + 2 \n\ +∂x \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Derivative(2*x*y, x, 17) + ascii_str = \ +"""\ + 17 \n\ +d \n\ +----(2*x*y)\n\ + 17 \n\ +dx \ +""" + ucode_str = \ +"""\ + 17 \n\ +∂ \n\ +────(2⋅x⋅y)\n\ + 17 \n\ +∂x \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Derivative(2*x*y, x, x, y) + ascii_str = \ +"""\ + 3 \n\ + d \n\ +------(2*x*y)\n\ + 2 \n\ +dy dx \ +""" + ucode_str = \ +"""\ + 3 \n\ + ∂ \n\ +──────(2⋅x⋅y)\n\ + 2 \n\ +∂y ∂x \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + # Greek letters + alpha = Symbol('alpha') + beta = Function('beta') + expr = beta(alpha).diff(alpha) + ascii_str = \ +"""\ + d \n\ +------(beta(alpha))\n\ +dalpha \ +""" + ucode_str = \ +"""\ +d \n\ +──(β(α))\n\ +dα \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Derivative(f(x), (x, n)) + + ascii_str = \ +"""\ + n \n\ +d \n\ +---(f(x))\n\ + n \n\ +dx \ +""" + ucode_str = \ +"""\ + n \n\ +d \n\ +───(f(x))\n\ + n \n\ +dx \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + +def test_pretty_integrals(): + expr = Integral(log(x), x) + ascii_str = \ +"""\ + / \n\ + | \n\ + | log(x) dx\n\ + | \n\ +/ \ +""" + ucode_str = \ +"""\ +⌠ \n\ +⎮ log(x) dx\n\ +⌡ \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Integral(x**2, x) + ascii_str = \ +"""\ + / \n\ + | \n\ + | 2 \n\ + | x dx\n\ + | \n\ +/ \ +""" + ucode_str = \ +"""\ +⌠ \n\ +⎮ 2 \n\ +⎮ x dx\n\ +⌡ \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Integral((sin(x))**2 / (tan(x))**2) + ascii_str = \ +"""\ + / \n\ + | \n\ + | 2 \n\ + | sin (x) \n\ + | ------- dx\n\ + | 2 \n\ + | tan (x) \n\ + | \n\ +/ \ +""" + ucode_str = \ +"""\ +⌠ \n\ +⎮ 2 \n\ +⎮ sin (x) \n\ +⎮ ─────── dx\n\ +⎮ 2 \n\ +⎮ tan (x) \n\ +⌡ \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Integral(x**(2**x), x) + ascii_str = \ +"""\ + / \n\ + | \n\ + | / x\\ \n\ + | \\2 / \n\ + | x dx\n\ + | \n\ +/ \ +""" + ucode_str = \ +"""\ +⌠ \n\ +⎮ ⎛ x⎞ \n\ +⎮ ⎝2 ⎠ \n\ +⎮ x dx\n\ +⌡ \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Integral(x**2, (x, 1, 2)) + ascii_str = \ +"""\ + 2 \n\ + / \n\ + | \n\ + | 2 \n\ + | x dx\n\ + | \n\ +/ \n\ +1 \ +""" + ucode_str = \ +"""\ +2 \n\ +⌠ \n\ +⎮ 2 \n\ +⎮ x dx\n\ +⌡ \n\ +1 \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Integral(x**2, (x, Rational(1, 2), 10)) + ascii_str = \ +"""\ + 10 \n\ + / \n\ + | \n\ + | 2 \n\ + | x dx\n\ + | \n\ +/ \n\ +1/2 \ +""" + ucode_str = \ +"""\ +10 \n\ +⌠ \n\ +⎮ 2 \n\ +⎮ x dx\n\ +⌡ \n\ +1/2 \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Integral(x**2*y**2, x, y) + ascii_str = \ +"""\ + / / \n\ + | | \n\ + | | 2 2 \n\ + | | x *y dx dy\n\ + | | \n\ +/ / \ +""" + ucode_str = \ +"""\ +⌠ ⌠ \n\ +⎮ ⎮ 2 2 \n\ +⎮ ⎮ x ⋅y dx dy\n\ +⌡ ⌡ \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Integral(sin(th)/cos(ph), (th, 0, pi), (ph, 0, 2*pi)) + ascii_str = \ +"""\ + 2*pi pi \n\ + / / \n\ + | | \n\ + | | sin(theta) \n\ + | | ---------- d(theta) d(phi)\n\ + | | cos(phi) \n\ + | | \n\ + / / \n\ +0 0 \ +""" + ucode_str = \ +"""\ +2⋅π π \n\ + ⌠ ⌠ \n\ + ⎮ ⎮ sin(θ) \n\ + ⎮ ⎮ ────── dθ dφ\n\ + ⎮ ⎮ cos(φ) \n\ + ⌡ ⌡ \n\ + 0 0 \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + +def test_pretty_matrix(): + # Empty Matrix + expr = Matrix() + ascii_str = "[]" + unicode_str = "[]" + assert pretty(expr) == ascii_str + assert upretty(expr) == unicode_str + expr = Matrix(2, 0, lambda i, j: 0) + ascii_str = "[]" + unicode_str = "[]" + assert pretty(expr) == ascii_str + assert upretty(expr) == unicode_str + expr = Matrix(0, 2, lambda i, j: 0) + ascii_str = "[]" + unicode_str = "[]" + assert pretty(expr) == ascii_str + assert upretty(expr) == unicode_str + expr = Matrix([[x**2 + 1, 1], [y, x + y]]) + ascii_str_1 = \ +"""\ +[ 2 ] +[1 + x 1 ] +[ ] +[ y x + y]\ +""" + ascii_str_2 = \ +"""\ +[ 2 ] +[x + 1 1 ] +[ ] +[ y x + y]\ +""" + ucode_str_1 = \ +"""\ +⎡ 2 ⎤ +⎢1 + x 1 ⎥ +⎢ ⎥ +⎣ y x + y⎦\ +""" + ucode_str_2 = \ +"""\ +⎡ 2 ⎤ +⎢x + 1 1 ⎥ +⎢ ⎥ +⎣ y x + y⎦\ +""" + assert pretty(expr) in [ascii_str_1, ascii_str_2] + assert upretty(expr) in [ucode_str_1, ucode_str_2] + + expr = Matrix([[x/y, y, th], [0, exp(I*k*ph), 1]]) + ascii_str = \ +"""\ +[x ] +[- y theta] +[y ] +[ ] +[ I*k*phi ] +[0 e 1 ]\ +""" + ucode_str = \ +"""\ +⎡x ⎤ +⎢─ y θ⎥ +⎢y ⎥ +⎢ ⎥ +⎢ ⅈ⋅k⋅φ ⎥ +⎣0 ℯ 1⎦\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + unicode_str = \ +"""\ +⎡v̇_msc_00 0 0 ⎤ +⎢ ⎥ +⎢ 0 v̇_msc_01 0 ⎥ +⎢ ⎥ +⎣ 0 0 v̇_msc_02⎦\ +""" + + expr = diag(*MatrixSymbol('vdot_msc',1,3)) + assert upretty(expr) == unicode_str + + +def test_pretty_ndim_arrays(): + x, y, z, w = symbols("x y z w") + + for ArrayType in (ImmutableDenseNDimArray, ImmutableSparseNDimArray, MutableDenseNDimArray, MutableSparseNDimArray): + # Basic: scalar array + M = ArrayType(x) + + assert pretty(M) == "x" + assert upretty(M) == "x" + + M = ArrayType([[1/x, y], [z, w]]) + M1 = ArrayType([1/x, y, z]) + + M2 = tensorproduct(M1, M) + M3 = tensorproduct(M, M) + + ascii_str = \ +"""\ +[1 ]\n\ +[- y]\n\ +[x ]\n\ +[ ]\n\ +[z w]\ +""" + ucode_str = \ +"""\ +⎡1 ⎤\n\ +⎢─ y⎥\n\ +⎢x ⎥\n\ +⎢ ⎥\n\ +⎣z w⎦\ +""" + assert pretty(M) == ascii_str + assert upretty(M) == ucode_str + + ascii_str = \ +"""\ +[1 ]\n\ +[- y z]\n\ +[x ]\ +""" + ucode_str = \ +"""\ +⎡1 ⎤\n\ +⎢─ y z⎥\n\ +⎣x ⎦\ +""" + assert pretty(M1) == ascii_str + assert upretty(M1) == ucode_str + + ascii_str = \ +"""\ +[[1 y] ]\n\ +[[-- -] [z ]]\n\ +[[ 2 x] [ y 2 ] [- y*z]]\n\ +[[x ] [ - y ] [x ]]\n\ +[[ ] [ x ] [ ]]\n\ +[[z w] [ ] [ 2 ]]\n\ +[[- -] [y*z w*y] [z w*z]]\n\ +[[x x] ]\ +""" + ucode_str = \ +"""\ +⎡⎡1 y⎤ ⎤\n\ +⎢⎢── ─⎥ ⎡z ⎤⎥\n\ +⎢⎢ 2 x⎥ ⎡ y 2 ⎤ ⎢─ y⋅z⎥⎥\n\ +⎢⎢x ⎥ ⎢ ─ y ⎥ ⎢x ⎥⎥\n\ +⎢⎢ ⎥ ⎢ x ⎥ ⎢ ⎥⎥\n\ +⎢⎢z w⎥ ⎢ ⎥ ⎢ 2 ⎥⎥\n\ +⎢⎢─ ─⎥ ⎣y⋅z w⋅y⎦ ⎣z w⋅z⎦⎥\n\ +⎣⎣x x⎦ ⎦\ +""" + assert pretty(M2) == ascii_str + assert upretty(M2) == ucode_str + + ascii_str = \ +"""\ +[ [1 y] ]\n\ +[ [-- -] ]\n\ +[ [ 2 x] [ y 2 ]]\n\ +[ [x ] [ - y ]]\n\ +[ [ ] [ x ]]\n\ +[ [z w] [ ]]\n\ +[ [- -] [y*z w*y]]\n\ +[ [x x] ]\n\ +[ ]\n\ +[[z ] [ w ]]\n\ +[[- y*z] [ - w*y]]\n\ +[[x ] [ x ]]\n\ +[[ ] [ ]]\n\ +[[ 2 ] [ 2 ]]\n\ +[[z w*z] [w*z w ]]\ +""" + ucode_str = \ +"""\ +⎡ ⎡1 y⎤ ⎤\n\ +⎢ ⎢── ─⎥ ⎥\n\ +⎢ ⎢ 2 x⎥ ⎡ y 2 ⎤⎥\n\ +⎢ ⎢x ⎥ ⎢ ─ y ⎥⎥\n\ +⎢ ⎢ ⎥ ⎢ x ⎥⎥\n\ +⎢ ⎢z w⎥ ⎢ ⎥⎥\n\ +⎢ ⎢─ ─⎥ ⎣y⋅z w⋅y⎦⎥\n\ +⎢ ⎣x x⎦ ⎥\n\ +⎢ ⎥\n\ +⎢⎡z ⎤ ⎡ w ⎤⎥\n\ +⎢⎢─ y⋅z⎥ ⎢ ─ w⋅y⎥⎥\n\ +⎢⎢x ⎥ ⎢ x ⎥⎥\n\ +⎢⎢ ⎥ ⎢ ⎥⎥\n\ +⎢⎢ 2 ⎥ ⎢ 2 ⎥⎥\n\ +⎣⎣z w⋅z⎦ ⎣w⋅z w ⎦⎦\ +""" + assert pretty(M3) == ascii_str + assert upretty(M3) == ucode_str + + Mrow = ArrayType([[x, y, 1 / z]]) + Mcolumn = ArrayType([[x], [y], [1 / z]]) + Mcol2 = ArrayType([Mcolumn.tolist()]) + + ascii_str = \ +"""\ +[[ 1]]\n\ +[[x y -]]\n\ +[[ z]]\ +""" + ucode_str = \ +"""\ +⎡⎡ 1⎤⎤\n\ +⎢⎢x y ─⎥⎥\n\ +⎣⎣ z⎦⎦\ +""" + assert pretty(Mrow) == ascii_str + assert upretty(Mrow) == ucode_str + + ascii_str = \ +"""\ +[x]\n\ +[ ]\n\ +[y]\n\ +[ ]\n\ +[1]\n\ +[-]\n\ +[z]\ +""" + ucode_str = \ +"""\ +⎡x⎤\n\ +⎢ ⎥\n\ +⎢y⎥\n\ +⎢ ⎥\n\ +⎢1⎥\n\ +⎢─⎥\n\ +⎣z⎦\ +""" + assert pretty(Mcolumn) == ascii_str + assert upretty(Mcolumn) == ucode_str + + ascii_str = \ +"""\ +[[x]]\n\ +[[ ]]\n\ +[[y]]\n\ +[[ ]]\n\ +[[1]]\n\ +[[-]]\n\ +[[z]]\ +""" + ucode_str = \ +"""\ +⎡⎡x⎤⎤\n\ +⎢⎢ ⎥⎥\n\ +⎢⎢y⎥⎥\n\ +⎢⎢ ⎥⎥\n\ +⎢⎢1⎥⎥\n\ +⎢⎢─⎥⎥\n\ +⎣⎣z⎦⎦\ +""" + assert pretty(Mcol2) == ascii_str + assert upretty(Mcol2) == ucode_str + + +def test_tensor_TensorProduct(): + A = MatrixSymbol("A", 3, 3) + B = MatrixSymbol("B", 3, 3) + assert upretty(TensorProduct(A, B)) == "A\u2297B" + assert upretty(TensorProduct(A, B, A)) == "A\u2297B\u2297A" + + +def test_diffgeom_print_WedgeProduct(): + from sympy.diffgeom.rn import R2 + from sympy.diffgeom import WedgeProduct + wp = WedgeProduct(R2.dx, R2.dy) + assert upretty(wp) == "ⅆ x∧ⅆ y" + assert pretty(wp) == r"d x/\d y" + + +def test_Adjoint(): + X = MatrixSymbol('X', 2, 2) + Y = MatrixSymbol('Y', 2, 2) + assert pretty(Adjoint(X)) == " +\nX " + assert pretty(Adjoint(X + Y)) == " +\n(X + Y) " + assert pretty(Adjoint(X) + Adjoint(Y)) == " + +\nX + Y " + assert pretty(Adjoint(X*Y)) == " +\n(X*Y) " + assert pretty(Adjoint(Y)*Adjoint(X)) == " + +\nY *X " + assert pretty(Adjoint(X**2)) == " +\n/ 2\\ \n\\X / " + assert pretty(Adjoint(X)**2) == " 2\n/ +\\ \n\\X / " + assert pretty(Adjoint(Inverse(X))) == " +\n/ -1\\ \n\\X / " + assert pretty(Inverse(Adjoint(X))) == " -1\n/ +\\ \n\\X / " + assert pretty(Adjoint(Transpose(X))) == " +\n/ T\\ \n\\X / " + assert pretty(Transpose(Adjoint(X))) == " T\n/ +\\ \n\\X / " + assert upretty(Adjoint(X)) == " †\nX " + assert upretty(Adjoint(X + Y)) == " †\n(X + Y) " + assert upretty(Adjoint(X) + Adjoint(Y)) == " † †\nX + Y " + assert upretty(Adjoint(X*Y)) == " †\n(X⋅Y) " + assert upretty(Adjoint(Y)*Adjoint(X)) == " † †\nY ⋅X " + assert upretty(Adjoint(X**2)) == \ + " †\n⎛ 2⎞ \n⎝X ⎠ " + assert upretty(Adjoint(X)**2) == \ + " 2\n⎛ †⎞ \n⎝X ⎠ " + assert upretty(Adjoint(Inverse(X))) == \ + " †\n⎛ -1⎞ \n⎝X ⎠ " + assert upretty(Inverse(Adjoint(X))) == \ + " -1\n⎛ †⎞ \n⎝X ⎠ " + assert upretty(Adjoint(Transpose(X))) == \ + " †\n⎛ T⎞ \n⎝X ⎠ " + assert upretty(Transpose(Adjoint(X))) == \ + " T\n⎛ †⎞ \n⎝X ⎠ " + m = Matrix(((1, 2), (3, 4))) + assert upretty(Adjoint(m)) == \ + ' †\n'\ + '⎡1 2⎤ \n'\ + '⎢ ⎥ \n'\ + '⎣3 4⎦ ' + assert upretty(Adjoint(m+X)) == \ + ' †\n'\ + '⎛⎡1 2⎤ ⎞ \n'\ + '⎜⎢ ⎥ + X⎟ \n'\ + '⎝⎣3 4⎦ ⎠ ' + assert upretty(Adjoint(BlockMatrix(((OneMatrix(2, 2), X), + (m, ZeroMatrix(2, 2)))))) == \ + ' †\n'\ + '⎡ 𝟙 X⎤ \n'\ + '⎢ ⎥ \n'\ + '⎢⎡1 2⎤ ⎥ \n'\ + '⎢⎢ ⎥ 𝟘⎥ \n'\ + '⎣⎣3 4⎦ ⎦ ' + + +def test_Transpose(): + X = MatrixSymbol('X', 2, 2) + Y = MatrixSymbol('Y', 2, 2) + assert pretty(Transpose(X)) == " T\nX " + assert pretty(Transpose(X + Y)) == " T\n(X + Y) " + assert pretty(Transpose(X) + Transpose(Y)) == " T T\nX + Y " + assert pretty(Transpose(X*Y)) == " T\n(X*Y) " + assert pretty(Transpose(Y)*Transpose(X)) == " T T\nY *X " + assert pretty(Transpose(X**2)) == " T\n/ 2\\ \n\\X / " + assert pretty(Transpose(X)**2) == " 2\n/ T\\ \n\\X / " + assert pretty(Transpose(Inverse(X))) == " T\n/ -1\\ \n\\X / " + assert pretty(Inverse(Transpose(X))) == " -1\n/ T\\ \n\\X / " + assert upretty(Transpose(X)) == " T\nX " + assert upretty(Transpose(X + Y)) == " T\n(X + Y) " + assert upretty(Transpose(X) + Transpose(Y)) == " T T\nX + Y " + assert upretty(Transpose(X*Y)) == " T\n(X⋅Y) " + assert upretty(Transpose(Y)*Transpose(X)) == " T T\nY ⋅X " + assert upretty(Transpose(X**2)) == \ + " T\n⎛ 2⎞ \n⎝X ⎠ " + assert upretty(Transpose(X)**2) == \ + " 2\n⎛ T⎞ \n⎝X ⎠ " + assert upretty(Transpose(Inverse(X))) == \ + " T\n⎛ -1⎞ \n⎝X ⎠ " + assert upretty(Inverse(Transpose(X))) == \ + " -1\n⎛ T⎞ \n⎝X ⎠ " + m = Matrix(((1, 2), (3, 4))) + assert upretty(Transpose(m)) == \ + ' T\n'\ + '⎡1 2⎤ \n'\ + '⎢ ⎥ \n'\ + '⎣3 4⎦ ' + assert upretty(Transpose(m+X)) == \ + ' T\n'\ + '⎛⎡1 2⎤ ⎞ \n'\ + '⎜⎢ ⎥ + X⎟ \n'\ + '⎝⎣3 4⎦ ⎠ ' + assert upretty(Transpose(BlockMatrix(((OneMatrix(2, 2), X), + (m, ZeroMatrix(2, 2)))))) == \ + ' T\n'\ + '⎡ 𝟙 X⎤ \n'\ + '⎢ ⎥ \n'\ + '⎢⎡1 2⎤ ⎥ \n'\ + '⎢⎢ ⎥ 𝟘⎥ \n'\ + '⎣⎣3 4⎦ ⎦ ' + + +def test_pretty_Trace_issue_9044(): + X = Matrix([[1, 2], [3, 4]]) + Y = Matrix([[2, 4], [6, 8]]) + ascii_str_1 = \ +"""\ + /[1 2]\\ +tr|[ ]| + \\[3 4]/\ +""" + ucode_str_1 = \ +"""\ + ⎛⎡1 2⎤⎞ +tr⎜⎢ ⎥⎟ + ⎝⎣3 4⎦⎠\ +""" + ascii_str_2 = \ +"""\ + /[1 2]\\ /[2 4]\\ +tr|[ ]| + tr|[ ]| + \\[3 4]/ \\[6 8]/\ +""" + ucode_str_2 = \ +"""\ + ⎛⎡1 2⎤⎞ ⎛⎡2 4⎤⎞ +tr⎜⎢ ⎥⎟ + tr⎜⎢ ⎥⎟ + ⎝⎣3 4⎦⎠ ⎝⎣6 8⎦⎠\ +""" + assert pretty(Trace(X)) == ascii_str_1 + assert upretty(Trace(X)) == ucode_str_1 + + assert pretty(Trace(X) + Trace(Y)) == ascii_str_2 + assert upretty(Trace(X) + Trace(Y)) == ucode_str_2 + + +def test_MatrixSlice(): + n = Symbol('n', integer=True) + x, y, z, w, t, = symbols('x y z w t') + X = MatrixSymbol('X', n, n) + Y = MatrixSymbol('Y', 10, 10) + Z = MatrixSymbol('Z', 10, 10) + + expr = MatrixSlice(X, (None, None, None), (None, None, None)) + assert pretty(expr) == upretty(expr) == 'X[:, :]' + expr = X[x:x + 1, y:y + 1] + assert pretty(expr) == upretty(expr) == 'X[x:x + 1, y:y + 1]' + expr = X[x:x + 1:2, y:y + 1:2] + assert pretty(expr) == upretty(expr) == 'X[x:x + 1:2, y:y + 1:2]' + expr = X[:x, y:] + assert pretty(expr) == upretty(expr) == 'X[:x, y:]' + expr = X[:x, y:] + assert pretty(expr) == upretty(expr) == 'X[:x, y:]' + expr = X[x:, :y] + assert pretty(expr) == upretty(expr) == 'X[x:, :y]' + expr = X[x:y, z:w] + assert pretty(expr) == upretty(expr) == 'X[x:y, z:w]' + expr = X[x:y:t, w:t:x] + assert pretty(expr) == upretty(expr) == 'X[x:y:t, w:t:x]' + expr = X[x::y, t::w] + assert pretty(expr) == upretty(expr) == 'X[x::y, t::w]' + expr = X[:x:y, :t:w] + assert pretty(expr) == upretty(expr) == 'X[:x:y, :t:w]' + expr = X[::x, ::y] + assert pretty(expr) == upretty(expr) == 'X[::x, ::y]' + expr = MatrixSlice(X, (0, None, None), (0, None, None)) + assert pretty(expr) == upretty(expr) == 'X[:, :]' + expr = MatrixSlice(X, (None, n, None), (None, n, None)) + assert pretty(expr) == upretty(expr) == 'X[:, :]' + expr = MatrixSlice(X, (0, n, None), (0, n, None)) + assert pretty(expr) == upretty(expr) == 'X[:, :]' + expr = MatrixSlice(X, (0, n, 2), (0, n, 2)) + assert pretty(expr) == upretty(expr) == 'X[::2, ::2]' + expr = X[1:2:3, 4:5:6] + assert pretty(expr) == upretty(expr) == 'X[1:2:3, 4:5:6]' + expr = X[1:3:5, 4:6:8] + assert pretty(expr) == upretty(expr) == 'X[1:3:5, 4:6:8]' + expr = X[1:10:2] + assert pretty(expr) == upretty(expr) == 'X[1:10:2, :]' + expr = Y[:5, 1:9:2] + assert pretty(expr) == upretty(expr) == 'Y[:5, 1:9:2]' + expr = Y[:5, 1:10:2] + assert pretty(expr) == upretty(expr) == 'Y[:5, 1::2]' + expr = Y[5, :5:2] + assert pretty(expr) == upretty(expr) == 'Y[5:6, :5:2]' + expr = X[0:1, 0:1] + assert pretty(expr) == upretty(expr) == 'X[:1, :1]' + expr = X[0:1:2, 0:1:2] + assert pretty(expr) == upretty(expr) == 'X[:1:2, :1:2]' + expr = (Y + Z)[2:, 2:] + assert pretty(expr) == upretty(expr) == '(Y + Z)[2:, 2:]' + + +def test_MatrixExpressions(): + n = Symbol('n', integer=True) + X = MatrixSymbol('X', n, n) + + assert pretty(X) == upretty(X) == "X" + + # Apply function elementwise (`ElementwiseApplyFunc`): + + expr = (X.T*X).applyfunc(sin) + + ascii_str = """\ + / T \\\n\ +(d -> sin(d)).\\X *X/\ +""" + ucode_str = """\ + ⎛ T ⎞\n\ +(d ↦ sin(d))˳⎝X ⋅X⎠\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + lamda = Lambda(x, 1/x) + expr = (n*X).applyfunc(lamda) + ascii_str = """\ +/ 1\\ \n\ +|x -> -|.(n*X)\n\ +\\ x/ \ +""" + ucode_str = """\ +⎛ 1⎞ \n\ +⎜x ↦ ─⎟˳(n⋅X)\n\ +⎝ x⎠ \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + +def test_pretty_dotproduct(): + from sympy.matrices.expressions.dotproduct import DotProduct + n = symbols("n", integer=True) + A = MatrixSymbol('A', n, 1) + B = MatrixSymbol('B', n, 1) + C = Matrix(1, 3, [1, 2, 3]) + D = Matrix(1, 3, [1, 3, 4]) + + assert pretty(DotProduct(A, B)) == "A*B" + assert pretty(DotProduct(C, D)) == "[1 2 3]*[1 3 4]" + assert upretty(DotProduct(A, B)) == "A⋅B" + assert upretty(DotProduct(C, D)) == "[1 2 3]⋅[1 3 4]" + + +def test_pretty_Determinant(): + from sympy.matrices import Determinant, Inverse, BlockMatrix, OneMatrix, ZeroMatrix + m = Matrix(((1, 2), (3, 4))) + assert upretty(Determinant(m)) == '│1 2│\n│ │\n│3 4│' + assert upretty(Determinant(Inverse(m))) == \ + '│ -1│\n'\ + '│⎡1 2⎤ │\n'\ + '│⎢ ⎥ │\n'\ + '│⎣3 4⎦ │' + X = MatrixSymbol('X', 2, 2) + assert upretty(Determinant(X)) == '│X│' + assert upretty(Determinant(X + m)) == \ + '│⎡1 2⎤ │\n'\ + '│⎢ ⎥ + X│\n'\ + '│⎣3 4⎦ │' + assert upretty(Determinant(BlockMatrix(((OneMatrix(2, 2), X), + (m, ZeroMatrix(2, 2)))))) == \ + '│ 𝟙 X│\n'\ + '│ │\n'\ + '│⎡1 2⎤ │\n'\ + '│⎢ ⎥ 𝟘│\n'\ + '│⎣3 4⎦ │' + + +def test_pretty_piecewise(): + expr = Piecewise((x, x < 1), (x**2, True)) + ascii_str = \ +"""\ +/x for x < 1\n\ +| \n\ +< 2 \n\ +|x otherwise\n\ +\\ \ +""" + ucode_str = \ +"""\ +⎧x for x < 1\n\ +⎪ \n\ +⎨ 2 \n\ +⎪x otherwise\n\ +⎩ \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = -Piecewise((x, x < 1), (x**2, True)) + ascii_str = \ +"""\ + //x for x < 1\\\n\ + || |\n\ +-|< 2 |\n\ + ||x otherwise|\n\ + \\\\ /\ +""" + ucode_str = \ +"""\ + ⎛⎧x for x < 1⎞\n\ + ⎜⎪ ⎟\n\ +-⎜⎨ 2 ⎟\n\ + ⎜⎪x otherwise⎟\n\ + ⎝⎩ ⎠\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = x + Piecewise((x, x > 0), (y, True)) + Piecewise((x/y, x < 2), + (y**2, x > 2), (1, True)) + 1 + ascii_str = \ +"""\ + //x \\ \n\ + ||- for x < 2| \n\ + ||y | \n\ + //x for x > 0\\ || | \n\ +x + |< | + |< 2 | + 1\n\ + \\\\y otherwise/ ||y for x > 2| \n\ + || | \n\ + ||1 otherwise| \n\ + \\\\ / \ +""" + ucode_str = \ +"""\ + ⎛⎧x ⎞ \n\ + ⎜⎪─ for x < 2⎟ \n\ + ⎜⎪y ⎟ \n\ + ⎛⎧x for x > 0⎞ ⎜⎪ ⎟ \n\ +x + ⎜⎨ ⎟ + ⎜⎨ 2 ⎟ + 1\n\ + ⎝⎩y otherwise⎠ ⎜⎪y for x > 2⎟ \n\ + ⎜⎪ ⎟ \n\ + ⎜⎪1 otherwise⎟ \n\ + ⎝⎩ ⎠ \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = x - Piecewise((x, x > 0), (y, True)) + Piecewise((x/y, x < 2), + (y**2, x > 2), (1, True)) + 1 + ascii_str = \ +"""\ + //x \\ \n\ + ||- for x < 2| \n\ + ||y | \n\ + //x for x > 0\\ || | \n\ +x - |< | + |< 2 | + 1\n\ + \\\\y otherwise/ ||y for x > 2| \n\ + || | \n\ + ||1 otherwise| \n\ + \\\\ / \ +""" + ucode_str = \ +"""\ + ⎛⎧x ⎞ \n\ + ⎜⎪─ for x < 2⎟ \n\ + ⎜⎪y ⎟ \n\ + ⎛⎧x for x > 0⎞ ⎜⎪ ⎟ \n\ +x - ⎜⎨ ⎟ + ⎜⎨ 2 ⎟ + 1\n\ + ⎝⎩y otherwise⎠ ⎜⎪y for x > 2⎟ \n\ + ⎜⎪ ⎟ \n\ + ⎜⎪1 otherwise⎟ \n\ + ⎝⎩ ⎠ \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = x*Piecewise((x, x > 0), (y, True)) + ascii_str = \ +"""\ + //x for x > 0\\\n\ +x*|< |\n\ + \\\\y otherwise/\ +""" + ucode_str = \ +"""\ + ⎛⎧x for x > 0⎞\n\ +x⋅⎜⎨ ⎟\n\ + ⎝⎩y otherwise⎠\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Piecewise((x, x > 0), (y, True))*Piecewise((x/y, x < 2), (y**2, x > + 2), (1, True)) + ascii_str = \ +"""\ + //x \\\n\ + ||- for x < 2|\n\ + ||y |\n\ +//x for x > 0\\ || |\n\ +|< |*|< 2 |\n\ +\\\\y otherwise/ ||y for x > 2|\n\ + || |\n\ + ||1 otherwise|\n\ + \\\\ /\ +""" + ucode_str = \ +"""\ + ⎛⎧x ⎞\n\ + ⎜⎪─ for x < 2⎟\n\ + ⎜⎪y ⎟\n\ +⎛⎧x for x > 0⎞ ⎜⎪ ⎟\n\ +⎜⎨ ⎟⋅⎜⎨ 2 ⎟\n\ +⎝⎩y otherwise⎠ ⎜⎪y for x > 2⎟\n\ + ⎜⎪ ⎟\n\ + ⎜⎪1 otherwise⎟\n\ + ⎝⎩ ⎠\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = -Piecewise((x, x > 0), (y, True))*Piecewise((x/y, x < 2), (y**2, x + > 2), (1, True)) + ascii_str = \ +"""\ + //x \\\n\ + ||- for x < 2|\n\ + ||y |\n\ + //x for x > 0\\ || |\n\ +-|< |*|< 2 |\n\ + \\\\y otherwise/ ||y for x > 2|\n\ + || |\n\ + ||1 otherwise|\n\ + \\\\ /\ +""" + ucode_str = \ +"""\ + ⎛⎧x ⎞\n\ + ⎜⎪─ for x < 2⎟\n\ + ⎜⎪y ⎟\n\ + ⎛⎧x for x > 0⎞ ⎜⎪ ⎟\n\ +-⎜⎨ ⎟⋅⎜⎨ 2 ⎟\n\ + ⎝⎩y otherwise⎠ ⎜⎪y for x > 2⎟\n\ + ⎜⎪ ⎟\n\ + ⎜⎪1 otherwise⎟\n\ + ⎝⎩ ⎠\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Piecewise((0, Abs(1/y) < 1), (1, Abs(y) < 1), (y*meijerg(((2, 1), + ()), ((), (1, 0)), 1/y), True)) + ascii_str = \ +"""\ +/ 1 \n\ +| 0 for --- < 1\n\ +| |y| \n\ +| \n\ +< 1 for |y| < 1\n\ +| \n\ +| __0, 2 /1, 2 | 1\\ \n\ +|y*/__ | | -| otherwise \n\ +\\ \\_|2, 2 \\ 0, 1 | y/ \ +""" + ucode_str = \ +"""\ +⎧ 1 \n\ +⎪ 0 for ─── < 1\n\ +⎪ │y│ \n\ +⎪ \n\ +⎨ 1 for │y│ < 1\n\ +⎪ \n\ +⎪ ╭─╮0, 2 ⎛1, 2 │ 1⎞ \n\ +⎪y⋅│╶┐ ⎜ │ ─⎟ otherwise \n\ +⎩ ╰─╯2, 2 ⎝ 0, 1 │ y⎠ \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + # XXX: We have to use evaluate=False here because Piecewise._eval_power + # denests the power. + expr = Pow(Piecewise((x, x > 0), (y, True)), 2, evaluate=False) + ascii_str = \ +"""\ + 2\n\ +//x for x > 0\\ \n\ +|< | \n\ +\\\\y otherwise/ \ +""" + ucode_str = \ +"""\ + 2\n\ +⎛⎧x for x > 0⎞ \n\ +⎜⎨ ⎟ \n\ +⎝⎩y otherwise⎠ \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + +def test_pretty_ITE(): + expr = ITE(x, y, z) + assert pretty(expr) == ( + '/y for x \n' + '< \n' + '\\z otherwise' + ) + assert upretty(expr) == """\ +⎧y for x \n\ +⎨ \n\ +⎩z otherwise\ +""" + + +def test_pretty_seq(): + expr = () + ascii_str = \ +"""\ +()\ +""" + ucode_str = \ +"""\ +()\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = [] + ascii_str = \ +"""\ +[]\ +""" + ucode_str = \ +"""\ +[]\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = {} + expr_2 = {} + ascii_str = \ +"""\ +{}\ +""" + ucode_str = \ +"""\ +{}\ +""" + assert pretty(expr) == ascii_str + assert pretty(expr_2) == ascii_str + assert upretty(expr) == ucode_str + assert upretty(expr_2) == ucode_str + + expr = (1/x,) + ascii_str = \ +"""\ + 1 \n\ +(-,)\n\ + x \ +""" + ucode_str = \ +"""\ +⎛1 ⎞\n\ +⎜─,⎟\n\ +⎝x ⎠\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = [x**2, 1/x, x, y, sin(th)**2/cos(ph)**2] + ascii_str = \ +"""\ + 2 \n\ + 2 1 sin (theta) \n\ +[x , -, x, y, -----------]\n\ + x 2 \n\ + cos (phi) \ +""" + ucode_str = \ +"""\ +⎡ 2 ⎤\n\ +⎢ 2 1 sin (θ)⎥\n\ +⎢x , ─, x, y, ───────⎥\n\ +⎢ x 2 ⎥\n\ +⎣ cos (φ)⎦\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = (x**2, 1/x, x, y, sin(th)**2/cos(ph)**2) + ascii_str = \ +"""\ + 2 \n\ + 2 1 sin (theta) \n\ +(x , -, x, y, -----------)\n\ + x 2 \n\ + cos (phi) \ +""" + ucode_str = \ +"""\ +⎛ 2 ⎞\n\ +⎜ 2 1 sin (θ)⎟\n\ +⎜x , ─, x, y, ───────⎟\n\ +⎜ x 2 ⎟\n\ +⎝ cos (φ)⎠\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Tuple(x**2, 1/x, x, y, sin(th)**2/cos(ph)**2) + ascii_str = \ +"""\ + 2 \n\ + 2 1 sin (theta) \n\ +(x , -, x, y, -----------)\n\ + x 2 \n\ + cos (phi) \ +""" + ucode_str = \ +"""\ +⎛ 2 ⎞\n\ +⎜ 2 1 sin (θ)⎟\n\ +⎜x , ─, x, y, ───────⎟\n\ +⎜ x 2 ⎟\n\ +⎝ cos (φ)⎠\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = {x: sin(x)} + expr_2 = Dict({x: sin(x)}) + ascii_str = \ +"""\ +{x: sin(x)}\ +""" + ucode_str = \ +"""\ +{x: sin(x)}\ +""" + assert pretty(expr) == ascii_str + assert pretty(expr_2) == ascii_str + assert upretty(expr) == ucode_str + assert upretty(expr_2) == ucode_str + + expr = {1/x: 1/y, x: sin(x)**2} + expr_2 = Dict({1/x: 1/y, x: sin(x)**2}) + ascii_str = \ +"""\ + 1 1 2 \n\ +{-: -, x: sin (x)}\n\ + x y \ +""" + ucode_str = \ +"""\ +⎧1 1 2 ⎫\n\ +⎨─: ─, x: sin (x)⎬\n\ +⎩x y ⎭\ +""" + assert pretty(expr) == ascii_str + assert pretty(expr_2) == ascii_str + assert upretty(expr) == ucode_str + assert upretty(expr_2) == ucode_str + + # There used to be a bug with pretty-printing sequences of even height. + expr = [x**2] + ascii_str = \ +"""\ + 2 \n\ +[x ]\ +""" + ucode_str = \ +"""\ +⎡ 2⎤\n\ +⎣x ⎦\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = (x**2,) + ascii_str = \ +"""\ + 2 \n\ +(x ,)\ +""" + ucode_str = \ +"""\ +⎛ 2 ⎞\n\ +⎝x ,⎠\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Tuple(x**2) + ascii_str = \ +"""\ + 2 \n\ +(x ,)\ +""" + ucode_str = \ +"""\ +⎛ 2 ⎞\n\ +⎝x ,⎠\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = {x**2: 1} + expr_2 = Dict({x**2: 1}) + ascii_str = \ +"""\ + 2 \n\ +{x : 1}\ +""" + ucode_str = \ +"""\ +⎧ 2 ⎫\n\ +⎨x : 1⎬\n\ +⎩ ⎭\ +""" + assert pretty(expr) == ascii_str + assert pretty(expr_2) == ascii_str + assert upretty(expr) == ucode_str + assert upretty(expr_2) == ucode_str + + +def test_any_object_in_sequence(): + # Cf. issue 5306 + b1 = Basic() + b2 = Basic(Basic()) + + expr = [b2, b1] + assert pretty(expr) == "[Basic(Basic()), Basic()]" + assert upretty(expr) == "[Basic(Basic()), Basic()]" + + expr = {b2, b1} + assert pretty(expr) == "{Basic(), Basic(Basic())}" + assert upretty(expr) == "{Basic(), Basic(Basic())}" + + expr = {b2: b1, b1: b2} + expr2 = Dict({b2: b1, b1: b2}) + assert pretty(expr) == "{Basic(): Basic(Basic()), Basic(Basic()): Basic()}" + assert pretty( + expr2) == "{Basic(): Basic(Basic()), Basic(Basic()): Basic()}" + assert upretty( + expr) == "{Basic(): Basic(Basic()), Basic(Basic()): Basic()}" + assert upretty( + expr2) == "{Basic(): Basic(Basic()), Basic(Basic()): Basic()}" + + +def test_print_builtin_set(): + assert pretty(set()) == 'set()' + assert upretty(set()) == 'set()' + + assert pretty(frozenset()) == 'frozenset()' + assert upretty(frozenset()) == 'frozenset()' + + s1 = {1/x, x} + s2 = frozenset(s1) + + assert pretty(s1) == \ +"""\ + 1 \n\ +{-, x} + x \ +""" + assert upretty(s1) == \ +"""\ +⎧1 ⎫ +⎨─, x⎬ +⎩x ⎭\ +""" + + assert pretty(s2) == \ +"""\ + 1 \n\ +frozenset({-, x}) + x \ +""" + assert upretty(s2) == \ +"""\ + ⎛⎧1 ⎫⎞ +frozenset⎜⎨─, x⎬⎟ + ⎝⎩x ⎭⎠\ +""" + + +def test_pretty_sets(): + s = FiniteSet + assert pretty(s(*[x*y, x**2])) == \ +"""\ + 2 \n\ +{x , x*y}\ +""" + assert pretty(s(*range(1, 6))) == "{1, 2, 3, 4, 5}" + assert pretty(s(*range(1, 13))) == "{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}" + + assert pretty({x*y, x**2}) == \ +"""\ + 2 \n\ +{x , x*y}\ +""" + assert pretty(set(range(1, 6))) == "{1, 2, 3, 4, 5}" + assert pretty(set(range(1, 13))) == \ + "{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}" + + assert pretty(frozenset([x*y, x**2])) == \ +"""\ + 2 \n\ +frozenset({x , x*y})\ +""" + assert pretty(frozenset(range(1, 6))) == "frozenset({1, 2, 3, 4, 5})" + assert pretty(frozenset(range(1, 13))) == \ + "frozenset({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12})" + + assert pretty(Range(0, 3, 1)) == '{0, 1, 2}' + + ascii_str = '{0, 1, ..., 29}' + ucode_str = '{0, 1, …, 29}' + assert pretty(Range(0, 30, 1)) == ascii_str + assert upretty(Range(0, 30, 1)) == ucode_str + + ascii_str = '{30, 29, ..., 2}' + ucode_str = '{30, 29, …, 2}' + assert pretty(Range(30, 1, -1)) == ascii_str + assert upretty(Range(30, 1, -1)) == ucode_str + + ascii_str = '{0, 2, ...}' + ucode_str = '{0, 2, …}' + assert pretty(Range(0, oo, 2)) == ascii_str + assert upretty(Range(0, oo, 2)) == ucode_str + + ascii_str = '{..., 2, 0}' + ucode_str = '{…, 2, 0}' + assert pretty(Range(oo, -2, -2)) == ascii_str + assert upretty(Range(oo, -2, -2)) == ucode_str + + ascii_str = '{-2, -3, ...}' + ucode_str = '{-2, -3, …}' + assert pretty(Range(-2, -oo, -1)) == ascii_str + assert upretty(Range(-2, -oo, -1)) == ucode_str + + +def test_pretty_SetExpr(): + iv = Interval(1, 3) + se = SetExpr(iv) + ascii_str = "SetExpr([1, 3])" + ucode_str = "SetExpr([1, 3])" + assert pretty(se) == ascii_str + assert upretty(se) == ucode_str + + +def test_pretty_ImageSet(): + imgset = ImageSet(Lambda((x, y), x + y), {1, 2, 3}, {3, 4}) + ascii_str = '{x + y | x in {1, 2, 3}, y in {3, 4}}' + ucode_str = '{x + y │ x ∊ {1, 2, 3}, y ∊ {3, 4}}' + assert pretty(imgset) == ascii_str + assert upretty(imgset) == ucode_str + + imgset = ImageSet(Lambda(((x, y),), x + y), ProductSet({1, 2, 3}, {3, 4})) + ascii_str = '{x + y | (x, y) in {1, 2, 3} x {3, 4}}' + ucode_str = '{x + y │ (x, y) ∊ {1, 2, 3} × {3, 4}}' + assert pretty(imgset) == ascii_str + assert upretty(imgset) == ucode_str + + imgset = ImageSet(Lambda(x, x**2), S.Naturals) + ascii_str = '''\ + 2 \n\ +{x | x in Naturals}''' + ucode_str = '''\ +⎧ 2 │ ⎫\n\ +⎨x │ x ∊ ℕ⎬\n\ +⎩ │ ⎭''' + assert pretty(imgset) == ascii_str + assert upretty(imgset) == ucode_str + + # TODO: The "x in N" parts below should be centered independently of the + # 1/x**2 fraction + imgset = ImageSet(Lambda(x, 1/x**2), S.Naturals) + ascii_str = '''\ + 1 \n\ +{-- | x in Naturals} + 2 \n\ + x ''' + ucode_str = '''\ +⎧1 │ ⎫\n\ +⎪── │ x ∊ ℕ⎪\n\ +⎨ 2 │ ⎬\n\ +⎪x │ ⎪\n\ +⎩ │ ⎭''' + assert pretty(imgset) == ascii_str + assert upretty(imgset) == ucode_str + + imgset = ImageSet(Lambda((x, y), 1/(x + y)**2), S.Naturals, S.Naturals) + ascii_str = '''\ + 1 \n\ +{-------- | x in Naturals, y in Naturals} + 2 \n\ + (x + y) ''' + ucode_str = '''\ +⎧ 1 │ ⎫ +⎪──────── │ x ∊ ℕ, y ∊ ℕ⎪ +⎨ 2 │ ⎬ +⎪(x + y) │ ⎪ +⎩ │ ⎭''' + assert pretty(imgset) == ascii_str + assert upretty(imgset) == ucode_str + + # issue 23449 centering issue + assert upretty([Symbol("ihat") / (Symbol("i") + 1)]) == '''\ +⎡ î ⎤ +⎢─────⎥ +⎣i + 1⎦\ +''' + assert upretty(Matrix([Symbol("ihat"), Symbol("i") + 1])) == '''\ +⎡ î ⎤ +⎢ ⎥ +⎣i + 1⎦\ +''' + + +def test_pretty_ConditionSet(): + ascii_str = '{x | x in (-oo, oo) and sin(x) = 0}' + ucode_str = '{x │ x ∊ ℝ ∧ (sin(x) = 0)}' + assert pretty(ConditionSet(x, Eq(sin(x), 0), S.Reals)) == ascii_str + assert upretty(ConditionSet(x, Eq(sin(x), 0), S.Reals)) == ucode_str + + assert pretty(ConditionSet(x, Contains(x, S.Reals, evaluate=False), FiniteSet(1))) == '{1}' + assert upretty(ConditionSet(x, Contains(x, S.Reals, evaluate=False), FiniteSet(1))) == '{1}' + + assert pretty(ConditionSet(x, And(x > 1, x < -1), FiniteSet(1, 2, 3))) == "EmptySet" + assert upretty(ConditionSet(x, And(x > 1, x < -1), FiniteSet(1, 2, 3))) == "∅" + + assert pretty(ConditionSet(x, Or(x > 1, x < -1), FiniteSet(1, 2))) == '{2}' + assert upretty(ConditionSet(x, Or(x > 1, x < -1), FiniteSet(1, 2))) == '{2}' + + condset = ConditionSet(x, 1/x**2 > 0) + ascii_str = '''\ + 1 \n\ +{x | -- > 0} + 2 \n\ + x ''' + ucode_str = '''\ +⎧ │ ⎛1 ⎞⎫ +⎪x │ ⎜── > 0⎟⎪ +⎨ │ ⎜ 2 ⎟⎬ +⎪ │ ⎝x ⎠⎪ +⎩ │ ⎭''' + assert pretty(condset) == ascii_str + assert upretty(condset) == ucode_str + + condset = ConditionSet(x, 1/x**2 > 0, S.Reals) + ascii_str = '''\ + 1 \n\ +{x | x in (-oo, oo) and -- > 0} + 2 \n\ + x ''' + ucode_str = '''\ +⎧ │ ⎛1 ⎞⎫ +⎪x │ x ∊ ℝ ∧ ⎜── > 0⎟⎪ +⎨ │ ⎜ 2 ⎟⎬ +⎪ │ ⎝x ⎠⎪ +⎩ │ ⎭''' + assert pretty(condset) == ascii_str + assert upretty(condset) == ucode_str + + +def test_pretty_ComplexRegion(): + from sympy.sets.fancysets import ComplexRegion + cregion = ComplexRegion(Interval(3, 5)*Interval(4, 6)) + ascii_str = '{x + y*I | x, y in [3, 5] x [4, 6]}' + ucode_str = '{x + y⋅ⅈ │ x, y ∊ [3, 5] × [4, 6]}' + assert pretty(cregion) == ascii_str + assert upretty(cregion) == ucode_str + + cregion = ComplexRegion(Interval(0, 1)*Interval(0, 2*pi), polar=True) + ascii_str = '{r*(I*sin(theta) + cos(theta)) | r, theta in [0, 1] x [0, 2*pi)}' + ucode_str = '{r⋅(ⅈ⋅sin(θ) + cos(θ)) │ r, θ ∊ [0, 1] × [0, 2⋅π)}' + assert pretty(cregion) == ascii_str + assert upretty(cregion) == ucode_str + + cregion = ComplexRegion(Interval(3, 1/a**2)*Interval(4, 6)) + ascii_str = '''\ + 1 \n\ +{x + y*I | x, y in [3, --] x [4, 6]} + 2 \n\ + a ''' + ucode_str = '''\ +⎧ │ ⎡ 1 ⎤ ⎫ +⎪x + y⋅ⅈ │ x, y ∊ ⎢3, ──⎥ × [4, 6]⎪ +⎨ │ ⎢ 2⎥ ⎬ +⎪ │ ⎣ a ⎦ ⎪ +⎩ │ ⎭''' + assert pretty(cregion) == ascii_str + assert upretty(cregion) == ucode_str + + cregion = ComplexRegion(Interval(0, 1/a**2)*Interval(0, 2*pi), polar=True) + ascii_str = '''\ + 1 \n\ +{r*(I*sin(theta) + cos(theta)) | r, theta in [0, --] x [0, 2*pi)} + 2 \n\ + a ''' + ucode_str = '''\ +⎧ │ ⎡ 1 ⎤ ⎫ +⎪r⋅(ⅈ⋅sin(θ) + cos(θ)) │ r, θ ∊ ⎢0, ──⎥ × [0, 2⋅π)⎪ +⎨ │ ⎢ 2⎥ ⎬ +⎪ │ ⎣ a ⎦ ⎪ +⎩ │ ⎭''' + assert pretty(cregion) == ascii_str + assert upretty(cregion) == ucode_str + + +def test_pretty_Union_issue_10414(): + a, b = Interval(2, 3), Interval(4, 7) + ucode_str = '[2, 3] ∪ [4, 7]' + ascii_str = '[2, 3] U [4, 7]' + assert upretty(Union(a, b)) == ucode_str + assert pretty(Union(a, b)) == ascii_str + + +def test_pretty_Intersection_issue_10414(): + x, y, z, w = symbols('x, y, z, w') + a, b = Interval(x, y), Interval(z, w) + ucode_str = '[x, y] ∩ [z, w]' + ascii_str = '[x, y] n [z, w]' + assert upretty(Intersection(a, b)) == ucode_str + assert pretty(Intersection(a, b)) == ascii_str + + +def test_ProductSet_exponent(): + ucode_str = ' 1\n[0, 1] ' + assert upretty(Interval(0, 1)**1) == ucode_str + ucode_str = ' 2\n[0, 1] ' + assert upretty(Interval(0, 1)**2) == ucode_str + + +def test_ProductSet_parenthesis(): + ucode_str = '([4, 7] × {1, 2}) ∪ ([2, 3] × [4, 7])' + + a, b = Interval(2, 3), Interval(4, 7) + assert upretty(Union(a*b, b*FiniteSet(1, 2))) == ucode_str + + +def test_ProductSet_prod_char_issue_10413(): + ascii_str = '[2, 3] x [4, 7]' + ucode_str = '[2, 3] × [4, 7]' + + a, b = Interval(2, 3), Interval(4, 7) + assert pretty(a*b) == ascii_str + assert upretty(a*b) == ucode_str + + +def test_pretty_sequences(): + s1 = SeqFormula(a**2, (0, oo)) + s2 = SeqPer((1, 2)) + + ascii_str = '[0, 1, 4, 9, ...]' + ucode_str = '[0, 1, 4, 9, …]' + + assert pretty(s1) == ascii_str + assert upretty(s1) == ucode_str + + ascii_str = '[1, 2, 1, 2, ...]' + ucode_str = '[1, 2, 1, 2, …]' + assert pretty(s2) == ascii_str + assert upretty(s2) == ucode_str + + s3 = SeqFormula(a**2, (0, 2)) + s4 = SeqPer((1, 2), (0, 2)) + + ascii_str = '[0, 1, 4]' + ucode_str = '[0, 1, 4]' + + assert pretty(s3) == ascii_str + assert upretty(s3) == ucode_str + + ascii_str = '[1, 2, 1]' + ucode_str = '[1, 2, 1]' + assert pretty(s4) == ascii_str + assert upretty(s4) == ucode_str + + s5 = SeqFormula(a**2, (-oo, 0)) + s6 = SeqPer((1, 2), (-oo, 0)) + + ascii_str = '[..., 9, 4, 1, 0]' + ucode_str = '[…, 9, 4, 1, 0]' + + assert pretty(s5) == ascii_str + assert upretty(s5) == ucode_str + + ascii_str = '[..., 2, 1, 2, 1]' + ucode_str = '[…, 2, 1, 2, 1]' + assert pretty(s6) == ascii_str + assert upretty(s6) == ucode_str + + ascii_str = '[1, 3, 5, 11, ...]' + ucode_str = '[1, 3, 5, 11, …]' + + assert pretty(SeqAdd(s1, s2)) == ascii_str + assert upretty(SeqAdd(s1, s2)) == ucode_str + + ascii_str = '[1, 3, 5]' + ucode_str = '[1, 3, 5]' + + assert pretty(SeqAdd(s3, s4)) == ascii_str + assert upretty(SeqAdd(s3, s4)) == ucode_str + + ascii_str = '[..., 11, 5, 3, 1]' + ucode_str = '[…, 11, 5, 3, 1]' + + assert pretty(SeqAdd(s5, s6)) == ascii_str + assert upretty(SeqAdd(s5, s6)) == ucode_str + + ascii_str = '[0, 2, 4, 18, ...]' + ucode_str = '[0, 2, 4, 18, …]' + + assert pretty(SeqMul(s1, s2)) == ascii_str + assert upretty(SeqMul(s1, s2)) == ucode_str + + ascii_str = '[0, 2, 4]' + ucode_str = '[0, 2, 4]' + + assert pretty(SeqMul(s3, s4)) == ascii_str + assert upretty(SeqMul(s3, s4)) == ucode_str + + ascii_str = '[..., 18, 4, 2, 0]' + ucode_str = '[…, 18, 4, 2, 0]' + + assert pretty(SeqMul(s5, s6)) == ascii_str + assert upretty(SeqMul(s5, s6)) == ucode_str + + # Sequences with symbolic limits, issue 12629 + s7 = SeqFormula(a**2, (a, 0, x)) + raises(NotImplementedError, lambda: pretty(s7)) + raises(NotImplementedError, lambda: upretty(s7)) + + b = Symbol('b') + s8 = SeqFormula(b*a**2, (a, 0, 2)) + ascii_str = '[0, b, 4*b]' + ucode_str = '[0, b, 4⋅b]' + assert pretty(s8) == ascii_str + assert upretty(s8) == ucode_str + + +def test_pretty_FourierSeries(): + f = fourier_series(x, (x, -pi, pi)) + + ascii_str = \ +"""\ + 2*sin(3*x) \n\ +2*sin(x) - sin(2*x) + ---------- + ...\n\ + 3 \ +""" + + ucode_str = \ +"""\ + 2⋅sin(3⋅x) \n\ +2⋅sin(x) - sin(2⋅x) + ────────── + …\n\ + 3 \ +""" + + assert pretty(f) == ascii_str + assert upretty(f) == ucode_str + + +def test_pretty_FormalPowerSeries(): + f = fps(log(1 + x)) + + + ascii_str = \ +"""\ + oo \n\ +____ \n\ +\\ ` \n\ + \\ -k k \n\ + \\ -(-1) *x \n\ + / -----------\n\ + / k \n\ +/___, \n\ +k = 1 \ +""" + + ucode_str = \ +"""\ + ∞ \n\ +____ \n\ +╲ \n\ + ╲ -k k \n\ + ╲ -(-1) ⋅x \n\ + ╱ ───────────\n\ + ╱ k \n\ +╱ \n\ +‾‾‾‾ \n\ +k = 1 \ +""" + + assert pretty(f) == ascii_str + assert upretty(f) == ucode_str + + +def test_pretty_limits(): + expr = Limit(x, x, oo) + ascii_str = \ +"""\ + lim x\n\ +x->oo \ +""" + ucode_str = \ +"""\ +lim x\n\ +x─→∞ \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Limit(x**2, x, 0) + ascii_str = \ +"""\ + 2\n\ + lim x \n\ +x->0+ \ +""" + ucode_str = \ +"""\ + 2\n\ + lim x \n\ +x─→0⁺ \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Limit(1/x, x, 0) + ascii_str = \ +"""\ + 1\n\ + lim -\n\ +x->0+x\ +""" + ucode_str = \ +"""\ + 1\n\ + lim ─\n\ +x─→0⁺x\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Limit(sin(x)/x, x, 0) + ascii_str = \ +"""\ + /sin(x)\\\n\ + lim |------|\n\ +x->0+\\ x /\ +""" + ucode_str = \ +"""\ + ⎛sin(x)⎞\n\ + lim ⎜──────⎟\n\ +x─→0⁺⎝ x ⎠\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Limit(sin(x)/x, x, 0, "-") + ascii_str = \ +"""\ + /sin(x)\\\n\ + lim |------|\n\ +x->0-\\ x /\ +""" + ucode_str = \ +"""\ + ⎛sin(x)⎞\n\ + lim ⎜──────⎟\n\ +x─→0⁻⎝ x ⎠\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Limit(x + sin(x), x, 0) + ascii_str = \ +"""\ + lim (x + sin(x))\n\ +x->0+ \ +""" + ucode_str = \ +"""\ + lim (x + sin(x))\n\ +x─→0⁺ \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Limit(x, x, 0)**2 + ascii_str = \ +"""\ + 2\n\ +/ lim x\\ \n\ +\\x->0+ / \ +""" + ucode_str = \ +"""\ + 2\n\ +⎛ lim x⎞ \n\ +⎝x─→0⁺ ⎠ \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Limit(x*Limit(y/2,y,0), x, 0) + ascii_str = \ +"""\ + / /y\\\\\n\ + lim |x* lim |-||\n\ +x->0+\\ y->0+\\2//\ +""" + ucode_str = \ +"""\ + ⎛ ⎛y⎞⎞\n\ + lim ⎜x⋅ lim ⎜─⎟⎟\n\ +x─→0⁺⎝ y─→0⁺⎝2⎠⎠\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = 2*Limit(x*Limit(y/2,y,0), x, 0) + ascii_str = \ +"""\ + / /y\\\\\n\ +2* lim |x* lim |-||\n\ + x->0+\\ y->0+\\2//\ +""" + ucode_str = \ +"""\ + ⎛ ⎛y⎞⎞\n\ +2⋅ lim ⎜x⋅ lim ⎜─⎟⎟\n\ + x─→0⁺⎝ y─→0⁺⎝2⎠⎠\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Limit(sin(x), x, 0, dir='+-') + ascii_str = \ +"""\ +lim sin(x)\n\ +x->0 \ +""" + ucode_str = \ +"""\ +lim sin(x)\n\ +x─→0 \ +""" + + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + +def test_pretty_ComplexRootOf(): + expr = rootof(x**5 + 11*x - 2, 0) + ascii_str = \ +"""\ + / 5 \\\n\ +CRootOf\\x + 11*x - 2, 0/\ +""" + ucode_str = \ +"""\ + ⎛ 5 ⎞\n\ +CRootOf⎝x + 11⋅x - 2, 0⎠\ +""" + + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + +def test_pretty_RootSum(): + expr = RootSum(x**5 + 11*x - 2, auto=False) + ascii_str = \ +"""\ + / 5 \\\n\ +RootSum\\x + 11*x - 2/\ +""" + ucode_str = \ +"""\ + ⎛ 5 ⎞\n\ +RootSum⎝x + 11⋅x - 2⎠\ +""" + + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = RootSum(x**5 + 11*x - 2, Lambda(z, exp(z))) + ascii_str = \ +"""\ + / 5 z\\\n\ +RootSum\\x + 11*x - 2, z -> e /\ +""" + ucode_str = \ +"""\ + ⎛ 5 z⎞\n\ +RootSum⎝x + 11⋅x - 2, z ↦ ℯ ⎠\ +""" + + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + +def test_GroebnerBasis(): + expr = groebner([], x, y) + + ascii_str = \ +"""\ +GroebnerBasis([], x, y, domain=ZZ, order=lex)\ +""" + ucode_str = \ +"""\ +GroebnerBasis([], x, y, domain=ℤ, order=lex)\ +""" + + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + F = [x**2 - 3*y - x + 1, y**2 - 2*x + y - 1] + expr = groebner(F, x, y, order='grlex') + + ascii_str = \ +"""\ + /[ 2 2 ] \\\n\ +GroebnerBasis\\[x - x - 3*y + 1, y - 2*x + y - 1], x, y, domain=ZZ, order=grlex/\ +""" + ucode_str = \ +"""\ + ⎛⎡ 2 2 ⎤ ⎞\n\ +GroebnerBasis⎝⎣x - x - 3⋅y + 1, y - 2⋅x + y - 1⎦, x, y, domain=ℤ, order=grlex⎠\ +""" + + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = expr.fglm('lex') + + ascii_str = \ +"""\ + /[ 2 4 3 2 ] \\\n\ +GroebnerBasis\\[2*x - y - y + 1, y + 2*y - 3*y - 16*y + 7], x, y, domain=ZZ, order=lex/\ +""" + ucode_str = \ +"""\ + ⎛⎡ 2 4 3 2 ⎤ ⎞\n\ +GroebnerBasis⎝⎣2⋅x - y - y + 1, y + 2⋅y - 3⋅y - 16⋅y + 7⎦, x, y, domain=ℤ, order=lex⎠\ +""" + + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + +def test_pretty_UniversalSet(): + assert pretty(S.UniversalSet) == "UniversalSet" + assert upretty(S.UniversalSet) == '𝕌' + + +def test_pretty_Boolean(): + expr = Not(x, evaluate=False) + + assert pretty(expr) == "Not(x)" + assert upretty(expr) == "¬x" + + expr = And(x, y) + + assert pretty(expr) == "And(x, y)" + assert upretty(expr) == "x ∧ y" + + expr = Or(x, y) + + assert pretty(expr) == "Or(x, y)" + assert upretty(expr) == "x ∨ y" + + syms = symbols('a:f') + expr = And(*syms) + + assert pretty(expr) == "And(a, b, c, d, e, f)" + assert upretty(expr) == "a ∧ b ∧ c ∧ d ∧ e ∧ f" + + expr = Or(*syms) + + assert pretty(expr) == "Or(a, b, c, d, e, f)" + assert upretty(expr) == "a ∨ b ∨ c ∨ d ∨ e ∨ f" + + expr = Xor(x, y, evaluate=False) + + assert pretty(expr) == "Xor(x, y)" + assert upretty(expr) == "x ⊻ y" + + expr = Nand(x, y, evaluate=False) + + assert pretty(expr) == "Nand(x, y)" + assert upretty(expr) == "x ⊼ y" + + expr = Nor(x, y, evaluate=False) + + assert pretty(expr) == "Nor(x, y)" + assert upretty(expr) == "x ⊽ y" + + expr = Implies(x, y, evaluate=False) + + assert pretty(expr) == "Implies(x, y)" + assert upretty(expr) == "x → y" + + # don't sort args + expr = Implies(y, x, evaluate=False) + + assert pretty(expr) == "Implies(y, x)" + assert upretty(expr) == "y → x" + + expr = Equivalent(x, y, evaluate=False) + + assert pretty(expr) == "Equivalent(x, y)" + assert upretty(expr) == "x ⇔ y" + + expr = Equivalent(y, x, evaluate=False) + + assert pretty(expr) == "Equivalent(x, y)" + assert upretty(expr) == "x ⇔ y" + + +def test_pretty_Domain(): + expr = FF(23) + + assert pretty(expr) == "GF(23)" + assert upretty(expr) == "ℤ₂₃" + + expr = ZZ + + assert pretty(expr) == "ZZ" + assert upretty(expr) == "ℤ" + + expr = QQ + + assert pretty(expr) == "QQ" + assert upretty(expr) == "ℚ" + + expr = RR + + assert pretty(expr) == "RR" + assert upretty(expr) == "ℝ" + + expr = QQ[x] + + assert pretty(expr) == "QQ[x]" + assert upretty(expr) == "ℚ[x]" + + expr = QQ[x, y] + + assert pretty(expr) == "QQ[x, y]" + assert upretty(expr) == "ℚ[x, y]" + + expr = ZZ.frac_field(x) + + assert pretty(expr) == "ZZ(x)" + assert upretty(expr) == "ℤ(x)" + + expr = ZZ.frac_field(x, y) + + assert pretty(expr) == "ZZ(x, y)" + assert upretty(expr) == "ℤ(x, y)" + + expr = QQ.poly_ring(x, y, order=grlex) + + assert pretty(expr) == "QQ[x, y, order=grlex]" + assert upretty(expr) == "ℚ[x, y, order=grlex]" + + expr = QQ.poly_ring(x, y, order=ilex) + + assert pretty(expr) == "QQ[x, y, order=ilex]" + assert upretty(expr) == "ℚ[x, y, order=ilex]" + + +def test_pretty_prec(): + assert xpretty(S("0.3"), full_prec=True, wrap_line=False) == "0.300000000000000" + assert xpretty(S("0.3"), full_prec="auto", wrap_line=False) == "0.300000000000000" + assert xpretty(S("0.3"), full_prec=False, wrap_line=False) == "0.3" + assert xpretty(S("0.3")*x, full_prec=True, use_unicode=False, wrap_line=False) in [ + "0.300000000000000*x", + "x*0.300000000000000" + ] + assert xpretty(S("0.3")*x, full_prec="auto", use_unicode=False, wrap_line=False) in [ + "0.3*x", + "x*0.3" + ] + assert xpretty(S("0.3")*x, full_prec=False, use_unicode=False, wrap_line=False) in [ + "0.3*x", + "x*0.3" + ] + + +def test_pprint(): + import sys + from io import StringIO + fd = StringIO() + sso = sys.stdout + sys.stdout = fd + try: + pprint(pi, use_unicode=False, wrap_line=False) + finally: + sys.stdout = sso + assert fd.getvalue() == 'pi\n' + + +def test_pretty_class(): + """Test that the printer dispatcher correctly handles classes.""" + class C: + pass # C has no .__class__ and this was causing problems + + class D: + pass + + assert pretty( C ) == str( C ) + assert pretty( D ) == str( D ) + + +def test_pretty_no_wrap_line(): + huge_expr = 0 + for i in range(20): + huge_expr += i*sin(i + x) + assert xpretty(huge_expr ).find('\n') != -1 + assert xpretty(huge_expr, wrap_line=False).find('\n') == -1 + + +def test_settings(): + raises(TypeError, lambda: pretty(S(4), method="garbage")) + + +def test_pretty_sum(): + from sympy.abc import x, a, b, k, m, n + + expr = Sum(k**k, (k, 0, n)) + ascii_str = \ +"""\ + n \n\ +___ \n\ +\\ ` \n\ + \\ k\n\ + / k \n\ +/__, \n\ +k = 0 \ +""" + ucode_str = \ +"""\ + n \n\ + ___ \n\ + ╲ \n\ + ╲ k\n\ + ╱ k \n\ + ╱ \n\ + ‾‾‾ \n\ +k = 0 \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Sum(k**k, (k, oo, n)) + ascii_str = \ +"""\ + n \n\ + ___ \n\ + \\ ` \n\ + \\ k\n\ + / k \n\ + /__, \n\ +k = oo \ +""" + ucode_str = \ +"""\ + n \n\ + ___ \n\ + ╲ \n\ + ╲ k\n\ + ╱ k \n\ + ╱ \n\ + ‾‾‾ \n\ +k = ∞ \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Sum(k**(Integral(x**n, (x, -oo, oo))), (k, 0, n**n)) + ascii_str = \ +"""\ + n \n\ + n \n\ +______ \n\ +\\ ` \n\ + \\ oo \n\ + \\ / \n\ + \\ | \n\ + \\ | n \n\ + ) | x dx\n\ + / | \n\ + / / \n\ + / -oo \n\ + / k \n\ +/_____, \n\ + k = 0 \ +""" + ucode_str = \ +"""\ + n \n\ + n \n\ +______ \n\ +╲ \n\ + ╲ \n\ + ╲ ∞ \n\ + ╲ ⌠ \n\ + ╲ ⎮ n \n\ + ╱ ⎮ x dx\n\ + ╱ ⌡ \n\ + ╱ -∞ \n\ + ╱ k \n\ +╱ \n\ +‾‾‾‾‾‾ \n\ +k = 0 \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Sum(k**( + Integral(x**n, (x, -oo, oo))), (k, 0, Integral(x**x, (x, -oo, oo)))) + ascii_str = \ +"""\ + oo \n\ + / \n\ + | \n\ + | x \n\ + | x dx \n\ + | \n\ +/ \n\ +-oo \n\ + ______ \n\ + \\ ` \n\ + \\ oo \n\ + \\ / \n\ + \\ | \n\ + \\ | n \n\ + ) | x dx\n\ + / | \n\ + / / \n\ + / -oo \n\ + / k \n\ + /_____, \n\ + k = 0 \ +""" + ucode_str = \ +"""\ +∞ \n\ +⌠ \n\ +⎮ x \n\ +⎮ x dx \n\ +⌡ \n\ +-∞ \n\ + ______ \n\ + ╲ \n\ + ╲ \n\ + ╲ ∞ \n\ + ╲ ⌠ \n\ + ╲ ⎮ n \n\ + ╱ ⎮ x dx\n\ + ╱ ⌡ \n\ + ╱ -∞ \n\ + ╱ k \n\ + ╱ \n\ + ‾‾‾‾‾‾ \n\ + k = 0 \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Sum(k**(Integral(x**n, (x, -oo, oo))), ( + k, x + n + x**2 + n**2 + (x/n) + (1/x), Integral(x**x, (x, -oo, oo)))) + ascii_str = \ +"""\ + oo \n\ + / \n\ + | \n\ + | x \n\ + | x dx \n\ + | \n\ + / \n\ + -oo \n\ + ______ \n\ + \\ ` \n\ + \\ oo \n\ + \\ / \n\ + \\ | \n\ + \\ | n \n\ + ) | x dx\n\ + / | \n\ + / / \n\ + / -oo \n\ + / k \n\ + /_____, \n\ + 2 2 1 x \n\ +k = n + n + x + x + - + - \n\ + x n \ +""" + ucode_str = \ +"""\ + ∞ \n\ + ⌠ \n\ + ⎮ x \n\ + ⎮ x dx \n\ + ⌡ \n\ + -∞ \n\ + ______ \n\ + ╲ \n\ + ╲ \n\ + ╲ ∞ \n\ + ╲ ⌠ \n\ + ╲ ⎮ n \n\ + ╱ ⎮ x dx\n\ + ╱ ⌡ \n\ + ╱ -∞ \n\ + ╱ k \n\ + ╱ \n\ + ‾‾‾‾‾‾ \n\ + 2 2 1 x \n\ +k = n + n + x + x + ─ + ─ \n\ + x n \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Sum(k**( + Integral(x**n, (x, -oo, oo))), (k, 0, x + n + x**2 + n**2 + (x/n) + (1/x))) + ascii_str = \ +"""\ + 2 2 1 x \n\ +n + n + x + x + - + - \n\ + x n \n\ + ______ \n\ + \\ ` \n\ + \\ oo \n\ + \\ / \n\ + \\ | \n\ + \\ | n \n\ + ) | x dx\n\ + / | \n\ + / / \n\ + / -oo \n\ + / k \n\ + /_____, \n\ + k = 0 \ +""" + ucode_str = \ +"""\ + 2 2 1 x \n\ +n + n + x + x + ─ + ─ \n\ + x n \n\ + ______ \n\ + ╲ \n\ + ╲ \n\ + ╲ ∞ \n\ + ╲ ⌠ \n\ + ╲ ⎮ n \n\ + ╱ ⎮ x dx\n\ + ╱ ⌡ \n\ + ╱ -∞ \n\ + ╱ k \n\ + ╱ \n\ + ‾‾‾‾‾‾ \n\ + k = 0 \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Sum(x, (x, 0, oo)) + ascii_str = \ +"""\ + oo \n\ + __ \n\ + \\ ` \n\ + ) x\n\ + /_, \n\ +x = 0 \ +""" + ucode_str = \ +"""\ + ∞ \n\ + ___ \n\ + ╲ \n\ + ╲ \n\ + ╱ x\n\ + ╱ \n\ + ‾‾‾ \n\ +x = 0 \ +""" + + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Sum(x**2, (x, 0, oo)) + ascii_str = \ +"""\ + oo \n\ +___ \n\ +\\ ` \n\ + \\ 2\n\ + / x \n\ +/__, \n\ +x = 0 \ +""" + ucode_str = \ +"""\ + ∞ \n\ + ___ \n\ + ╲ \n\ + ╲ 2\n\ + ╱ x \n\ + ╱ \n\ + ‾‾‾ \n\ +x = 0 \ +""" + + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Sum(x/2, (x, 0, oo)) + ascii_str = \ +"""\ + oo \n\ +___ \n\ +\\ ` \n\ + \\ x\n\ + ) -\n\ + / 2\n\ +/__, \n\ +x = 0 \ +""" + ucode_str = \ +"""\ + ∞ \n\ +____ \n\ +╲ \n\ + ╲ \n\ + ╲ x\n\ + ╱ ─\n\ + ╱ 2\n\ +╱ \n\ +‾‾‾‾ \n\ +x = 0 \ +""" + + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Sum(x**3/2, (x, 0, oo)) + ascii_str = \ +"""\ + oo \n\ +____ \n\ +\\ ` \n\ + \\ 3\n\ + \\ x \n\ + / --\n\ + / 2 \n\ +/___, \n\ +x = 0 \ +""" + ucode_str = \ +"""\ + ∞ \n\ +____ \n\ +╲ \n\ + ╲ 3\n\ + ╲ x \n\ + ╱ ──\n\ + ╱ 2 \n\ +╱ \n\ +‾‾‾‾ \n\ +x = 0 \ +""" + + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Sum((x**3*y**(x/2))**n, (x, 0, oo)) + ascii_str = \ +"""\ + oo \n\ +____ \n\ +\\ ` \n\ + \\ n\n\ + \\ / x\\ \n\ + ) | -| \n\ + / | 3 2| \n\ + / \\x *y / \n\ +/___, \n\ +x = 0 \ +""" + ucode_str = \ +"""\ + ∞ \n\ +_____ \n\ +╲ \n\ + ╲ \n\ + ╲ n\n\ + ╲ ⎛ x⎞ \n\ + ╱ ⎜ ─⎟ \n\ + ╱ ⎜ 3 2⎟ \n\ + ╱ ⎝x ⋅y ⎠ \n\ +╱ \n\ +‾‾‾‾‾ \n\ +x = 0 \ +""" + + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Sum(1/x**2, (x, 0, oo)) + ascii_str = \ +"""\ + oo \n\ +____ \n\ +\\ ` \n\ + \\ 1 \n\ + \\ --\n\ + / 2\n\ + / x \n\ +/___, \n\ +x = 0 \ +""" + ucode_str = \ +"""\ + ∞ \n\ +____ \n\ +╲ \n\ + ╲ 1 \n\ + ╲ ──\n\ + ╱ 2\n\ + ╱ x \n\ +╱ \n\ +‾‾‾‾ \n\ +x = 0 \ +""" + + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Sum(1/y**(a/b), (x, 0, oo)) + ascii_str = \ +"""\ + oo \n\ +____ \n\ +\\ ` \n\ + \\ -a \n\ + \\ ---\n\ + / b \n\ + / y \n\ +/___, \n\ +x = 0 \ +""" + ucode_str = \ +"""\ + ∞ \n\ +____ \n\ +╲ \n\ + ╲ -a \n\ + ╲ ───\n\ + ╱ b \n\ + ╱ y \n\ +╱ \n\ +‾‾‾‾ \n\ +x = 0 \ +""" + + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Sum(1/y**(a/b), (x, 0, oo), (y, 1, 2)) + ascii_str = \ +"""\ + 2 oo \n\ +____ ____ \n\ +\\ ` \\ ` \n\ + \\ \\ -a\n\ + \\ \\ --\n\ + / / b \n\ + / / y \n\ +/___, /___, \n\ +y = 1 x = 0 \ +""" + ucode_str = \ +"""\ + 2 ∞ \n\ +____ ____ \n\ +╲ ╲ \n\ + ╲ ╲ -a\n\ + ╲ ╲ ──\n\ + ╱ ╱ b \n\ + ╱ ╱ y \n\ +╱ ╱ \n\ +‾‾‾‾ ‾‾‾‾ \n\ +y = 1 x = 0 \ +""" + expr = Sum(1/(1 + 1/( + 1 + 1/k)) + 1, (k, 111, 1 + 1/n), (k, 1/(1 + m), oo)) + 1/(1 + 1/k) + ascii_str = \ +"""\ + 1 \n\ + 1 + - \n\ + oo n \n\ + _____ _____ \n\ + \\ ` \\ ` \n\ + \\ \\ / 1 \\ \n\ + \\ \\ |1 + ---------| \n\ + \\ \\ | 1 | 1 \n\ + ) ) | 1 + -----| + -----\n\ + / / | 1| 1\n\ + / / | 1 + -| 1 + -\n\ + / / \\ k/ k\n\ + /____, /____, \n\ + 1 k = 111 \n\ +k = ----- \n\ + m + 1 \ +""" + ucode_str = \ +"""\ + 1 \n\ + 1 + ─ \n\ + ∞ n \n\ + ______ ______ \n\ + ╲ ╲ \n\ + ╲ ╲ \n\ + ╲ ╲ ⎛ 1 ⎞ \n\ + ╲ ╲ ⎜1 + ─────────⎟ \n\ + ╲ ╲ ⎜ 1 ⎟ 1 \n\ + ╱ ╱ ⎜ 1 + ─────⎟ + ─────\n\ + ╱ ╱ ⎜ 1⎟ 1\n\ + ╱ ╱ ⎜ 1 + ─⎟ 1 + ─\n\ + ╱ ╱ ⎝ k⎠ k\n\ + ╱ ╱ \n\ + ‾‾‾‾‾‾ ‾‾‾‾‾‾ \n\ + 1 k = 111 \n\ +k = ───── \n\ + m + 1 \ +""" + + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + +def test_units(): + expr = joule + ascii_str1 = \ +"""\ + 2\n\ +kilogram*meter \n\ +---------------\n\ + 2 \n\ + second \ +""" + unicode_str1 = \ +"""\ + 2\n\ +kilogram⋅meter \n\ +───────────────\n\ + 2 \n\ + second \ +""" + + ascii_str2 = \ +"""\ + 2\n\ +3*x*y*kilogram*meter \n\ +---------------------\n\ + 2 \n\ + second \ +""" + unicode_str2 = \ +"""\ + 2\n\ +3⋅x⋅y⋅kilogram⋅meter \n\ +─────────────────────\n\ + 2 \n\ + second \ +""" + + from sympy.physics.units import kg, m, s + assert upretty(expr) == "joule" + assert pretty(expr) == "joule" + assert upretty(expr.convert_to(kg*m**2/s**2)) == unicode_str1 + assert pretty(expr.convert_to(kg*m**2/s**2)) == ascii_str1 + assert upretty(3*kg*x*m**2*y/s**2) == unicode_str2 + assert pretty(3*kg*x*m**2*y/s**2) == ascii_str2 + + +def test_pretty_Subs(): + f = Function('f') + expr = Subs(f(x), x, ph**2) + ascii_str = \ +"""\ +(f(x))| 2\n\ + |x=phi \ +""" + unicode_str = \ +"""\ +(f(x))│ 2\n\ + │x=φ \ +""" + + assert pretty(expr) == ascii_str + assert upretty(expr) == unicode_str + + expr = Subs(f(x).diff(x), x, 0) + ascii_str = \ +"""\ +/d \\| \n\ +|--(f(x))|| \n\ +\\dx /|x=0\ +""" + unicode_str = \ +"""\ +⎛d ⎞│ \n\ +⎜──(f(x))⎟│ \n\ +⎝dx ⎠│x=0\ +""" + + assert pretty(expr) == ascii_str + assert upretty(expr) == unicode_str + + expr = Subs(f(x).diff(x)/y, (x, y), (0, Rational(1, 2))) + ascii_str = \ +"""\ +/d \\| \n\ +|--(f(x))|| \n\ +|dx || \n\ +|--------|| \n\ +\\ y /|x=0, y=1/2\ +""" + unicode_str = \ +"""\ +⎛d ⎞│ \n\ +⎜──(f(x))⎟│ \n\ +⎜dx ⎟│ \n\ +⎜────────⎟│ \n\ +⎝ y ⎠│x=0, y=1/2\ +""" + + assert pretty(expr) == ascii_str + assert upretty(expr) == unicode_str + + +def test_gammas(): + assert upretty(lowergamma(x, y)) == "γ(x, y)" + assert upretty(uppergamma(x, y)) == "Γ(x, y)" + assert xpretty(gamma(x), use_unicode=True) == 'Γ(x)' + assert xpretty(gamma, use_unicode=True) == 'Γ' + assert xpretty(symbols('gamma', cls=Function)(x), use_unicode=True) == 'γ(x)' + assert xpretty(symbols('gamma', cls=Function), use_unicode=True) == 'γ' + + +def test_beta(): + assert xpretty(beta(x,y), use_unicode=True) == 'Β(x, y)' + assert xpretty(beta(x,y), use_unicode=False) == 'B(x, y)' + assert xpretty(beta, use_unicode=True) == 'Β' + assert xpretty(beta, use_unicode=False) == 'B' + mybeta = Function('beta') + assert xpretty(mybeta(x), use_unicode=True) == 'β(x)' + assert xpretty(mybeta(x, y, z), use_unicode=False) == 'beta(x, y, z)' + assert xpretty(mybeta, use_unicode=True) == 'β' + + +# test that notation passes to subclasses of the same name only +def test_function_subclass_different_name(): + class mygamma(gamma): + pass + assert xpretty(mygamma, use_unicode=True) == r"mygamma" + assert xpretty(mygamma(x), use_unicode=True) == r"mygamma(x)" + + +def test_SingularityFunction(): + assert xpretty(SingularityFunction(x, 0, n), use_unicode=True) == ( +"""\ + n\n\ + \ +""") + assert xpretty(SingularityFunction(x, 1, n), use_unicode=True) == ( +"""\ + n\n\ + \ +""") + assert xpretty(SingularityFunction(x, -1, n), use_unicode=True) == ( +"""\ + n\n\ + \ +""") + assert xpretty(SingularityFunction(x, a, n), use_unicode=True) == ( +"""\ + n\n\ +<-a + x> \ +""") + assert xpretty(SingularityFunction(x, y, n), use_unicode=True) == ( +"""\ + n\n\ + \ +""") + assert xpretty(SingularityFunction(x, 0, n), use_unicode=False) == ( +"""\ + n\n\ + \ +""") + assert xpretty(SingularityFunction(x, 1, n), use_unicode=False) == ( +"""\ + n\n\ + \ +""") + assert xpretty(SingularityFunction(x, -1, n), use_unicode=False) == ( +"""\ + n\n\ + \ +""") + assert xpretty(SingularityFunction(x, a, n), use_unicode=False) == ( +"""\ + n\n\ +<-a + x> \ +""") + assert xpretty(SingularityFunction(x, y, n), use_unicode=False) == ( +"""\ + n\n\ + \ +""") + + +def test_deltas(): + assert xpretty(DiracDelta(x), use_unicode=True) == 'δ(x)' + assert xpretty(DiracDelta(x, 1), use_unicode=True) == \ +"""\ + (1) \n\ +δ (x)\ +""" + assert xpretty(x*DiracDelta(x, 1), use_unicode=True) == \ +"""\ + (1) \n\ +x⋅δ (x)\ +""" + + +def test_hyper(): + expr = hyper((), (), z) + ucode_str = \ +"""\ + ┌─ ⎛ │ ⎞\n\ + ├─ ⎜ │ z⎟\n\ +0╵ 0 ⎝ │ ⎠\ +""" + ascii_str = \ +"""\ + _ \n\ + |_ / | \\\n\ + | | | z|\n\ +0 0 \\ | /\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = hyper((), (1,), x) + ucode_str = \ +"""\ + ┌─ ⎛ │ ⎞\n\ + ├─ ⎜ │ x⎟\n\ +0╵ 1 ⎝1 │ ⎠\ +""" + ascii_str = \ +"""\ + _ \n\ + |_ / | \\\n\ + | | | x|\n\ +0 1 \\1 | /\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = hyper([2], [1], x) + ucode_str = \ +"""\ + ┌─ ⎛2 │ ⎞\n\ + ├─ ⎜ │ x⎟\n\ +1╵ 1 ⎝1 │ ⎠\ +""" + ascii_str = \ +"""\ + _ \n\ + |_ /2 | \\\n\ + | | | x|\n\ +1 1 \\1 | /\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = hyper((pi/3, -2*k), (3, 4, 5, -3), x) + ucode_str = \ +"""\ + ⎛ π │ ⎞\n\ + ┌─ ⎜ ─, -2⋅k │ ⎟\n\ + ├─ ⎜ 3 │ x⎟\n\ +2╵ 4 ⎜ │ ⎟\n\ + ⎝-3, 3, 4, 5 │ ⎠\ +""" + ascii_str = \ +"""\ + \n\ + _ / pi | \\\n\ + |_ | --, -2*k | |\n\ + | | 3 | x|\n\ +2 4 | | |\n\ + \\-3, 3, 4, 5 | /\ +""" + + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = hyper((pi, S('2/3'), -2*k), (3, 4, 5, -3), x**2) + ucode_str = \ +"""\ + ┌─ ⎛2/3, π, -2⋅k │ 2⎞\n\ + ├─ ⎜ │ x ⎟\n\ +3╵ 4 ⎝-3, 3, 4, 5 │ ⎠\ +""" + ascii_str = \ +"""\ + _ \n\ + |_ /2/3, pi, -2*k | 2\\ + | | | x | +3 4 \\ -3, 3, 4, 5 | /""" + + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = hyper([1, 2], [3, 4], 1/(1/(1/(1/x + 1) + 1) + 1)) + ucode_str = \ +"""\ + ⎛ │ 1 ⎞\n\ + ⎜ │ ─────────────⎟\n\ + ⎜ │ 1 ⎟\n\ + ┌─ ⎜1, 2 │ 1 + ─────────⎟\n\ + ├─ ⎜ │ 1 ⎟\n\ +2╵ 2 ⎜3, 4 │ 1 + ─────⎟\n\ + ⎜ │ 1⎟\n\ + ⎜ │ 1 + ─⎟\n\ + ⎝ │ x⎠\ +""" + + ascii_str = \ +"""\ + \n\ + / | 1 \\\n\ + | | -------------|\n\ + _ | | 1 |\n\ + |_ |1, 2 | 1 + ---------|\n\ + | | | 1 |\n\ +2 2 |3, 4 | 1 + -----|\n\ + | | 1|\n\ + | | 1 + -|\n\ + \\ | x/\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + +def test_meijerg(): + expr = meijerg([pi, pi, x], [1], [0, 1], [1, 2, 3], z) + ucode_str = \ +"""\ +╭─╮2, 3 ⎛π, π, x 1 │ ⎞\n\ +│╶┐ ⎜ │ z⎟\n\ +╰─╯4, 5 ⎝ 0, 1 1, 2, 3 │ ⎠\ +""" + ascii_str = \ +"""\ + __2, 3 /pi, pi, x 1 | \\\n\ +/__ | | z|\n\ +\\_|4, 5 \\ 0, 1 1, 2, 3 | /\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = meijerg([1, pi/7], [2, pi, 5], [], [], z**2) + ucode_str = \ +"""\ + ⎛ π │ ⎞\n\ +╭─╮0, 2 ⎜1, ─ 2, 5, π │ 2⎟\n\ +│╶┐ ⎜ 7 │ z ⎟\n\ +╰─╯5, 0 ⎜ │ ⎟\n\ + ⎝ │ ⎠\ +""" + ascii_str = \ +"""\ + / pi | \\\n\ + __0, 2 |1, -- 2, 5, pi | 2|\n\ +/__ | 7 | z |\n\ +\\_|5, 0 | | |\n\ + \\ | /\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + ucode_str = \ +"""\ +╭─╮ 1, 10 ⎛1, 1, 1, 1, 1, 1, 1, 1, 1, 1 1 │ ⎞\n\ +│╶┐ ⎜ │ z⎟\n\ +╰─╯11, 2 ⎝ 1 1 │ ⎠\ +""" + ascii_str = \ +"""\ + __ 1, 10 /1, 1, 1, 1, 1, 1, 1, 1, 1, 1 1 | \\\n\ +/__ | | z|\n\ +\\_|11, 2 \\ 1 1 | /\ +""" + + expr = meijerg([1]*10, [1], [1], [1], z) + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = meijerg([1, 2, ], [4, 3], [3], [4, 5], 1/(1/(1/(1/x + 1) + 1) + 1)) + + ucode_str = \ +"""\ + ⎛ │ 1 ⎞\n\ + ⎜ │ ─────────────⎟\n\ + ⎜ │ 1 ⎟\n\ +╭─╮1, 2 ⎜1, 2 3, 4 │ 1 + ─────────⎟\n\ +│╶┐ ⎜ │ 1 ⎟\n\ +╰─╯4, 3 ⎜ 3 4, 5 │ 1 + ─────⎟\n\ + ⎜ │ 1⎟\n\ + ⎜ │ 1 + ─⎟\n\ + ⎝ │ x⎠\ +""" + + ascii_str = \ +"""\ + / | 1 \\\n\ + | | -------------|\n\ + | | 1 |\n\ + __1, 2 |1, 2 3, 4 | 1 + ---------|\n\ +/__ | | 1 |\n\ +\\_|4, 3 | 3 4, 5 | 1 + -----|\n\ + | | 1|\n\ + | | 1 + -|\n\ + \\ | x/\ +""" + + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = Integral(expr, x) + + ucode_str = \ +"""\ +⌠ \n\ +⎮ ⎛ │ 1 ⎞ \n\ +⎮ ⎜ │ ─────────────⎟ \n\ +⎮ ⎜ │ 1 ⎟ \n\ +⎮ ╭─╮1, 2 ⎜1, 2 3, 4 │ 1 + ─────────⎟ \n\ +⎮ │╶┐ ⎜ │ 1 ⎟ dx\n\ +⎮ ╰─╯4, 3 ⎜ 3 4, 5 │ 1 + ─────⎟ \n\ +⎮ ⎜ │ 1⎟ \n\ +⎮ ⎜ │ 1 + ─⎟ \n\ +⎮ ⎝ │ x⎠ \n\ +⌡ \ +""" + + ascii_str = \ +"""\ + / \n\ + | \n\ + | / | 1 \\ \n\ + | | | -------------| \n\ + | | | 1 | \n\ + | __1, 2 |1, 2 3, 4 | 1 + ---------| \n\ + | /__ | | 1 | dx\n\ + | \\_|4, 3 | 3 4, 5 | 1 + -----| \n\ + | | | 1| \n\ + | | | 1 + -| \n\ + | \\ | x/ \n\ + | \n\ +/ \ +""" + + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + +def test_noncommutative(): + A, B, C = symbols('A,B,C', commutative=False) + + expr = A*B*C**-1 + ascii_str = \ +"""\ + -1\n\ +A*B*C \ +""" + ucode_str = \ +"""\ + -1\n\ +A⋅B⋅C \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = C**-1*A*B + ascii_str = \ +"""\ + -1 \n\ +C *A*B\ +""" + ucode_str = \ +"""\ + -1 \n\ +C ⋅A⋅B\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = A*C**-1*B + ascii_str = \ +"""\ + -1 \n\ +A*C *B\ +""" + ucode_str = \ +"""\ + -1 \n\ +A⋅C ⋅B\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = A*C**-1*B/x + ascii_str = \ +"""\ + -1 \n\ +A*C *B\n\ +-------\n\ + x \ +""" + ucode_str = \ +"""\ + -1 \n\ +A⋅C ⋅B\n\ +───────\n\ + x \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + +def test_pretty_special_functions(): + x, y = symbols("x y") + + # atan2 + expr = atan2(y/sqrt(200), sqrt(x)) + ascii_str = \ +"""\ + / ___ \\\n\ + |\\/ 2 *y ___|\n\ +atan2|-------, \\/ x |\n\ + \\ 20 /\ +""" + ucode_str = \ +"""\ + ⎛√2⋅y ⎞\n\ +atan2⎜────, √x⎟\n\ + ⎝ 20 ⎠\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + +def test_pretty_geometry(): + e = Segment((0, 1), (0, 2)) + assert pretty(e) == 'Segment2D(Point2D(0, 1), Point2D(0, 2))' + e = Ray((1, 1), angle=4.02*pi) + assert pretty(e) == 'Ray2D(Point2D(1, 1), Point2D(2, tan(pi/50) + 1))' + + +def test_expint(): + expr = Ei(x) + string = 'Ei(x)' + assert pretty(expr) == string + assert upretty(expr) == string + + expr = expint(1, z) + ucode_str = "E₁(z)" + ascii_str = "expint(1, z)" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + assert pretty(Shi(x)) == 'Shi(x)' + assert pretty(Si(x)) == 'Si(x)' + assert pretty(Ci(x)) == 'Ci(x)' + assert pretty(Chi(x)) == 'Chi(x)' + assert upretty(Shi(x)) == 'Shi(x)' + assert upretty(Si(x)) == 'Si(x)' + assert upretty(Ci(x)) == 'Ci(x)' + assert upretty(Chi(x)) == 'Chi(x)' + + +def test_elliptic_functions(): + ascii_str = \ +"""\ + / 1 \\\n\ +K|-----|\n\ + \\z + 1/\ +""" + ucode_str = \ +"""\ + ⎛ 1 ⎞\n\ +K⎜─────⎟\n\ + ⎝z + 1⎠\ +""" + expr = elliptic_k(1/(z + 1)) + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + ascii_str = \ +"""\ + / | 1 \\\n\ +F|1|-----|\n\ + \\ |z + 1/\ +""" + ucode_str = \ +"""\ + ⎛ │ 1 ⎞\n\ +F⎜1│─────⎟\n\ + ⎝ │z + 1⎠\ +""" + expr = elliptic_f(1, 1/(1 + z)) + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + ascii_str = \ +"""\ + / 1 \\\n\ +E|-----|\n\ + \\z + 1/\ +""" + ucode_str = \ +"""\ + ⎛ 1 ⎞\n\ +E⎜─────⎟\n\ + ⎝z + 1⎠\ +""" + expr = elliptic_e(1/(z + 1)) + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + ascii_str = \ +"""\ + / | 1 \\\n\ +E|1|-----|\n\ + \\ |z + 1/\ +""" + ucode_str = \ +"""\ + ⎛ │ 1 ⎞\n\ +E⎜1│─────⎟\n\ + ⎝ │z + 1⎠\ +""" + expr = elliptic_e(1, 1/(1 + z)) + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + ascii_str = \ +"""\ + / |4\\\n\ +Pi|3|-|\n\ + \\ |x/\ +""" + ucode_str = \ +"""\ + ⎛ │4⎞\n\ +Π⎜3│─⎟\n\ + ⎝ │x⎠\ +""" + expr = elliptic_pi(3, 4/x) + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + ascii_str = \ +"""\ + / 4| \\\n\ +Pi|3; -|6|\n\ + \\ x| /\ +""" + ucode_str = \ +"""\ + ⎛ 4│ ⎞\n\ +Π⎜3; ─│6⎟\n\ + ⎝ x│ ⎠\ +""" + expr = elliptic_pi(3, 4/x, 6) + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + +def test_RandomDomain(): + from sympy.stats import Normal, Die, Exponential, pspace, where + X = Normal('x1', 0, 1) + assert upretty(where(X > 0)) == "Domain: 0 < x₁ ∧ x₁ < ∞" + + D = Die('d1', 6) + assert upretty(where(D > 4)) == 'Domain: d₁ = 5 ∨ d₁ = 6' + + A = Exponential('a', 1) + B = Exponential('b', 1) + assert upretty(pspace(Tuple(A, B)).domain) == \ + 'Domain: 0 ≤ a ∧ 0 ≤ b ∧ a < ∞ ∧ b < ∞' + + +def test_PrettyPoly(): + F = QQ.frac_field(x, y) + R = QQ.poly_ring(x, y) + + expr = F.convert(x/(x + y)) + assert pretty(expr) == "x/(x + y)" + assert upretty(expr) == "x/(x + y)" + + expr = R.convert(x + y) + assert pretty(expr) == "x + y" + assert upretty(expr) == "x + y" + + +def test_issue_6285(): + assert pretty(Pow(2, -5, evaluate=False)) == '1 \n--\n 5\n2 ' + assert pretty(Pow(x, (1/pi))) == \ + ' 1 \n'\ + ' --\n'\ + ' pi\n'\ + 'x ' + + +def test_issue_6359(): + assert pretty(Integral(x**2, x)**2) == \ +"""\ + 2 +/ / \\ \n\ +| | | \n\ +| | 2 | \n\ +| | x dx| \n\ +| | | \n\ +\\/ / \ +""" + assert upretty(Integral(x**2, x)**2) == \ +"""\ + 2 +⎛⌠ ⎞ \n\ +⎜⎮ 2 ⎟ \n\ +⎜⎮ x dx⎟ \n\ +⎝⌡ ⎠ \ +""" + + assert pretty(Sum(x**2, (x, 0, 1))**2) == \ +"""\ + 2\n\ +/ 1 \\ \n\ +|___ | \n\ +|\\ ` | \n\ +| \\ 2| \n\ +| / x | \n\ +|/__, | \n\ +\\x = 0 / \ +""" + assert upretty(Sum(x**2, (x, 0, 1))**2) == \ +"""\ + 2 +⎛ 1 ⎞ \n\ +⎜ ___ ⎟ \n\ +⎜ ╲ ⎟ \n\ +⎜ ╲ 2⎟ \n\ +⎜ ╱ x ⎟ \n\ +⎜ ╱ ⎟ \n\ +⎜ ‾‾‾ ⎟ \n\ +⎝x = 0 ⎠ \ +""" + + assert pretty(Product(x**2, (x, 1, 2))**2) == \ +"""\ + 2 +/ 2 \\ \n\ +|______ | \n\ +| | | 2| \n\ +| | | x | \n\ +| | | | \n\ +\\x = 1 / \ +""" + assert upretty(Product(x**2, (x, 1, 2))**2) == \ +"""\ + 2 +⎛ 2 ⎞ \n\ +⎜─┬──┬─ ⎟ \n\ +⎜ │ │ 2⎟ \n\ +⎜ │ │ x ⎟ \n\ +⎜ │ │ ⎟ \n\ +⎝x = 1 ⎠ \ +""" + + f = Function('f') + assert pretty(Derivative(f(x), x)**2) == \ +"""\ + 2 +/d \\ \n\ +|--(f(x))| \n\ +\\dx / \ +""" + assert upretty(Derivative(f(x), x)**2) == \ +"""\ + 2 +⎛d ⎞ \n\ +⎜──(f(x))⎟ \n\ +⎝dx ⎠ \ +""" + + +def test_issue_6739(): + ascii_str = \ +"""\ + 1 \n\ +-----\n\ + ___\n\ +\\/ x \ +""" + ucode_str = \ +"""\ +1 \n\ +──\n\ +√x\ +""" + assert pretty(1/sqrt(x)) == ascii_str + assert upretty(1/sqrt(x)) == ucode_str + + +def test_complicated_symbol_unchanged(): + for symb_name in ["dexpr2_d1tau", "dexpr2^d1tau"]: + assert pretty(Symbol(symb_name)) == symb_name + + +def test_categories(): + from sympy.categories import (Object, IdentityMorphism, + NamedMorphism, Category, Diagram, DiagramGrid) + + A1 = Object("A1") + A2 = Object("A2") + A3 = Object("A3") + + f1 = NamedMorphism(A1, A2, "f1") + f2 = NamedMorphism(A2, A3, "f2") + id_A1 = IdentityMorphism(A1) + + K1 = Category("K1") + + assert pretty(A1) == "A1" + assert upretty(A1) == "A₁" + + assert pretty(f1) == "f1:A1-->A2" + assert upretty(f1) == "f₁:A₁——▶A₂" + assert pretty(id_A1) == "id:A1-->A1" + assert upretty(id_A1) == "id:A₁——▶A₁" + + assert pretty(f2*f1) == "f2*f1:A1-->A3" + assert upretty(f2*f1) == "f₂∘f₁:A₁——▶A₃" + + assert pretty(K1) == "K1" + assert upretty(K1) == "K₁" + + # Test how diagrams are printed. + d = Diagram() + assert pretty(d) == "EmptySet" + assert upretty(d) == "∅" + + d = Diagram({f1: "unique", f2: S.EmptySet}) + assert pretty(d) == "{f2*f1:A1-->A3: EmptySet, id:A1-->A1: " \ + "EmptySet, id:A2-->A2: EmptySet, id:A3-->A3: " \ + "EmptySet, f1:A1-->A2: {unique}, f2:A2-->A3: EmptySet}" + + assert upretty(d) == "{f₂∘f₁:A₁——▶A₃: ∅, id:A₁——▶A₁: ∅, " \ + "id:A₂——▶A₂: ∅, id:A₃——▶A₃: ∅, f₁:A₁——▶A₂: {unique}, f₂:A₂——▶A₃: ∅}" + + d = Diagram({f1: "unique", f2: S.EmptySet}, {f2 * f1: "unique"}) + assert pretty(d) == "{f2*f1:A1-->A3: EmptySet, id:A1-->A1: " \ + "EmptySet, id:A2-->A2: EmptySet, id:A3-->A3: " \ + "EmptySet, f1:A1-->A2: {unique}, f2:A2-->A3: EmptySet}" \ + " ==> {f2*f1:A1-->A3: {unique}}" + assert upretty(d) == "{f₂∘f₁:A₁——▶A₃: ∅, id:A₁——▶A₁: ∅, id:A₂——▶A₂: " \ + "∅, id:A₃——▶A₃: ∅, f₁:A₁——▶A₂: {unique}, f₂:A₂——▶A₃: ∅}" \ + " ══▶ {f₂∘f₁:A₁——▶A₃: {unique}}" + + grid = DiagramGrid(d) + assert pretty(grid) == "A1 A2\n \nA3 " + assert upretty(grid) == "A₁ A₂\n \nA₃ " + + +def test_PrettyModules(): + R = QQ.old_poly_ring(x, y) + F = R.free_module(2) + M = F.submodule([x, y], [1, x**2]) + + ucode_str = \ +"""\ + 2\n\ +ℚ[x, y] \ +""" + ascii_str = \ +"""\ + 2\n\ +QQ[x, y] \ +""" + + assert upretty(F) == ucode_str + assert pretty(F) == ascii_str + + ucode_str = \ +"""\ +╱ ⎡ 2⎤╲\n\ +╲[x, y], ⎣1, x ⎦╱\ +""" + ascii_str = \ +"""\ + 2 \n\ +<[x, y], [1, x ]>\ +""" + + assert upretty(M) == ucode_str + assert pretty(M) == ascii_str + + I = R.ideal(x**2, y) + + ucode_str = \ +"""\ +╱ 2 ╲\n\ +╲x , y╱\ +""" + + ascii_str = \ +"""\ + 2 \n\ +\ +""" + + assert upretty(I) == ucode_str + assert pretty(I) == ascii_str + + Q = F / M + + ucode_str = \ +"""\ + 2 \n\ + ℚ[x, y] \n\ +─────────────────\n\ +╱ ⎡ 2⎤╲\n\ +╲[x, y], ⎣1, x ⎦╱\ +""" + + ascii_str = \ +"""\ + 2 \n\ + QQ[x, y] \n\ +-----------------\n\ + 2 \n\ +<[x, y], [1, x ]>\ +""" + + assert upretty(Q) == ucode_str + assert pretty(Q) == ascii_str + + ucode_str = \ +"""\ +╱⎡ 3⎤ ╲\n\ +│⎢ x ⎥ ╱ ⎡ 2⎤╲ ╱ ⎡ 2⎤╲│\n\ +│⎢1, ──⎥ + ╲[x, y], ⎣1, x ⎦╱, [2, y] + ╲[x, y], ⎣1, x ⎦╱│\n\ +╲⎣ 2 ⎦ ╱\ +""" + + ascii_str = \ +"""\ + 3 \n\ + x 2 2 \n\ +<[1, --] + <[x, y], [1, x ]>, [2, y] + <[x, y], [1, x ]>>\n\ + 2 \ +""" + + +def test_QuotientRing(): + R = QQ.old_poly_ring(x)/[x**2 + 1] + + ucode_str = \ +"""\ + ℚ[x] \n\ +────────\n\ +╱ 2 ╲\n\ +╲x + 1╱\ +""" + + ascii_str = \ +"""\ + QQ[x] \n\ +--------\n\ + 2 \n\ +\ +""" + + assert upretty(R) == ucode_str + assert pretty(R) == ascii_str + + ucode_str = \ +"""\ + ╱ 2 ╲\n\ +1 + ╲x + 1╱\ +""" + + ascii_str = \ +"""\ + 2 \n\ +1 + \ +""" + + assert upretty(R.one) == ucode_str + assert pretty(R.one) == ascii_str + + +def test_Homomorphism(): + from sympy.polys.agca import homomorphism + + R = QQ.old_poly_ring(x) + + expr = homomorphism(R.free_module(1), R.free_module(1), [0]) + + ucode_str = \ +"""\ + 1 1\n\ +[0] : ℚ[x] ──> ℚ[x] \ +""" + + ascii_str = \ +"""\ + 1 1\n\ +[0] : QQ[x] --> QQ[x] \ +""" + + assert upretty(expr) == ucode_str + assert pretty(expr) == ascii_str + + expr = homomorphism(R.free_module(2), R.free_module(2), [0, 0]) + + ucode_str = \ +"""\ +⎡0 0⎤ 2 2\n\ +⎢ ⎥ : ℚ[x] ──> ℚ[x] \n\ +⎣0 0⎦ \ +""" + + ascii_str = \ +"""\ +[0 0] 2 2\n\ +[ ] : QQ[x] --> QQ[x] \n\ +[0 0] \ +""" + + assert upretty(expr) == ucode_str + assert pretty(expr) == ascii_str + + expr = homomorphism(R.free_module(1), R.free_module(1) / [[x]], [0]) + + ucode_str = \ +"""\ + 1\n\ + 1 ℚ[x] \n\ +[0] : ℚ[x] ──> ─────\n\ + <[x]>\ +""" + + ascii_str = \ +"""\ + 1\n\ + 1 QQ[x] \n\ +[0] : QQ[x] --> ------\n\ + <[x]> \ +""" + + assert upretty(expr) == ucode_str + assert pretty(expr) == ascii_str + + +def test_Tr(): + A, B = symbols('A B', commutative=False) + t = Tr(A*B) + assert pretty(t) == r'Tr(A*B)' + assert upretty(t) == 'Tr(A⋅B)' + + +def test_pretty_Add(): + eq = Mul(-2, x - 2, evaluate=False) + 5 + assert pretty(eq) == '5 - 2*(x - 2)' + + +def test_issue_7179(): + assert upretty(Not(Equivalent(x, y))) == 'x ⇎ y' + assert upretty(Not(Implies(x, y))) == 'x ↛ y' + + +def test_issue_7180(): + assert upretty(Equivalent(x, y)) == 'x ⇔ y' + + +def test_pretty_Complement(): + assert pretty(S.Reals - S.Naturals) == '(-oo, oo) \\ Naturals' + assert upretty(S.Reals - S.Naturals) == 'ℝ \\ ℕ' + assert pretty(S.Reals - S.Naturals0) == '(-oo, oo) \\ Naturals0' + assert upretty(S.Reals - S.Naturals0) == 'ℝ \\ ℕ₀' + + +def test_pretty_SymmetricDifference(): + from sympy.sets.sets import SymmetricDifference + assert upretty(SymmetricDifference(Interval(2,3), Interval(3,5), \ + evaluate = False)) == '[2, 3] ∆ [3, 5]' + with raises(NotImplementedError): + pretty(SymmetricDifference(Interval(2,3), Interval(3,5), evaluate = False)) + + +def test_pretty_Contains(): + assert pretty(Contains(x, S.Integers)) == 'Contains(x, Integers)' + assert upretty(Contains(x, S.Integers)) == 'x ∈ ℤ' + + +def test_issue_8292(): + from sympy.core import sympify + e = sympify('((x+x**4)/(x-1))-(2*(x-1)**4/(x-1)**4)', evaluate=False) + ucode_str = \ +"""\ + 4 4 \n\ + 2⋅(x - 1) x + x\n\ +- ────────── + ──────\n\ + 4 x - 1 \n\ + (x - 1) \ +""" + ascii_str = \ +"""\ + 4 4 \n\ + 2*(x - 1) x + x\n\ +- ---------- + ------\n\ + 4 x - 1 \n\ + (x - 1) \ +""" + assert pretty(e) == ascii_str + assert upretty(e) == ucode_str + + +def test_issue_4335(): + y = Function('y') + expr = -y(x).diff(x) + ucode_str = \ +"""\ + d \n\ +-──(y(x))\n\ + dx \ +""" + ascii_str = \ +"""\ + d \n\ +- --(y(x))\n\ + dx \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + +def test_issue_8344(): + from sympy.core import sympify + e = sympify('2*x*y**2/1**2 + 1', evaluate=False) + ucode_str = \ +"""\ + 2 \n\ +2⋅x⋅y \n\ +────── + 1\n\ + 2 \n\ + 1 \ +""" + assert upretty(e) == ucode_str + + +def test_issue_6324(): + x = Pow(2, 3, evaluate=False) + y = Pow(10, -2, evaluate=False) + e = Mul(x, y, evaluate=False) + ucode_str = \ +"""\ + 3 \n\ +2 \n\ +───\n\ + 2\n\ +10 \ +""" + assert upretty(e) == ucode_str + + +def test_issue_7927(): + e = sin(x/2)**cos(x/2) + ucode_str = \ +"""\ + ⎛x⎞\n\ + cos⎜─⎟\n\ + ⎝2⎠\n\ +⎛ ⎛x⎞⎞ \n\ +⎜sin⎜─⎟⎟ \n\ +⎝ ⎝2⎠⎠ \ +""" + assert upretty(e) == ucode_str + e = sin(x)**(S(11)/13) + ucode_str = \ +"""\ + 11\n\ + ──\n\ + 13\n\ +(sin(x)) \ +""" + assert upretty(e) == ucode_str + + +def test_issue_6134(): + from sympy.abc import lamda, t + phi = Function('phi') + + e = lamda*x*Integral(phi(t)*pi*sin(pi*t), (t, 0, 1)) + lamda*x**2*Integral(phi(t)*2*pi*sin(2*pi*t), (t, 0, 1)) + ucode_str = \ +"""\ + 1 1 \n\ + 2 ⌠ ⌠ \n\ +λ⋅x ⋅⎮ 2⋅π⋅φ(t)⋅sin(2⋅π⋅t) dt + λ⋅x⋅⎮ π⋅φ(t)⋅sin(π⋅t) dt\n\ + ⌡ ⌡ \n\ + 0 0 \ +""" + assert upretty(e) == ucode_str + + +def test_issue_9877(): + ucode_str1 = '(2, 3) ∪ ([1, 2] \\ {x})' + a, b, c = Interval(2, 3, True, True), Interval(1, 2), FiniteSet(x) + assert upretty(Union(a, Complement(b, c))) == ucode_str1 + + ucode_str2 = '{x} ∩ {y} ∩ ({z} \\ [1, 2])' + d, e, f, g = FiniteSet(x), FiniteSet(y), FiniteSet(z), Interval(1, 2) + assert upretty(Intersection(d, e, Complement(f, g))) == ucode_str2 + + +def test_issue_13651(): + expr1 = c + Mul(-1, a + b, evaluate=False) + assert pretty(expr1) == 'c - (a + b)' + expr2 = c + Mul(-1, a - b + d, evaluate=False) + assert pretty(expr2) == 'c - (a - b + d)' + + +def test_pretty_primenu(): + from sympy.functions.combinatorial.numbers import primenu + + ascii_str1 = "nu(n)" + ucode_str1 = "ν(n)" + + n = symbols('n', integer=True) + assert pretty(primenu(n)) == ascii_str1 + assert upretty(primenu(n)) == ucode_str1 + + +def test_pretty_primeomega(): + from sympy.functions.combinatorial.numbers import primeomega + + ascii_str1 = "Omega(n)" + ucode_str1 = "Ω(n)" + + n = symbols('n', integer=True) + assert pretty(primeomega(n)) == ascii_str1 + assert upretty(primeomega(n)) == ucode_str1 + + +def test_pretty_Mod(): + from sympy.core import Mod + + ascii_str1 = "x mod 7" + ucode_str1 = "x mod 7" + + ascii_str2 = "(x + 1) mod 7" + ucode_str2 = "(x + 1) mod 7" + + ascii_str3 = "2*x mod 7" + ucode_str3 = "2⋅x mod 7" + + ascii_str4 = "(x mod 7) + 1" + ucode_str4 = "(x mod 7) + 1" + + ascii_str5 = "2*(x mod 7)" + ucode_str5 = "2⋅(x mod 7)" + + x = symbols('x', integer=True) + assert pretty(Mod(x, 7)) == ascii_str1 + assert upretty(Mod(x, 7)) == ucode_str1 + assert pretty(Mod(x + 1, 7)) == ascii_str2 + assert upretty(Mod(x + 1, 7)) == ucode_str2 + assert pretty(Mod(2 * x, 7)) == ascii_str3 + assert upretty(Mod(2 * x, 7)) == ucode_str3 + assert pretty(Mod(x, 7) + 1) == ascii_str4 + assert upretty(Mod(x, 7) + 1) == ucode_str4 + assert pretty(2 * Mod(x, 7)) == ascii_str5 + assert upretty(2 * Mod(x, 7)) == ucode_str5 + + +def test_issue_11801(): + assert pretty(Symbol("")) == "" + assert upretty(Symbol("")) == "" + + +def test_pretty_UnevaluatedExpr(): + x = symbols('x') + he = UnevaluatedExpr(1/x) + + ucode_str = \ +"""\ +1\n\ +─\n\ +x\ +""" + + assert upretty(he) == ucode_str + + ucode_str = \ +"""\ + 2\n\ +⎛1⎞ \n\ +⎜─⎟ \n\ +⎝x⎠ \ +""" + + assert upretty(he**2) == ucode_str + + ucode_str = \ +"""\ + 1\n\ +1 + ─\n\ + x\ +""" + + assert upretty(he + 1) == ucode_str + + ucode_str = \ +('''\ + 1\n\ +x⋅─\n\ + x\ +''') + assert upretty(x*he) == ucode_str + + +def test_issue_10472(): + M = (Matrix([[0, 0], [0, 0]]), Matrix([0, 0])) + + ucode_str = \ +"""\ +⎛⎡0 0⎤ ⎡0⎤⎞ +⎜⎢ ⎥, ⎢ ⎥⎟ +⎝⎣0 0⎦ ⎣0⎦⎠\ +""" + assert upretty(M) == ucode_str + + +def test_MatrixElement_printing(): + # test cases for issue #11821 + A = MatrixSymbol("A", 1, 3) + B = MatrixSymbol("B", 1, 3) + C = MatrixSymbol("C", 1, 3) + + ascii_str1 = "A_00" + ucode_str1 = "A₀₀" + assert pretty(A[0, 0]) == ascii_str1 + assert upretty(A[0, 0]) == ucode_str1 + + ascii_str1 = "3*A_00" + ucode_str1 = "3⋅A₀₀" + assert pretty(3*A[0, 0]) == ascii_str1 + assert upretty(3*A[0, 0]) == ucode_str1 + + ascii_str1 = "(-B + A)[0, 0]" + ucode_str1 = "(-B + A)[0, 0]" + F = C[0, 0].subs(C, A - B) + assert pretty(F) == ascii_str1 + assert upretty(F) == ucode_str1 + + +def test_issue_12675(): + x, y, t, j = symbols('x y t j') + e = CoordSys3D('e') + + ucode_str = \ +"""\ +⎛ t⎞ \n\ +⎜⎛x⎞ ⎟ j_e\n\ +⎜⎜─⎟ ⎟ \n\ +⎝⎝y⎠ ⎠ \ +""" + assert upretty((x/y)**t*e.j) == ucode_str + ucode_str = \ +"""\ +⎛1⎞ \n\ +⎜─⎟ j_e\n\ +⎝y⎠ \ +""" + assert upretty((1/y)*e.j) == ucode_str + + +def test_MatrixSymbol_printing(): + # test cases for issue #14237 + A = MatrixSymbol("A", 3, 3) + B = MatrixSymbol("B", 3, 3) + C = MatrixSymbol("C", 3, 3) + assert pretty(-A*B*C) == "-A*B*C" + assert pretty(A - B) == "-B + A" + assert pretty(A*B*C - A*B - B*C) == "-A*B -B*C + A*B*C" + + # issue #14814 + x = MatrixSymbol('x', n, n) + y = MatrixSymbol('y*', n, n) + assert pretty(x + y) == "x + y*" + ascii_str = \ +"""\ + 2 \n\ +-2*y* -a*x\ +""" + assert pretty(-a*x + -2*y*y) == ascii_str + + +def test_degree_printing(): + expr1 = 90*degree + assert pretty(expr1) == '90°' + expr2 = x*degree + assert pretty(expr2) == 'x°' + expr3 = cos(x*degree + 90*degree) + assert pretty(expr3) == 'cos(x° + 90°)' + + +def test_vector_expr_pretty_printing(): + A = CoordSys3D('A') + + assert upretty(Cross(A.i, A.x*A.i+3*A.y*A.j)) == "(i_A)×((x_A) i_A + (3⋅y_A) j_A)" + assert upretty(x*Cross(A.i, A.j)) == 'x⋅(i_A)×(j_A)' + + assert upretty(Curl(A.x*A.i + 3*A.y*A.j)) == "∇×((x_A) i_A + (3⋅y_A) j_A)" + + assert upretty(Divergence(A.x*A.i + 3*A.y*A.j)) == "∇⋅((x_A) i_A + (3⋅y_A) j_A)" + + assert upretty(Dot(A.i, A.x*A.i+3*A.y*A.j)) == "(i_A)⋅((x_A) i_A + (3⋅y_A) j_A)" + + assert upretty(Gradient(A.x+3*A.y)) == "∇(x_A + 3⋅y_A)" + assert upretty(Laplacian(A.x+3*A.y)) == "∆(x_A + 3⋅y_A)" + # TODO: add support for ASCII pretty. + + +def test_pretty_print_tensor_expr(): + L = TensorIndexType("L") + i, j, k = tensor_indices("i j k", L) + i0 = tensor_indices("i_0", L) + A, B, C, D = tensor_heads("A B C D", [L]) + H = TensorHead("H", [L, L]) + + expr = -i + ascii_str = \ +"""\ +-i\ +""" + ucode_str = \ +"""\ +-i\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = A(i) + ascii_str = \ +"""\ + i\n\ +A \n\ + \ +""" + ucode_str = \ +"""\ + i\n\ +A \n\ + \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = A(i0) + ascii_str = \ +"""\ + i_0\n\ +A \n\ + \ +""" + ucode_str = \ +"""\ + i₀\n\ +A \n\ + \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = A(-i) + ascii_str = \ +"""\ + \n\ +A \n\ + i\ +""" + ucode_str = \ +"""\ + \n\ +A \n\ + i\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = -3*A(-i) + ascii_str = \ +"""\ + \n\ +-3*A \n\ + i\ +""" + ucode_str = \ +"""\ + \n\ +-3⋅A \n\ + i\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = H(i, -j) + ascii_str = \ +"""\ + i \n\ +H \n\ + j\ +""" + ucode_str = \ +"""\ + i \n\ +H \n\ + j\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = H(i, -i) + ascii_str = \ +"""\ + L_0 \n\ +H \n\ + L_0\ +""" + ucode_str = \ +"""\ + L₀ \n\ +H \n\ + L₀\ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = H(i, -j)*A(j)*B(k) + ascii_str = \ +"""\ + i L_0 k\n\ +H *A *B \n\ + L_0 \ +""" + ucode_str = \ +"""\ + i L₀ k\n\ +H ⋅A ⋅B \n\ + L₀ \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = (1+x)*A(i) + ascii_str = \ +"""\ + i\n\ +(x + 1)*A \n\ + \ +""" + ucode_str = \ +"""\ + i\n\ +(x + 1)⋅A \n\ + \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = A(i) + 3*B(i) + ascii_str = \ +"""\ + i i\n\ +3*B + A \n\ + \ +""" + ucode_str = \ +"""\ + i i\n\ +3⋅B + A \n\ + \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + +def test_pretty_print_tensor_partial_deriv(): + from sympy.tensor.toperators import PartialDerivative + + L = TensorIndexType("L") + i, j, k = tensor_indices("i j k", L) + + A, B, C, D = tensor_heads("A B C D", [L]) + + H = TensorHead("H", [L, L]) + + expr = PartialDerivative(A(i), A(j)) + ascii_str = \ +"""\ + d / i\\\n\ +---|A |\n\ + j\\ /\n\ +dA \n\ + \ +""" + ucode_str = \ +"""\ + ∂ ⎛ i⎞\n\ +───⎜A ⎟\n\ + j⎝ ⎠\n\ +∂A \n\ + \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = A(i)*PartialDerivative(H(k, -i), A(j)) + ascii_str = \ +"""\ + L_0 d / k \\\n\ +A *---|H |\n\ + j\\ L_0/\n\ + dA \n\ + \ +""" + ucode_str = \ +"""\ + L₀ ∂ ⎛ k ⎞\n\ +A ⋅───⎜H ⎟\n\ + j⎝ L₀⎠\n\ + ∂A \n\ + \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = A(i)*PartialDerivative(B(k)*C(-i) + 3*H(k, -i), A(j)) + ascii_str = \ +"""\ + L_0 d / k k \\\n\ +A *---|3*H + B *C |\n\ + j\\ L_0 L_0/\n\ + dA \n\ + \ +""" + ucode_str = \ +"""\ + L₀ ∂ ⎛ k k ⎞\n\ +A ⋅───⎜3⋅H + B ⋅C ⎟\n\ + j⎝ L₀ L₀⎠\n\ + ∂A \n\ + \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = (A(i) + B(i))*PartialDerivative(C(j), D(j)) + ascii_str = \ +"""\ +/ i i\\ d / L_0\\\n\ +|A + B |*-----|C |\n\ +\\ / L_0\\ /\n\ + dD \n\ + \ +""" + ucode_str = \ +"""\ +⎛ i i⎞ ∂ ⎛ L₀⎞\n\ +⎜A + B ⎟⋅────⎜C ⎟\n\ +⎝ ⎠ L₀⎝ ⎠\n\ + ∂D \n\ + \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = (A(i) + B(i))*PartialDerivative(C(-i), D(j)) + ascii_str = \ +"""\ +/ L_0 L_0\\ d / \\\n\ +|A + B |*---|C |\n\ +\\ / j\\ L_0/\n\ + dD \n\ + \ +""" + ucode_str = \ +"""\ +⎛ L₀ L₀⎞ ∂ ⎛ ⎞\n\ +⎜A + B ⎟⋅───⎜C ⎟\n\ +⎝ ⎠ j⎝ L₀⎠\n\ + ∂D \n\ + \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = PartialDerivative(B(-i) + A(-i), A(-j), A(-n)) + ucode_str = """\ + 2 \n\ + ∂ ⎛ ⎞\n\ +───────⎜A + B ⎟\n\ + ⎝ i i⎠\n\ +∂A ∂A \n\ + n j \ +""" + assert upretty(expr) == ucode_str + + expr = PartialDerivative(3*A(-i), A(-j), A(-n)) + ucode_str = """\ + 2 \n\ + ∂ ⎛ ⎞\n\ +───────⎜3⋅A ⎟\n\ + ⎝ i⎠\n\ +∂A ∂A \n\ + n j \ +""" + assert upretty(expr) == ucode_str + + expr = TensorElement(H(i, j), {i:1}) + ascii_str = \ +"""\ + i=1,j\n\ +H \n\ + \ +""" + ucode_str = ascii_str + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = TensorElement(H(i, j), {i: 1, j: 1}) + ascii_str = \ +"""\ + i=1,j=1\n\ +H \n\ + \ +""" + ucode_str = ascii_str + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = TensorElement(H(i, j), {j: 1}) + ascii_str = \ +"""\ + i,j=1\n\ +H \n\ + \ +""" + ucode_str = ascii_str + + expr = TensorElement(H(-i, j), {-i: 1}) + ascii_str = \ +"""\ + j\n\ +H \n\ + i=1 \ +""" + ucode_str = ascii_str + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + +def test_issue_15560(): + a = MatrixSymbol('a', 1, 1) + e = pretty(a*(KroneckerProduct(a, a))) + result = 'a*(a x a)' + assert e == result + + +def test_print_polylog(): + # Part of issue 6013 + uresult = 'Li₂(3)' + aresult = 'polylog(2, 3)' + assert pretty(polylog(2, 3)) == aresult + assert upretty(polylog(2, 3)) == uresult + + +# Issue #25312 +def test_print_expint_polylog_symbolic_order(): + s, z = symbols("s, z") + uresult = 'Liₛ(z)' + aresult = 'polylog(s, z)' + assert pretty(polylog(s, z)) == aresult + assert upretty(polylog(s, z)) == uresult + # TODO: TBD polylog(s - 1, z) + uresult = 'Eₛ(z)' + aresult = 'expint(s, z)' + assert pretty(expint(s, z)) == aresult + assert upretty(expint(s, z)) == uresult + + + +def test_print_polylog_long_order_issue_25309(): + s, z = symbols("s, z") + ucode_str = \ +"""\ + ⎛ 2 ⎞\n\ +polylog⎝s , z⎠\ +""" + assert upretty(polylog(s**2, z)) == ucode_str + + +def test_print_lerchphi(): + # Part of issue 6013 + a = Symbol('a') + pretty(lerchphi(a, 1, 2)) + uresult = 'Φ(a, 1, 2)' + aresult = 'lerchphi(a, 1, 2)' + assert pretty(lerchphi(a, 1, 2)) == aresult + assert upretty(lerchphi(a, 1, 2)) == uresult + + +def test_issue_15583(): + + N = mechanics.ReferenceFrame('N') + result = '(n_x, n_y, n_z)' + e = pretty((N.x, N.y, N.z)) + assert e == result + + +def test_matrixSymbolBold(): + # Issue 15871 + def boldpretty(expr): + return xpretty(expr, use_unicode=True, wrap_line=False, mat_symbol_style="bold") + + from sympy.matrices.expressions.trace import trace + A = MatrixSymbol("A", 2, 2) + assert boldpretty(trace(A)) == 'tr(𝐀)' + + A = MatrixSymbol("A", 3, 3) + B = MatrixSymbol("B", 3, 3) + C = MatrixSymbol("C", 3, 3) + + assert boldpretty(-A) == '-𝐀' + assert boldpretty(A - A*B - B) == '-𝐁 -𝐀⋅𝐁 + 𝐀' + assert boldpretty(-A*B - A*B*C - B) == '-𝐁 -𝐀⋅𝐁 -𝐀⋅𝐁⋅𝐂' + + A = MatrixSymbol("Addot", 3, 3) + assert boldpretty(A) == '𝐀̈' + omega = MatrixSymbol("omega", 3, 3) + assert boldpretty(omega) == 'ω' + omega = MatrixSymbol("omeganorm", 3, 3) + assert boldpretty(omega) == '‖ω‖' + + a = Symbol('alpha') + b = Symbol('b') + c = MatrixSymbol("c", 3, 1) + d = MatrixSymbol("d", 3, 1) + + assert boldpretty(a*B*c+b*d) == 'b⋅𝐝 + α⋅𝐁⋅𝐜' + + d = MatrixSymbol("delta", 3, 1) + B = MatrixSymbol("Beta", 3, 3) + + assert boldpretty(a*B*c+b*d) == 'b⋅δ + α⋅Β⋅𝐜' + + A = MatrixSymbol("A_2", 3, 3) + assert boldpretty(A) == '𝐀₂' + + +def test_center_accent(): + assert center_accent('a', '\N{COMBINING TILDE}') == 'ã' + assert center_accent('aa', '\N{COMBINING TILDE}') == 'aã' + assert center_accent('aaa', '\N{COMBINING TILDE}') == 'aãa' + assert center_accent('aaaa', '\N{COMBINING TILDE}') == 'aaãa' + assert center_accent('aaaaa', '\N{COMBINING TILDE}') == 'aaãaa' + assert center_accent('abcdefg', '\N{COMBINING FOUR DOTS ABOVE}') == 'abcd⃜efg' + + +def test_imaginary_unit(): + from sympy.printing.pretty import pretty # b/c it was redefined above + assert pretty(1 + I, use_unicode=False) == '1 + I' + assert pretty(1 + I, use_unicode=True) == '1 + ⅈ' + assert pretty(1 + I, use_unicode=False, imaginary_unit='j') == '1 + I' + assert pretty(1 + I, use_unicode=True, imaginary_unit='j') == '1 + ⅉ' + + raises(TypeError, lambda: pretty(I, imaginary_unit=I)) + raises(ValueError, lambda: pretty(I, imaginary_unit="kkk")) + + +def test_str_special_matrices(): + from sympy.matrices import Identity, ZeroMatrix, OneMatrix + assert pretty(Identity(4)) == 'I' + assert upretty(Identity(4)) == '𝕀' + assert pretty(ZeroMatrix(2, 2)) == '0' + assert upretty(ZeroMatrix(2, 2)) == '𝟘' + assert pretty(OneMatrix(2, 2)) == '1' + assert upretty(OneMatrix(2, 2)) == '𝟙' + + +def test_pretty_misc_functions(): + assert pretty(LambertW(x)) == 'W(x)' + assert upretty(LambertW(x)) == 'W(x)' + assert pretty(LambertW(x, y)) == 'W(x, y)' + assert upretty(LambertW(x, y)) == 'W(x, y)' + assert pretty(airyai(x)) == 'Ai(x)' + assert upretty(airyai(x)) == 'Ai(x)' + assert pretty(airybi(x)) == 'Bi(x)' + assert upretty(airybi(x)) == 'Bi(x)' + assert pretty(airyaiprime(x)) == "Ai'(x)" + assert upretty(airyaiprime(x)) == "Ai'(x)" + assert pretty(airybiprime(x)) == "Bi'(x)" + assert upretty(airybiprime(x)) == "Bi'(x)" + assert pretty(fresnelc(x)) == 'C(x)' + assert upretty(fresnelc(x)) == 'C(x)' + assert pretty(fresnels(x)) == 'S(x)' + assert upretty(fresnels(x)) == 'S(x)' + assert pretty(Heaviside(x)) == 'Heaviside(x)' + assert upretty(Heaviside(x)) == 'θ(x)' + assert pretty(Heaviside(x, y)) == 'Heaviside(x, y)' + assert upretty(Heaviside(x, y)) == 'θ(x, y)' + assert pretty(dirichlet_eta(x)) == 'dirichlet_eta(x)' + assert upretty(dirichlet_eta(x)) == 'η(x)' + + +def test_hadamard_power(): + m, n, p = symbols('m, n, p', integer=True) + A = MatrixSymbol('A', m, n) + B = MatrixSymbol('B', m, n) + + # Testing printer: + expr = hadamard_power(A, n) + ascii_str = \ +"""\ + .n\n\ +A \ +""" + ucode_str = \ +"""\ + ∘n\n\ +A \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = hadamard_power(A, 1+n) + ascii_str = \ +"""\ + .(n + 1)\n\ +A \ +""" + ucode_str = \ +"""\ + ∘(n + 1)\n\ +A \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + expr = hadamard_power(A*B.T, 1+n) + ascii_str = \ +"""\ + .(n + 1)\n\ +/ T\\ \n\ +\\A*B / \ +""" + ucode_str = \ +"""\ + ∘(n + 1)\n\ +⎛ T⎞ \n\ +⎝A⋅B ⎠ \ +""" + assert pretty(expr) == ascii_str + assert upretty(expr) == ucode_str + + +def test_issue_17258(): + n = Symbol('n', integer=True) + assert pretty(Sum(n, (n, -oo, 1))) == \ + ' 1 \n'\ + ' __ \n'\ + ' \\ ` \n'\ + ' ) n\n'\ + ' /_, \n'\ + 'n = -oo ' + + assert upretty(Sum(n, (n, -oo, 1))) == \ +"""\ + 1 \n\ + ___ \n\ + ╲ \n\ + ╲ \n\ + ╱ n\n\ + ╱ \n\ + ‾‾‾ \n\ +n = -∞ \ +""" + + +def test_is_combining(): + line = "v̇_m" + assert [is_combining(sym) for sym in line] == \ + [False, True, False, False] + + +def test_issue_17616(): + assert pretty(pi**(1/exp(1))) == \ + ' / -1\\\n'\ + ' \\e /\n'\ + 'pi ' + + assert upretty(pi**(1/exp(1))) == \ + ' ⎛ -1⎞\n'\ + ' ⎝ℯ ⎠\n'\ + 'π ' + + assert pretty(pi**(1/pi)) == \ + ' 1 \n'\ + ' --\n'\ + ' pi\n'\ + 'pi ' + + assert upretty(pi**(1/pi)) == \ + ' 1\n'\ + ' ─\n'\ + ' π\n'\ + 'π ' + + assert pretty(pi**(1/EulerGamma)) == \ + ' 1 \n'\ + ' ----------\n'\ + ' EulerGamma\n'\ + 'pi ' + + assert upretty(pi**(1/EulerGamma)) == \ + ' 1\n'\ + ' ─\n'\ + ' γ\n'\ + 'π ' + + z = Symbol("x_17") + assert upretty(7**(1/z)) == \ + 'x₁₇___\n'\ + ' ╲╱ 7 ' + + assert pretty(7**(1/z)) == \ + 'x_17___\n'\ + ' \\/ 7 ' + + +def test_issue_17857(): + assert pretty(Range(-oo, oo)) == '{..., -1, 0, 1, ...}' + assert pretty(Range(oo, -oo, -1)) == '{..., 1, 0, -1, ...}' + + +def test_issue_18272(): + x = Symbol('x') + n = Symbol('n') + + assert upretty(ConditionSet(x, Eq(-x + exp(x), 0), S.Complexes)) == \ + '⎧ │ ⎛ x ⎞⎫\n'\ + '⎨x │ x ∊ ℂ ∧ ⎝-x + ℯ = 0⎠⎬\n'\ + '⎩ │ ⎭' + assert upretty(ConditionSet(x, Contains(n/2, Interval(0, oo)), FiniteSet(-n/2, n/2))) == \ + '⎧ │ ⎧-n n⎫ ⎛n ⎞⎫\n'\ + '⎨x │ x ∊ ⎨───, ─⎬ ∧ ⎜─ ∈ [0, ∞)⎟⎬\n'\ + '⎩ │ ⎩ 2 2⎭ ⎝2 ⎠⎭' + assert upretty(ConditionSet(x, Eq(Piecewise((1, x >= 3), (x/2 - 1/2, x >= 2), (1/2, x >= 1), + (x/2, True)) - 1/2, 0), Interval(0, 3))) == \ + '⎧ │ ⎛⎛⎧ 1 for x ≥ 3⎞ ⎞⎫\n'\ + '⎪ │ ⎜⎜⎪ ⎟ ⎟⎪\n'\ + '⎪ │ ⎜⎜⎪x ⎟ ⎟⎪\n'\ + '⎪ │ ⎜⎜⎪─ - 0.5 for x ≥ 2⎟ ⎟⎪\n'\ + '⎪ │ ⎜⎜⎪2 ⎟ ⎟⎪\n'\ + '⎨x │ x ∊ [0, 3] ∧ ⎜⎜⎨ ⎟ - 0.5 = 0⎟⎬\n'\ + '⎪ │ ⎜⎜⎪ 0.5 for x ≥ 1⎟ ⎟⎪\n'\ + '⎪ │ ⎜⎜⎪ ⎟ ⎟⎪\n'\ + '⎪ │ ⎜⎜⎪ x ⎟ ⎟⎪\n'\ + '⎪ │ ⎜⎜⎪ ─ otherwise⎟ ⎟⎪\n'\ + '⎩ │ ⎝⎝⎩ 2 ⎠ ⎠⎭' + + +def test_Str(): + from sympy.core.symbol import Str + assert pretty(Str('x')) == 'x' + + +def test_symbolic_probability(): + mu = symbols("mu") + sigma = symbols("sigma", positive=True) + X = Normal("X", mu, sigma) + assert pretty(Expectation(X)) == r'E[X]' + assert pretty(Variance(X)) == r'Var(X)' + assert pretty(Probability(X > 0)) == r'P(X > 0)' + Y = Normal("Y", mu, sigma) + assert pretty(Covariance(X, Y)) == 'Cov(X, Y)' + + +def test_issue_21758(): + from sympy.functions.elementary.piecewise import piecewise_fold + from sympy.series.fourier import FourierSeries + x = Symbol('x') + k, n = symbols('k n') + fo = FourierSeries(x, (x, -pi, pi), (0, SeqFormula(0, (k, 1, oo)), SeqFormula( + Piecewise((-2*pi*cos(n*pi)/n + 2*sin(n*pi)/n**2, (n > -oo) & (n < oo) & Ne(n, 0)), + (0, True))*sin(n*x)/pi, (n, 1, oo)))) + assert upretty(piecewise_fold(fo)) == \ + '⎧ 2⋅sin(3⋅x) \n'\ + '⎪2⋅sin(x) - sin(2⋅x) + ────────── + … for n > -∞ ∧ n < ∞ ∧ n ≠ 0\n'\ + '⎨ 3 \n'\ + '⎪ \n'\ + '⎩ 0 otherwise ' + assert pretty(FourierSeries(x, (x, -pi, pi), (0, SeqFormula(0, (k, 1, oo)), + SeqFormula(0, (n, 1, oo))))) == '0' + + +def test_diffgeom(): + from sympy.diffgeom import Manifold, Patch, CoordSystem, BaseScalarField + x,y = symbols('x y', real=True) + m = Manifold('M', 2) + assert pretty(m) == 'M' + p = Patch('P', m) + assert pretty(p) == "P" + rect = CoordSystem('rect', p, [x, y]) + assert pretty(rect) == "rect" + b = BaseScalarField(rect, 0) + assert pretty(b) == "x" + + +def test_deprecated_prettyForm(): + with warns_deprecated_sympy(): + from sympy.printing.pretty.pretty_symbology import xstr + assert xstr(1) == '1' + + with warns_deprecated_sympy(): + from sympy.printing.pretty.stringpict import prettyForm + p = prettyForm('s', unicode='s') + + with warns_deprecated_sympy(): + assert p.unicode == p.s == 's' + + +def test_center(): + assert center('1', 2) == '1 ' + assert center('1', 3) == ' 1 ' + assert center('1', 3, '-') == '-1-' + assert center('1', 5, '-') == '--1--' diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..32ead5c5b1cc881292bc7eeb687dde70b48c6b54 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_aesaracode.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_aesaracode.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4778c12d570f280827f1b676665c3749b30bead8 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_aesaracode.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_c.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_c.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..93fe102cc1dd3dd92ff750b54049099bd2b0ce74 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_c.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_codeprinter.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_codeprinter.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e049e4a9021be7c6ccdecad02e3e4dec6eb8f80b Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_codeprinter.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_conventions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_conventions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9e75603244b12e80f5432d6a2b10b244ea04de01 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_conventions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_cupy.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_cupy.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ee94cda08d6d7438b9d9711b853b2cf41afa9afe Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_cupy.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_cxx.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_cxx.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a4f34dad79dd27e87192aae811dcb8f0c7341b14 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_cxx.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_dot.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_dot.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..31e71505ee5ae7fde12d419f3b988e9c6f166c5a Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_dot.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_fortran.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_fortran.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d37785f5b2b5435a00e4caf8ce94039032b2443e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_fortran.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_glsl.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_glsl.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ac2ca823afab27a0f288010c19d51a0a4fc7f1db Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_glsl.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_gtk.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_gtk.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..146e0804184b5b81ccc3ddb9fbe5ae27c88a05a0 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_gtk.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_jax.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_jax.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0153abeea33b39587242abec903d4e812df0fa59 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_jax.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_jscode.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_jscode.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..df8e165132b70a2c40d00a6ede2cb2c58a1c3c9e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_jscode.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_julia.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_julia.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..29b9d976cec0628264019935f3ced4a9633d6048 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_julia.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_lambdarepr.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_lambdarepr.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7883794588bb95567ff08d5afddb8c0ac9bc800b Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_lambdarepr.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_llvmjit.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_llvmjit.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8c0a4cca376081efc34f639ec49376a7ddd8f65d Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_llvmjit.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_maple.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_maple.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..530fd25256ddce2d37fe2a41df84aaef48e09ed2 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_maple.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_mathematica.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_mathematica.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8adc8f7e73bf3ddbcd87bcd8acd9178cce1f7915 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_mathematica.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_numpy.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_numpy.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..83c3224e0dd180630b54112081e1cb03c9d1fa4a Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_numpy.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_octave.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_octave.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9662892d9ea18be2cde1194bd0d10ea55b933470 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_octave.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_precedence.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_precedence.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4de291b4a904bcc2179a538502ed178fc639391e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_precedence.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_preview.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_preview.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b71e3172cbf57c71024d2b302d8d8367ff463800 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_preview.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_pycode.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_pycode.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..943c30d0a29ee0a3e2a801ea3a93e5ce71bcd477 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_pycode.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_python.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_python.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4304dda6fcd18ed02b2cffe5afc96816772aea95 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_python.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_rcode.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_rcode.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8c5bc6cb331f4eae7f6136490399e73438e68567 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_rcode.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_repr.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_repr.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c290525149ef941c7ecd9d1a6e9120d28666bcd8 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_repr.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_rust.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_rust.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..599cec3976c77f5b2c62a5f9c1f5b18fb60e6c2f Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_rust.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_smtlib.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_smtlib.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b2bb0470ef9f6fdf0784124a779eb7c1dab096cd Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_smtlib.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_str.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_str.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0d2fea07ab54668da2f01c19ee66123d11968d78 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_str.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_tableform.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_tableform.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..124a6d372cba88b1982585f4ae293f53ec49673d Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_tableform.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_tensorflow.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_tensorflow.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1c5de40fe006127b2a15f06f5db0fb9299104651 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_tensorflow.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_theanocode.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_theanocode.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..11e6de95548551aa5019ea8ba38654d626cf2340 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_theanocode.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_torch.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_torch.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..017479f7648122bff2aa3012b4cc3139a1979d63 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_torch.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_tree.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_tree.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6b698dedc245ab942c151fd16fc9abcbd8799f5d Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/__pycache__/test_tree.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_aesaracode.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_aesaracode.py new file mode 100644 index 0000000000000000000000000000000000000000..13308af65b382e77de33302bcd75344d2b00adbf --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_aesaracode.py @@ -0,0 +1,633 @@ +""" +Important note on tests in this module - the Aesara printing functions use a +global cache by default, which means that tests using it will modify global +state and thus not be independent from each other. Instead of using the "cache" +keyword argument each time, this module uses the aesara_code_ and +aesara_function_ functions defined below which default to using a new, empty +cache instead. +""" + +import logging + +from sympy.external import import_module +from sympy.testing.pytest import raises, SKIP, warns_deprecated_sympy + +from sympy.utilities.exceptions import ignore_warnings + + +aesaralogger = logging.getLogger('aesara.configdefaults') +aesaralogger.setLevel(logging.CRITICAL) +aesara = import_module('aesara') +aesaralogger.setLevel(logging.WARNING) + + +if aesara: + import numpy as np + aet = aesara.tensor + from aesara.scalar.basic import ScalarType + from aesara.graph.basic import Variable + from aesara.tensor.var import TensorVariable + from aesara.tensor.elemwise import Elemwise, DimShuffle + from aesara.tensor.math import Dot + + from sympy.printing.aesaracode import true_divide + + xt, yt, zt = [aet.scalar(name, 'floatX') for name in 'xyz'] + Xt, Yt, Zt = [aet.tensor('floatX', (False, False), name=n) for n in 'XYZ'] +else: + #bin/test will not execute any tests now + disabled = True + +import sympy as sy +from sympy.core.singleton import S +from sympy.abc import x, y, z, t +from sympy.printing.aesaracode import (aesara_code, dim_handling, + aesara_function) + + +# Default set of matrix symbols for testing - make square so we can both +# multiply and perform elementwise operations between them. +X, Y, Z = [sy.MatrixSymbol(n, 4, 4) for n in 'XYZ'] + +# For testing AppliedUndef +f_t = sy.Function('f')(t) + + +def aesara_code_(expr, **kwargs): + """ Wrapper for aesara_code that uses a new, empty cache by default. """ + kwargs.setdefault('cache', {}) + with warns_deprecated_sympy(): + return aesara_code(expr, **kwargs) + +def aesara_function_(inputs, outputs, **kwargs): + """ Wrapper for aesara_function that uses a new, empty cache by default. """ + kwargs.setdefault('cache', {}) + with warns_deprecated_sympy(): + return aesara_function(inputs, outputs, **kwargs) + + +def fgraph_of(*exprs): + """ Transform SymPy expressions into Aesara Computation. + + Parameters + ========== + exprs + SymPy expressions + + Returns + ======= + aesara.graph.fg.FunctionGraph + """ + outs = list(map(aesara_code_, exprs)) + ins = list(aesara.graph.basic.graph_inputs(outs)) + ins, outs = aesara.graph.basic.clone(ins, outs) + return aesara.graph.fg.FunctionGraph(ins, outs) + + +def aesara_simplify(fgraph): + """ Simplify a Aesara Computation. + + Parameters + ========== + fgraph : aesara.graph.fg.FunctionGraph + + Returns + ======= + aesara.graph.fg.FunctionGraph + """ + mode = aesara.compile.get_default_mode().excluding("fusion") + fgraph = fgraph.clone() + mode.optimizer.rewrite(fgraph) + return fgraph + + +def theq(a, b): + """ Test two Aesara objects for equality. + + Also accepts numeric types and lists/tuples of supported types. + + Note - debugprint() has a bug where it will accept numeric types but does + not respect the "file" argument and in this case and instead prints the number + to stdout and returns an empty string. This can lead to tests passing where + they should fail because any two numbers will always compare as equal. To + prevent this we treat numbers as a separate case. + """ + numeric_types = (int, float, np.number) + a_is_num = isinstance(a, numeric_types) + b_is_num = isinstance(b, numeric_types) + + # Compare numeric types using regular equality + if a_is_num or b_is_num: + if not (a_is_num and b_is_num): + return False + + return a == b + + # Compare sequences element-wise + a_is_seq = isinstance(a, (tuple, list)) + b_is_seq = isinstance(b, (tuple, list)) + + if a_is_seq or b_is_seq: + if not (a_is_seq and b_is_seq) or type(a) != type(b): + return False + + return list(map(theq, a)) == list(map(theq, b)) + + # Otherwise, assume debugprint() can handle it + astr = aesara.printing.debugprint(a, file='str') + bstr = aesara.printing.debugprint(b, file='str') + + # Check for bug mentioned above + for argname, argval, argstr in [('a', a, astr), ('b', b, bstr)]: + if argstr == '': + raise TypeError( + 'aesara.printing.debugprint(%s) returned empty string ' + '(%s is instance of %r)' + % (argname, argname, type(argval)) + ) + + return astr == bstr + + +def test_example_symbols(): + """ + Check that the example symbols in this module print to their Aesara + equivalents, as many of the other tests depend on this. + """ + assert theq(xt, aesara_code_(x)) + assert theq(yt, aesara_code_(y)) + assert theq(zt, aesara_code_(z)) + assert theq(Xt, aesara_code_(X)) + assert theq(Yt, aesara_code_(Y)) + assert theq(Zt, aesara_code_(Z)) + + +def test_Symbol(): + """ Test printing a Symbol to a aesara variable. """ + xx = aesara_code_(x) + assert isinstance(xx, Variable) + assert xx.broadcastable == () + assert xx.name == x.name + + xx2 = aesara_code_(x, broadcastables={x: (False,)}) + assert xx2.broadcastable == (False,) + assert xx2.name == x.name + +def test_MatrixSymbol(): + """ Test printing a MatrixSymbol to a aesara variable. """ + XX = aesara_code_(X) + assert isinstance(XX, TensorVariable) + assert XX.broadcastable == (False, False) + +@SKIP # TODO - this is currently not checked but should be implemented +def test_MatrixSymbol_wrong_dims(): + """ Test MatrixSymbol with invalid broadcastable. """ + bcs = [(), (False,), (True,), (True, False), (False, True,), (True, True)] + for bc in bcs: + with raises(ValueError): + aesara_code_(X, broadcastables={X: bc}) + +def test_AppliedUndef(): + """ Test printing AppliedUndef instance, which works similarly to Symbol. """ + ftt = aesara_code_(f_t) + assert isinstance(ftt, TensorVariable) + assert ftt.broadcastable == () + assert ftt.name == 'f_t' + + +def test_add(): + expr = x + y + comp = aesara_code_(expr) + assert comp.owner.op == aesara.tensor.add + +def test_trig(): + assert theq(aesara_code_(sy.sin(x)), aet.sin(xt)) + assert theq(aesara_code_(sy.tan(x)), aet.tan(xt)) + +def test_many(): + """ Test printing a complex expression with multiple symbols. """ + expr = sy.exp(x**2 + sy.cos(y)) * sy.log(2*z) + comp = aesara_code_(expr) + expected = aet.exp(xt**2 + aet.cos(yt)) * aet.log(2*zt) + assert theq(comp, expected) + + +def test_dtype(): + """ Test specifying specific data types through the dtype argument. """ + for dtype in ['float32', 'float64', 'int8', 'int16', 'int32', 'int64']: + assert aesara_code_(x, dtypes={x: dtype}).type.dtype == dtype + + # "floatX" type + assert aesara_code_(x, dtypes={x: 'floatX'}).type.dtype in ('float32', 'float64') + + # Type promotion + assert aesara_code_(x + 1, dtypes={x: 'float32'}).type.dtype == 'float32' + assert aesara_code_(x + y, dtypes={x: 'float64', y: 'float32'}).type.dtype == 'float64' + + +def test_broadcastables(): + """ Test the "broadcastables" argument when printing symbol-like objects. """ + + # No restrictions on shape + for s in [x, f_t]: + for bc in [(), (False,), (True,), (False, False), (True, False)]: + assert aesara_code_(s, broadcastables={s: bc}).broadcastable == bc + + # TODO - matrix broadcasting? + +def test_broadcasting(): + """ Test "broadcastable" attribute after applying element-wise binary op. """ + + expr = x + y + + cases = [ + [(), (), ()], + [(False,), (False,), (False,)], + [(True,), (False,), (False,)], + [(False, True), (False, False), (False, False)], + [(True, False), (False, False), (False, False)], + ] + + for bc1, bc2, bc3 in cases: + comp = aesara_code_(expr, broadcastables={x: bc1, y: bc2}) + assert comp.broadcastable == bc3 + + +def test_MatMul(): + expr = X*Y*Z + expr_t = aesara_code_(expr) + assert isinstance(expr_t.owner.op, Dot) + assert theq(expr_t, Xt.dot(Yt).dot(Zt)) + +def test_Transpose(): + assert isinstance(aesara_code_(X.T).owner.op, DimShuffle) + +def test_MatAdd(): + expr = X+Y+Z + assert isinstance(aesara_code_(expr).owner.op, Elemwise) + + +def test_Rationals(): + assert theq(aesara_code_(sy.Integer(2) / 3), true_divide(2, 3)) + assert theq(aesara_code_(S.Half), true_divide(1, 2)) + +def test_Integers(): + assert aesara_code_(sy.Integer(3)) == 3 + +def test_factorial(): + n = sy.Symbol('n') + assert aesara_code_(sy.factorial(n)) + +def test_Derivative(): + with ignore_warnings(UserWarning): + simp = lambda expr: aesara_simplify(fgraph_of(expr)) + assert theq(simp(aesara_code_(sy.Derivative(sy.sin(x), x, evaluate=False))), + simp(aesara.grad(aet.sin(xt), xt))) + + +def test_aesara_function_simple(): + """ Test aesara_function() with single output. """ + f = aesara_function_([x, y], [x+y]) + assert f(2, 3) == 5 + +def test_aesara_function_multi(): + """ Test aesara_function() with multiple outputs. """ + f = aesara_function_([x, y], [x+y, x-y]) + o1, o2 = f(2, 3) + assert o1 == 5 + assert o2 == -1 + +def test_aesara_function_numpy(): + """ Test aesara_function() vs Numpy implementation. """ + f = aesara_function_([x, y], [x+y], dim=1, + dtypes={x: 'float64', y: 'float64'}) + assert np.linalg.norm(f([1, 2], [3, 4]) - np.asarray([4, 6])) < 1e-9 + + f = aesara_function_([x, y], [x+y], dtypes={x: 'float64', y: 'float64'}, + dim=1) + xx = np.arange(3).astype('float64') + yy = 2*np.arange(3).astype('float64') + assert np.linalg.norm(f(xx, yy) - 3*np.arange(3)) < 1e-9 + + +def test_aesara_function_matrix(): + m = sy.Matrix([[x, y], [z, x + y + z]]) + expected = np.array([[1.0, 2.0], [3.0, 1.0 + 2.0 + 3.0]]) + f = aesara_function_([x, y, z], [m]) + np.testing.assert_allclose(f(1.0, 2.0, 3.0), expected) + f = aesara_function_([x, y, z], [m], scalar=True) + np.testing.assert_allclose(f(1.0, 2.0, 3.0), expected) + f = aesara_function_([x, y, z], [m, m]) + assert isinstance(f(1.0, 2.0, 3.0), type([])) + np.testing.assert_allclose(f(1.0, 2.0, 3.0)[0], expected) + np.testing.assert_allclose(f(1.0, 2.0, 3.0)[1], expected) + +def test_dim_handling(): + assert dim_handling([x], dim=2) == {x: (False, False)} + assert dim_handling([x, y], dims={x: 1, y: 2}) == {x: (False, True), + y: (False, False)} + assert dim_handling([x], broadcastables={x: (False,)}) == {x: (False,)} + +def test_aesara_function_kwargs(): + """ + Test passing additional kwargs from aesara_function() to aesara.function(). + """ + import numpy as np + f = aesara_function_([x, y, z], [x+y], dim=1, on_unused_input='ignore', + dtypes={x: 'float64', y: 'float64', z: 'float64'}) + assert np.linalg.norm(f([1, 2], [3, 4], [0, 0]) - np.asarray([4, 6])) < 1e-9 + + f = aesara_function_([x, y, z], [x+y], + dtypes={x: 'float64', y: 'float64', z: 'float64'}, + dim=1, on_unused_input='ignore') + xx = np.arange(3).astype('float64') + yy = 2*np.arange(3).astype('float64') + zz = 2*np.arange(3).astype('float64') + assert np.linalg.norm(f(xx, yy, zz) - 3*np.arange(3)) < 1e-9 + +def test_aesara_function_scalar(): + """ Test the "scalar" argument to aesara_function(). """ + from aesara.compile.function.types import Function + + args = [ + ([x, y], [x + y], None, [0]), # Single 0d output + ([X, Y], [X + Y], None, [2]), # Single 2d output + ([x, y], [x + y], {x: 0, y: 1}, [1]), # Single 1d output + ([x, y], [x + y, x - y], None, [0, 0]), # Two 0d outputs + ([x, y, X, Y], [x + y, X + Y], None, [0, 2]), # One 0d output, one 2d + ] + + # Create and test functions with and without the scalar setting + for inputs, outputs, in_dims, out_dims in args: + for scalar in [False, True]: + + f = aesara_function_(inputs, outputs, dims=in_dims, scalar=scalar) + + # Check the aesara_function attribute is set whether wrapped or not + assert isinstance(f.aesara_function, Function) + + # Feed in inputs of the appropriate size and get outputs + in_values = [ + np.ones([1 if bc else 5 for bc in i.type.broadcastable]) + for i in f.aesara_function.input_storage + ] + out_values = f(*in_values) + if not isinstance(out_values, list): + out_values = [out_values] + + # Check output types and shapes + assert len(out_dims) == len(out_values) + for d, value in zip(out_dims, out_values): + + if scalar and d == 0: + # Should have been converted to a scalar value + assert isinstance(value, np.number) + + else: + # Otherwise should be an array + assert isinstance(value, np.ndarray) + assert value.ndim == d + +def test_aesara_function_bad_kwarg(): + """ + Passing an unknown keyword argument to aesara_function() should raise an + exception. + """ + raises(Exception, lambda : aesara_function_([x], [x+1], foobar=3)) + + +def test_slice(): + assert aesara_code_(slice(1, 2, 3)) == slice(1, 2, 3) + + def theq_slice(s1, s2): + for attr in ['start', 'stop', 'step']: + a1 = getattr(s1, attr) + a2 = getattr(s2, attr) + if a1 is None or a2 is None: + if not (a1 is None or a2 is None): + return False + elif not theq(a1, a2): + return False + return True + + dtypes = {x: 'int32', y: 'int32'} + assert theq_slice(aesara_code_(slice(x, y), dtypes=dtypes), slice(xt, yt)) + assert theq_slice(aesara_code_(slice(1, x, 3), dtypes=dtypes), slice(1, xt, 3)) + +def test_MatrixSlice(): + cache = {} + + n = sy.Symbol('n', integer=True) + X = sy.MatrixSymbol('X', n, n) + + Y = X[1:2:3, 4:5:6] + Yt = aesara_code_(Y, cache=cache) + + s = ScalarType('int64') + assert tuple(Yt.owner.op.idx_list) == (slice(s, s, s), slice(s, s, s)) + assert Yt.owner.inputs[0] == aesara_code_(X, cache=cache) + # == doesn't work in Aesara like it does in SymPy. You have to use + # equals. + assert all(Yt.owner.inputs[i].data == i for i in range(1, 7)) + + k = sy.Symbol('k') + aesara_code_(k, dtypes={k: 'int32'}) + start, stop, step = 4, k, 2 + Y = X[start:stop:step] + Yt = aesara_code_(Y, dtypes={n: 'int32', k: 'int32'}) + # assert Yt.owner.op.idx_list[0].stop == kt + +def test_BlockMatrix(): + n = sy.Symbol('n', integer=True) + A, B, C, D = [sy.MatrixSymbol(name, n, n) for name in 'ABCD'] + At, Bt, Ct, Dt = map(aesara_code_, (A, B, C, D)) + Block = sy.BlockMatrix([[A, B], [C, D]]) + Blockt = aesara_code_(Block) + solutions = [aet.join(0, aet.join(1, At, Bt), aet.join(1, Ct, Dt)), + aet.join(1, aet.join(0, At, Ct), aet.join(0, Bt, Dt))] + assert any(theq(Blockt, solution) for solution in solutions) + +@SKIP +def test_BlockMatrix_Inverse_execution(): + k, n = 2, 4 + dtype = 'float32' + A = sy.MatrixSymbol('A', n, k) + B = sy.MatrixSymbol('B', n, n) + inputs = A, B + output = B.I*A + + cutsizes = {A: [(n//2, n//2), (k//2, k//2)], + B: [(n//2, n//2), (n//2, n//2)]} + cutinputs = [sy.blockcut(i, *cutsizes[i]) for i in inputs] + cutoutput = output.subs(dict(zip(inputs, cutinputs))) + + dtypes = dict(zip(inputs, [dtype]*len(inputs))) + f = aesara_function_(inputs, [output], dtypes=dtypes, cache={}) + fblocked = aesara_function_(inputs, [sy.block_collapse(cutoutput)], + dtypes=dtypes, cache={}) + + ninputs = [np.random.rand(*x.shape).astype(dtype) for x in inputs] + ninputs = [np.arange(n*k).reshape(A.shape).astype(dtype), + np.eye(n).astype(dtype)] + ninputs[1] += np.ones(B.shape)*1e-5 + + assert np.allclose(f(*ninputs), fblocked(*ninputs), rtol=1e-5) + +def test_DenseMatrix(): + from aesara.tensor.basic import Join + + t = sy.Symbol('theta') + for MatrixType in [sy.Matrix, sy.ImmutableMatrix]: + X = MatrixType([[sy.cos(t), -sy.sin(t)], [sy.sin(t), sy.cos(t)]]) + tX = aesara_code_(X) + assert isinstance(tX, TensorVariable) + assert isinstance(tX.owner.op, Join) + + +def test_cache_basic(): + """ Test single symbol-like objects are cached when printed by themselves. """ + + # Pairs of objects which should be considered equivalent with respect to caching + pairs = [ + (x, sy.Symbol('x')), + (X, sy.MatrixSymbol('X', *X.shape)), + (f_t, sy.Function('f')(sy.Symbol('t'))), + ] + + for s1, s2 in pairs: + cache = {} + st = aesara_code_(s1, cache=cache) + + # Test hit with same instance + assert aesara_code_(s1, cache=cache) is st + + # Test miss with same instance but new cache + assert aesara_code_(s1, cache={}) is not st + + # Test hit with different but equivalent instance + assert aesara_code_(s2, cache=cache) is st + +def test_global_cache(): + """ Test use of the global cache. """ + from sympy.printing.aesaracode import global_cache + + backup = dict(global_cache) + try: + # Temporarily empty global cache + global_cache.clear() + + for s in [x, X, f_t]: + with warns_deprecated_sympy(): + st = aesara_code(s) + assert aesara_code(s) is st + + finally: + # Restore global cache + global_cache.update(backup) + +def test_cache_types_distinct(): + """ + Test that symbol-like objects of different types (Symbol, MatrixSymbol, + AppliedUndef) are distinguished by the cache even if they have the same + name. + """ + symbols = [sy.Symbol('f_t'), sy.MatrixSymbol('f_t', 4, 4), f_t] + + cache = {} # Single shared cache + printed = {} + + for s in symbols: + st = aesara_code_(s, cache=cache) + assert st not in printed.values() + printed[s] = st + + # Check all printed objects are distinct + assert len(set(map(id, printed.values()))) == len(symbols) + + # Check retrieving + for s, st in printed.items(): + with warns_deprecated_sympy(): + assert aesara_code(s, cache=cache) is st + +def test_symbols_are_created_once(): + """ + Test that a symbol is cached and reused when it appears in an expression + more than once. + """ + expr = sy.Add(x, x, evaluate=False) + comp = aesara_code_(expr) + + assert theq(comp, xt + xt) + assert not theq(comp, xt + aesara_code_(x)) + +def test_cache_complex(): + """ + Test caching on a complicated expression with multiple symbols appearing + multiple times. + """ + expr = x ** 2 + (y - sy.exp(x)) * sy.sin(z - x * y) + symbol_names = {s.name for s in expr.free_symbols} + expr_t = aesara_code_(expr) + + # Iterate through variables in the Aesara computational graph that the + # printed expression depends on + seen = set() + for v in aesara.graph.basic.ancestors([expr_t]): + # Owner-less, non-constant variables should be our symbols + if v.owner is None and not isinstance(v, aesara.graph.basic.Constant): + # Check it corresponds to a symbol and appears only once + assert v.name in symbol_names + assert v.name not in seen + seen.add(v.name) + + # Check all were present + assert seen == symbol_names + + +def test_Piecewise(): + # A piecewise linear + expr = sy.Piecewise((0, x<0), (x, x<2), (1, True)) # ___/III + result = aesara_code_(expr) + assert result.owner.op == aet.switch + + expected = aet.switch(xt<0, 0, aet.switch(xt<2, xt, 1)) + assert theq(result, expected) + + expr = sy.Piecewise((x, x < 0)) + result = aesara_code_(expr) + expected = aet.switch(xt < 0, xt, np.nan) + assert theq(result, expected) + + expr = sy.Piecewise((0, sy.And(x>0, x<2)), \ + (x, sy.Or(x>2, x<0))) + result = aesara_code_(expr) + expected = aet.switch(aet.and_(xt>0,xt<2), 0, \ + aet.switch(aet.or_(xt>2, xt<0), xt, np.nan)) + assert theq(result, expected) + + +def test_Relationals(): + assert theq(aesara_code_(sy.Eq(x, y)), aet.eq(xt, yt)) + # assert theq(aesara_code_(sy.Ne(x, y)), aet.neq(xt, yt)) # TODO - implement + assert theq(aesara_code_(x > y), xt > yt) + assert theq(aesara_code_(x < y), xt < yt) + assert theq(aesara_code_(x >= y), xt >= yt) + assert theq(aesara_code_(x <= y), xt <= yt) + + +def test_complexfunctions(): + dtypes = {x:'complex128', y:'complex128'} + with warns_deprecated_sympy(): + xt, yt = aesara_code(x, dtypes=dtypes), aesara_code(y, dtypes=dtypes) + from sympy.functions.elementary.complexes import conjugate + from aesara.tensor import as_tensor_variable as atv + from aesara.tensor import complex as cplx + with warns_deprecated_sympy(): + assert theq(aesara_code(y*conjugate(x), dtypes=dtypes), yt*(xt.conj())) + assert theq(aesara_code((1+2j)*x), xt*(atv(1.0)+atv(2.0)*cplx(0,1))) + + +def test_constantfunctions(): + with warns_deprecated_sympy(): + tf = aesara_function([],[1+1j]) + assert(tf()==1+1j) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_c.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_c.py new file mode 100644 index 0000000000000000000000000000000000000000..626e7b6f244ea3227b886cd897d327f5d7bf66ec --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_c.py @@ -0,0 +1,888 @@ +from sympy.core import ( + S, pi, oo, Symbol, symbols, Rational, Integer, Float, Function, Mod, GoldenRatio, EulerGamma, Catalan, + Lambda, Dummy, nan, Mul, Pow, UnevaluatedExpr +) +from sympy.core.relational import (Eq, Ge, Gt, Le, Lt, Ne) +from sympy.functions import ( + Abs, acos, acosh, asin, asinh, atan, atanh, atan2, ceiling, cos, cosh, erf, + erfc, exp, floor, gamma, log, loggamma, Max, Min, Piecewise, sign, sin, sinh, + sqrt, tan, tanh, fibonacci, lucas +) +from sympy.sets import Range +from sympy.logic import ITE, Implies, Equivalent +from sympy.codegen import For, aug_assign, Assignment +from sympy.testing.pytest import raises, XFAIL +from sympy.printing.codeprinter import PrintMethodNotImplementedError +from sympy.printing.c import C89CodePrinter, C99CodePrinter, get_math_macros +from sympy.codegen.ast import ( + AddAugmentedAssignment, Element, Type, FloatType, Declaration, Pointer, Variable, value_const, pointer_const, + While, Scope, Print, FunctionPrototype, FunctionDefinition, FunctionCall, Return, + real, float32, float64, float80, float128, intc, Comment, CodeBlock, stderr, QuotedString +) +from sympy.codegen.cfunctions import expm1, log1p, exp2, log2, fma, log10, Cbrt, hypot, Sqrt, isnan, isinf +from sympy.codegen.cnodes import restrict +from sympy.utilities.lambdify import implemented_function +from sympy.tensor import IndexedBase, Idx +from sympy.matrices import Matrix, MatrixSymbol, SparseMatrix + +from sympy.printing.codeprinter import ccode + +x, y, z = symbols('x,y,z') + + +def test_printmethod(): + class fabs(Abs): + def _ccode(self, printer): + return "fabs(%s)" % printer._print(self.args[0]) + + assert ccode(fabs(x)) == "fabs(x)" + + +def test_ccode_sqrt(): + assert ccode(sqrt(x)) == "sqrt(x)" + assert ccode(x**0.5) == "sqrt(x)" + assert ccode(sqrt(x)) == "sqrt(x)" + + +def test_ccode_Pow(): + assert ccode(x**3) == "pow(x, 3)" + assert ccode(x**(y**3)) == "pow(x, pow(y, 3))" + g = implemented_function('g', Lambda(x, 2*x)) + assert ccode(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ + "pow(3.5*2*x, -x + pow(y, x))/(pow(x, 2) + y)" + assert ccode(x**-1.0) == '1.0/x' + assert ccode(x**Rational(2, 3)) == 'pow(x, 2.0/3.0)' + assert ccode(x**Rational(2, 3), type_aliases={real: float80}) == 'powl(x, 2.0L/3.0L)' + _cond_cfunc = [(lambda base, exp: exp.is_integer, "dpowi"), + (lambda base, exp: not exp.is_integer, "pow")] + assert ccode(x**3, user_functions={'Pow': _cond_cfunc}) == 'dpowi(x, 3)' + assert ccode(x**0.5, user_functions={'Pow': _cond_cfunc}) == 'pow(x, 0.5)' + assert ccode(x**Rational(16, 5), user_functions={'Pow': _cond_cfunc}) == 'pow(x, 16.0/5.0)' + _cond_cfunc2 = [(lambda base, exp: base == 2, lambda base, exp: 'exp2(%s)' % exp), + (lambda base, exp: base != 2, 'pow')] + # Related to gh-11353 + assert ccode(2**x, user_functions={'Pow': _cond_cfunc2}) == 'exp2(x)' + assert ccode(x**2, user_functions={'Pow': _cond_cfunc2}) == 'pow(x, 2)' + # For issue 14160 + assert ccode(Mul(-2, x, Pow(Mul(y,y,evaluate=False), -1, evaluate=False), + evaluate=False)) == '-2*x/(y*y)' + + +def test_ccode_Max(): + # Test for gh-11926 + assert ccode(Max(x,x*x),user_functions={"Max":"my_max", "Pow":"my_pow"}) == 'my_max(x, my_pow(x, 2))' + + +def test_ccode_Min_performance(): + #Shouldn't take more than a few seconds + big_min = Min(*symbols('a[0:50]')) + for curr_standard in ('c89', 'c99', 'c11'): + output = ccode(big_min, standard=curr_standard) + assert output.count('(') == output.count(')') + + +def test_ccode_constants_mathh(): + assert ccode(exp(1)) == "M_E" + assert ccode(pi) == "M_PI" + assert ccode(oo, standard='c89') == "HUGE_VAL" + assert ccode(-oo, standard='c89') == "-HUGE_VAL" + assert ccode(oo) == "INFINITY" + assert ccode(-oo, standard='c99') == "-INFINITY" + assert ccode(pi, type_aliases={real: float80}) == "M_PIl" + + +def test_ccode_constants_other(): + assert ccode(2*GoldenRatio) == "const double GoldenRatio = %s;\n2*GoldenRatio" % GoldenRatio.evalf(17) + assert ccode( + 2*Catalan) == "const double Catalan = %s;\n2*Catalan" % Catalan.evalf(17) + assert ccode(2*EulerGamma) == "const double EulerGamma = %s;\n2*EulerGamma" % EulerGamma.evalf(17) + + +def test_ccode_Rational(): + assert ccode(Rational(3, 7)) == "3.0/7.0" + assert ccode(Rational(3, 7), type_aliases={real: float80}) == "3.0L/7.0L" + assert ccode(Rational(18, 9)) == "2" + assert ccode(Rational(3, -7)) == "-3.0/7.0" + assert ccode(Rational(3, -7), type_aliases={real: float80}) == "-3.0L/7.0L" + assert ccode(Rational(-3, -7)) == "3.0/7.0" + assert ccode(Rational(-3, -7), type_aliases={real: float80}) == "3.0L/7.0L" + assert ccode(x + Rational(3, 7)) == "x + 3.0/7.0" + assert ccode(x + Rational(3, 7), type_aliases={real: float80}) == "x + 3.0L/7.0L" + assert ccode(Rational(3, 7)*x) == "(3.0/7.0)*x" + assert ccode(Rational(3, 7)*x, type_aliases={real: float80}) == "(3.0L/7.0L)*x" + + +def test_ccode_Integer(): + assert ccode(Integer(67)) == "67" + assert ccode(Integer(-1)) == "-1" + + +def test_ccode_functions(): + assert ccode(sin(x) ** cos(x)) == "pow(sin(x), cos(x))" + + +def test_ccode_inline_function(): + x = symbols('x') + g = implemented_function('g', Lambda(x, 2*x)) + assert ccode(g(x)) == "2*x" + g = implemented_function('g', Lambda(x, 2*x/Catalan)) + assert ccode( + g(x)) == "const double Catalan = %s;\n2*x/Catalan" % Catalan.evalf(17) + A = IndexedBase('A') + i = Idx('i', symbols('n', integer=True)) + g = implemented_function('g', Lambda(x, x*(1 + x)*(2 + x))) + assert ccode(g(A[i]), assign_to=A[i]) == ( + "for (int i=0; i y" + assert ccode(Ge(x, y)) == "x >= y" + + +def test_ccode_Piecewise(): + expr = Piecewise((x, x < 1), (x**2, True)) + assert ccode(expr) == ( + "((x < 1) ? (\n" + " x\n" + ")\n" + ": (\n" + " pow(x, 2)\n" + "))") + assert ccode(expr, assign_to="c") == ( + "if (x < 1) {\n" + " c = x;\n" + "}\n" + "else {\n" + " c = pow(x, 2);\n" + "}") + expr = Piecewise((x, x < 1), (x + 1, x < 2), (x**2, True)) + assert ccode(expr) == ( + "((x < 1) ? (\n" + " x\n" + ")\n" + ": ((x < 2) ? (\n" + " x + 1\n" + ")\n" + ": (\n" + " pow(x, 2)\n" + ")))") + assert ccode(expr, assign_to='c') == ( + "if (x < 1) {\n" + " c = x;\n" + "}\n" + "else if (x < 2) {\n" + " c = x + 1;\n" + "}\n" + "else {\n" + " c = pow(x, 2);\n" + "}") + # Check that Piecewise without a True (default) condition error + expr = Piecewise((x, x < 1), (x**2, x > 1), (sin(x), x > 0)) + raises(ValueError, lambda: ccode(expr)) + + +def test_ccode_sinc(): + from sympy.functions.elementary.trigonometric import sinc + expr = sinc(x) + assert ccode(expr) == ( + "(((x != 0) ? (\n" + " sin(x)/x\n" + ")\n" + ": (\n" + " 1\n" + ")))") + + +def test_ccode_Piecewise_deep(): + p = ccode(2*Piecewise((x, x < 1), (x + 1, x < 2), (x**2, True))) + assert p == ( + "2*((x < 1) ? (\n" + " x\n" + ")\n" + ": ((x < 2) ? (\n" + " x + 1\n" + ")\n" + ": (\n" + " pow(x, 2)\n" + ")))") + expr = x*y*z + x**2 + y**2 + Piecewise((0, x < 0.5), (1, True)) + cos(z) - 1 + assert ccode(expr) == ( + "pow(x, 2) + x*y*z + pow(y, 2) + ((x < 0.5) ? (\n" + " 0\n" + ")\n" + ": (\n" + " 1\n" + ")) + cos(z) - 1") + assert ccode(expr, assign_to='c') == ( + "c = pow(x, 2) + x*y*z + pow(y, 2) + ((x < 0.5) ? (\n" + " 0\n" + ")\n" + ": (\n" + " 1\n" + ")) + cos(z) - 1;") + + +def test_ccode_ITE(): + expr = ITE(x < 1, y, z) + assert ccode(expr) == ( + "((x < 1) ? (\n" + " y\n" + ")\n" + ": (\n" + " z\n" + "))") + + +def test_ccode_settings(): + raises(TypeError, lambda: ccode(sin(x), method="garbage")) + + +def test_ccode_Indexed(): + s, n, m, o = symbols('s n m o', integer=True) + i, j, k = Idx('i', n), Idx('j', m), Idx('k', o) + + x = IndexedBase('x')[j] + A = IndexedBase('A')[i, j] + B = IndexedBase('B')[i, j, k] + + p = C99CodePrinter() + + assert p._print_Indexed(x) == 'x[j]' + assert p._print_Indexed(A) == 'A[%s]' % (m*i+j) + assert p._print_Indexed(B) == 'B[%s]' % (i*o*m+j*o+k) + + A = IndexedBase('A', shape=(5,3))[i, j] + assert p._print_Indexed(A) == 'A[%s]' % (3*i + j) + + A = IndexedBase('A', shape=(5,3), strides='F')[i, j] + assert ccode(A) == 'A[%s]' % (i + 5*j) + + A = IndexedBase('A', shape=(29,29), strides=(1, s), offset=o)[i, j] + assert ccode(A) == 'A[o + s*j + i]' + + Abase = IndexedBase('A', strides=(s, m, n), offset=o) + assert ccode(Abase[i, j, k]) == 'A[m*j + n*k + o + s*i]' + assert ccode(Abase[2, 3, k]) == 'A[3*m + n*k + o + 2*s]' + + +def test_Element(): + assert ccode(Element('x', 'ij')) == 'x[i][j]' + assert ccode(Element('x', 'ij', strides='kl', offset='o')) == 'x[i*k + j*l + o]' + assert ccode(Element('x', (3,))) == 'x[3]' + assert ccode(Element('x', (3,4,5))) == 'x[3][4][5]' + + +def test_ccode_Indexed_without_looking_for_contraction(): + len_y = 5 + y = IndexedBase('y', shape=(len_y,)) + x = IndexedBase('x', shape=(len_y,)) + Dy = IndexedBase('Dy', shape=(len_y-1,)) + i = Idx('i', len_y-1) + e = Eq(Dy[i], (y[i+1]-y[i])/(x[i+1]-x[i])) + code0 = ccode(e.rhs, assign_to=e.lhs, contract=False) + assert code0 == 'Dy[i] = (y[%s] - y[i])/(x[%s] - x[i]);' % (i + 1, i + 1) + + +def test_ccode_loops_matrix_vector(): + n, m = symbols('n m', integer=True) + A = IndexedBase('A') + x = IndexedBase('x') + y = IndexedBase('y') + i = Idx('i', m) + j = Idx('j', n) + + s = ( + 'for (int i=0; i0), (y, True)), sin(z)]) + A = MatrixSymbol('A', 3, 1) + assert ccode(mat, A) == ( + "A[0] = x*y;\n" + "if (y > 0) {\n" + " A[1] = x + 2;\n" + "}\n" + "else {\n" + " A[1] = y;\n" + "}\n" + "A[2] = sin(z);") + # Test using MatrixElements in expressions + expr = Piecewise((2*A[2, 0], x > 0), (A[2, 0], True)) + sin(A[1, 0]) + A[0, 0] + assert ccode(expr) == ( + "((x > 0) ? (\n" + " 2*A[2]\n" + ")\n" + ": (\n" + " A[2]\n" + ")) + sin(A[1]) + A[0]") + # Test using MatrixElements in a Matrix + q = MatrixSymbol('q', 5, 1) + M = MatrixSymbol('M', 3, 3) + m = Matrix([[sin(q[1,0]), 0, cos(q[2,0])], + [q[1,0] + q[2,0], q[3, 0], 5], + [2*q[4, 0]/q[1,0], sqrt(q[0,0]) + 4, 0]]) + assert ccode(m, M) == ( + "M[0] = sin(q[1]);\n" + "M[1] = 0;\n" + "M[2] = cos(q[2]);\n" + "M[3] = q[1] + q[2];\n" + "M[4] = q[3];\n" + "M[5] = 5;\n" + "M[6] = 2*q[4]/q[1];\n" + "M[7] = sqrt(q[0]) + 4;\n" + "M[8] = 0;") + + +def test_sparse_matrix(): + # gh-15791 + with raises(PrintMethodNotImplementedError): + ccode(SparseMatrix([[1, 2, 3]])) + + assert 'Not supported in C' in C89CodePrinter({'strict': False}).doprint(SparseMatrix([[1, 2, 3]])) + + + +def test_ccode_reserved_words(): + x, y = symbols('x, if') + with raises(ValueError): + ccode(y**2, error_on_reserved=True, standard='C99') + assert ccode(y**2) == 'pow(if_, 2)' + assert ccode(x * y**2, dereference=[y]) == 'pow((*if_), 2)*x' + assert ccode(y**2, reserved_word_suffix='_unreserved') == 'pow(if_unreserved, 2)' + + +def test_ccode_sign(): + expr1, ref1 = sign(x) * y, 'y*(((x) > 0) - ((x) < 0))' + expr2, ref2 = sign(cos(x)), '(((cos(x)) > 0) - ((cos(x)) < 0))' + expr3, ref3 = sign(2 * x + x**2) * x + x**2, 'pow(x, 2) + x*(((pow(x, 2) + 2*x) > 0) - ((pow(x, 2) + 2*x) < 0))' + assert ccode(expr1) == ref1 + assert ccode(expr1, 'z') == 'z = %s;' % ref1 + assert ccode(expr2) == ref2 + assert ccode(expr3) == ref3 + +def test_ccode_Assignment(): + assert ccode(Assignment(x, y + z)) == 'x = y + z;' + assert ccode(aug_assign(x, '+', y + z)) == 'x += y + z;' + + +def test_ccode_For(): + f = For(x, Range(0, 10, 2), [aug_assign(y, '*', x)]) + assert ccode(f) == ("for (x = 0; x < 10; x += 2) {\n" + " y *= x;\n" + "}") + +def test_ccode_Max_Min(): + assert ccode(Max(x, 0), standard='C89') == '((0 > x) ? 0 : x)' + assert ccode(Max(x, 0), standard='C99') == 'fmax(0, x)' + assert ccode(Min(x, 0, sqrt(x)), standard='c89') == ( + '((0 < ((x < sqrt(x)) ? x : sqrt(x))) ? 0 : ((x < sqrt(x)) ? x : sqrt(x)))' + ) + +def test_ccode_standard(): + assert ccode(expm1(x), standard='c99') == 'expm1(x)' + assert ccode(nan, standard='c99') == 'NAN' + assert ccode(float('nan'), standard='c99') == 'NAN' + + +def test_C89CodePrinter(): + c89printer = C89CodePrinter() + assert c89printer.language == 'C' + assert c89printer.standard == 'C89' + assert 'void' in c89printer.reserved_words + assert 'template' not in c89printer.reserved_words + assert c89printer.doprint(log10(x)) == 'log10(x)' + + +def test_C99CodePrinter(): + assert C99CodePrinter().doprint(expm1(x)) == 'expm1(x)' + assert C99CodePrinter().doprint(log1p(x)) == 'log1p(x)' + assert C99CodePrinter().doprint(exp2(x)) == 'exp2(x)' + assert C99CodePrinter().doprint(log2(x)) == 'log2(x)' + assert C99CodePrinter().doprint(fma(x, y, -z)) == 'fma(x, y, -z)' + assert C99CodePrinter().doprint(log10(x)) == 'log10(x)' + assert C99CodePrinter().doprint(Cbrt(x)) == 'cbrt(x)' # note Cbrt due to cbrt already taken. + assert C99CodePrinter().doprint(hypot(x, y)) == 'hypot(x, y)' + assert C99CodePrinter().doprint(loggamma(x)) == 'lgamma(x)' + assert C99CodePrinter().doprint(Max(x, 3, x**2)) == 'fmax(3, fmax(x, pow(x, 2)))' + assert C99CodePrinter().doprint(Min(x, 3)) == 'fmin(3, x)' + c99printer = C99CodePrinter() + assert c99printer.language == 'C' + assert c99printer.standard == 'C99' + assert 'restrict' in c99printer.reserved_words + assert 'using' not in c99printer.reserved_words + + +@XFAIL +def test_C99CodePrinter__precision_f80(): + f80_printer = C99CodePrinter({"type_aliases": {real: float80}}) + assert f80_printer.doprint(sin(x + Float('2.1'))) == 'sinl(x + 2.1L)' + + +def test_C99CodePrinter__precision(): + n = symbols('n', integer=True) + p = symbols('p', integer=True, positive=True) + f32_printer = C99CodePrinter({"type_aliases": {real: float32}}) + f64_printer = C99CodePrinter({"type_aliases": {real: float64}}) + f80_printer = C99CodePrinter({"type_aliases": {real: float80}}) + assert f32_printer.doprint(sin(x+2.1)) == 'sinf(x + 2.1F)' + assert f64_printer.doprint(sin(x+2.1)) == 'sin(x + 2.1000000000000001)' + assert f80_printer.doprint(sin(x+Float('2.0'))) == 'sinl(x + 2.0L)' + + for printer, suffix in zip([f32_printer, f64_printer, f80_printer], ['f', '', 'l']): + def check(expr, ref): + assert printer.doprint(expr) == ref.format(s=suffix, S=suffix.upper()) + check(Abs(n), 'abs(n)') + check(Abs(x + 2.0), 'fabs{s}(x + 2.0{S})') + check(sin(x + 4.0)**cos(x - 2.0), 'pow{s}(sin{s}(x + 4.0{S}), cos{s}(x - 2.0{S}))') + check(exp(x*8.0), 'exp{s}(8.0{S}*x)') + check(exp2(x), 'exp2{s}(x)') + check(expm1(x*4.0), 'expm1{s}(4.0{S}*x)') + check(Mod(p, 2), 'p % 2') + check(Mod(2*p + 3, 3*p + 5, evaluate=False), '(2*p + 3) % (3*p + 5)') + check(Mod(x + 2.0, 3.0), 'fmod{s}(1.0{S}*x + 2.0{S}, 3.0{S})') + check(Mod(x, 2.0*x + 3.0), 'fmod{s}(1.0{S}*x, 2.0{S}*x + 3.0{S})') + check(log(x/2), 'log{s}((1.0{S}/2.0{S})*x)') + check(log10(3*x/2), 'log10{s}((3.0{S}/2.0{S})*x)') + check(log2(x*8.0), 'log2{s}(8.0{S}*x)') + check(log1p(x), 'log1p{s}(x)') + check(2**x, 'pow{s}(2, x)') + check(2.0**x, 'pow{s}(2.0{S}, x)') + check(x**3, 'pow{s}(x, 3)') + check(x**4.0, 'pow{s}(x, 4.0{S})') + check(sqrt(3+x), 'sqrt{s}(x + 3)') + check(Cbrt(x-2.0), 'cbrt{s}(x - 2.0{S})') + check(hypot(x, y), 'hypot{s}(x, y)') + check(sin(3.*x + 2.), 'sin{s}(3.0{S}*x + 2.0{S})') + check(cos(3.*x - 1.), 'cos{s}(3.0{S}*x - 1.0{S})') + check(tan(4.*y + 2.), 'tan{s}(4.0{S}*y + 2.0{S})') + check(asin(3.*x + 2.), 'asin{s}(3.0{S}*x + 2.0{S})') + check(acos(3.*x + 2.), 'acos{s}(3.0{S}*x + 2.0{S})') + check(atan(3.*x + 2.), 'atan{s}(3.0{S}*x + 2.0{S})') + check(atan2(3.*x, 2.*y), 'atan2{s}(3.0{S}*x, 2.0{S}*y)') + + check(sinh(3.*x + 2.), 'sinh{s}(3.0{S}*x + 2.0{S})') + check(cosh(3.*x - 1.), 'cosh{s}(3.0{S}*x - 1.0{S})') + check(tanh(4.0*y + 2.), 'tanh{s}(4.0{S}*y + 2.0{S})') + check(asinh(3.*x + 2.), 'asinh{s}(3.0{S}*x + 2.0{S})') + check(acosh(3.*x + 2.), 'acosh{s}(3.0{S}*x + 2.0{S})') + check(atanh(3.*x + 2.), 'atanh{s}(3.0{S}*x + 2.0{S})') + check(erf(42.*x), 'erf{s}(42.0{S}*x)') + check(erfc(42.*x), 'erfc{s}(42.0{S}*x)') + check(gamma(x), 'tgamma{s}(x)') + check(loggamma(x), 'lgamma{s}(x)') + + check(ceiling(x + 2.), "ceil{s}(x) + 2") + check(floor(x + 2.), "floor{s}(x) + 2") + check(fma(x, y, -z), 'fma{s}(x, y, -z)') + check(Max(x, 8.0, x**4.0), 'fmax{s}(8.0{S}, fmax{s}(x, pow{s}(x, 4.0{S})))') + check(Min(x, 2.0), 'fmin{s}(2.0{S}, x)') + + +def test_get_math_macros(): + macros = get_math_macros() + assert macros[exp(1)] == 'M_E' + assert macros[1/Sqrt(2)] == 'M_SQRT1_2' + + +def test_ccode_Declaration(): + i = symbols('i', integer=True) + var1 = Variable(i, type=Type.from_expr(i)) + dcl1 = Declaration(var1) + assert ccode(dcl1) == 'int i' + + var2 = Variable(x, type=float32, attrs={value_const}) + dcl2a = Declaration(var2) + assert ccode(dcl2a) == 'const float x' + dcl2b = var2.as_Declaration(value=pi) + assert ccode(dcl2b) == 'const float x = M_PI' + + var3 = Variable(y, type=Type('bool')) + dcl3 = Declaration(var3) + printer = C89CodePrinter() + assert 'stdbool.h' not in printer.headers + assert printer.doprint(dcl3) == 'bool y' + assert 'stdbool.h' in printer.headers + + u = symbols('u', real=True) + ptr4 = Pointer.deduced(u, attrs={pointer_const, restrict}) + dcl4 = Declaration(ptr4) + assert ccode(dcl4) == 'double * const restrict u' + + var5 = Variable(x, Type('__float128'), attrs={value_const}) + dcl5a = Declaration(var5) + assert ccode(dcl5a) == 'const __float128 x' + var5b = Variable(var5.symbol, var5.type, pi, attrs=var5.attrs) + dcl5b = Declaration(var5b) + assert ccode(dcl5b) == 'const __float128 x = M_PI' + + +def test_C99CodePrinter_custom_type(): + # We will look at __float128 (new in glibc 2.26) + f128 = FloatType('_Float128', float128.nbits, float128.nmant, float128.nexp) + p128 = C99CodePrinter({ + "type_aliases": {real: f128}, + "type_literal_suffixes": {f128: 'Q'}, + "type_func_suffixes": {f128: 'f128'}, + "type_math_macro_suffixes": { + real: 'f128', + f128: 'f128' + }, + "type_macros": { + f128: ('__STDC_WANT_IEC_60559_TYPES_EXT__',) + } + }) + assert p128.doprint(x) == 'x' + assert not p128.headers + assert not p128.libraries + assert not p128.macros + assert p128.doprint(2.0) == '2.0Q' + assert not p128.headers + assert not p128.libraries + assert p128.macros == {'__STDC_WANT_IEC_60559_TYPES_EXT__'} + + assert p128.doprint(Rational(1, 2)) == '1.0Q/2.0Q' + assert p128.doprint(sin(x)) == 'sinf128(x)' + assert p128.doprint(cos(2., evaluate=False)) == 'cosf128(2.0Q)' + assert p128.doprint(x**-1.0) == '1.0Q/x' + + var5 = Variable(x, f128, attrs={value_const}) + + dcl5a = Declaration(var5) + assert ccode(dcl5a) == 'const _Float128 x' + var5b = Variable(x, f128, pi, attrs={value_const}) + dcl5b = Declaration(var5b) + assert p128.doprint(dcl5b) == 'const _Float128 x = M_PIf128' + var5b = Variable(x, f128, value=Catalan.evalf(38), attrs={value_const}) + dcl5c = Declaration(var5b) + assert p128.doprint(dcl5c) == 'const _Float128 x = %sQ' % Catalan.evalf(f128.decimal_dig) + + +def test_MatrixElement_printing(): + # test cases for issue #11821 + A = MatrixSymbol("A", 1, 3) + B = MatrixSymbol("B", 1, 3) + C = MatrixSymbol("C", 1, 3) + + assert(ccode(A[0, 0]) == "A[0]") + assert(ccode(3 * A[0, 0]) == "3*A[0]") + + F = C[0, 0].subs(C, A - B) + assert(ccode(F) == "(A - B)[0]") + +def test_ccode_math_macros(): + assert ccode(z + exp(1)) == 'z + M_E' + assert ccode(z + log2(exp(1))) == 'z + M_LOG2E' + assert ccode(z + 1/log(2)) == 'z + M_LOG2E' + assert ccode(z + log(2)) == 'z + M_LN2' + assert ccode(z + log(10)) == 'z + M_LN10' + assert ccode(z + pi) == 'z + M_PI' + assert ccode(z + pi/2) == 'z + M_PI_2' + assert ccode(z + pi/4) == 'z + M_PI_4' + assert ccode(z + 1/pi) == 'z + M_1_PI' + assert ccode(z + 2/pi) == 'z + M_2_PI' + assert ccode(z + 2/sqrt(pi)) == 'z + M_2_SQRTPI' + assert ccode(z + 2/Sqrt(pi)) == 'z + M_2_SQRTPI' + assert ccode(z + sqrt(2)) == 'z + M_SQRT2' + assert ccode(z + Sqrt(2)) == 'z + M_SQRT2' + assert ccode(z + 1/sqrt(2)) == 'z + M_SQRT1_2' + assert ccode(z + 1/Sqrt(2)) == 'z + M_SQRT1_2' + + +def test_ccode_Type(): + assert ccode(Type('float')) == 'float' + assert ccode(intc) == 'int' + + +def test_ccode_codegen_ast(): + # Note that C only allows comments of the form /* ... */, double forward + # slash is not standard C, and some C compilers will grind to a halt upon + # encountering them. + assert ccode(Comment("this is a comment")) == "/* this is a comment */" # not // + assert ccode(While(abs(x) > 1, [aug_assign(x, '-', 1)])) == ( + 'while (fabs(x) > 1) {\n' + ' x -= 1;\n' + '}' + ) + assert ccode(Scope([AddAugmentedAssignment(x, 1)])) == ( + '{\n' + ' x += 1;\n' + '}' + ) + inp_x = Declaration(Variable(x, type=real)) + assert ccode(FunctionPrototype(real, 'pwer', [inp_x])) == 'double pwer(double x)' + assert ccode(FunctionDefinition(real, 'pwer', [inp_x], [Assignment(x, x**2)])) == ( + 'double pwer(double x){\n' + ' x = pow(x, 2);\n' + '}' + ) + + # Elements of CodeBlock are formatted as statements: + block = CodeBlock( + x, + Print([x, y], "%d %d"), + Print([QuotedString('hello'), y], "%s %d", file=stderr), + FunctionCall('pwer', [x]), + Return(x), + ) + assert ccode(block) == '\n'.join([ + 'x;', + 'printf("%d %d", x, y);', + 'fprintf(stderr, "%s %d", "hello", y);', + 'pwer(x);', + 'return x;', + ]) + +def test_ccode_UnevaluatedExpr(): + assert ccode(UnevaluatedExpr(y * x) + z) == "z + x*y" + assert ccode(UnevaluatedExpr(y + x) + z) == "z + (x + y)" # gh-21955 + w = symbols('w') + assert ccode(UnevaluatedExpr(y + x) + UnevaluatedExpr(z + w)) == "(w + z) + (x + y)" + + p, q, r = symbols("p q r", real=True) + q_r = UnevaluatedExpr(q + r) + expr = abs(exp(p+q_r)) + assert ccode(expr) == "exp(p + (q + r))" + + +def test_ccode_array_like_containers(): + assert ccode([2,3,4]) == "{2, 3, 4}" + assert ccode((2,3,4)) == "{2, 3, 4}" + +def test_ccode__isinf_isnan(): + assert ccode(isinf(x)) == 'isinf(x)' + assert ccode(isnan(x)) == 'isnan(x)' diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_codeprinter.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_codeprinter.py new file mode 100644 index 0000000000000000000000000000000000000000..4b077037eb84e218fcfd4a05fc03e40b211e45b9 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_codeprinter.py @@ -0,0 +1,77 @@ +from sympy.printing.codeprinter import CodePrinter, PrintMethodNotImplementedError +from sympy.core import symbols +from sympy.core.symbol import Dummy +from sympy.testing.pytest import raises +from sympy import cos +from sympy.utilities.lambdify import lambdify +from math import cos as math_cos +from sympy.printing.lambdarepr import LambdaPrinter + + +def setup_test_printer(**kwargs): + p = CodePrinter(settings=kwargs) + p._not_supported = set() + p._number_symbols = set() + return p + + +def test_print_Dummy(): + d = Dummy('d') + p = setup_test_printer() + assert p._print_Dummy(d) == "d_%i" % d.dummy_index + +def test_print_Symbol(): + + x, y = symbols('x, if') + + p = setup_test_printer() + assert p._print(x) == 'x' + assert p._print(y) == 'if' + + p.reserved_words.update(['if']) + assert p._print(y) == 'if_' + + p = setup_test_printer(error_on_reserved=True) + p.reserved_words.update(['if']) + with raises(ValueError): + p._print(y) + + p = setup_test_printer(reserved_word_suffix='_He_Man') + p.reserved_words.update(['if']) + assert p._print(y) == 'if_He_Man' + + +def test_lambdify_LaTeX_symbols_issue_23374(): + # Create symbols with Latex style names + x1, x2 = symbols("x_{1} x_2") + + # Lambdify the function + f1 = lambdify([x1, x2], cos(x1 ** 2 + x2 ** 2)) + + # Test that the function works correctly (numerically) + assert f1(1, 2) == math_cos(1 ** 2 + 2 ** 2) + + # Explicitly generate a custom printer to verify the naming convention + p = LambdaPrinter() + expr_str = p.doprint(cos(x1 ** 2 + x2 ** 2)) + assert 'x_1' in expr_str + assert 'x_2' in expr_str + + +def test_issue_15791(): + class CrashingCodePrinter(CodePrinter): + def emptyPrinter(self, obj): + raise NotImplementedError + + from sympy.matrices import ( + MutableSparseMatrix, + ImmutableSparseMatrix, + ) + + c = CrashingCodePrinter() + + # these should not silently succeed + with raises(PrintMethodNotImplementedError): + c.doprint(ImmutableSparseMatrix(2, 2, {})) + with raises(PrintMethodNotImplementedError): + c.doprint(MutableSparseMatrix(2, 2, {})) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_conventions.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_conventions.py new file mode 100644 index 0000000000000000000000000000000000000000..e8f1fa8532f96130828b89d1ba5ba11fd5bed7a4 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_conventions.py @@ -0,0 +1,116 @@ +# -*- coding: utf-8 -*- + +from sympy.core.function import (Derivative, Function) +from sympy.core.numbers import oo +from sympy.core.symbol import symbols +from sympy.functions.elementary.exponential import exp +from sympy.functions.elementary.trigonometric import cos +from sympy.integrals.integrals import Integral +from sympy.functions.special.bessel import besselj +from sympy.functions.special.polynomials import legendre +from sympy.functions.combinatorial.numbers import bell +from sympy.printing.conventions import split_super_sub, requires_partial +from sympy.testing.pytest import XFAIL + +def test_super_sub(): + assert split_super_sub("beta_13_2") == ("beta", [], ["13", "2"]) + assert split_super_sub("beta_132_20") == ("beta", [], ["132", "20"]) + assert split_super_sub("beta_13") == ("beta", [], ["13"]) + assert split_super_sub("x_a_b") == ("x", [], ["a", "b"]) + assert split_super_sub("x_1_2_3") == ("x", [], ["1", "2", "3"]) + assert split_super_sub("x_a_b1") == ("x", [], ["a", "b1"]) + assert split_super_sub("x_a_1") == ("x", [], ["a", "1"]) + assert split_super_sub("x_1_a") == ("x", [], ["1", "a"]) + assert split_super_sub("x_1^aa") == ("x", ["aa"], ["1"]) + assert split_super_sub("x_1__aa") == ("x", ["aa"], ["1"]) + assert split_super_sub("x_11^a") == ("x", ["a"], ["11"]) + assert split_super_sub("x_11__a") == ("x", ["a"], ["11"]) + assert split_super_sub("x_a_b_c_d") == ("x", [], ["a", "b", "c", "d"]) + assert split_super_sub("x_a_b^c^d") == ("x", ["c", "d"], ["a", "b"]) + assert split_super_sub("x_a_b__c__d") == ("x", ["c", "d"], ["a", "b"]) + assert split_super_sub("x_a^b_c^d") == ("x", ["b", "d"], ["a", "c"]) + assert split_super_sub("x_a__b_c__d") == ("x", ["b", "d"], ["a", "c"]) + assert split_super_sub("x^a^b_c_d") == ("x", ["a", "b"], ["c", "d"]) + assert split_super_sub("x__a__b_c_d") == ("x", ["a", "b"], ["c", "d"]) + assert split_super_sub("x^a^b^c^d") == ("x", ["a", "b", "c", "d"], []) + assert split_super_sub("x__a__b__c__d") == ("x", ["a", "b", "c", "d"], []) + assert split_super_sub("alpha_11") == ("alpha", [], ["11"]) + assert split_super_sub("alpha_11_11") == ("alpha", [], ["11", "11"]) + assert split_super_sub("w1") == ("w", [], ["1"]) + assert split_super_sub("w𝟙") == ("w", [], ["𝟙"]) + assert split_super_sub("w11") == ("w", [], ["11"]) + assert split_super_sub("w𝟙𝟙") == ("w", [], ["𝟙𝟙"]) + assert split_super_sub("w𝟙2𝟙") == ("w", [], ["𝟙2𝟙"]) + assert split_super_sub("w1^a") == ("w", ["a"], ["1"]) + assert split_super_sub("ω1") == ("ω", [], ["1"]) + assert split_super_sub("ω11") == ("ω", [], ["11"]) + assert split_super_sub("ω1^a") == ("ω", ["a"], ["1"]) + assert split_super_sub("ω𝟙^α") == ("ω", ["α"], ["𝟙"]) + assert split_super_sub("ω𝟙2^3α") == ("ω", ["3α"], ["𝟙2"]) + assert split_super_sub("") == ("", [], []) + + +def test_requires_partial(): + x, y, z, t, nu = symbols('x y z t nu') + n = symbols('n', integer=True) + + f = x * y + assert requires_partial(Derivative(f, x)) is True + assert requires_partial(Derivative(f, y)) is True + + ## integrating out one of the variables + assert requires_partial(Derivative(Integral(exp(-x * y), (x, 0, oo)), y, evaluate=False)) is False + + ## bessel function with smooth parameter + f = besselj(nu, x) + assert requires_partial(Derivative(f, x)) is True + assert requires_partial(Derivative(f, nu)) is True + + ## bessel function with integer parameter + f = besselj(n, x) + assert requires_partial(Derivative(f, x)) is False + # this is not really valid (differentiating with respect to an integer) + # but there's no reason to use the partial derivative symbol there. make + # sure we don't throw an exception here, though + assert requires_partial(Derivative(f, n)) is False + + ## bell polynomial + f = bell(n, x) + assert requires_partial(Derivative(f, x)) is False + # again, invalid + assert requires_partial(Derivative(f, n)) is False + + ## legendre polynomial + f = legendre(0, x) + assert requires_partial(Derivative(f, x)) is False + + f = legendre(n, x) + assert requires_partial(Derivative(f, x)) is False + # again, invalid + assert requires_partial(Derivative(f, n)) is False + + f = x ** n + assert requires_partial(Derivative(f, x)) is False + + assert requires_partial(Derivative(Integral((x*y) ** n * exp(-x * y), (x, 0, oo)), y, evaluate=False)) is False + + # parametric equation + f = (exp(t), cos(t)) + g = sum(f) + assert requires_partial(Derivative(g, t)) is False + + f = symbols('f', cls=Function) + assert requires_partial(Derivative(f(x), x)) is False + assert requires_partial(Derivative(f(x), y)) is False + assert requires_partial(Derivative(f(x, y), x)) is True + assert requires_partial(Derivative(f(x, y), y)) is True + assert requires_partial(Derivative(f(x, y), z)) is True + assert requires_partial(Derivative(f(x, y), x, y)) is True + +@XFAIL +def test_requires_partial_unspecified_variables(): + x, y = symbols('x y') + # function of unspecified variables + f = symbols('f', cls=Function) + assert requires_partial(Derivative(f, x)) is False + assert requires_partial(Derivative(f, x, y)) is True diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_cupy.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_cupy.py new file mode 100644 index 0000000000000000000000000000000000000000..cf111ec1623390a3dbbf489235d2ed387624a36c --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_cupy.py @@ -0,0 +1,56 @@ +from sympy.concrete.summations import Sum +from sympy.functions.elementary.exponential import log +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.utilities.lambdify import lambdify +from sympy.abc import x, i, a, b +from sympy.codegen.numpy_nodes import logaddexp +from sympy.printing.numpy import CuPyPrinter, _cupy_known_constants, _cupy_known_functions + +from sympy.testing.pytest import skip, raises +from sympy.external import import_module + +cp = import_module('cupy') + +def test_cupy_print(): + prntr = CuPyPrinter() + assert prntr.doprint(logaddexp(a, b)) == 'cupy.logaddexp(a, b)' + assert prntr.doprint(sqrt(x)) == 'cupy.sqrt(x)' + assert prntr.doprint(log(x)) == 'cupy.log(x)' + assert prntr.doprint("acos(x)") == 'cupy.arccos(x)' + assert prntr.doprint("exp(x)") == 'cupy.exp(x)' + assert prntr.doprint("Abs(x)") == 'abs(x)' + +def test_not_cupy_print(): + prntr = CuPyPrinter() + with raises(NotImplementedError): + prntr.doprint("abcd(x)") + +def test_cupy_sum(): + if not cp: + skip("CuPy not installed") + + s = Sum(x ** i, (i, a, b)) + f = lambdify((a, b, x), s, 'cupy') + + a_, b_ = 0, 10 + x_ = cp.linspace(-1, +1, 10) + assert cp.allclose(f(a_, b_, x_), sum(x_ ** i_ for i_ in range(a_, b_ + 1))) + + s = Sum(i * x, (i, a, b)) + f = lambdify((a, b, x), s, 'numpy') + + a_, b_ = 0, 10 + x_ = cp.linspace(-1, +1, 10) + assert cp.allclose(f(a_, b_, x_), sum(i_ * x_ for i_ in range(a_, b_ + 1))) + +def test_cupy_known_funcs_consts(): + assert _cupy_known_constants['NaN'] == 'cupy.nan' + assert _cupy_known_constants['EulerGamma'] == 'cupy.euler_gamma' + + assert _cupy_known_functions['acos'] == 'cupy.arccos' + assert _cupy_known_functions['log'] == 'cupy.log' + +def test_cupy_print_methods(): + prntr = CuPyPrinter() + assert hasattr(prntr, '_print_acos') + assert hasattr(prntr, '_print_log') diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_cxx.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_cxx.py new file mode 100644 index 0000000000000000000000000000000000000000..d84ec75cbf0eeb60a1176b9cb3b401a3384454e7 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_cxx.py @@ -0,0 +1,86 @@ +from sympy.core.numbers import Float, Integer, Rational +from sympy.core.symbol import symbols +from sympy.functions import beta, Ei, zeta, Max, Min, sqrt, riemann_xi, frac +from sympy.printing.cxx import CXX98CodePrinter, CXX11CodePrinter, CXX17CodePrinter, cxxcode +from sympy.codegen.cfunctions import log1p + + +x, y, u, v = symbols('x y u v') + + +def test_CXX98CodePrinter(): + assert CXX98CodePrinter().doprint(Max(x, 3)) in ('std::max(x, 3)', 'std::max(3, x)') + assert CXX98CodePrinter().doprint(Min(x, 3, sqrt(x))) == 'std::min(3, std::min(x, std::sqrt(x)))' + cxx98printer = CXX98CodePrinter() + assert cxx98printer.language == 'C++' + assert cxx98printer.standard == 'C++98' + assert 'template' in cxx98printer.reserved_words + assert 'alignas' not in cxx98printer.reserved_words + + +def test_CXX11CodePrinter(): + assert CXX11CodePrinter().doprint(log1p(x)) == 'std::log1p(x)' + + cxx11printer = CXX11CodePrinter() + assert cxx11printer.language == 'C++' + assert cxx11printer.standard == 'C++11' + assert 'operator' in cxx11printer.reserved_words + assert 'noexcept' in cxx11printer.reserved_words + assert 'concept' not in cxx11printer.reserved_words + + +def test_subclass_print_method(): + class MyPrinter(CXX11CodePrinter): + def _print_log1p(self, expr): + return 'my_library::log1p(%s)' % ', '.join(map(self._print, expr.args)) + + assert MyPrinter().doprint(log1p(x)) == 'my_library::log1p(x)' + + +def test_subclass_print_method__ns(): + class MyPrinter(CXX11CodePrinter): + _ns = 'my_library::' + + p = CXX11CodePrinter() + myp = MyPrinter() + + assert p.doprint(log1p(x)) == 'std::log1p(x)' + assert myp.doprint(log1p(x)) == 'my_library::log1p(x)' + + +def test_CXX17CodePrinter(): + assert CXX17CodePrinter().doprint(beta(x, y)) == 'std::beta(x, y)' + assert CXX17CodePrinter().doprint(Ei(x)) == 'std::expint(x)' + assert CXX17CodePrinter().doprint(zeta(x)) == 'std::riemann_zeta(x)' + + # Automatic rewrite + assert CXX17CodePrinter().doprint(frac(x)) == '(x - std::floor(x))' + assert CXX17CodePrinter().doprint(riemann_xi(x)) == '((1.0/2.0)*std::pow(M_PI, -1.0/2.0*x)*x*(x - 1)*std::tgamma((1.0/2.0)*x)*std::riemann_zeta(x))' + + +def test_cxxcode(): + assert sorted(cxxcode(sqrt(x)*.5).split('*')) == sorted(['0.5', 'std::sqrt(x)']) + +def test_cxxcode_nested_minmax(): + assert cxxcode(Max(Min(x, y), Min(u, v))) \ + == 'std::max(std::min(u, v), std::min(x, y))' + assert cxxcode(Min(Max(x, y), Max(u, v))) \ + == 'std::min(std::max(u, v), std::max(x, y))' + +def test_subclass_Integer_Float(): + class MyPrinter(CXX17CodePrinter): + def _print_Integer(self, arg): + return 'bigInt("%s")' % super()._print_Integer(arg) + + def _print_Float(self, arg): + rat = Rational(arg) + return 'bigFloat(%s, %s)' % ( + self._print(Integer(rat.p)), + self._print(Integer(rat.q)) + ) + + p = MyPrinter() + for i in range(13): + assert p.doprint(i) == 'bigInt("%d")' % i + assert p.doprint(Float(0.5)) == 'bigFloat(bigInt("1"), bigInt("2"))' + assert p.doprint(x**-1.0) == 'bigFloat(bigInt("1"), bigInt("1"))/x' diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_dot.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_dot.py new file mode 100644 index 0000000000000000000000000000000000000000..6213e237fb7aac6460a956b4c9fc1f7c8710fec6 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_dot.py @@ -0,0 +1,134 @@ +from sympy.printing.dot import (purestr, styleof, attrprint, dotnode, + dotedges, dotprint) +from sympy.core.basic import Basic +from sympy.core.expr import Expr +from sympy.core.numbers import (Float, Integer) +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.printing.repr import srepr +from sympy.abc import x + + +def test_purestr(): + assert purestr(Symbol('x')) == "Symbol('x')" + assert purestr(Basic(S(1), S(2))) == "Basic(Integer(1), Integer(2))" + assert purestr(Float(2)) == "Float('2.0', precision=53)" + + assert purestr(Symbol('x'), with_args=True) == ("Symbol('x')", ()) + assert purestr(Basic(S(1), S(2)), with_args=True) == \ + ('Basic(Integer(1), Integer(2))', ('Integer(1)', 'Integer(2)')) + assert purestr(Float(2), with_args=True) == \ + ("Float('2.0', precision=53)", ()) + + +def test_styleof(): + styles = [(Basic, {'color': 'blue', 'shape': 'ellipse'}), + (Expr, {'color': 'black'})] + assert styleof(Basic(S(1)), styles) == {'color': 'blue', 'shape': 'ellipse'} + + assert styleof(x + 1, styles) == {'color': 'black', 'shape': 'ellipse'} + + +def test_attrprint(): + assert attrprint({'color': 'blue', 'shape': 'ellipse'}) == \ + '"color"="blue", "shape"="ellipse"' + +def test_dotnode(): + + assert dotnode(x, repeat=False) == \ + '"Symbol(\'x\')" ["color"="black", "label"="x", "shape"="ellipse"];' + assert dotnode(x+2, repeat=False) == \ + '"Add(Integer(2), Symbol(\'x\'))" ' \ + '["color"="black", "label"="Add", "shape"="ellipse"];', \ + dotnode(x+2,repeat=0) + + assert dotnode(x + x**2, repeat=False) == \ + '"Add(Symbol(\'x\'), Pow(Symbol(\'x\'), Integer(2)))" ' \ + '["color"="black", "label"="Add", "shape"="ellipse"];' + assert dotnode(x + x**2, repeat=True) == \ + '"Add(Symbol(\'x\'), Pow(Symbol(\'x\'), Integer(2)))_()" ' \ + '["color"="black", "label"="Add", "shape"="ellipse"];' + +def test_dotedges(): + assert sorted(dotedges(x+2, repeat=False)) == [ + '"Add(Integer(2), Symbol(\'x\'))" -> "Integer(2)";', + '"Add(Integer(2), Symbol(\'x\'))" -> "Symbol(\'x\')";' + ] + assert sorted(dotedges(x + 2, repeat=True)) == [ + '"Add(Integer(2), Symbol(\'x\'))_()" -> "Integer(2)_(0,)";', + '"Add(Integer(2), Symbol(\'x\'))_()" -> "Symbol(\'x\')_(1,)";' + ] + +def test_dotprint(): + text = dotprint(x+2, repeat=False) + assert all(e in text for e in dotedges(x+2, repeat=False)) + assert all( + n in text for n in [dotnode(expr, repeat=False) + for expr in (x, Integer(2), x+2)]) + assert 'digraph' in text + + text = dotprint(x+x**2, repeat=False) + assert all(e in text for e in dotedges(x+x**2, repeat=False)) + assert all( + n in text for n in [dotnode(expr, repeat=False) + for expr in (x, Integer(2), x**2)]) + assert 'digraph' in text + + text = dotprint(x+x**2, repeat=True) + assert all(e in text for e in dotedges(x+x**2, repeat=True)) + assert all( + n in text for n in [dotnode(expr, pos=()) + for expr in [x + x**2]]) + + text = dotprint(x**x, repeat=True) + assert all(e in text for e in dotedges(x**x, repeat=True)) + assert all( + n in text for n in [dotnode(x, pos=(0,)), dotnode(x, pos=(1,))]) + assert 'digraph' in text + +def test_dotprint_depth(): + text = dotprint(3*x+2, depth=1) + assert dotnode(3*x+2) in text + assert dotnode(x) not in text + text = dotprint(3*x+2) + assert "depth" not in text + +def test_Matrix_and_non_basics(): + from sympy.matrices.expressions.matexpr import MatrixSymbol + n = Symbol('n') + assert dotprint(MatrixSymbol('X', n, n)) == \ +"""digraph{ + +# Graph style +"ordering"="out" +"rankdir"="TD" + +######### +# Nodes # +######### + +"MatrixSymbol(Str('X'), Symbol('n'), Symbol('n'))_()" ["color"="black", "label"="MatrixSymbol", "shape"="ellipse"]; +"Str('X')_(0,)" ["color"="blue", "label"="X", "shape"="ellipse"]; +"Symbol('n')_(1,)" ["color"="black", "label"="n", "shape"="ellipse"]; +"Symbol('n')_(2,)" ["color"="black", "label"="n", "shape"="ellipse"]; + +######### +# Edges # +######### + +"MatrixSymbol(Str('X'), Symbol('n'), Symbol('n'))_()" -> "Str('X')_(0,)"; +"MatrixSymbol(Str('X'), Symbol('n'), Symbol('n'))_()" -> "Symbol('n')_(1,)"; +"MatrixSymbol(Str('X'), Symbol('n'), Symbol('n'))_()" -> "Symbol('n')_(2,)"; +}""" + + +def test_labelfunc(): + text = dotprint(x + 2, labelfunc=srepr) + assert "Symbol('x')" in text + assert "Integer(2)" in text + + +def test_commutative(): + x, y = symbols('x y', commutative=False) + assert dotprint(x + y) == dotprint(y + x) + assert dotprint(x*y) != dotprint(y*x) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_fortran.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_fortran.py new file mode 100644 index 0000000000000000000000000000000000000000..c28a1ea16dcf2157b58d763286428dccc1944b71 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_fortran.py @@ -0,0 +1,854 @@ +from sympy.core.add import Add +from sympy.core.expr import Expr +from sympy.core.function import (Function, Lambda, diff) +from sympy.core.mod import Mod +from sympy.core import (Catalan, EulerGamma, GoldenRatio) +from sympy.core.numbers import (E, Float, I, Integer, Rational, pi) +from sympy.core.relational import Eq +from sympy.core.singleton import S +from sympy.core.symbol import (Dummy, symbols) +from sympy.functions.combinatorial.factorials import factorial +from sympy.functions.elementary.complexes import (conjugate, sign) +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.piecewise import Piecewise +from sympy.functions.elementary.trigonometric import (atan2, cos, sin) +from sympy.functions.special.gamma_functions import gamma +from sympy.integrals.integrals import Integral +from sympy.sets.fancysets import Range + +from sympy.codegen import For, Assignment, aug_assign +from sympy.codegen.ast import Declaration, Variable, float32, float64, \ + value_const, real, bool_, While, FunctionPrototype, FunctionDefinition, \ + integer, Return, Element +from sympy.core.expr import UnevaluatedExpr +from sympy.core.relational import Relational +from sympy.logic.boolalg import And, Or, Not, Equivalent, Xor +from sympy.matrices import Matrix, MatrixSymbol +from sympy.printing.fortran import fcode, FCodePrinter +from sympy.tensor import IndexedBase, Idx +from sympy.tensor.array.expressions import ArraySymbol, ArrayElement +from sympy.utilities.lambdify import implemented_function +from sympy.testing.pytest import raises + + +def test_UnevaluatedExpr(): + p, q, r = symbols("p q r", real=True) + q_r = UnevaluatedExpr(q + r) + expr = abs(exp(p+q_r)) + assert fcode(expr, source_format="free") == "exp(p + (q + r))" + x, y, z = symbols("x y z") + y_z = UnevaluatedExpr(y + z) + expr2 = abs(exp(x+y_z)) + assert fcode(expr2, human=False)[2].lstrip() == "exp(re(x) + re(y + z))" + assert fcode(expr2, user_functions={"re": "realpart"}).lstrip() == "exp(realpart(x) + realpart(y + z))" + + +def test_printmethod(): + x = symbols('x') + + class nint(Function): + def _fcode(self, printer): + return "nint(%s)" % printer._print(self.args[0]) + assert fcode(nint(x)) == " nint(x)" + + +def test_fcode_sign(): #issue 12267 + x=symbols('x') + y=symbols('y', integer=True) + z=symbols('z', complex=True) + assert fcode(sign(x), standard=95, source_format='free') == "merge(0d0, dsign(1d0, x), x == 0d0)" + assert fcode(sign(y), standard=95, source_format='free') == "merge(0, isign(1, y), y == 0)" + assert fcode(sign(z), standard=95, source_format='free') == "merge(cmplx(0d0, 0d0), z/abs(z), abs(z) == 0d0)" + raises(NotImplementedError, lambda: fcode(sign(x))) + + +def test_fcode_Pow(): + x, y = symbols('x,y') + n = symbols('n', integer=True) + + assert fcode(x**3) == " x**3" + assert fcode(x**(y**3)) == " x**(y**3)" + assert fcode(1/(sin(x)*3.5)**(x - y**x)/(x**2 + y)) == \ + " (3.5d0*sin(x))**(-x + y**x)/(x**2 + y)" + assert fcode(sqrt(x)) == ' sqrt(x)' + assert fcode(sqrt(n)) == ' sqrt(dble(n))' + assert fcode(x**0.5) == ' sqrt(x)' + assert fcode(sqrt(x)) == ' sqrt(x)' + assert fcode(sqrt(10)) == ' sqrt(10.0d0)' + assert fcode(x**-1.0) == ' 1d0/x' + assert fcode(x**-2.0, 'y', source_format='free') == 'y = x**(-2.0d0)' # 2823 + assert fcode(x**Rational(3, 7)) == ' x**(3.0d0/7.0d0)' + + +def test_fcode_Rational(): + x = symbols('x') + assert fcode(Rational(3, 7)) == " 3.0d0/7.0d0" + assert fcode(Rational(18, 9)) == " 2" + assert fcode(Rational(3, -7)) == " -3.0d0/7.0d0" + assert fcode(Rational(-3, -7)) == " 3.0d0/7.0d0" + assert fcode(x + Rational(3, 7)) == " x + 3.0d0/7.0d0" + assert fcode(Rational(3, 7)*x) == " (3.0d0/7.0d0)*x" + + +def test_fcode_Integer(): + assert fcode(Integer(67)) == " 67" + assert fcode(Integer(-1)) == " -1" + + +def test_fcode_Float(): + assert fcode(Float(42.0)) == " 42.0000000000000d0" + assert fcode(Float(-1e20)) == " -1.00000000000000d+20" + + +def test_fcode_functions(): + x, y = symbols('x,y') + assert fcode(sin(x) ** cos(y)) == " sin(x)**cos(y)" + raises(NotImplementedError, lambda: fcode(Mod(x, y), standard=66)) + raises(NotImplementedError, lambda: fcode(x % y, standard=66)) + raises(NotImplementedError, lambda: fcode(Mod(x, y), standard=77)) + raises(NotImplementedError, lambda: fcode(x % y, standard=77)) + for standard in [90, 95, 2003, 2008]: + assert fcode(Mod(x, y), standard=standard) == " modulo(x, y)" + assert fcode(x % y, standard=standard) == " modulo(x, y)" + + +def test_case(): + ob = FCodePrinter() + x,x_,x__,y,X,X_,Y = symbols('x,x_,x__,y,X,X_,Y') + assert fcode(exp(x_) + sin(x*y) + cos(X*Y)) == \ + ' exp(x_) + sin(x*y) + cos(X__*Y_)' + assert fcode(exp(x__) + 2*x*Y*X_**Rational(7, 2)) == \ + ' 2*X_**(7.0d0/2.0d0)*Y*x + exp(x__)' + assert fcode(exp(x_) + sin(x*y) + cos(X*Y), name_mangling=False) == \ + ' exp(x_) + sin(x*y) + cos(X*Y)' + assert fcode(x - cos(X), name_mangling=False) == ' x - cos(X)' + assert ob.doprint(X*sin(x) + x_, assign_to='me') == ' me = X*sin(x_) + x__' + assert ob.doprint(X*sin(x), assign_to='mu') == ' mu = X*sin(x_)' + assert ob.doprint(x_, assign_to='ad') == ' ad = x__' + n, m = symbols('n,m', integer=True) + A = IndexedBase('A') + x = IndexedBase('x') + y = IndexedBase('y') + i = Idx('i', m) + I = Idx('I', n) + assert fcode(A[i, I]*x[I], assign_to=y[i], source_format='free') == ( + "do i = 1, m\n" + " y(i) = 0\n" + "end do\n" + "do i = 1, m\n" + " do I_ = 1, n\n" + " y(i) = A(i, I_)*x(I_) + y(i)\n" + " end do\n" + "end do" ) + + +#issue 6814 +def test_fcode_functions_with_integers(): + x= symbols('x') + log10_17 = log(10).evalf(17) + loglog10_17 = '0.8340324452479558d0' + assert fcode(x * log(10)) == " x*%sd0" % log10_17 + assert fcode(x * log(10)) == " x*%sd0" % log10_17 + assert fcode(x * log(S(10))) == " x*%sd0" % log10_17 + assert fcode(log(S(10))) == " %sd0" % log10_17 + assert fcode(exp(10)) == " %sd0" % exp(10).evalf(17) + assert fcode(x * log(log(10))) == " x*%s" % loglog10_17 + assert fcode(x * log(log(S(10)))) == " x*%s" % loglog10_17 + + +def test_fcode_NumberSymbol(): + prec = 17 + p = FCodePrinter() + assert fcode(Catalan) == ' parameter (Catalan = %sd0)\n Catalan' % Catalan.evalf(prec) + assert fcode(EulerGamma) == ' parameter (EulerGamma = %sd0)\n EulerGamma' % EulerGamma.evalf(prec) + assert fcode(E) == ' parameter (E = %sd0)\n E' % E.evalf(prec) + assert fcode(GoldenRatio) == ' parameter (GoldenRatio = %sd0)\n GoldenRatio' % GoldenRatio.evalf(prec) + assert fcode(pi) == ' parameter (pi = %sd0)\n pi' % pi.evalf(prec) + assert fcode( + pi, precision=5) == ' parameter (pi = %sd0)\n pi' % pi.evalf(5) + assert fcode(Catalan, human=False) == ({ + (Catalan, p._print(Catalan.evalf(prec)))}, set(), ' Catalan') + assert fcode(EulerGamma, human=False) == ({(EulerGamma, p._print( + EulerGamma.evalf(prec)))}, set(), ' EulerGamma') + assert fcode(E, human=False) == ( + {(E, p._print(E.evalf(prec)))}, set(), ' E') + assert fcode(GoldenRatio, human=False) == ({(GoldenRatio, p._print( + GoldenRatio.evalf(prec)))}, set(), ' GoldenRatio') + assert fcode(pi, human=False) == ( + {(pi, p._print(pi.evalf(prec)))}, set(), ' pi') + assert fcode(pi, precision=5, human=False) == ( + {(pi, p._print(pi.evalf(5)))}, set(), ' pi') + + +def test_fcode_complex(): + assert fcode(I) == " cmplx(0,1)" + x = symbols('x') + assert fcode(4*I) == " cmplx(0,4)" + assert fcode(3 + 4*I) == " cmplx(3,4)" + assert fcode(3 + 4*I + x) == " cmplx(3,4) + x" + assert fcode(I*x) == " cmplx(0,1)*x" + assert fcode(3 + 4*I - x) == " cmplx(3,4) - x" + x = symbols('x', imaginary=True) + assert fcode(5*x) == " 5*x" + assert fcode(I*x) == " cmplx(0,1)*x" + assert fcode(3 + x) == " x + 3" + + +def test_implicit(): + x, y = symbols('x,y') + assert fcode(sin(x)) == " sin(x)" + assert fcode(atan2(x, y)) == " atan2(x, y)" + assert fcode(conjugate(x)) == " conjg(x)" + + +def test_not_fortran(): + x = symbols('x') + g = Function('g') + with raises(NotImplementedError): + fcode(gamma(x)) + assert fcode(Integral(sin(x)), strict=False) == "C Not supported in Fortran:\nC Integral\n Integral(sin(x), x)" + with raises(NotImplementedError): + fcode(g(x)) + + +def test_user_functions(): + x = symbols('x') + assert fcode(sin(x), user_functions={"sin": "zsin"}) == " zsin(x)" + x = symbols('x') + assert fcode( + gamma(x), user_functions={"gamma": "mygamma"}) == " mygamma(x)" + g = Function('g') + assert fcode(g(x), user_functions={"g": "great"}) == " great(x)" + n = symbols('n', integer=True) + assert fcode( + factorial(n), user_functions={"factorial": "fct"}) == " fct(n)" + + +def test_inline_function(): + x = symbols('x') + g = implemented_function('g', Lambda(x, 2*x)) + assert fcode(g(x)) == " 2*x" + g = implemented_function('g', Lambda(x, 2*pi/x)) + assert fcode(g(x)) == ( + " parameter (pi = %sd0)\n" + " 2*pi/x" + ) % pi.evalf(17) + A = IndexedBase('A') + i = Idx('i', symbols('n', integer=True)) + g = implemented_function('g', Lambda(x, x*(1 + x)*(2 + x))) + assert fcode(g(A[i]), assign_to=A[i]) == ( + " do i = 1, n\n" + " A(i) = (A(i) + 1)*(A(i) + 2)*A(i)\n" + " end do" + ) + + +def test_assign_to(): + x = symbols('x') + assert fcode(sin(x), assign_to="s") == " s = sin(x)" + + +def test_line_wrapping(): + x, y = symbols('x,y') + assert fcode(((x + y)**10).expand(), assign_to="var") == ( + " var = x**10 + 10*x**9*y + 45*x**8*y**2 + 120*x**7*y**3 + 210*x**6*\n" + " @ y**4 + 252*x**5*y**5 + 210*x**4*y**6 + 120*x**3*y**7 + 45*x**2*y\n" + " @ **8 + 10*x*y**9 + y**10" + ) + e = [x**i for i in range(11)] + assert fcode(Add(*e)) == ( + " x**10 + x**9 + x**8 + x**7 + x**6 + x**5 + x**4 + x**3 + x**2 + x\n" + " @ + 1" + ) + + +def test_fcode_precedence(): + x, y = symbols("x y") + assert fcode(And(x < y, y < x + 1), source_format="free") == \ + "x < y .and. y < x + 1" + assert fcode(Or(x < y, y < x + 1), source_format="free") == \ + "x < y .or. y < x + 1" + assert fcode(Xor(x < y, y < x + 1, evaluate=False), + source_format="free") == "x < y .neqv. y < x + 1" + assert fcode(Equivalent(x < y, y < x + 1), source_format="free") == \ + "x < y .eqv. y < x + 1" + + +def test_fcode_Logical(): + x, y, z = symbols("x y z") + # unary Not + assert fcode(Not(x), source_format="free") == ".not. x" + # binary And + assert fcode(And(x, y), source_format="free") == "x .and. y" + assert fcode(And(x, Not(y)), source_format="free") == "x .and. .not. y" + assert fcode(And(Not(x), y), source_format="free") == "y .and. .not. x" + assert fcode(And(Not(x), Not(y)), source_format="free") == \ + ".not. x .and. .not. y" + assert fcode(Not(And(x, y), evaluate=False), source_format="free") == \ + ".not. (x .and. y)" + # binary Or + assert fcode(Or(x, y), source_format="free") == "x .or. y" + assert fcode(Or(x, Not(y)), source_format="free") == "x .or. .not. y" + assert fcode(Or(Not(x), y), source_format="free") == "y .or. .not. x" + assert fcode(Or(Not(x), Not(y)), source_format="free") == \ + ".not. x .or. .not. y" + assert fcode(Not(Or(x, y), evaluate=False), source_format="free") == \ + ".not. (x .or. y)" + # mixed And/Or + assert fcode(And(Or(y, z), x), source_format="free") == "x .and. (y .or. z)" + assert fcode(And(Or(z, x), y), source_format="free") == "y .and. (x .or. z)" + assert fcode(And(Or(x, y), z), source_format="free") == "z .and. (x .or. y)" + assert fcode(Or(And(y, z), x), source_format="free") == "x .or. y .and. z" + assert fcode(Or(And(z, x), y), source_format="free") == "y .or. x .and. z" + assert fcode(Or(And(x, y), z), source_format="free") == "z .or. x .and. y" + # trinary And + assert fcode(And(x, y, z), source_format="free") == "x .and. y .and. z" + assert fcode(And(x, y, Not(z)), source_format="free") == \ + "x .and. y .and. .not. z" + assert fcode(And(x, Not(y), z), source_format="free") == \ + "x .and. z .and. .not. y" + assert fcode(And(Not(x), y, z), source_format="free") == \ + "y .and. z .and. .not. x" + assert fcode(Not(And(x, y, z), evaluate=False), source_format="free") == \ + ".not. (x .and. y .and. z)" + # trinary Or + assert fcode(Or(x, y, z), source_format="free") == "x .or. y .or. z" + assert fcode(Or(x, y, Not(z)), source_format="free") == \ + "x .or. y .or. .not. z" + assert fcode(Or(x, Not(y), z), source_format="free") == \ + "x .or. z .or. .not. y" + assert fcode(Or(Not(x), y, z), source_format="free") == \ + "y .or. z .or. .not. x" + assert fcode(Not(Or(x, y, z), evaluate=False), source_format="free") == \ + ".not. (x .or. y .or. z)" + + +def test_fcode_Xlogical(): + x, y, z = symbols("x y z") + # binary Xor + assert fcode(Xor(x, y, evaluate=False), source_format="free") == \ + "x .neqv. y" + assert fcode(Xor(x, Not(y), evaluate=False), source_format="free") == \ + "x .neqv. .not. y" + assert fcode(Xor(Not(x), y, evaluate=False), source_format="free") == \ + "y .neqv. .not. x" + assert fcode(Xor(Not(x), Not(y), evaluate=False), + source_format="free") == ".not. x .neqv. .not. y" + assert fcode(Not(Xor(x, y, evaluate=False), evaluate=False), + source_format="free") == ".not. (x .neqv. y)" + # binary Equivalent + assert fcode(Equivalent(x, y), source_format="free") == "x .eqv. y" + assert fcode(Equivalent(x, Not(y)), source_format="free") == \ + "x .eqv. .not. y" + assert fcode(Equivalent(Not(x), y), source_format="free") == \ + "y .eqv. .not. x" + assert fcode(Equivalent(Not(x), Not(y)), source_format="free") == \ + ".not. x .eqv. .not. y" + assert fcode(Not(Equivalent(x, y), evaluate=False), + source_format="free") == ".not. (x .eqv. y)" + # mixed And/Equivalent + assert fcode(Equivalent(And(y, z), x), source_format="free") == \ + "x .eqv. y .and. z" + assert fcode(Equivalent(And(z, x), y), source_format="free") == \ + "y .eqv. x .and. z" + assert fcode(Equivalent(And(x, y), z), source_format="free") == \ + "z .eqv. x .and. y" + assert fcode(And(Equivalent(y, z), x), source_format="free") == \ + "x .and. (y .eqv. z)" + assert fcode(And(Equivalent(z, x), y), source_format="free") == \ + "y .and. (x .eqv. z)" + assert fcode(And(Equivalent(x, y), z), source_format="free") == \ + "z .and. (x .eqv. y)" + # mixed Or/Equivalent + assert fcode(Equivalent(Or(y, z), x), source_format="free") == \ + "x .eqv. y .or. z" + assert fcode(Equivalent(Or(z, x), y), source_format="free") == \ + "y .eqv. x .or. z" + assert fcode(Equivalent(Or(x, y), z), source_format="free") == \ + "z .eqv. x .or. y" + assert fcode(Or(Equivalent(y, z), x), source_format="free") == \ + "x .or. (y .eqv. z)" + assert fcode(Or(Equivalent(z, x), y), source_format="free") == \ + "y .or. (x .eqv. z)" + assert fcode(Or(Equivalent(x, y), z), source_format="free") == \ + "z .or. (x .eqv. y)" + # mixed Xor/Equivalent + assert fcode(Equivalent(Xor(y, z, evaluate=False), x), + source_format="free") == "x .eqv. (y .neqv. z)" + assert fcode(Equivalent(Xor(z, x, evaluate=False), y), + source_format="free") == "y .eqv. (x .neqv. z)" + assert fcode(Equivalent(Xor(x, y, evaluate=False), z), + source_format="free") == "z .eqv. (x .neqv. y)" + assert fcode(Xor(Equivalent(y, z), x, evaluate=False), + source_format="free") == "x .neqv. (y .eqv. z)" + assert fcode(Xor(Equivalent(z, x), y, evaluate=False), + source_format="free") == "y .neqv. (x .eqv. z)" + assert fcode(Xor(Equivalent(x, y), z, evaluate=False), + source_format="free") == "z .neqv. (x .eqv. y)" + # mixed And/Xor + assert fcode(Xor(And(y, z), x, evaluate=False), source_format="free") == \ + "x .neqv. y .and. z" + assert fcode(Xor(And(z, x), y, evaluate=False), source_format="free") == \ + "y .neqv. x .and. z" + assert fcode(Xor(And(x, y), z, evaluate=False), source_format="free") == \ + "z .neqv. x .and. y" + assert fcode(And(Xor(y, z, evaluate=False), x), source_format="free") == \ + "x .and. (y .neqv. z)" + assert fcode(And(Xor(z, x, evaluate=False), y), source_format="free") == \ + "y .and. (x .neqv. z)" + assert fcode(And(Xor(x, y, evaluate=False), z), source_format="free") == \ + "z .and. (x .neqv. y)" + # mixed Or/Xor + assert fcode(Xor(Or(y, z), x, evaluate=False), source_format="free") == \ + "x .neqv. y .or. z" + assert fcode(Xor(Or(z, x), y, evaluate=False), source_format="free") == \ + "y .neqv. x .or. z" + assert fcode(Xor(Or(x, y), z, evaluate=False), source_format="free") == \ + "z .neqv. x .or. y" + assert fcode(Or(Xor(y, z, evaluate=False), x), source_format="free") == \ + "x .or. (y .neqv. z)" + assert fcode(Or(Xor(z, x, evaluate=False), y), source_format="free") == \ + "y .or. (x .neqv. z)" + assert fcode(Or(Xor(x, y, evaluate=False), z), source_format="free") == \ + "z .or. (x .neqv. y)" + # trinary Xor + assert fcode(Xor(x, y, z, evaluate=False), source_format="free") == \ + "x .neqv. y .neqv. z" + assert fcode(Xor(x, y, Not(z), evaluate=False), source_format="free") == \ + "x .neqv. y .neqv. .not. z" + assert fcode(Xor(x, Not(y), z, evaluate=False), source_format="free") == \ + "x .neqv. z .neqv. .not. y" + assert fcode(Xor(Not(x), y, z, evaluate=False), source_format="free") == \ + "y .neqv. z .neqv. .not. x" + + +def test_fcode_Relational(): + x, y = symbols("x y") + assert fcode(Relational(x, y, "=="), source_format="free") == "x == y" + assert fcode(Relational(x, y, "!="), source_format="free") == "x /= y" + assert fcode(Relational(x, y, ">="), source_format="free") == "x >= y" + assert fcode(Relational(x, y, "<="), source_format="free") == "x <= y" + assert fcode(Relational(x, y, ">"), source_format="free") == "x > y" + assert fcode(Relational(x, y, "<"), source_format="free") == "x < y" + + +def test_fcode_Piecewise(): + x = symbols('x') + expr = Piecewise((x, x < 1), (x**2, True)) + # Check that inline conditional (merge) fails if standard isn't 95+ + raises(NotImplementedError, lambda: fcode(expr)) + code = fcode(expr, standard=95) + expected = " merge(x, x**2, x < 1)" + assert code == expected + assert fcode(Piecewise((x, x < 1), (x**2, True)), assign_to="var") == ( + " if (x < 1) then\n" + " var = x\n" + " else\n" + " var = x**2\n" + " end if" + ) + a = cos(x)/x + b = sin(x)/x + for i in range(10): + a = diff(a, x) + b = diff(b, x) + expected = ( + " if (x < 0) then\n" + " weird_name = -cos(x)/x + 10*sin(x)/x**2 + 90*cos(x)/x**3 - 720*\n" + " @ sin(x)/x**4 - 5040*cos(x)/x**5 + 30240*sin(x)/x**6 + 151200*cos(x\n" + " @ )/x**7 - 604800*sin(x)/x**8 - 1814400*cos(x)/x**9 + 3628800*sin(x\n" + " @ )/x**10 + 3628800*cos(x)/x**11\n" + " else\n" + " weird_name = -sin(x)/x - 10*cos(x)/x**2 + 90*sin(x)/x**3 + 720*\n" + " @ cos(x)/x**4 - 5040*sin(x)/x**5 - 30240*cos(x)/x**6 + 151200*sin(x\n" + " @ )/x**7 + 604800*cos(x)/x**8 - 1814400*sin(x)/x**9 - 3628800*cos(x\n" + " @ )/x**10 + 3628800*sin(x)/x**11\n" + " end if" + ) + code = fcode(Piecewise((a, x < 0), (b, True)), assign_to="weird_name") + assert code == expected + code = fcode(Piecewise((x, x < 1), (x**2, x > 1), (sin(x), True)), standard=95) + expected = " merge(x, merge(x**2, sin(x), x > 1), x < 1)" + assert code == expected + # Check that Piecewise without a True (default) condition error + expr = Piecewise((x, x < 1), (x**2, x > 1), (sin(x), x > 0)) + raises(ValueError, lambda: fcode(expr)) + + +def test_wrap_fortran(): + # "########################################################################" + printer = FCodePrinter() + lines = [ + "C This is a long comment on a single line that must be wrapped properly to produce nice output", + " this = is + a + long + and + nasty + fortran + statement + that * must + be + wrapped + properly", + " this = is + a + long + and + nasty + fortran + statement + that * must + be + wrapped + properly", + " this = is + a + long + and + nasty + fortran + statement + that * must + be + wrapped + properly", + " this = is + a + long + and + nasty + fortran + statement + that*must + be + wrapped + properly", + " this = is + a + long + and + nasty + fortran + statement + that*must + be + wrapped + properly", + " this = is + a + long + and + nasty + fortran + statement + that*must + be + wrapped + properly", + " this = is + a + long + and + nasty + fortran + statement + that*must + be + wrapped + properly", + " this = is + a + long + and + nasty + fortran + statement + that**must + be + wrapped + properly", + " this = is + a + long + and + nasty + fortran + statement + that**must + be + wrapped + properly", + " this = is + a + long + and + nasty + fortran + statement + that**must + be + wrapped + properly", + " this = is + a + long + and + nasty + fortran + statement + that**must + be + wrapped + properly", + " this = is + a + long + and + nasty + fortran + statement + that**must + be + wrapped + properly", + " this = is + a + long + and + nasty + fortran + statement(that)/must + be + wrapped + properly", + " this = is + a + long + and + nasty + fortran + statement(that)/must + be + wrapped + properly", + ] + wrapped_lines = printer._wrap_fortran(lines) + expected_lines = [ + "C This is a long comment on a single line that must be wrapped", + "C properly to produce nice output", + " this = is + a + long + and + nasty + fortran + statement + that *", + " @ must + be + wrapped + properly", + " this = is + a + long + and + nasty + fortran + statement + that *", + " @ must + be + wrapped + properly", + " this = is + a + long + and + nasty + fortran + statement + that", + " @ * must + be + wrapped + properly", + " this = is + a + long + and + nasty + fortran + statement + that*", + " @ must + be + wrapped + properly", + " this = is + a + long + and + nasty + fortran + statement + that*", + " @ must + be + wrapped + properly", + " this = is + a + long + and + nasty + fortran + statement + that", + " @ *must + be + wrapped + properly", + " this = is + a + long + and + nasty + fortran + statement +", + " @ that*must + be + wrapped + properly", + " this = is + a + long + and + nasty + fortran + statement + that**", + " @ must + be + wrapped + properly", + " this = is + a + long + and + nasty + fortran + statement + that**", + " @ must + be + wrapped + properly", + " this = is + a + long + and + nasty + fortran + statement + that", + " @ **must + be + wrapped + properly", + " this = is + a + long + and + nasty + fortran + statement + that", + " @ **must + be + wrapped + properly", + " this = is + a + long + and + nasty + fortran + statement +", + " @ that**must + be + wrapped + properly", + " this = is + a + long + and + nasty + fortran + statement(that)/", + " @ must + be + wrapped + properly", + " this = is + a + long + and + nasty + fortran + statement(that)", + " @ /must + be + wrapped + properly", + ] + for line in wrapped_lines: + assert len(line) <= 72 + for w, e in zip(wrapped_lines, expected_lines): + assert w == e + assert len(wrapped_lines) == len(expected_lines) + + +def test_wrap_fortran_keep_d0(): + printer = FCodePrinter() + lines = [ + ' this_variable_is_very_long_because_we_try_to_test_line_break=1.0d0', + ' this_variable_is_very_long_because_we_try_to_test_line_break =1.0d0', + ' this_variable_is_very_long_because_we_try_to_test_line_break = 1.0d0', + ' this_variable_is_very_long_because_we_try_to_test_line_break = 1.0d0', + ' this_variable_is_very_long_because_we_try_to_test_line_break = 1.0d0', + ' this_variable_is_very_long_because_we_try_to_test_line_break = 10.0d0' + ] + expected = [ + ' this_variable_is_very_long_because_we_try_to_test_line_break=1.0d0', + ' this_variable_is_very_long_because_we_try_to_test_line_break =', + ' @ 1.0d0', + ' this_variable_is_very_long_because_we_try_to_test_line_break =', + ' @ 1.0d0', + ' this_variable_is_very_long_because_we_try_to_test_line_break =', + ' @ 1.0d0', + ' this_variable_is_very_long_because_we_try_to_test_line_break =', + ' @ 1.0d0', + ' this_variable_is_very_long_because_we_try_to_test_line_break =', + ' @ 10.0d0' + ] + assert printer._wrap_fortran(lines) == expected + + +def test_settings(): + raises(TypeError, lambda: fcode(S(4), method="garbage")) + + +def test_free_form_code_line(): + x, y = symbols('x,y') + assert fcode(cos(x) + sin(y), source_format='free') == "sin(y) + cos(x)" + + +def test_free_form_continuation_line(): + x, y = symbols('x,y') + result = fcode(((cos(x) + sin(y))**(7)).expand(), source_format='free') + expected = ( + 'sin(y)**7 + 7*sin(y)**6*cos(x) + 21*sin(y)**5*cos(x)**2 + 35*sin(y)**4* &\n' + ' cos(x)**3 + 35*sin(y)**3*cos(x)**4 + 21*sin(y)**2*cos(x)**5 + 7* &\n' + ' sin(y)*cos(x)**6 + cos(x)**7' + ) + assert result == expected + + +def test_free_form_comment_line(): + printer = FCodePrinter({'source_format': 'free'}) + lines = [ "! This is a long comment on a single line that must be wrapped properly to produce nice output"] + expected = [ + '! This is a long comment on a single line that must be wrapped properly', + '! to produce nice output'] + assert printer._wrap_fortran(lines) == expected + + +def test_loops(): + n, m = symbols('n,m', integer=True) + A = IndexedBase('A') + x = IndexedBase('x') + y = IndexedBase('y') + i = Idx('i', m) + j = Idx('j', n) + + expected = ( + 'do i = 1, m\n' + ' y(i) = 0\n' + 'end do\n' + 'do i = 1, m\n' + ' do j = 1, n\n' + ' y(i) = %(rhs)s\n' + ' end do\n' + 'end do' + ) + + code = fcode(A[i, j]*x[j], assign_to=y[i], source_format='free') + assert (code == expected % {'rhs': 'y(i) + A(i, j)*x(j)'} or + code == expected % {'rhs': 'y(i) + x(j)*A(i, j)'} or + code == expected % {'rhs': 'x(j)*A(i, j) + y(i)'} or + code == expected % {'rhs': 'A(i, j)*x(j) + y(i)'}) + + +def test_dummy_loops(): + i, m = symbols('i m', integer=True, cls=Dummy) + x = IndexedBase('x') + y = IndexedBase('y') + i = Idx(i, m) + + expected = ( + 'do i_%(icount)i = 1, m_%(mcount)i\n' + ' y(i_%(icount)i) = x(i_%(icount)i)\n' + 'end do' + ) % {'icount': i.label.dummy_index, 'mcount': m.dummy_index} + code = fcode(x[i], assign_to=y[i], source_format='free') + assert code == expected + + +def test_fcode_Indexed_without_looking_for_contraction(): + len_y = 5 + y = IndexedBase('y', shape=(len_y,)) + x = IndexedBase('x', shape=(len_y,)) + Dy = IndexedBase('Dy', shape=(len_y-1,)) + i = Idx('i', len_y-1) + e=Eq(Dy[i], (y[i+1]-y[i])/(x[i+1]-x[i])) + code0 = fcode(e.rhs, assign_to=e.lhs, contract=False) + assert code0.endswith('Dy(i) = (y(i + 1) - y(i))/(x(i + 1) - x(i))') + + +def test_element_like_objects(): + len_y = 5 + y = ArraySymbol('y', shape=(len_y,)) + x = ArraySymbol('x', shape=(len_y,)) + Dy = ArraySymbol('Dy', shape=(len_y-1,)) + i = Idx('i', len_y-1) + e=Eq(Dy[i], (y[i+1]-y[i])/(x[i+1]-x[i])) + code0 = fcode(Assignment(e.lhs, e.rhs)) + assert code0.endswith('Dy(i) = (y(i + 1) - y(i))/(x(i + 1) - x(i))') + + class ElementExpr(Element, Expr): + pass + + e = e.subs((a, ElementExpr(a.name, a.indices)) for a in e.atoms(ArrayElement) ) + e=Eq(Dy[i], (y[i+1]-y[i])/(x[i+1]-x[i])) + code0 = fcode(Assignment(e.lhs, e.rhs)) + assert code0.endswith('Dy(i) = (y(i + 1) - y(i))/(x(i + 1) - x(i))') + + +def test_derived_classes(): + class MyFancyFCodePrinter(FCodePrinter): + _default_settings = FCodePrinter._default_settings.copy() + + printer = MyFancyFCodePrinter() + x = symbols('x') + assert printer.doprint(sin(x), "bork") == " bork = sin(x)" + + +def test_indent(): + codelines = ( + 'subroutine test(a)\n' + 'integer :: a, i, j\n' + '\n' + 'do\n' + 'do \n' + 'do j = 1, 5\n' + 'if (a>b) then\n' + 'if(b>0) then\n' + 'a = 3\n' + 'donot_indent_me = 2\n' + 'do_not_indent_me_either = 2\n' + 'ifIam_indented_something_went_wrong = 2\n' + 'if_I_am_indented_something_went_wrong = 2\n' + 'end should not be unindented here\n' + 'end if\n' + 'endif\n' + 'end do\n' + 'end do\n' + 'enddo\n' + 'end subroutine\n' + '\n' + 'subroutine test2(a)\n' + 'integer :: a\n' + 'do\n' + 'a = a + 1\n' + 'end do \n' + 'end subroutine\n' + ) + expected = ( + 'subroutine test(a)\n' + 'integer :: a, i, j\n' + '\n' + 'do\n' + ' do \n' + ' do j = 1, 5\n' + ' if (a>b) then\n' + ' if(b>0) then\n' + ' a = 3\n' + ' donot_indent_me = 2\n' + ' do_not_indent_me_either = 2\n' + ' ifIam_indented_something_went_wrong = 2\n' + ' if_I_am_indented_something_went_wrong = 2\n' + ' end should not be unindented here\n' + ' end if\n' + ' endif\n' + ' end do\n' + ' end do\n' + 'enddo\n' + 'end subroutine\n' + '\n' + 'subroutine test2(a)\n' + 'integer :: a\n' + 'do\n' + ' a = a + 1\n' + 'end do \n' + 'end subroutine\n' + ) + p = FCodePrinter({'source_format': 'free'}) + result = p.indent_code(codelines) + assert result == expected + +def test_Matrix_printing(): + x, y, z = symbols('x,y,z') + # Test returning a Matrix + mat = Matrix([x*y, Piecewise((2 + x, y>0), (y, True)), sin(z)]) + A = MatrixSymbol('A', 3, 1) + assert fcode(mat, A) == ( + " A(1, 1) = x*y\n" + " if (y > 0) then\n" + " A(2, 1) = x + 2\n" + " else\n" + " A(2, 1) = y\n" + " end if\n" + " A(3, 1) = sin(z)") + # Test using MatrixElements in expressions + expr = Piecewise((2*A[2, 0], x > 0), (A[2, 0], True)) + sin(A[1, 0]) + A[0, 0] + assert fcode(expr, standard=95) == ( + " merge(2*A(3, 1), A(3, 1), x > 0) + sin(A(2, 1)) + A(1, 1)") + # Test using MatrixElements in a Matrix + q = MatrixSymbol('q', 5, 1) + M = MatrixSymbol('M', 3, 3) + m = Matrix([[sin(q[1,0]), 0, cos(q[2,0])], + [q[1,0] + q[2,0], q[3, 0], 5], + [2*q[4, 0]/q[1,0], sqrt(q[0,0]) + 4, 0]]) + assert fcode(m, M) == ( + " M(1, 1) = sin(q(2, 1))\n" + " M(2, 1) = q(2, 1) + q(3, 1)\n" + " M(3, 1) = 2*q(5, 1)/q(2, 1)\n" + " M(1, 2) = 0\n" + " M(2, 2) = q(4, 1)\n" + " M(3, 2) = sqrt(q(1, 1)) + 4\n" + " M(1, 3) = cos(q(3, 1))\n" + " M(2, 3) = 5\n" + " M(3, 3) = 0") + + +def test_fcode_For(): + x, y = symbols('x y') + + f = For(x, Range(0, 10, 2), [Assignment(y, x * y)]) + sol = fcode(f) + assert sol == (" do x = 0, 9, 2\n" + " y = x*y\n" + " end do") + + +def test_fcode_Declaration(): + def check(expr, ref, **kwargs): + assert fcode(expr, standard=95, source_format='free', **kwargs) == ref + + i = symbols('i', integer=True) + var1 = Variable.deduced(i) + dcl1 = Declaration(var1) + check(dcl1, "integer*4 :: i") + + + x, y = symbols('x y') + var2 = Variable(x, float32, value=42, attrs={value_const}) + dcl2b = Declaration(var2) + check(dcl2b, 'real*4, parameter :: x = 42') + + var3 = Variable(y, type=bool_) + dcl3 = Declaration(var3) + check(dcl3, 'logical :: y') + + check(float32, "real*4") + check(float64, "real*8") + check(real, "real*4", type_aliases={real: float32}) + check(real, "real*8", type_aliases={real: float64}) + + +def test_MatrixElement_printing(): + # test cases for issue #11821 + A = MatrixSymbol("A", 1, 3) + B = MatrixSymbol("B", 1, 3) + C = MatrixSymbol("C", 1, 3) + + assert(fcode(A[0, 0]) == " A(1, 1)") + assert(fcode(3 * A[0, 0]) == " 3*A(1, 1)") + + F = C[0, 0].subs(C, A - B) + assert(fcode(F) == " (A - B)(1, 1)") + + +def test_aug_assign(): + x = symbols('x') + assert fcode(aug_assign(x, '+', 1), source_format='free') == 'x = x + 1' + + +def test_While(): + x = symbols('x') + assert fcode(While(abs(x) > 1, [aug_assign(x, '-', 1)]), source_format='free') == ( + 'do while (abs(x) > 1)\n' + ' x = x - 1\n' + 'end do' + ) + + +def test_FunctionPrototype_print(): + x = symbols('x') + n = symbols('n', integer=True) + vx = Variable(x, type=real) + vn = Variable(n, type=integer) + fp1 = FunctionPrototype(real, 'power', [vx, vn]) + # Should be changed to proper test once multi-line generation is working + # see https://github.com/sympy/sympy/issues/15824 + raises(NotImplementedError, lambda: fcode(fp1)) + + +def test_FunctionDefinition_print(): + x = symbols('x') + n = symbols('n', integer=True) + vx = Variable(x, type=real) + vn = Variable(n, type=integer) + body = [Assignment(x, x**n), Return(x)] + fd1 = FunctionDefinition(real, 'power', [vx, vn], body) + # Should be changed to proper test once multi-line generation is working + # see https://github.com/sympy/sympy/issues/15824 + raises(NotImplementedError, lambda: fcode(fd1)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_glsl.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_glsl.py new file mode 100644 index 0000000000000000000000000000000000000000..86ec1dfe4a37d141e8435c369cb692d3a9a3b7bc --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_glsl.py @@ -0,0 +1,998 @@ +from sympy.core import (pi, symbols, Rational, Integer, GoldenRatio, EulerGamma, + Catalan, Lambda, Dummy, Eq, Ne, Le, Lt, Gt, Ge) +from sympy.functions import Piecewise, sin, cos, Abs, exp, ceiling, sqrt +from sympy.testing.pytest import raises, warns_deprecated_sympy +from sympy.printing.glsl import GLSLPrinter +from sympy.printing.str import StrPrinter +from sympy.utilities.lambdify import implemented_function +from sympy.tensor import IndexedBase, Idx +from sympy.matrices import Matrix, MatrixSymbol +from sympy.core import Tuple +from sympy.printing.glsl import glsl_code +import textwrap + +x, y, z = symbols('x,y,z') + + +def test_printmethod(): + assert glsl_code(Abs(x)) == "abs(x)" + +def test_print_without_operators(): + assert glsl_code(x*y,use_operators = False) == 'mul(x, y)' + assert glsl_code(x**y+z,use_operators = False) == 'add(pow(x, y), z)' + assert glsl_code(x*(y+z),use_operators = False) == 'mul(x, add(y, z))' + assert glsl_code(x*(y+z),use_operators = False) == 'mul(x, add(y, z))' + assert glsl_code(x*(y+z**y**0.5),use_operators = False) == 'mul(x, add(y, pow(z, sqrt(y))))' + assert glsl_code(-x-y, use_operators=False, zero='zero()') == 'sub(zero(), add(x, y))' + assert glsl_code(-x-y, use_operators=False) == 'sub(0.0, add(x, y))' + +def test_glsl_code_sqrt(): + assert glsl_code(sqrt(x)) == "sqrt(x)" + assert glsl_code(x**0.5) == "sqrt(x)" + assert glsl_code(sqrt(x)) == "sqrt(x)" + + +def test_glsl_code_Pow(): + g = implemented_function('g', Lambda(x, 2*x)) + assert glsl_code(x**3) == "pow(x, 3.0)" + assert glsl_code(x**(y**3)) == "pow(x, pow(y, 3.0))" + assert glsl_code(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ + "pow(3.5*2*x, -x + pow(y, x))/(pow(x, 2.0) + y)" + assert glsl_code(x**-1.0) == '1.0/x' + + +def test_glsl_code_Relational(): + assert glsl_code(Eq(x, y)) == "x == y" + assert glsl_code(Ne(x, y)) == "x != y" + assert glsl_code(Le(x, y)) == "x <= y" + assert glsl_code(Lt(x, y)) == "x < y" + assert glsl_code(Gt(x, y)) == "x > y" + assert glsl_code(Ge(x, y)) == "x >= y" + + +def test_glsl_code_constants_mathh(): + assert glsl_code(exp(1)) == "float E = 2.71828183;\nE" + assert glsl_code(pi) == "float pi = 3.14159265;\npi" + # assert glsl_code(oo) == "Number.POSITIVE_INFINITY" + # assert glsl_code(-oo) == "Number.NEGATIVE_INFINITY" + + +def test_glsl_code_constants_other(): + assert glsl_code(2*GoldenRatio) == "float GoldenRatio = 1.61803399;\n2*GoldenRatio" + assert glsl_code(2*Catalan) == "float Catalan = 0.915965594;\n2*Catalan" + assert glsl_code(2*EulerGamma) == "float EulerGamma = 0.577215665;\n2*EulerGamma" + + +def test_glsl_code_Rational(): + assert glsl_code(Rational(3, 7)) == "3.0/7.0" + assert glsl_code(Rational(18, 9)) == "2" + assert glsl_code(Rational(3, -7)) == "-3.0/7.0" + assert glsl_code(Rational(-3, -7)) == "3.0/7.0" + + +def test_glsl_code_Integer(): + assert glsl_code(Integer(67)) == "67" + assert glsl_code(Integer(-1)) == "-1" + + +def test_glsl_code_functions(): + assert glsl_code(sin(x) ** cos(x)) == "pow(sin(x), cos(x))" + + +def test_glsl_code_inline_function(): + x = symbols('x') + g = implemented_function('g', Lambda(x, 2*x)) + assert glsl_code(g(x)) == "2*x" + g = implemented_function('g', Lambda(x, 2*x/Catalan)) + assert glsl_code(g(x)) == "float Catalan = 0.915965594;\n2*x/Catalan" + A = IndexedBase('A') + i = Idx('i', symbols('n', integer=True)) + g = implemented_function('g', Lambda(x, x*(1 + x)*(2 + x))) + assert glsl_code(g(A[i]), assign_to=A[i]) == ( + "for (int i=0; i 1), (sin(x), x > 0)) + raises(ValueError, lambda: glsl_code(expr)) + + +def test_glsl_code_Piecewise_deep(): + p = glsl_code(2*Piecewise((x, x < 1), (x**2, True))) + s = \ +"""\ +2*((x < 1) ? ( + x +) +: ( + pow(x, 2.0) +))\ +""" + assert p == s + + +def test_glsl_code_settings(): + raises(TypeError, lambda: glsl_code(sin(x), method="garbage")) + + +def test_glsl_code_Indexed(): + n, m, o = symbols('n m o', integer=True) + i, j, k = Idx('i', n), Idx('j', m), Idx('k', o) + p = GLSLPrinter() + p._not_c = set() + + x = IndexedBase('x')[j] + assert p._print_Indexed(x) == 'x[j]' + A = IndexedBase('A')[i, j] + assert p._print_Indexed(A) == 'A[%s]' % (m*i+j) + B = IndexedBase('B')[i, j, k] + assert p._print_Indexed(B) == 'B[%s]' % (i*o*m+j*o+k) + + assert p._not_c == set() + +def test_glsl_code_list_tuple_Tuple(): + assert glsl_code([1,2,3,4]) == 'vec4(1, 2, 3, 4)' + assert glsl_code([1,2,3],glsl_types=False) == 'float[3](1, 2, 3)' + assert glsl_code([1,2,3]) == glsl_code((1,2,3)) + assert glsl_code([1,2,3]) == glsl_code(Tuple(1,2,3)) + + m = MatrixSymbol('A',3,4) + assert glsl_code([m[0],m[1]]) + +def test_glsl_code_loops_matrix_vector(): + n, m = symbols('n m', integer=True) + A = IndexedBase('A') + x = IndexedBase('x') + y = IndexedBase('y') + i = Idx('i', m) + j = Idx('j', n) + + s = ( + 'for (int i=0; i0), (y, True)), sin(z)]) + A = MatrixSymbol('A', 3, 1) + assert glsl_code(mat, assign_to=A) == ( +'''A[0][0] = x*y; +if (y > 0) { + A[1][0] = x + 2; +} +else { + A[1][0] = y; +} +A[2][0] = sin(z);''' ) + assert glsl_code(Matrix([A[0],A[1]])) + # Test using MatrixElements in expressions + expr = Piecewise((2*A[2, 0], x > 0), (A[2, 0], True)) + sin(A[1, 0]) + A[0, 0] + assert glsl_code(expr) == ( +'''((x > 0) ? ( + 2*A[2][0] +) +: ( + A[2][0] +)) + sin(A[1][0]) + A[0][0]''' ) + + # Test using MatrixElements in a Matrix + q = MatrixSymbol('q', 5, 1) + M = MatrixSymbol('M', 3, 3) + m = Matrix([[sin(q[1,0]), 0, cos(q[2,0])], + [q[1,0] + q[2,0], q[3, 0], 5], + [2*q[4, 0]/q[1,0], sqrt(q[0,0]) + 4, 0]]) + assert glsl_code(m,M) == ( +'''M[0][0] = sin(q[1]); +M[0][1] = 0; +M[0][2] = cos(q[2]); +M[1][0] = q[1] + q[2]; +M[1][1] = q[3]; +M[1][2] = 5; +M[2][0] = 2*q[4]/q[1]; +M[2][1] = sqrt(q[0]) + 4; +M[2][2] = 0;''' + ) + +def test_Matrices_1x7(): + gl = glsl_code + A = Matrix([1,2,3,4,5,6,7]) + assert gl(A) == 'float[7](1, 2, 3, 4, 5, 6, 7)' + assert gl(A.transpose()) == 'float[7](1, 2, 3, 4, 5, 6, 7)' + +def test_Matrices_1x7_array_type_int(): + gl = glsl_code + A = Matrix([1,2,3,4,5,6,7]) + assert gl(A, array_type='int') == 'int[7](1, 2, 3, 4, 5, 6, 7)' + +def test_Tuple_array_type_custom(): + gl = glsl_code + A = symbols('a b c') + assert gl(A, array_type='AbcType', glsl_types=False) == 'AbcType[3](a, b, c)' + +def test_Matrices_1x7_spread_assign_to_symbols(): + gl = glsl_code + A = Matrix([1,2,3,4,5,6,7]) + assign_to = symbols('x.a x.b x.c x.d x.e x.f x.g') + assert gl(A, assign_to=assign_to) == textwrap.dedent('''\ + x.a = 1; + x.b = 2; + x.c = 3; + x.d = 4; + x.e = 5; + x.f = 6; + x.g = 7;''' + ) + +def test_spread_assign_to_nested_symbols(): + gl = glsl_code + expr = ((1,2,3), (1,2,3)) + assign_to = (symbols('a b c'), symbols('x y z')) + assert gl(expr, assign_to=assign_to) == textwrap.dedent('''\ + a = 1; + b = 2; + c = 3; + x = 1; + y = 2; + z = 3;''' + ) + +def test_spread_assign_to_deeply_nested_symbols(): + gl = glsl_code + a, b, c, x, y, z = symbols('a b c x y z') + expr = (((1,2),3), ((1,2),3)) + assign_to = (((a, b), c), ((x, y), z)) + assert gl(expr, assign_to=assign_to) == textwrap.dedent('''\ + a = 1; + b = 2; + c = 3; + x = 1; + y = 2; + z = 3;''' + ) + +def test_matrix_of_tuples_spread_assign_to_symbols(): + gl = glsl_code + with warns_deprecated_sympy(): + expr = Matrix([[(1,2),(3,4)],[(5,6),(7,8)]]) + assign_to = (symbols('a b'), symbols('c d'), symbols('e f'), symbols('g h')) + assert gl(expr, assign_to) == textwrap.dedent('''\ + a = 1; + b = 2; + c = 3; + d = 4; + e = 5; + f = 6; + g = 7; + h = 8;''' + ) + +def test_cannot_assign_to_cause_mismatched_length(): + expr = (1, 2) + assign_to = symbols('x y z') + raises(ValueError, lambda: glsl_code(expr, assign_to)) + +def test_matrix_4x4_assign(): + gl = glsl_code + expr = MatrixSymbol('A',4,4) * MatrixSymbol('B',4,4) + MatrixSymbol('C',4,4) + assign_to = MatrixSymbol('X',4,4) + assert gl(expr, assign_to=assign_to) == textwrap.dedent('''\ + X[0][0] = A[0][0]*B[0][0] + A[0][1]*B[1][0] + A[0][2]*B[2][0] + A[0][3]*B[3][0] + C[0][0]; + X[0][1] = A[0][0]*B[0][1] + A[0][1]*B[1][1] + A[0][2]*B[2][1] + A[0][3]*B[3][1] + C[0][1]; + X[0][2] = A[0][0]*B[0][2] + A[0][1]*B[1][2] + A[0][2]*B[2][2] + A[0][3]*B[3][2] + C[0][2]; + X[0][3] = A[0][0]*B[0][3] + A[0][1]*B[1][3] + A[0][2]*B[2][3] + A[0][3]*B[3][3] + C[0][3]; + X[1][0] = A[1][0]*B[0][0] + A[1][1]*B[1][0] + A[1][2]*B[2][0] + A[1][3]*B[3][0] + C[1][0]; + X[1][1] = A[1][0]*B[0][1] + A[1][1]*B[1][1] + A[1][2]*B[2][1] + A[1][3]*B[3][1] + C[1][1]; + X[1][2] = A[1][0]*B[0][2] + A[1][1]*B[1][2] + A[1][2]*B[2][2] + A[1][3]*B[3][2] + C[1][2]; + X[1][3] = A[1][0]*B[0][3] + A[1][1]*B[1][3] + A[1][2]*B[2][3] + A[1][3]*B[3][3] + C[1][3]; + X[2][0] = A[2][0]*B[0][0] + A[2][1]*B[1][0] + A[2][2]*B[2][0] + A[2][3]*B[3][0] + C[2][0]; + X[2][1] = A[2][0]*B[0][1] + A[2][1]*B[1][1] + A[2][2]*B[2][1] + A[2][3]*B[3][1] + C[2][1]; + X[2][2] = A[2][0]*B[0][2] + A[2][1]*B[1][2] + A[2][2]*B[2][2] + A[2][3]*B[3][2] + C[2][2]; + X[2][3] = A[2][0]*B[0][3] + A[2][1]*B[1][3] + A[2][2]*B[2][3] + A[2][3]*B[3][3] + C[2][3]; + X[3][0] = A[3][0]*B[0][0] + A[3][1]*B[1][0] + A[3][2]*B[2][0] + A[3][3]*B[3][0] + C[3][0]; + X[3][1] = A[3][0]*B[0][1] + A[3][1]*B[1][1] + A[3][2]*B[2][1] + A[3][3]*B[3][1] + C[3][1]; + X[3][2] = A[3][0]*B[0][2] + A[3][1]*B[1][2] + A[3][2]*B[2][2] + A[3][3]*B[3][2] + C[3][2]; + X[3][3] = A[3][0]*B[0][3] + A[3][1]*B[1][3] + A[3][2]*B[2][3] + A[3][3]*B[3][3] + C[3][3];''' + ) + +def test_1xN_vecs(): + gl = glsl_code + for i in range(1,10): + A = Matrix(range(i)) + assert gl(A.transpose()) == gl(A) + assert gl(A,mat_transpose=True) == gl(A) + if i > 1: + if i <= 4: + assert gl(A) == 'vec%s(%s)' % (i,', '.join(str(s) for s in range(i))) + else: + assert gl(A) == 'float[%s](%s)' % (i,', '.join(str(s) for s in range(i))) + +def test_MxN_mats(): + generatedAssertions='def test_misc_mats():\n' + for i in range(1,6): + for j in range(1,6): + A = Matrix([[x + y*j for x in range(j)] for y in range(i)]) + gl = glsl_code(A) + glTransposed = glsl_code(A,mat_transpose=True) + generatedAssertions+=' mat = '+StrPrinter()._print(A)+'\n\n' + generatedAssertions+=' gl = \'\'\''+gl+'\'\'\'\n' + generatedAssertions+=' glTransposed = \'\'\''+glTransposed+'\'\'\'\n\n' + generatedAssertions+=' assert glsl_code(mat) == gl\n' + generatedAssertions+=' assert glsl_code(mat,mat_transpose=True) == glTransposed\n' + if i == 1 and j == 1: + assert gl == '0' + elif i <= 4 and j <= 4 and i>1 and j>1: + assert gl.startswith('mat%s' % j) + assert glTransposed.startswith('mat%s' % i) + elif i == 1 and j <= 4: + assert gl.startswith('vec') + elif j == 1 and i <= 4: + assert gl.startswith('vec') + elif i == 1: + assert gl.startswith('float[%s]('% j*i) + assert glTransposed.startswith('float[%s]('% j*i) + elif j == 1: + assert gl.startswith('float[%s]('% i*j) + assert glTransposed.startswith('float[%s]('% i*j) + else: + assert gl.startswith('float[%s](' % (i*j)) + assert glTransposed.startswith('float[%s](' % (i*j)) + glNested = glsl_code(A,mat_nested=True) + glNestedTransposed = glsl_code(A,mat_transpose=True,mat_nested=True) + assert glNested.startswith('float[%s][%s]' % (i,j)) + assert glNestedTransposed.startswith('float[%s][%s]' % (j,i)) + generatedAssertions+=' glNested = \'\'\''+glNested+'\'\'\'\n' + generatedAssertions+=' glNestedTransposed = \'\'\''+glNestedTransposed+'\'\'\'\n\n' + generatedAssertions+=' assert glsl_code(mat,mat_nested=True) == glNested\n' + generatedAssertions+=' assert glsl_code(mat,mat_nested=True,mat_transpose=True) == glNestedTransposed\n\n' + generateAssertions = False # set this to true to write bake these generated tests to a file + if generateAssertions: + gen = open('test_glsl_generated_matrices.py','w') + gen.write(generatedAssertions) + gen.close() + + +# these assertions were generated from the previous function +# glsl has complicated rules and this makes it easier to look over all the cases +def test_misc_mats(): + + mat = Matrix([[0]]) + + gl = '''0''' + glTransposed = '''0''' + + assert glsl_code(mat) == gl + assert glsl_code(mat,mat_transpose=True) == glTransposed + + mat = Matrix([[0, 1]]) + + gl = '''vec2(0, 1)''' + glTransposed = '''vec2(0, 1)''' + + assert glsl_code(mat) == gl + assert glsl_code(mat,mat_transpose=True) == glTransposed + + mat = Matrix([[0, 1, 2]]) + + gl = '''vec3(0, 1, 2)''' + glTransposed = '''vec3(0, 1, 2)''' + + assert glsl_code(mat) == gl + assert glsl_code(mat,mat_transpose=True) == glTransposed + + mat = Matrix([[0, 1, 2, 3]]) + + gl = '''vec4(0, 1, 2, 3)''' + glTransposed = '''vec4(0, 1, 2, 3)''' + + assert glsl_code(mat) == gl + assert glsl_code(mat,mat_transpose=True) == glTransposed + + mat = Matrix([[0, 1, 2, 3, 4]]) + + gl = '''float[5](0, 1, 2, 3, 4)''' + glTransposed = '''float[5](0, 1, 2, 3, 4)''' + + assert glsl_code(mat) == gl + assert glsl_code(mat,mat_transpose=True) == glTransposed + + mat = Matrix([ +[0], +[1]]) + + gl = '''vec2(0, 1)''' + glTransposed = '''vec2(0, 1)''' + + assert glsl_code(mat) == gl + assert glsl_code(mat,mat_transpose=True) == glTransposed + + mat = Matrix([ +[0, 1], +[2, 3]]) + + gl = '''mat2(0, 1, 2, 3)''' + glTransposed = '''mat2(0, 2, 1, 3)''' + + assert glsl_code(mat) == gl + assert glsl_code(mat,mat_transpose=True) == glTransposed + + mat = Matrix([ +[0, 1, 2], +[3, 4, 5]]) + + gl = '''mat3x2(0, 1, 2, 3, 4, 5)''' + glTransposed = '''mat2x3(0, 3, 1, 4, 2, 5)''' + + assert glsl_code(mat) == gl + assert glsl_code(mat,mat_transpose=True) == glTransposed + + mat = Matrix([ +[0, 1, 2, 3], +[4, 5, 6, 7]]) + + gl = '''mat4x2(0, 1, 2, 3, 4, 5, 6, 7)''' + glTransposed = '''mat2x4(0, 4, 1, 5, 2, 6, 3, 7)''' + + assert glsl_code(mat) == gl + assert glsl_code(mat,mat_transpose=True) == glTransposed + + mat = Matrix([ +[0, 1, 2, 3, 4], +[5, 6, 7, 8, 9]]) + + gl = '''float[10]( + 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9 +) /* a 2x5 matrix */''' + glTransposed = '''float[10]( + 0, 5, + 1, 6, + 2, 7, + 3, 8, + 4, 9 +) /* a 5x2 matrix */''' + + assert glsl_code(mat) == gl + assert glsl_code(mat,mat_transpose=True) == glTransposed + glNested = '''float[2][5]( + float[](0, 1, 2, 3, 4), + float[](5, 6, 7, 8, 9) +)''' + glNestedTransposed = '''float[5][2]( + float[](0, 5), + float[](1, 6), + float[](2, 7), + float[](3, 8), + float[](4, 9) +)''' + + assert glsl_code(mat,mat_nested=True) == glNested + assert glsl_code(mat,mat_nested=True,mat_transpose=True) == glNestedTransposed + + mat = Matrix([ +[0], +[1], +[2]]) + + gl = '''vec3(0, 1, 2)''' + glTransposed = '''vec3(0, 1, 2)''' + + assert glsl_code(mat) == gl + assert glsl_code(mat,mat_transpose=True) == glTransposed + + mat = Matrix([ +[0, 1], +[2, 3], +[4, 5]]) + + gl = '''mat2x3(0, 1, 2, 3, 4, 5)''' + glTransposed = '''mat3x2(0, 2, 4, 1, 3, 5)''' + + assert glsl_code(mat) == gl + assert glsl_code(mat,mat_transpose=True) == glTransposed + + mat = Matrix([ +[0, 1, 2], +[3, 4, 5], +[6, 7, 8]]) + + gl = '''mat3(0, 1, 2, 3, 4, 5, 6, 7, 8)''' + glTransposed = '''mat3(0, 3, 6, 1, 4, 7, 2, 5, 8)''' + + assert glsl_code(mat) == gl + assert glsl_code(mat,mat_transpose=True) == glTransposed + + mat = Matrix([ +[0, 1, 2, 3], +[4, 5, 6, 7], +[8, 9, 10, 11]]) + + gl = '''mat4x3(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)''' + glTransposed = '''mat3x4(0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11)''' + + assert glsl_code(mat) == gl + assert glsl_code(mat,mat_transpose=True) == glTransposed + + mat = Matrix([ +[ 0, 1, 2, 3, 4], +[ 5, 6, 7, 8, 9], +[10, 11, 12, 13, 14]]) + + gl = '''float[15]( + 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14 +) /* a 3x5 matrix */''' + glTransposed = '''float[15]( + 0, 5, 10, + 1, 6, 11, + 2, 7, 12, + 3, 8, 13, + 4, 9, 14 +) /* a 5x3 matrix */''' + + assert glsl_code(mat) == gl + assert glsl_code(mat,mat_transpose=True) == glTransposed + glNested = '''float[3][5]( + float[]( 0, 1, 2, 3, 4), + float[]( 5, 6, 7, 8, 9), + float[](10, 11, 12, 13, 14) +)''' + glNestedTransposed = '''float[5][3]( + float[](0, 5, 10), + float[](1, 6, 11), + float[](2, 7, 12), + float[](3, 8, 13), + float[](4, 9, 14) +)''' + + assert glsl_code(mat,mat_nested=True) == glNested + assert glsl_code(mat,mat_nested=True,mat_transpose=True) == glNestedTransposed + + mat = Matrix([ +[0], +[1], +[2], +[3]]) + + gl = '''vec4(0, 1, 2, 3)''' + glTransposed = '''vec4(0, 1, 2, 3)''' + + assert glsl_code(mat) == gl + assert glsl_code(mat,mat_transpose=True) == glTransposed + + mat = Matrix([ +[0, 1], +[2, 3], +[4, 5], +[6, 7]]) + + gl = '''mat2x4(0, 1, 2, 3, 4, 5, 6, 7)''' + glTransposed = '''mat4x2(0, 2, 4, 6, 1, 3, 5, 7)''' + + assert glsl_code(mat) == gl + assert glsl_code(mat,mat_transpose=True) == glTransposed + + mat = Matrix([ +[0, 1, 2], +[3, 4, 5], +[6, 7, 8], +[9, 10, 11]]) + + gl = '''mat3x4(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)''' + glTransposed = '''mat4x3(0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8, 11)''' + + assert glsl_code(mat) == gl + assert glsl_code(mat,mat_transpose=True) == glTransposed + + mat = Matrix([ +[ 0, 1, 2, 3], +[ 4, 5, 6, 7], +[ 8, 9, 10, 11], +[12, 13, 14, 15]]) + + gl = '''mat4( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)''' + glTransposed = '''mat4(0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15)''' + + assert glsl_code(mat) == gl + assert glsl_code(mat,mat_transpose=True) == glTransposed + + mat = Matrix([ +[ 0, 1, 2, 3, 4], +[ 5, 6, 7, 8, 9], +[10, 11, 12, 13, 14], +[15, 16, 17, 18, 19]]) + + gl = '''float[20]( + 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19 +) /* a 4x5 matrix */''' + glTransposed = '''float[20]( + 0, 5, 10, 15, + 1, 6, 11, 16, + 2, 7, 12, 17, + 3, 8, 13, 18, + 4, 9, 14, 19 +) /* a 5x4 matrix */''' + + assert glsl_code(mat) == gl + assert glsl_code(mat,mat_transpose=True) == glTransposed + glNested = '''float[4][5]( + float[]( 0, 1, 2, 3, 4), + float[]( 5, 6, 7, 8, 9), + float[](10, 11, 12, 13, 14), + float[](15, 16, 17, 18, 19) +)''' + glNestedTransposed = '''float[5][4]( + float[](0, 5, 10, 15), + float[](1, 6, 11, 16), + float[](2, 7, 12, 17), + float[](3, 8, 13, 18), + float[](4, 9, 14, 19) +)''' + + assert glsl_code(mat,mat_nested=True) == glNested + assert glsl_code(mat,mat_nested=True,mat_transpose=True) == glNestedTransposed + + mat = Matrix([ +[0], +[1], +[2], +[3], +[4]]) + + gl = '''float[5](0, 1, 2, 3, 4)''' + glTransposed = '''float[5](0, 1, 2, 3, 4)''' + + assert glsl_code(mat) == gl + assert glsl_code(mat,mat_transpose=True) == glTransposed + + mat = Matrix([ +[0, 1], +[2, 3], +[4, 5], +[6, 7], +[8, 9]]) + + gl = '''float[10]( + 0, 1, + 2, 3, + 4, 5, + 6, 7, + 8, 9 +) /* a 5x2 matrix */''' + glTransposed = '''float[10]( + 0, 2, 4, 6, 8, + 1, 3, 5, 7, 9 +) /* a 2x5 matrix */''' + + assert glsl_code(mat) == gl + assert glsl_code(mat,mat_transpose=True) == glTransposed + glNested = '''float[5][2]( + float[](0, 1), + float[](2, 3), + float[](4, 5), + float[](6, 7), + float[](8, 9) +)''' + glNestedTransposed = '''float[2][5]( + float[](0, 2, 4, 6, 8), + float[](1, 3, 5, 7, 9) +)''' + + assert glsl_code(mat,mat_nested=True) == glNested + assert glsl_code(mat,mat_nested=True,mat_transpose=True) == glNestedTransposed + + mat = Matrix([ +[ 0, 1, 2], +[ 3, 4, 5], +[ 6, 7, 8], +[ 9, 10, 11], +[12, 13, 14]]) + + gl = '''float[15]( + 0, 1, 2, + 3, 4, 5, + 6, 7, 8, + 9, 10, 11, + 12, 13, 14 +) /* a 5x3 matrix */''' + glTransposed = '''float[15]( + 0, 3, 6, 9, 12, + 1, 4, 7, 10, 13, + 2, 5, 8, 11, 14 +) /* a 3x5 matrix */''' + + assert glsl_code(mat) == gl + assert glsl_code(mat,mat_transpose=True) == glTransposed + glNested = '''float[5][3]( + float[]( 0, 1, 2), + float[]( 3, 4, 5), + float[]( 6, 7, 8), + float[]( 9, 10, 11), + float[](12, 13, 14) +)''' + glNestedTransposed = '''float[3][5]( + float[](0, 3, 6, 9, 12), + float[](1, 4, 7, 10, 13), + float[](2, 5, 8, 11, 14) +)''' + + assert glsl_code(mat,mat_nested=True) == glNested + assert glsl_code(mat,mat_nested=True,mat_transpose=True) == glNestedTransposed + + mat = Matrix([ +[ 0, 1, 2, 3], +[ 4, 5, 6, 7], +[ 8, 9, 10, 11], +[12, 13, 14, 15], +[16, 17, 18, 19]]) + + gl = '''float[20]( + 0, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, 14, 15, + 16, 17, 18, 19 +) /* a 5x4 matrix */''' + glTransposed = '''float[20]( + 0, 4, 8, 12, 16, + 1, 5, 9, 13, 17, + 2, 6, 10, 14, 18, + 3, 7, 11, 15, 19 +) /* a 4x5 matrix */''' + + assert glsl_code(mat) == gl + assert glsl_code(mat,mat_transpose=True) == glTransposed + glNested = '''float[5][4]( + float[]( 0, 1, 2, 3), + float[]( 4, 5, 6, 7), + float[]( 8, 9, 10, 11), + float[](12, 13, 14, 15), + float[](16, 17, 18, 19) +)''' + glNestedTransposed = '''float[4][5]( + float[](0, 4, 8, 12, 16), + float[](1, 5, 9, 13, 17), + float[](2, 6, 10, 14, 18), + float[](3, 7, 11, 15, 19) +)''' + + assert glsl_code(mat,mat_nested=True) == glNested + assert glsl_code(mat,mat_nested=True,mat_transpose=True) == glNestedTransposed + + mat = Matrix([ +[ 0, 1, 2, 3, 4], +[ 5, 6, 7, 8, 9], +[10, 11, 12, 13, 14], +[15, 16, 17, 18, 19], +[20, 21, 22, 23, 24]]) + + gl = '''float[25]( + 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24 +) /* a 5x5 matrix */''' + glTransposed = '''float[25]( + 0, 5, 10, 15, 20, + 1, 6, 11, 16, 21, + 2, 7, 12, 17, 22, + 3, 8, 13, 18, 23, + 4, 9, 14, 19, 24 +) /* a 5x5 matrix */''' + + assert glsl_code(mat) == gl + assert glsl_code(mat,mat_transpose=True) == glTransposed + glNested = '''float[5][5]( + float[]( 0, 1, 2, 3, 4), + float[]( 5, 6, 7, 8, 9), + float[](10, 11, 12, 13, 14), + float[](15, 16, 17, 18, 19), + float[](20, 21, 22, 23, 24) +)''' + glNestedTransposed = '''float[5][5]( + float[](0, 5, 10, 15, 20), + float[](1, 6, 11, 16, 21), + float[](2, 7, 12, 17, 22), + float[](3, 8, 13, 18, 23), + float[](4, 9, 14, 19, 24) +)''' + + assert glsl_code(mat,mat_nested=True) == glNested + assert glsl_code(mat,mat_nested=True,mat_transpose=True) == glNestedTransposed diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_gtk.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_gtk.py new file mode 100644 index 0000000000000000000000000000000000000000..5a595ab04d3a29d23e06ec12207bf917392aebce --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_gtk.py @@ -0,0 +1,18 @@ +from sympy.functions.elementary.trigonometric import sin +from sympy.printing.gtk import print_gtk +from sympy.testing.pytest import XFAIL, raises + +# this test fails if python-lxml isn't installed. We don't want to depend on +# anything with SymPy + + +@XFAIL +def test_1(): + from sympy.abc import x + print_gtk(x**2, start_viewer=False) + print_gtk(x**2 + sin(x)/4, start_viewer=False) + + +def test_settings(): + from sympy.abc import x + raises(TypeError, lambda: print_gtk(x, method="garbage")) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_jax.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_jax.py new file mode 100644 index 0000000000000000000000000000000000000000..365d87c5b91fdd49a8e46cfde9c2b5792c23a03c --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_jax.py @@ -0,0 +1,370 @@ +from sympy.concrete.summations import Sum +from sympy.core.mod import Mod +from sympy.core.relational import (Equality, Unequality) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.piecewise import Piecewise +from sympy.matrices.expressions.blockmatrix import BlockMatrix +from sympy.matrices.expressions.matexpr import MatrixSymbol +from sympy.matrices.expressions.special import Identity +from sympy.utilities.lambdify import lambdify + +from sympy.abc import x, i, j, a, b, c, d +from sympy.core import Function, Pow, Symbol +from sympy.codegen.matrix_nodes import MatrixSolve +from sympy.codegen.numpy_nodes import logaddexp, logaddexp2 +from sympy.codegen.cfunctions import log1p, expm1, hypot, log10, exp2, log2, Sqrt +from sympy.tensor.array import Array +from sympy.tensor.array.expressions.array_expressions import ArrayTensorProduct, ArrayAdd, \ + PermuteDims, ArrayDiagonal +from sympy.printing.numpy import JaxPrinter, _jax_known_constants, _jax_known_functions +from sympy.tensor.array.expressions.from_matrix_to_array import convert_matrix_to_array + +from sympy.testing.pytest import skip, raises +from sympy.external import import_module + +# Unlike NumPy which will aggressively promote operands to double precision, +# jax always uses single precision. Double precision in jax can be +# configured before the call to `import jax`, however this must be explicitly +# configured and is not fully supported. Thus, the tests here have been modified +# from the tests in test_numpy.py, only in the fact that they assert lambdify +# function accuracy to only single precision accuracy. +# https://jax.readthedocs.io/en/latest/notebooks/Common_Gotchas_in_JAX.html#double-64bit-precision + +jax = import_module('jax') + +if jax: + deafult_float_info = jax.numpy.finfo(jax.numpy.array([]).dtype) + JAX_DEFAULT_EPSILON = deafult_float_info.eps + + +def test_jax_piecewise_regression(): + """ + NumPyPrinter needs to print Piecewise()'s choicelist as a list to avoid + breaking compatibility with numpy 1.8. This is not necessary in numpy 1.9+. + See gh-9747 and gh-9749 for details. + """ + printer = JaxPrinter() + p = Piecewise((1, x < 0), (0, True)) + assert printer.doprint(p) == \ + 'jax.numpy.select([jax.numpy.less(x, 0),True], [1,0], default=jax.numpy.nan)' + assert printer.module_imports == {'jax.numpy': {'select', 'less', 'nan'}} + + +def test_jax_logaddexp(): + lae = logaddexp(a, b) + assert JaxPrinter().doprint(lae) == 'jax.numpy.logaddexp(a, b)' + lae2 = logaddexp2(a, b) + assert JaxPrinter().doprint(lae2) == 'jax.numpy.logaddexp2(a, b)' + + +def test_jax_sum(): + if not jax: + skip("JAX not installed") + + s = Sum(x ** i, (i, a, b)) + f = lambdify((a, b, x), s, 'jax') + + a_, b_ = 0, 10 + x_ = jax.numpy.linspace(-1, +1, 10) + assert jax.numpy.allclose(f(a_, b_, x_), sum(x_ ** i_ for i_ in range(a_, b_ + 1))) + + s = Sum(i * x, (i, a, b)) + f = lambdify((a, b, x), s, 'jax') + + a_, b_ = 0, 10 + x_ = jax.numpy.linspace(-1, +1, 10) + assert jax.numpy.allclose(f(a_, b_, x_), sum(i_ * x_ for i_ in range(a_, b_ + 1))) + + +def test_jax_multiple_sums(): + if not jax: + skip("JAX not installed") + + s = Sum((x + j) * i, (i, a, b), (j, c, d)) + f = lambdify((a, b, c, d, x), s, 'jax') + + a_, b_ = 0, 10 + c_, d_ = 11, 21 + x_ = jax.numpy.linspace(-1, +1, 10) + assert jax.numpy.allclose(f(a_, b_, c_, d_, x_), + sum((x_ + j_) * i_ for i_ in range(a_, b_ + 1) for j_ in range(c_, d_ + 1))) + + +def test_jax_codegen_einsum(): + if not jax: + skip("JAX not installed") + + M = MatrixSymbol("M", 2, 2) + N = MatrixSymbol("N", 2, 2) + + cg = convert_matrix_to_array(M * N) + f = lambdify((M, N), cg, 'jax') + + ma = jax.numpy.array([[1, 2], [3, 4]]) + mb = jax.numpy.array([[1,-2], [-1, 3]]) + assert (f(ma, mb) == jax.numpy.matmul(ma, mb)).all() + + +def test_jax_codegen_extra(): + if not jax: + skip("JAX not installed") + + M = MatrixSymbol("M", 2, 2) + N = MatrixSymbol("N", 2, 2) + P = MatrixSymbol("P", 2, 2) + Q = MatrixSymbol("Q", 2, 2) + ma = jax.numpy.array([[1, 2], [3, 4]]) + mb = jax.numpy.array([[1,-2], [-1, 3]]) + mc = jax.numpy.array([[2, 0], [1, 2]]) + md = jax.numpy.array([[1,-1], [4, 7]]) + + cg = ArrayTensorProduct(M, N) + f = lambdify((M, N), cg, 'jax') + assert (f(ma, mb) == jax.numpy.einsum(ma, [0, 1], mb, [2, 3])).all() + + cg = ArrayAdd(M, N) + f = lambdify((M, N), cg, 'jax') + assert (f(ma, mb) == ma+mb).all() + + cg = ArrayAdd(M, N, P) + f = lambdify((M, N, P), cg, 'jax') + assert (f(ma, mb, mc) == ma+mb+mc).all() + + cg = ArrayAdd(M, N, P, Q) + f = lambdify((M, N, P, Q), cg, 'jax') + assert (f(ma, mb, mc, md) == ma+mb+mc+md).all() + + cg = PermuteDims(M, [1, 0]) + f = lambdify((M,), cg, 'jax') + assert (f(ma) == ma.T).all() + + cg = PermuteDims(ArrayTensorProduct(M, N), [1, 2, 3, 0]) + f = lambdify((M, N), cg, 'jax') + assert (f(ma, mb) == jax.numpy.transpose(jax.numpy.einsum(ma, [0, 1], mb, [2, 3]), (1, 2, 3, 0))).all() + + cg = ArrayDiagonal(ArrayTensorProduct(M, N), (1, 2)) + f = lambdify((M, N), cg, 'jax') + assert (f(ma, mb) == jax.numpy.diagonal(jax.numpy.einsum(ma, [0, 1], mb, [2, 3]), axis1=1, axis2=2)).all() + + +def test_jax_relational(): + if not jax: + skip("JAX not installed") + + e = Equality(x, 1) + + f = lambdify((x,), e, 'jax') + x_ = jax.numpy.array([0, 1, 2]) + assert jax.numpy.array_equal(f(x_), [False, True, False]) + + e = Unequality(x, 1) + + f = lambdify((x,), e, 'jax') + x_ = jax.numpy.array([0, 1, 2]) + assert jax.numpy.array_equal(f(x_), [True, False, True]) + + e = (x < 1) + + f = lambdify((x,), e, 'jax') + x_ = jax.numpy.array([0, 1, 2]) + assert jax.numpy.array_equal(f(x_), [True, False, False]) + + e = (x <= 1) + + f = lambdify((x,), e, 'jax') + x_ = jax.numpy.array([0, 1, 2]) + assert jax.numpy.array_equal(f(x_), [True, True, False]) + + e = (x > 1) + + f = lambdify((x,), e, 'jax') + x_ = jax.numpy.array([0, 1, 2]) + assert jax.numpy.array_equal(f(x_), [False, False, True]) + + e = (x >= 1) + + f = lambdify((x,), e, 'jax') + x_ = jax.numpy.array([0, 1, 2]) + assert jax.numpy.array_equal(f(x_), [False, True, True]) + + # Multi-condition expressions + e = (x >= 1) & (x < 2) + f = lambdify((x,), e, 'jax') + x_ = jax.numpy.array([0, 1, 2]) + assert jax.numpy.array_equal(f(x_), [False, True, False]) + + e = (x >= 1) | (x < 2) + f = lambdify((x,), e, 'jax') + x_ = jax.numpy.array([0, 1, 2]) + assert jax.numpy.array_equal(f(x_), [True, True, True]) + +def test_jax_mod(): + if not jax: + skip("JAX not installed") + + e = Mod(a, b) + f = lambdify((a, b), e, 'jax') + + a_ = jax.numpy.array([0, 1, 2, 3]) + b_ = 2 + assert jax.numpy.array_equal(f(a_, b_), [0, 1, 0, 1]) + + a_ = jax.numpy.array([0, 1, 2, 3]) + b_ = jax.numpy.array([2, 2, 2, 2]) + assert jax.numpy.array_equal(f(a_, b_), [0, 1, 0, 1]) + + a_ = jax.numpy.array([2, 3, 4, 5]) + b_ = jax.numpy.array([2, 3, 4, 5]) + assert jax.numpy.array_equal(f(a_, b_), [0, 0, 0, 0]) + + +def test_jax_pow(): + if not jax: + skip('JAX not installed') + + expr = Pow(2, -1, evaluate=False) + f = lambdify([], expr, 'jax') + assert f() == 0.5 + + +def test_jax_expm1(): + if not jax: + skip("JAX not installed") + + f = lambdify((a,), expm1(a), 'jax') + assert abs(f(1e-10) - 1e-10 - 5e-21) <= 1e-10 * JAX_DEFAULT_EPSILON + + +def test_jax_log1p(): + if not jax: + skip("JAX not installed") + + f = lambdify((a,), log1p(a), 'jax') + assert abs(f(1e-99) - 1e-99) <= 1e-99 * JAX_DEFAULT_EPSILON + +def test_jax_hypot(): + if not jax: + skip("JAX not installed") + assert abs(lambdify((a, b), hypot(a, b), 'jax')(3, 4) - 5) <= JAX_DEFAULT_EPSILON + +def test_jax_log10(): + if not jax: + skip("JAX not installed") + + assert abs(lambdify((a,), log10(a), 'jax')(100) - 2) <= JAX_DEFAULT_EPSILON + + +def test_jax_exp2(): + if not jax: + skip("JAX not installed") + assert abs(lambdify((a,), exp2(a), 'jax')(5) - 32) <= JAX_DEFAULT_EPSILON + + +def test_jax_log2(): + if not jax: + skip("JAX not installed") + assert abs(lambdify((a,), log2(a), 'jax')(256) - 8) <= JAX_DEFAULT_EPSILON + + +def test_jax_Sqrt(): + if not jax: + skip("JAX not installed") + assert abs(lambdify((a,), Sqrt(a), 'jax')(4) - 2) <= JAX_DEFAULT_EPSILON + + +def test_jax_sqrt(): + if not jax: + skip("JAX not installed") + assert abs(lambdify((a,), sqrt(a), 'jax')(4) - 2) <= JAX_DEFAULT_EPSILON + + +def test_jax_matsolve(): + if not jax: + skip("JAX not installed") + + M = MatrixSymbol("M", 3, 3) + x = MatrixSymbol("x", 3, 1) + + expr = M**(-1) * x + x + matsolve_expr = MatrixSolve(M, x) + x + + f = lambdify((M, x), expr, 'jax') + f_matsolve = lambdify((M, x), matsolve_expr, 'jax') + + m0 = jax.numpy.array([[1, 2, 3], [3, 2, 5], [5, 6, 7]]) + assert jax.numpy.linalg.matrix_rank(m0) == 3 + + x0 = jax.numpy.array([3, 4, 5]) + + assert jax.numpy.allclose(f_matsolve(m0, x0), f(m0, x0)) + + +def test_16857(): + if not jax: + skip("JAX not installed") + + a_1 = MatrixSymbol('a_1', 10, 3) + a_2 = MatrixSymbol('a_2', 10, 3) + a_3 = MatrixSymbol('a_3', 10, 3) + a_4 = MatrixSymbol('a_4', 10, 3) + A = BlockMatrix([[a_1, a_2], [a_3, a_4]]) + assert A.shape == (20, 6) + + printer = JaxPrinter() + assert printer.doprint(A) == 'jax.numpy.block([[a_1, a_2], [a_3, a_4]])' + + +def test_issue_17006(): + if not jax: + skip("JAX not installed") + + M = MatrixSymbol("M", 2, 2) + + f = lambdify(M, M + Identity(2), 'jax') + ma = jax.numpy.array([[1, 2], [3, 4]]) + mr = jax.numpy.array([[2, 2], [3, 5]]) + + assert (f(ma) == mr).all() + + from sympy.core.symbol import symbols + n = symbols('n', integer=True) + N = MatrixSymbol("M", n, n) + raises(NotImplementedError, lambda: lambdify(N, N + Identity(n), 'jax')) + + +def test_jax_array(): + assert JaxPrinter().doprint(Array(((1, 2), (3, 5)))) == 'jax.numpy.array([[1, 2], [3, 5]])' + assert JaxPrinter().doprint(Array((1, 2))) == 'jax.numpy.array([1, 2])' + + +def test_jax_known_funcs_consts(): + assert _jax_known_constants['NaN'] == 'jax.numpy.nan' + assert _jax_known_constants['EulerGamma'] == 'jax.numpy.euler_gamma' + + assert _jax_known_functions['acos'] == 'jax.numpy.arccos' + assert _jax_known_functions['log'] == 'jax.numpy.log' + + +def test_jax_print_methods(): + prntr = JaxPrinter() + assert hasattr(prntr, '_print_acos') + assert hasattr(prntr, '_print_log') + + +def test_jax_printmethod(): + printer = JaxPrinter() + assert hasattr(printer, 'printmethod') + assert printer.printmethod == '_jaxcode' + + +def test_jax_custom_print_method(): + + class expm1(Function): + + def _jaxcode(self, printer): + x, = self.args + function = f'expm1({printer._print(x)})' + return printer._module_format(printer._module + '.' + function) + + printer = JaxPrinter() + assert printer.doprint(expm1(Symbol('x'))) == 'jax.numpy.expm1(x)' diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_jscode.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_jscode.py new file mode 100644 index 0000000000000000000000000000000000000000..9199a8e0d62e87f2e964cb1712726a21c894fd20 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_jscode.py @@ -0,0 +1,396 @@ +from sympy.core import (pi, oo, symbols, Rational, Integer, GoldenRatio, + EulerGamma, Catalan, Lambda, Dummy, S, Eq, Ne, Le, + Lt, Gt, Ge, Mod) +from sympy.functions import (Piecewise, sin, cos, Abs, exp, ceiling, sqrt, + sinh, cosh, tanh, asin, acos, acosh, Max, Min) +from sympy.testing.pytest import raises +from sympy.printing.jscode import JavascriptCodePrinter +from sympy.utilities.lambdify import implemented_function +from sympy.tensor import IndexedBase, Idx +from sympy.matrices import Matrix, MatrixSymbol + +from sympy.printing.jscode import jscode + +x, y, z = symbols('x,y,z') + + +def test_printmethod(): + assert jscode(Abs(x)) == "Math.abs(x)" + + +def test_jscode_sqrt(): + assert jscode(sqrt(x)) == "Math.sqrt(x)" + assert jscode(x**0.5) == "Math.sqrt(x)" + assert jscode(x**(S.One/3)) == "Math.cbrt(x)" + + +def test_jscode_Pow(): + g = implemented_function('g', Lambda(x, 2*x)) + assert jscode(x**3) == "Math.pow(x, 3)" + assert jscode(x**(y**3)) == "Math.pow(x, Math.pow(y, 3))" + assert jscode(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ + "Math.pow(3.5*2*x, -x + Math.pow(y, x))/(Math.pow(x, 2) + y)" + assert jscode(x**-1.0) == '1/x' + + +def test_jscode_constants_mathh(): + assert jscode(exp(1)) == "Math.E" + assert jscode(pi) == "Math.PI" + assert jscode(oo) == "Number.POSITIVE_INFINITY" + assert jscode(-oo) == "Number.NEGATIVE_INFINITY" + + +def test_jscode_constants_other(): + assert jscode( + 2*GoldenRatio) == "var GoldenRatio = %s;\n2*GoldenRatio" % GoldenRatio.evalf(17) + assert jscode(2*Catalan) == "var Catalan = %s;\n2*Catalan" % Catalan.evalf(17) + assert jscode( + 2*EulerGamma) == "var EulerGamma = %s;\n2*EulerGamma" % EulerGamma.evalf(17) + + +def test_jscode_Rational(): + assert jscode(Rational(3, 7)) == "3/7" + assert jscode(Rational(18, 9)) == "2" + assert jscode(Rational(3, -7)) == "-3/7" + assert jscode(Rational(-3, -7)) == "3/7" + + +def test_Relational(): + assert jscode(Eq(x, y)) == "x == y" + assert jscode(Ne(x, y)) == "x != y" + assert jscode(Le(x, y)) == "x <= y" + assert jscode(Lt(x, y)) == "x < y" + assert jscode(Gt(x, y)) == "x > y" + assert jscode(Ge(x, y)) == "x >= y" + + +def test_Mod(): + assert jscode(Mod(x, y)) == '((x % y) + y) % y' + assert jscode(Mod(x, x + y)) == '((x % (x + y)) + (x + y)) % (x + y)' + p1, p2 = symbols('p1 p2', positive=True) + assert jscode(Mod(p1, p2)) == 'p1 % p2' + assert jscode(Mod(p1, p2 + 3)) == 'p1 % (p2 + 3)' + assert jscode(Mod(-3, -7, evaluate=False)) == '(-3) % (-7)' + assert jscode(-Mod(p1, p2)) == '-(p1 % p2)' + assert jscode(x*Mod(p1, p2)) == 'x*(p1 % p2)' + + +def test_jscode_Integer(): + assert jscode(Integer(67)) == "67" + assert jscode(Integer(-1)) == "-1" + + +def test_jscode_functions(): + assert jscode(sin(x) ** cos(x)) == "Math.pow(Math.sin(x), Math.cos(x))" + assert jscode(sinh(x) * cosh(x)) == "Math.sinh(x)*Math.cosh(x)" + assert jscode(Max(x, y) + Min(x, y)) == "Math.max(x, y) + Math.min(x, y)" + assert jscode(tanh(x)*acosh(y)) == "Math.tanh(x)*Math.acosh(y)" + assert jscode(asin(x)-acos(y)) == "-Math.acos(y) + Math.asin(x)" + + +def test_jscode_inline_function(): + x = symbols('x') + g = implemented_function('g', Lambda(x, 2*x)) + assert jscode(g(x)) == "2*x" + g = implemented_function('g', Lambda(x, 2*x/Catalan)) + assert jscode(g(x)) == "var Catalan = %s;\n2*x/Catalan" % Catalan.evalf(17) + A = IndexedBase('A') + i = Idx('i', symbols('n', integer=True)) + g = implemented_function('g', Lambda(x, x*(1 + x)*(2 + x))) + assert jscode(g(A[i]), assign_to=A[i]) == ( + "for (var i=0; i 1), (sin(x), x > 0)) + raises(ValueError, lambda: jscode(expr)) + + +def test_jscode_Piecewise_deep(): + p = jscode(2*Piecewise((x, x < 1), (x**2, True))) + s = \ +"""\ +2*((x < 1) ? ( + x +) +: ( + Math.pow(x, 2) +))\ +""" + assert p == s + + +def test_jscode_settings(): + raises(TypeError, lambda: jscode(sin(x), method="garbage")) + + +def test_jscode_Indexed(): + n, m, o = symbols('n m o', integer=True) + i, j, k = Idx('i', n), Idx('j', m), Idx('k', o) + p = JavascriptCodePrinter() + p._not_c = set() + + x = IndexedBase('x')[j] + assert p._print_Indexed(x) == 'x[j]' + A = IndexedBase('A')[i, j] + assert p._print_Indexed(A) == 'A[%s]' % (m*i+j) + B = IndexedBase('B')[i, j, k] + assert p._print_Indexed(B) == 'B[%s]' % (i*o*m+j*o+k) + + assert p._not_c == set() + + +def test_jscode_loops_matrix_vector(): + n, m = symbols('n m', integer=True) + A = IndexedBase('A') + x = IndexedBase('x') + y = IndexedBase('y') + i = Idx('i', m) + j = Idx('j', n) + + s = ( + 'for (var i=0; i0), (y, True)), sin(z)]) + A = MatrixSymbol('A', 3, 1) + assert jscode(mat, A) == ( + "A[0] = x*y;\n" + "if (y > 0) {\n" + " A[1] = x + 2;\n" + "}\n" + "else {\n" + " A[1] = y;\n" + "}\n" + "A[2] = Math.sin(z);") + # Test using MatrixElements in expressions + expr = Piecewise((2*A[2, 0], x > 0), (A[2, 0], True)) + sin(A[1, 0]) + A[0, 0] + assert jscode(expr) == ( + "((x > 0) ? (\n" + " 2*A[2]\n" + ")\n" + ": (\n" + " A[2]\n" + ")) + Math.sin(A[1]) + A[0]") + # Test using MatrixElements in a Matrix + q = MatrixSymbol('q', 5, 1) + M = MatrixSymbol('M', 3, 3) + m = Matrix([[sin(q[1,0]), 0, cos(q[2,0])], + [q[1,0] + q[2,0], q[3, 0], 5], + [2*q[4, 0]/q[1,0], sqrt(q[0,0]) + 4, 0]]) + assert jscode(m, M) == ( + "M[0] = Math.sin(q[1]);\n" + "M[1] = 0;\n" + "M[2] = Math.cos(q[2]);\n" + "M[3] = q[1] + q[2];\n" + "M[4] = q[3];\n" + "M[5] = 5;\n" + "M[6] = 2*q[4]/q[1];\n" + "M[7] = Math.sqrt(q[0]) + 4;\n" + "M[8] = 0;") + + +def test_MatrixElement_printing(): + # test cases for issue #11821 + A = MatrixSymbol("A", 1, 3) + B = MatrixSymbol("B", 1, 3) + C = MatrixSymbol("C", 1, 3) + + assert(jscode(A[0, 0]) == "A[0]") + assert(jscode(3 * A[0, 0]) == "3*A[0]") + + F = C[0, 0].subs(C, A - B) + assert(jscode(F) == "(A - B)[0]") diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_julia.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_julia.py new file mode 100644 index 0000000000000000000000000000000000000000..b19c7b4fd4f21d8402ca2f577605322b3ec10f5b --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_julia.py @@ -0,0 +1,390 @@ +from sympy.core import (S, pi, oo, symbols, Function, Rational, Integer, + Tuple, Symbol, Eq, Ne, Le, Lt, Gt, Ge) +from sympy.core import EulerGamma, GoldenRatio, Catalan, Lambda, Mul, Pow +from sympy.functions import Piecewise, sqrt, ceiling, exp, sin, cos, sinc +from sympy.testing.pytest import raises +from sympy.utilities.lambdify import implemented_function +from sympy.matrices import (eye, Matrix, MatrixSymbol, Identity, + HadamardProduct, SparseMatrix) +from sympy.functions.special.bessel import (jn, yn, besselj, bessely, besseli, + besselk, hankel1, hankel2, airyai, + airybi, airyaiprime, airybiprime) +from sympy.testing.pytest import XFAIL + +from sympy.printing.julia import julia_code + +x, y, z = symbols('x,y,z') + + +def test_Integer(): + assert julia_code(Integer(67)) == "67" + assert julia_code(Integer(-1)) == "-1" + + +def test_Rational(): + assert julia_code(Rational(3, 7)) == "3 // 7" + assert julia_code(Rational(18, 9)) == "2" + assert julia_code(Rational(3, -7)) == "-3 // 7" + assert julia_code(Rational(-3, -7)) == "3 // 7" + assert julia_code(x + Rational(3, 7)) == "x + 3 // 7" + assert julia_code(Rational(3, 7)*x) == "(3 // 7) * x" + + +def test_Relational(): + assert julia_code(Eq(x, y)) == "x == y" + assert julia_code(Ne(x, y)) == "x != y" + assert julia_code(Le(x, y)) == "x <= y" + assert julia_code(Lt(x, y)) == "x < y" + assert julia_code(Gt(x, y)) == "x > y" + assert julia_code(Ge(x, y)) == "x >= y" + + +def test_Function(): + assert julia_code(sin(x) ** cos(x)) == "sin(x) .^ cos(x)" + assert julia_code(abs(x)) == "abs(x)" + assert julia_code(ceiling(x)) == "ceil(x)" + + +def test_Pow(): + assert julia_code(x**3) == "x .^ 3" + assert julia_code(x**(y**3)) == "x .^ (y .^ 3)" + assert julia_code(x**Rational(2, 3)) == 'x .^ (2 // 3)' + g = implemented_function('g', Lambda(x, 2*x)) + assert julia_code(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ + "(3.5 * 2 * x) .^ (-x + y .^ x) ./ (x .^ 2 + y)" + # For issue 14160 + assert julia_code(Mul(-2, x, Pow(Mul(y,y,evaluate=False), -1, evaluate=False), + evaluate=False)) == '-2 * x ./ (y .* y)' + + +def test_basic_ops(): + assert julia_code(x*y) == "x .* y" + assert julia_code(x + y) == "x + y" + assert julia_code(x - y) == "x - y" + assert julia_code(-x) == "-x" + + +def test_1_over_x_and_sqrt(): + # 1.0 and 0.5 would do something different in regular StrPrinter, + # but these are exact in IEEE floating point so no different here. + assert julia_code(1/x) == '1 ./ x' + assert julia_code(x**-1) == julia_code(x**-1.0) == '1 ./ x' + assert julia_code(1/sqrt(x)) == '1 ./ sqrt(x)' + assert julia_code(x**-S.Half) == julia_code(x**-0.5) == '1 ./ sqrt(x)' + assert julia_code(sqrt(x)) == 'sqrt(x)' + assert julia_code(x**S.Half) == julia_code(x**0.5) == 'sqrt(x)' + assert julia_code(1/pi) == '1 / pi' + assert julia_code(pi**-1) == julia_code(pi**-1.0) == '1 / pi' + assert julia_code(pi**-0.5) == '1 / sqrt(pi)' + + +def test_mix_number_mult_symbols(): + assert julia_code(3*x) == "3 * x" + assert julia_code(pi*x) == "pi * x" + assert julia_code(3/x) == "3 ./ x" + assert julia_code(pi/x) == "pi ./ x" + assert julia_code(x/3) == "x / 3" + assert julia_code(x/pi) == "x / pi" + assert julia_code(x*y) == "x .* y" + assert julia_code(3*x*y) == "3 * x .* y" + assert julia_code(3*pi*x*y) == "3 * pi * x .* y" + assert julia_code(x/y) == "x ./ y" + assert julia_code(3*x/y) == "3 * x ./ y" + assert julia_code(x*y/z) == "x .* y ./ z" + assert julia_code(x/y*z) == "x .* z ./ y" + assert julia_code(1/x/y) == "1 ./ (x .* y)" + assert julia_code(2*pi*x/y/z) == "2 * pi * x ./ (y .* z)" + assert julia_code(3*pi/x) == "3 * pi ./ x" + assert julia_code(S(3)/5) == "3 // 5" + assert julia_code(S(3)/5*x) == "(3 // 5) * x" + assert julia_code(x/y/z) == "x ./ (y .* z)" + assert julia_code((x+y)/z) == "(x + y) ./ z" + assert julia_code((x+y)/(z+x)) == "(x + y) ./ (x + z)" + assert julia_code((x+y)/EulerGamma) == "(x + y) / eulergamma" + assert julia_code(x/3/pi) == "x / (3 * pi)" + assert julia_code(S(3)/5*x*y/pi) == "(3 // 5) * x .* y / pi" + + +def test_mix_number_pow_symbols(): + assert julia_code(pi**3) == 'pi ^ 3' + assert julia_code(x**2) == 'x .^ 2' + assert julia_code(x**(pi**3)) == 'x .^ (pi ^ 3)' + assert julia_code(x**y) == 'x .^ y' + assert julia_code(x**(y**z)) == 'x .^ (y .^ z)' + assert julia_code((x**y)**z) == '(x .^ y) .^ z' + + +def test_imag(): + I = S('I') + assert julia_code(I) == "im" + assert julia_code(5*I) == "5im" + assert julia_code((S(3)/2)*I) == "(3 // 2) * im" + assert julia_code(3+4*I) == "3 + 4im" + + +def test_constants(): + assert julia_code(pi) == "pi" + assert julia_code(oo) == "Inf" + assert julia_code(-oo) == "-Inf" + assert julia_code(S.NegativeInfinity) == "-Inf" + assert julia_code(S.NaN) == "NaN" + assert julia_code(S.Exp1) == "e" + assert julia_code(exp(1)) == "e" + + +def test_constants_other(): + assert julia_code(2*GoldenRatio) == "2 * golden" + assert julia_code(2*Catalan) == "2 * catalan" + assert julia_code(2*EulerGamma) == "2 * eulergamma" + + +def test_boolean(): + assert julia_code(x & y) == "x && y" + assert julia_code(x | y) == "x || y" + assert julia_code(~x) == "!x" + assert julia_code(x & y & z) == "x && y && z" + assert julia_code(x | y | z) == "x || y || z" + assert julia_code((x & y) | z) == "z || x && y" + assert julia_code((x | y) & z) == "z && (x || y)" + +def test_sinc(): + assert julia_code(sinc(x)) == 'sinc(x / pi)' + assert julia_code(sinc(x + 3)) == 'sinc((x + 3) / pi)' + assert julia_code(sinc(pi * (x + 3))) == 'sinc(x + 3)' + +def test_Matrices(): + assert julia_code(Matrix(1, 1, [10])) == "[10]" + A = Matrix([[1, sin(x/2), abs(x)], + [0, 1, pi], + [0, exp(1), ceiling(x)]]) + expected = ("[1 sin(x / 2) abs(x);\n" + "0 1 pi;\n" + "0 e ceil(x)]") + assert julia_code(A) == expected + # row and columns + assert julia_code(A[:,0]) == "[1, 0, 0]" + assert julia_code(A[0,:]) == "[1 sin(x / 2) abs(x)]" + # empty matrices + assert julia_code(Matrix(0, 0, [])) == 'zeros(0, 0)' + assert julia_code(Matrix(0, 3, [])) == 'zeros(0, 3)' + # annoying to read but correct + assert julia_code(Matrix([[x, x - y, -y]])) == "[x x - y -y]" + + +def test_vector_entries_hadamard(): + # For a row or column, user might to use the other dimension + A = Matrix([[1, sin(2/x), 3*pi/x/5]]) + assert julia_code(A) == "[1 sin(2 ./ x) (3 // 5) * pi ./ x]" + assert julia_code(A.T) == "[1, sin(2 ./ x), (3 // 5) * pi ./ x]" + + +@XFAIL +def test_Matrices_entries_not_hadamard(): + # For Matrix with col >= 2, row >= 2, they need to be scalars + # FIXME: is it worth worrying about this? Its not wrong, just + # leave it user's responsibility to put scalar data for x. + A = Matrix([[1, sin(2/x), 3*pi/x/5], [1, 2, x*y]]) + expected = ("[1 sin(2/x) 3*pi/(5*x);\n" + "1 2 x*y]") # <- we give x.*y + assert julia_code(A) == expected + + +def test_MatrixSymbol(): + n = Symbol('n', integer=True) + A = MatrixSymbol('A', n, n) + B = MatrixSymbol('B', n, n) + assert julia_code(A*B) == "A * B" + assert julia_code(B*A) == "B * A" + assert julia_code(2*A*B) == "2 * A * B" + assert julia_code(B*2*A) == "2 * B * A" + assert julia_code(A*(B + 3*Identity(n))) == "A * (3 * eye(n) + B)" + assert julia_code(A**(x**2)) == "A ^ (x .^ 2)" + assert julia_code(A**3) == "A ^ 3" + assert julia_code(A**S.Half) == "A ^ (1 // 2)" + + +def test_special_matrices(): + assert julia_code(6*Identity(3)) == "6 * eye(3)" + + +def test_containers(): + assert julia_code([1, 2, 3, [4, 5, [6, 7]], 8, [9, 10], 11]) == \ + "Any[1, 2, 3, Any[4, 5, Any[6, 7]], 8, Any[9, 10], 11]" + assert julia_code((1, 2, (3, 4))) == "(1, 2, (3, 4))" + assert julia_code([1]) == "Any[1]" + assert julia_code((1,)) == "(1,)" + assert julia_code(Tuple(*[1, 2, 3])) == "(1, 2, 3)" + assert julia_code((1, x*y, (3, x**2))) == "(1, x .* y, (3, x .^ 2))" + # scalar, matrix, empty matrix and empty list + assert julia_code((1, eye(3), Matrix(0, 0, []), [])) == "(1, [1 0 0;\n0 1 0;\n0 0 1], zeros(0, 0), Any[])" + + +def test_julia_noninline(): + source = julia_code((x+y)/Catalan, assign_to='me', inline=False) + expected = ( + "const Catalan = %s\n" + "me = (x + y) / Catalan" + ) % Catalan.evalf(17) + assert source == expected + + +def test_julia_piecewise(): + expr = Piecewise((x, x < 1), (x**2, True)) + assert julia_code(expr) == "((x < 1) ? (x) : (x .^ 2))" + assert julia_code(expr, assign_to="r") == ( + "r = ((x < 1) ? (x) : (x .^ 2))") + assert julia_code(expr, assign_to="r", inline=False) == ( + "if (x < 1)\n" + " r = x\n" + "else\n" + " r = x .^ 2\n" + "end") + expr = Piecewise((x**2, x < 1), (x**3, x < 2), (x**4, x < 3), (x**5, True)) + expected = ("((x < 1) ? (x .^ 2) :\n" + "(x < 2) ? (x .^ 3) :\n" + "(x < 3) ? (x .^ 4) : (x .^ 5))") + assert julia_code(expr) == expected + assert julia_code(expr, assign_to="r") == "r = " + expected + assert julia_code(expr, assign_to="r", inline=False) == ( + "if (x < 1)\n" + " r = x .^ 2\n" + "elseif (x < 2)\n" + " r = x .^ 3\n" + "elseif (x < 3)\n" + " r = x .^ 4\n" + "else\n" + " r = x .^ 5\n" + "end") + # Check that Piecewise without a True (default) condition error + expr = Piecewise((x, x < 1), (x**2, x > 1), (sin(x), x > 0)) + raises(ValueError, lambda: julia_code(expr)) + + +def test_julia_piecewise_times_const(): + pw = Piecewise((x, x < 1), (x**2, True)) + assert julia_code(2*pw) == "2 * ((x < 1) ? (x) : (x .^ 2))" + assert julia_code(pw/x) == "((x < 1) ? (x) : (x .^ 2)) ./ x" + assert julia_code(pw/(x*y)) == "((x < 1) ? (x) : (x .^ 2)) ./ (x .* y)" + assert julia_code(pw/3) == "((x < 1) ? (x) : (x .^ 2)) / 3" + + +def test_julia_matrix_assign_to(): + A = Matrix([[1, 2, 3]]) + assert julia_code(A, assign_to='a') == "a = [1 2 3]" + A = Matrix([[1, 2], [3, 4]]) + assert julia_code(A, assign_to='A') == "A = [1 2;\n3 4]" + + +def test_julia_matrix_assign_to_more(): + # assigning to Symbol or MatrixSymbol requires lhs/rhs match + A = Matrix([[1, 2, 3]]) + B = MatrixSymbol('B', 1, 3) + C = MatrixSymbol('C', 2, 3) + assert julia_code(A, assign_to=B) == "B = [1 2 3]" + raises(ValueError, lambda: julia_code(A, assign_to=x)) + raises(ValueError, lambda: julia_code(A, assign_to=C)) + + +def test_julia_matrix_1x1(): + A = Matrix([[3]]) + B = MatrixSymbol('B', 1, 1) + C = MatrixSymbol('C', 1, 2) + assert julia_code(A, assign_to=B) == "B = [3]" + # FIXME? + #assert julia_code(A, assign_to=x) == "x = [3]" + raises(ValueError, lambda: julia_code(A, assign_to=C)) + + +def test_julia_matrix_elements(): + A = Matrix([[x, 2, x*y]]) + assert julia_code(A[0, 0]**2 + A[0, 1] + A[0, 2]) == "x .^ 2 + x .* y + 2" + A = MatrixSymbol('AA', 1, 3) + assert julia_code(A) == "AA" + assert julia_code(A[0, 0]**2 + sin(A[0,1]) + A[0,2]) == \ + "sin(AA[1,2]) + AA[1,1] .^ 2 + AA[1,3]" + assert julia_code(sum(A)) == "AA[1,1] + AA[1,2] + AA[1,3]" + + +def test_julia_boolean(): + assert julia_code(True) == "true" + assert julia_code(S.true) == "true" + assert julia_code(False) == "false" + assert julia_code(S.false) == "false" + + +def test_julia_not_supported(): + with raises(NotImplementedError): + julia_code(S.ComplexInfinity) + + f = Function('f') + assert julia_code(f(x).diff(x), strict=False) == ( + "# Not supported in Julia:\n" + "# Derivative\n" + "Derivative(f(x), x)" + ) + + +def test_trick_indent_with_end_else_words(): + # words starting with "end" or "else" do not confuse the indenter + t1 = S('endless') + t2 = S('elsewhere') + pw = Piecewise((t1, x < 0), (t2, x <= 1), (1, True)) + assert julia_code(pw, inline=False) == ( + "if (x < 0)\n" + " endless\n" + "elseif (x <= 1)\n" + " elsewhere\n" + "else\n" + " 1\n" + "end") + + +def test_haramard(): + A = MatrixSymbol('A', 3, 3) + B = MatrixSymbol('B', 3, 3) + v = MatrixSymbol('v', 3, 1) + h = MatrixSymbol('h', 1, 3) + C = HadamardProduct(A, B) + assert julia_code(C) == "A .* B" + assert julia_code(C*v) == "(A .* B) * v" + assert julia_code(h*C*v) == "h * (A .* B) * v" + assert julia_code(C*A) == "(A .* B) * A" + # mixing Hadamard and scalar strange b/c we vectorize scalars + assert julia_code(C*x*y) == "(x .* y) * (A .* B)" + + +def test_sparse(): + M = SparseMatrix(5, 6, {}) + M[2, 2] = 10 + M[1, 2] = 20 + M[1, 3] = 22 + M[0, 3] = 30 + M[3, 0] = x*y + assert julia_code(M) == ( + "sparse([4, 2, 3, 1, 2], [1, 3, 3, 4, 4], [x .* y, 20, 10, 30, 22], 5, 6)" + ) + + +def test_specfun(): + n = Symbol('n') + for f in [besselj, bessely, besseli, besselk]: + assert julia_code(f(n, x)) == f.__name__ + '(n, x)' + for f in [airyai, airyaiprime, airybi, airybiprime]: + assert julia_code(f(x)) == f.__name__ + '(x)' + assert julia_code(hankel1(n, x)) == 'hankelh1(n, x)' + assert julia_code(hankel2(n, x)) == 'hankelh2(n, x)' + assert julia_code(jn(n, x)) == 'sqrt(2) * sqrt(pi) * sqrt(1 ./ x) .* besselj(n + 1 // 2, x) / 2' + assert julia_code(yn(n, x)) == 'sqrt(2) * sqrt(pi) * sqrt(1 ./ x) .* bessely(n + 1 // 2, x) / 2' + + +def test_MatrixElement_printing(): + # test cases for issue #11821 + A = MatrixSymbol("A", 1, 3) + B = MatrixSymbol("B", 1, 3) + C = MatrixSymbol("C", 1, 3) + + assert(julia_code(A[0, 0]) == "A[1,1]") + assert(julia_code(3 * A[0, 0]) == "3 * A[1,1]") + + F = C[0, 0].subs(C, A - B) + assert(julia_code(F) == "(A - B)[1,1]") diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_lambdarepr.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_lambdarepr.py new file mode 100644 index 0000000000000000000000000000000000000000..94e09ada7a9ce7d01667edd8fc6ec35ebfbb9639 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_lambdarepr.py @@ -0,0 +1,246 @@ +from sympy.concrete.summations import Sum +from sympy.core.expr import Expr +from sympy.core.symbol import symbols +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.piecewise import Piecewise +from sympy.functions.elementary.trigonometric import sin +from sympy.matrices.dense import MutableDenseMatrix as Matrix +from sympy.sets.sets import Interval +from sympy.utilities.lambdify import lambdify +from sympy.testing.pytest import raises + +from sympy.printing.tensorflow import TensorflowPrinter +from sympy.printing.lambdarepr import lambdarepr, LambdaPrinter, NumExprPrinter + + +x, y, z = symbols("x,y,z") +i, a, b = symbols("i,a,b") +j, c, d = symbols("j,c,d") + + +def test_basic(): + assert lambdarepr(x*y) == "x*y" + assert lambdarepr(x + y) in ["y + x", "x + y"] + assert lambdarepr(x**y) == "x**y" + + +def test_matrix(): + # Test printing a Matrix that has an element that is printed differently + # with the LambdaPrinter than with the StrPrinter. + e = x % 2 + assert lambdarepr(e) != str(e) + assert lambdarepr(Matrix([e])) == 'ImmutableDenseMatrix([[x % 2]])' + + +def test_piecewise(): + # In each case, test eval() the lambdarepr() to make sure there are a + # correct number of parentheses. It will give a SyntaxError if there aren't. + + h = "lambda x: " + + p = Piecewise((x, x < 0)) + l = lambdarepr(p) + eval(h + l) + assert l == "((x) if (x < 0) else None)" + + p = Piecewise( + (1, x < 1), + (2, x < 2), + (0, True) + ) + l = lambdarepr(p) + eval(h + l) + assert l == "((1) if (x < 1) else (2) if (x < 2) else (0))" + + p = Piecewise( + (1, x < 1), + (2, x < 2), + ) + l = lambdarepr(p) + eval(h + l) + assert l == "((1) if (x < 1) else (2) if (x < 2) else None)" + + p = Piecewise( + (x, x < 1), + (x**2, Interval(3, 4, True, False).contains(x)), + (0, True), + ) + l = lambdarepr(p) + eval(h + l) + assert l == "((x) if (x < 1) else (x**2) if (((x <= 4)) and ((x > 3))) else (0))" + + p = Piecewise( + (x**2, x < 0), + (x, x < 1), + (2 - x, x >= 1), + (0, True), evaluate=False + ) + l = lambdarepr(p) + eval(h + l) + assert l == "((x**2) if (x < 0) else (x) if (x < 1)"\ + " else (2 - x) if (x >= 1) else (0))" + + p = Piecewise( + (x**2, x < 0), + (x, x < 1), + (2 - x, x >= 1), evaluate=False + ) + l = lambdarepr(p) + eval(h + l) + assert l == "((x**2) if (x < 0) else (x) if (x < 1)"\ + " else (2 - x) if (x >= 1) else None)" + + p = Piecewise( + (1, x >= 1), + (2, x >= 2), + (3, x >= 3), + (4, x >= 4), + (5, x >= 5), + (6, True) + ) + l = lambdarepr(p) + eval(h + l) + assert l == "((1) if (x >= 1) else (2) if (x >= 2) else (3) if (x >= 3)"\ + " else (4) if (x >= 4) else (5) if (x >= 5) else (6))" + + p = Piecewise( + (1, x <= 1), + (2, x <= 2), + (3, x <= 3), + (4, x <= 4), + (5, x <= 5), + (6, True) + ) + l = lambdarepr(p) + eval(h + l) + assert l == "((1) if (x <= 1) else (2) if (x <= 2) else (3) if (x <= 3)"\ + " else (4) if (x <= 4) else (5) if (x <= 5) else (6))" + + p = Piecewise( + (1, x > 1), + (2, x > 2), + (3, x > 3), + (4, x > 4), + (5, x > 5), + (6, True) + ) + l = lambdarepr(p) + eval(h + l) + assert l =="((1) if (x > 1) else (2) if (x > 2) else (3) if (x > 3)"\ + " else (4) if (x > 4) else (5) if (x > 5) else (6))" + + p = Piecewise( + (1, x < 1), + (2, x < 2), + (3, x < 3), + (4, x < 4), + (5, x < 5), + (6, True) + ) + l = lambdarepr(p) + eval(h + l) + assert l == "((1) if (x < 1) else (2) if (x < 2) else (3) if (x < 3)"\ + " else (4) if (x < 4) else (5) if (x < 5) else (6))" + + p = Piecewise( + (Piecewise( + (1, x > 0), + (2, True) + ), y > 0), + (3, True) + ) + l = lambdarepr(p) + eval(h + l) + assert l == "((((1) if (x > 0) else (2))) if (y > 0) else (3))" + + +def test_sum__1(): + # In each case, test eval() the lambdarepr() to make sure that + # it evaluates to the same results as the symbolic expression + s = Sum(x ** i, (i, a, b)) + l = lambdarepr(s) + assert l == "(builtins.sum(x**i for i in range(a, b+1)))" + + args = x, a, b + f = lambdify(args, s) + v = 2, 3, 8 + assert f(*v) == s.subs(zip(args, v)).doit() + +def test_sum__2(): + s = Sum(i * x, (i, a, b)) + l = lambdarepr(s) + assert l == "(builtins.sum(i*x for i in range(a, b+1)))" + + args = x, a, b + f = lambdify(args, s) + v = 2, 3, 8 + assert f(*v) == s.subs(zip(args, v)).doit() + + +def test_multiple_sums(): + s = Sum(i * x + j, (i, a, b), (j, c, d)) + + l = lambdarepr(s) + assert l == "(builtins.sum(i*x + j for j in range(c, d+1) for i in range(a, b+1)))" + + args = x, a, b, c, d + f = lambdify(args, s) + vals = 2, 3, 4, 5, 6 + f_ref = s.subs(zip(args, vals)).doit() + f_res = f(*vals) + assert f_res == f_ref + + +def test_sqrt(): + prntr = LambdaPrinter({'standard' : 'python3'}) + assert prntr._print_Pow(sqrt(x), rational=False) == 'sqrt(x)' + assert prntr._print_Pow(sqrt(x), rational=True) == 'x**(1/2)' + + +def test_settings(): + raises(TypeError, lambda: lambdarepr(sin(x), method="garbage")) + + +def test_numexpr(): + # test ITE rewrite as Piecewise + from sympy.logic.boolalg import ITE + expr = ITE(x > 0, True, False, evaluate=False) + assert NumExprPrinter().doprint(expr) == \ + "numexpr.evaluate('where((x > 0), True, False)', truediv=True)" + + from sympy.codegen.ast import Return, FunctionDefinition, Variable, Assignment + func_def = FunctionDefinition(None, 'foo', [Variable(x)], [Assignment(y,x), Return(y**2)]) + expected = "def foo(x):\n"\ + " y = numexpr.evaluate('x', truediv=True)\n"\ + " return numexpr.evaluate('y**2', truediv=True)" + assert NumExprPrinter().doprint(func_def) == expected + + +class CustomPrintedObject(Expr): + def _lambdacode(self, printer): + return 'lambda' + + def _tensorflowcode(self, printer): + return 'tensorflow' + + def _numpycode(self, printer): + return 'numpy' + + def _numexprcode(self, printer): + return 'numexpr' + + def _mpmathcode(self, printer): + return 'mpmath' + + +def test_printmethod(): + # In each case, printmethod is called to test + # its working + + obj = CustomPrintedObject() + assert LambdaPrinter().doprint(obj) == 'lambda' + assert TensorflowPrinter().doprint(obj) == 'tensorflow' + assert NumExprPrinter().doprint(obj) == "numexpr.evaluate('numexpr', truediv=True)" + + assert NumExprPrinter().doprint(Piecewise((y, x >= 0), (z, x < 0))) == \ + "numexpr.evaluate('where((x >= 0), y, z)', truediv=True)" diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_latex.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_latex.py new file mode 100644 index 0000000000000000000000000000000000000000..063611d09a923881cd94bd693f3f3f721535fd0c --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_latex.py @@ -0,0 +1,3164 @@ +from sympy import MatAdd, MatMul, Array +from sympy.algebras.quaternion import Quaternion +from sympy.calculus.accumulationbounds import AccumBounds +from sympy.combinatorics.permutations import Cycle, Permutation, AppliedPermutation +from sympy.concrete.products import Product +from sympy.concrete.summations import Sum +from sympy.core.containers import Tuple, Dict +from sympy.core.expr import UnevaluatedExpr +from sympy.core.function import (Derivative, Function, Lambda, Subs, diff) +from sympy.core.mod import Mod +from sympy.core.mul import Mul +from sympy.core.numbers import (AlgebraicNumber, Float, I, Integer, Rational, oo, pi) +from sympy.core.parameters import evaluate +from sympy.core.power import Pow +from sympy.core.relational import Eq, Ne +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, Wild, symbols) +from sympy.functions.combinatorial.factorials import (FallingFactorial, RisingFactorial, binomial, factorial, factorial2, subfactorial) +from sympy.functions.combinatorial.numbers import (bernoulli, bell, catalan, euler, genocchi, + lucas, fibonacci, tribonacci, divisor_sigma, udivisor_sigma, + mobius, primenu, primeomega, + totient, reduced_totient) +from sympy.functions.elementary.complexes import (Abs, arg, conjugate, im, polar_lift, re) +from sympy.functions.elementary.exponential import (LambertW, exp, log) +from sympy.functions.elementary.hyperbolic import (asinh, coth) +from sympy.functions.elementary.integers import (ceiling, floor, frac) +from sympy.functions.elementary.miscellaneous import (Max, Min, root, sqrt) +from sympy.functions.elementary.piecewise import Piecewise +from sympy.functions.elementary.trigonometric import (acsc, asin, cos, cot, sin, tan) +from sympy.functions.special.beta_functions import beta +from sympy.functions.special.delta_functions import (DiracDelta, Heaviside) +from sympy.functions.special.elliptic_integrals import (elliptic_e, elliptic_f, elliptic_k, elliptic_pi) +from sympy.functions.special.error_functions import (Chi, Ci, Ei, Shi, Si, expint) +from sympy.functions.special.gamma_functions import (gamma, uppergamma) +from sympy.functions.special.hyper import (hyper, meijerg) +from sympy.functions.special.mathieu_functions import (mathieuc, mathieucprime, mathieus, mathieusprime) +from sympy.functions.special.polynomials import (assoc_laguerre, assoc_legendre, chebyshevt, chebyshevu, gegenbauer, hermite, jacobi, laguerre, legendre) +from sympy.functions.special.singularity_functions import SingularityFunction +from sympy.functions.special.spherical_harmonics import (Ynm, Znm) +from sympy.functions.special.tensor_functions import (KroneckerDelta, LeviCivita) +from sympy.functions.special.zeta_functions import (dirichlet_eta, lerchphi, polylog, stieltjes, zeta) +from sympy.integrals.integrals import Integral +from sympy.integrals.transforms import (CosineTransform, FourierTransform, InverseCosineTransform, InverseFourierTransform, InverseLaplaceTransform, InverseMellinTransform, InverseSineTransform, LaplaceTransform, MellinTransform, SineTransform) +from sympy.logic import Implies +from sympy.logic.boolalg import (And, Or, Xor, Equivalent, false, Not, true) +from sympy.matrices.dense import Matrix +from sympy.matrices.expressions.kronecker import KroneckerProduct +from sympy.matrices.expressions.matexpr import MatrixSymbol +from sympy.matrices.expressions.permutation import PermutationMatrix +from sympy.matrices.expressions.slice import MatrixSlice +from sympy.matrices.expressions.dotproduct import DotProduct +from sympy.physics.control.lti import TransferFunction, Series, Parallel, Feedback, TransferFunctionMatrix, MIMOSeries, MIMOParallel, MIMOFeedback +from sympy.physics.quantum import Commutator, Operator +from sympy.physics.quantum.trace import Tr +from sympy.physics.units import meter, gibibyte, gram, microgram, second, milli, micro +from sympy.polys.domains.integerring import ZZ +from sympy.polys.fields import field +from sympy.polys.polytools import Poly +from sympy.polys.rings import ring +from sympy.polys.rootoftools import (RootSum, rootof) +from sympy.series.formal import fps +from sympy.series.fourier import fourier_series +from sympy.series.limits import Limit +from sympy.series.order import Order +from sympy.series.sequences import (SeqAdd, SeqFormula, SeqMul, SeqPer) +from sympy.sets.conditionset import ConditionSet +from sympy.sets.contains import Contains +from sympy.sets.fancysets import (ComplexRegion, ImageSet, Range) +from sympy.sets.ordinals import Ordinal, OrdinalOmega, OmegaPower +from sympy.sets.powerset import PowerSet +from sympy.sets.sets import (FiniteSet, Interval, Union, Intersection, Complement, SymmetricDifference, ProductSet) +from sympy.sets.setexpr import SetExpr +from sympy.stats.crv_types import Normal +from sympy.stats.symbolic_probability import (Covariance, Expectation, + Probability, Variance) +from sympy.tensor.array import (ImmutableDenseNDimArray, + ImmutableSparseNDimArray, + MutableSparseNDimArray, + MutableDenseNDimArray, + tensorproduct) +from sympy.tensor.array.expressions.array_expressions import ArraySymbol, ArrayElement +from sympy.tensor.indexed import (Idx, Indexed, IndexedBase) +from sympy.tensor.toperators import PartialDerivative +from sympy.vector import CoordSys3D, Cross, Curl, Dot, Divergence, Gradient, Laplacian + + +from sympy.testing.pytest import (XFAIL, raises, _both_exp_pow, + warns_deprecated_sympy) +from sympy.printing.latex import (latex, translate, greek_letters_set, + tex_greek_dictionary, multiline_latex, + latex_escape, LatexPrinter) + +import sympy as sym + +from sympy.abc import mu, tau + + +class lowergamma(sym.lowergamma): + pass # testing notation inheritance by a subclass with same name + + +x, y, z, t, w, a, b, c, s, p = symbols('x y z t w a b c s p') +k, m, n = symbols('k m n', integer=True) + + +def test_printmethod(): + class R(Abs): + def _latex(self, printer): + return "foo(%s)" % printer._print(self.args[0]) + assert latex(R(x)) == r"foo(x)" + + class R(Abs): + def _latex(self, printer): + return "foo" + assert latex(R(x)) == r"foo" + + +def test_latex_basic(): + assert latex(1 + x) == r"x + 1" + assert latex(x**2) == r"x^{2}" + assert latex(x**(1 + x)) == r"x^{x + 1}" + assert latex(x**3 + x + 1 + x**2) == r"x^{3} + x^{2} + x + 1" + + assert latex(2*x*y) == r"2 x y" + assert latex(2*x*y, mul_symbol='dot') == r"2 \cdot x \cdot y" + assert latex(3*x**2*y, mul_symbol='\\,') == r"3\,x^{2}\,y" + assert latex(1.5*3**x, mul_symbol='\\,') == r"1.5 \cdot 3^{x}" + + assert latex(x**S.Half**5) == r"\sqrt[32]{x}" + assert latex(Mul(S.Half, x**2, -5, evaluate=False)) == r"\frac{1}{2} x^{2} \left(-5\right)" + assert latex(Mul(S.Half, x**2, 5, evaluate=False)) == r"\frac{1}{2} x^{2} \cdot 5" + assert latex(Mul(-5, -5, evaluate=False)) == r"\left(-5\right) \left(-5\right)" + assert latex(Mul(5, -5, evaluate=False)) == r"5 \left(-5\right)" + assert latex(Mul(S.Half, -5, S.Half, evaluate=False)) == r"\frac{1}{2} \left(-5\right) \frac{1}{2}" + assert latex(Mul(5, I, 5, evaluate=False)) == r"5 i 5" + assert latex(Mul(5, I, -5, evaluate=False)) == r"5 i \left(-5\right)" + assert latex(Mul(Pow(x, 2), S.Half*x + 1)) == r"x^{2} \left(\frac{x}{2} + 1\right)" + assert latex(Mul(Pow(x, 3), Rational(2, 3)*x + 1)) == r"x^{3} \left(\frac{2 x}{3} + 1\right)" + assert latex(Mul(Pow(x, 11), 2*x + 1)) == r"x^{11} \left(2 x + 1\right)" + + assert latex(Mul(0, 1, evaluate=False)) == r'0 \cdot 1' + assert latex(Mul(1, 0, evaluate=False)) == r'1 \cdot 0' + assert latex(Mul(1, 1, evaluate=False)) == r'1 \cdot 1' + assert latex(Mul(-1, 1, evaluate=False)) == r'\left(-1\right) 1' + assert latex(Mul(1, 1, 1, evaluate=False)) == r'1 \cdot 1 \cdot 1' + assert latex(Mul(1, 2, evaluate=False)) == r'1 \cdot 2' + assert latex(Mul(1, S.Half, evaluate=False)) == r'1 \cdot \frac{1}{2}' + assert latex(Mul(1, 1, S.Half, evaluate=False)) == \ + r'1 \cdot 1 \cdot \frac{1}{2}' + assert latex(Mul(1, 1, 2, 3, x, evaluate=False)) == \ + r'1 \cdot 1 \cdot 2 \cdot 3 x' + assert latex(Mul(1, -1, evaluate=False)) == r'1 \left(-1\right)' + assert latex(Mul(4, 3, 2, 1, 0, y, x, evaluate=False)) == \ + r'4 \cdot 3 \cdot 2 \cdot 1 \cdot 0 y x' + assert latex(Mul(4, 3, 2, 1+z, 0, y, x, evaluate=False)) == \ + r'4 \cdot 3 \cdot 2 \left(z + 1\right) 0 y x' + assert latex(Mul(Rational(2, 3), Rational(5, 7), evaluate=False)) == \ + r'\frac{2}{3} \cdot \frac{5}{7}' + + assert latex(1/x) == r"\frac{1}{x}" + assert latex(1/x, fold_short_frac=True) == r"1 / x" + assert latex(-S(3)/2) == r"- \frac{3}{2}" + assert latex(-S(3)/2, fold_short_frac=True) == r"- 3 / 2" + assert latex(1/x**2) == r"\frac{1}{x^{2}}" + assert latex(1/(x + y)/2) == r"\frac{1}{2 \left(x + y\right)}" + assert latex(x/2) == r"\frac{x}{2}" + assert latex(x/2, fold_short_frac=True) == r"x / 2" + assert latex((x + y)/(2*x)) == r"\frac{x + y}{2 x}" + assert latex((x + y)/(2*x), fold_short_frac=True) == \ + r"\left(x + y\right) / 2 x" + assert latex((x + y)/(2*x), long_frac_ratio=0) == \ + r"\frac{1}{2 x} \left(x + y\right)" + assert latex((x + y)/x) == r"\frac{x + y}{x}" + assert latex((x + y)/x, long_frac_ratio=3) == r"\frac{x + y}{x}" + assert latex((2*sqrt(2)*x)/3) == r"\frac{2 \sqrt{2} x}{3}" + assert latex((2*sqrt(2)*x)/3, long_frac_ratio=2) == \ + r"\frac{2 x}{3} \sqrt{2}" + assert latex(binomial(x, y)) == r"{\binom{x}{y}}" + + x_star = Symbol('x^*') + f = Function('f') + assert latex(x_star**2) == r"\left(x^{*}\right)^{2}" + assert latex(x_star**2, parenthesize_super=False) == r"{x^{*}}^{2}" + assert latex(Derivative(f(x_star), x_star,2)) == r"\frac{d^{2}}{d \left(x^{*}\right)^{2}} f{\left(x^{*} \right)}" + assert latex(Derivative(f(x_star), x_star,2), parenthesize_super=False) == r"\frac{d^{2}}{d {x^{*}}^{2}} f{\left(x^{*} \right)}" + + assert latex(2*Integral(x, x)/3) == r"\frac{2 \int x\, dx}{3}" + assert latex(2*Integral(x, x)/3, fold_short_frac=True) == \ + r"\left(2 \int x\, dx\right) / 3" + + assert latex(sqrt(x)) == r"\sqrt{x}" + assert latex(x**Rational(1, 3)) == r"\sqrt[3]{x}" + assert latex(x**Rational(1, 3), root_notation=False) == r"x^{\frac{1}{3}}" + assert latex(sqrt(x)**3) == r"x^{\frac{3}{2}}" + assert latex(sqrt(x), itex=True) == r"\sqrt{x}" + assert latex(x**Rational(1, 3), itex=True) == r"\root{3}{x}" + assert latex(sqrt(x)**3, itex=True) == r"x^{\frac{3}{2}}" + assert latex(x**Rational(3, 4)) == r"x^{\frac{3}{4}}" + assert latex(x**Rational(3, 4), fold_frac_powers=True) == r"x^{3/4}" + assert latex((x + 1)**Rational(3, 4)) == \ + r"\left(x + 1\right)^{\frac{3}{4}}" + assert latex((x + 1)**Rational(3, 4), fold_frac_powers=True) == \ + r"\left(x + 1\right)^{3/4}" + assert latex(AlgebraicNumber(sqrt(2))) == r"\sqrt{2}" + assert latex(AlgebraicNumber(sqrt(2), [3, -7])) == r"-7 + 3 \sqrt{2}" + assert latex(AlgebraicNumber(sqrt(2), alias='alpha')) == r"\alpha" + assert latex(AlgebraicNumber(sqrt(2), [3, -7], alias='alpha')) == \ + r"3 \alpha - 7" + assert latex(AlgebraicNumber(2**(S(1)/3), [1, 3, -7], alias='beta')) == \ + r"\beta^{2} + 3 \beta - 7" + + k = ZZ.cyclotomic_field(5) + assert latex(k.ext.field_element([1, 2, 3, 4])) == \ + r"\zeta^{3} + 2 \zeta^{2} + 3 \zeta + 4" + assert latex(k.ext.field_element([1, 2, 3, 4]), order='old') == \ + r"4 + 3 \zeta + 2 \zeta^{2} + \zeta^{3}" + assert latex(k.primes_above(19)[0]) == \ + r"\left(19, \zeta^{2} + 5 \zeta + 1\right)" + assert latex(k.primes_above(19)[0], order='old') == \ + r"\left(19, 1 + 5 \zeta + \zeta^{2}\right)" + assert latex(k.primes_above(7)[0]) == r"\left(7\right)" + + assert latex(1.5e20*x) == r"1.5 \cdot 10^{20} x" + assert latex(1.5e20*x, mul_symbol='dot') == r"1.5 \cdot 10^{20} \cdot x" + assert latex(1.5e20*x, mul_symbol='times') == \ + r"1.5 \times 10^{20} \times x" + + assert latex(1/sin(x)) == r"\frac{1}{\sin{\left(x \right)}}" + assert latex(sin(x)**-1) == r"\frac{1}{\sin{\left(x \right)}}" + assert latex(sin(x)**Rational(3, 2)) == \ + r"\sin^{\frac{3}{2}}{\left(x \right)}" + assert latex(sin(x)**Rational(3, 2), fold_frac_powers=True) == \ + r"\sin^{3/2}{\left(x \right)}" + + assert latex(~x) == r"\neg x" + assert latex(x & y) == r"x \wedge y" + assert latex(x & y & z) == r"x \wedge y \wedge z" + assert latex(x | y) == r"x \vee y" + assert latex(x | y | z) == r"x \vee y \vee z" + assert latex((x & y) | z) == r"z \vee \left(x \wedge y\right)" + assert latex(Implies(x, y)) == r"x \Rightarrow y" + assert latex(~(x >> ~y)) == r"x \not\Rightarrow \neg y" + assert latex(Implies(Or(x,y), z)) == r"\left(x \vee y\right) \Rightarrow z" + assert latex(Implies(z, Or(x,y))) == r"z \Rightarrow \left(x \vee y\right)" + assert latex(~(x & y)) == r"\neg \left(x \wedge y\right)" + + assert latex(~x, symbol_names={x: "x_i"}) == r"\neg x_i" + assert latex(x & y, symbol_names={x: "x_i", y: "y_i"}) == \ + r"x_i \wedge y_i" + assert latex(x & y & z, symbol_names={x: "x_i", y: "y_i", z: "z_i"}) == \ + r"x_i \wedge y_i \wedge z_i" + assert latex(x | y, symbol_names={x: "x_i", y: "y_i"}) == r"x_i \vee y_i" + assert latex(x | y | z, symbol_names={x: "x_i", y: "y_i", z: "z_i"}) == \ + r"x_i \vee y_i \vee z_i" + assert latex((x & y) | z, symbol_names={x: "x_i", y: "y_i", z: "z_i"}) == \ + r"z_i \vee \left(x_i \wedge y_i\right)" + assert latex(Implies(x, y), symbol_names={x: "x_i", y: "y_i"}) == \ + r"x_i \Rightarrow y_i" + assert latex(Pow(Rational(1, 3), -1, evaluate=False)) == r"\frac{1}{\frac{1}{3}}" + assert latex(Pow(Rational(1, 3), -2, evaluate=False)) == r"\frac{1}{(\frac{1}{3})^{2}}" + assert latex(Pow(Integer(1)/100, -1, evaluate=False)) == r"\frac{1}{\frac{1}{100}}" + + p = Symbol('p', positive=True) + assert latex(exp(-p)*log(p)) == r"e^{- p} \log{\left(p \right)}" + + assert latex(Pow(Rational(2, 3), -1, evaluate=False)) == r'\frac{1}{\frac{2}{3}}' + assert latex(Pow(Rational(4, 3), -1, evaluate=False)) == r'\frac{1}{\frac{4}{3}}' + assert latex(Pow(Rational(-3, 4), -1, evaluate=False)) == r'\frac{1}{- \frac{3}{4}}' + assert latex(Pow(Rational(-4, 4), -1, evaluate=False)) == r'\frac{1}{-1}' + assert latex(Pow(Rational(1, 3), -1, evaluate=False)) == r'\frac{1}{\frac{1}{3}}' + assert latex(Pow(Rational(-1, 3), -1, evaluate=False)) == r'\frac{1}{- \frac{1}{3}}' + + +def test_latex_builtins(): + assert latex(True) == r"\text{True}" + assert latex(False) == r"\text{False}" + assert latex(None) == r"\text{None}" + assert latex(true) == r"\text{True}" + assert latex(false) == r'\text{False}' + + +def test_latex_SingularityFunction(): + assert latex(SingularityFunction(x, 4, 5)) == \ + r"{\left\langle x - 4 \right\rangle}^{5}" + assert latex(SingularityFunction(x, -3, 4)) == \ + r"{\left\langle x + 3 \right\rangle}^{4}" + assert latex(SingularityFunction(x, 0, 4)) == \ + r"{\left\langle x \right\rangle}^{4}" + assert latex(SingularityFunction(x, a, n)) == \ + r"{\left\langle - a + x \right\rangle}^{n}" + assert latex(SingularityFunction(x, 4, -2)) == \ + r"{\left\langle x - 4 \right\rangle}^{-2}" + assert latex(SingularityFunction(x, 4, -1)) == \ + r"{\left\langle x - 4 \right\rangle}^{-1}" + + assert latex(SingularityFunction(x, 4, 5)**3) == \ + r"{\left({\langle x - 4 \rangle}^{5}\right)}^{3}" + assert latex(SingularityFunction(x, -3, 4)**3) == \ + r"{\left({\langle x + 3 \rangle}^{4}\right)}^{3}" + assert latex(SingularityFunction(x, 0, 4)**3) == \ + r"{\left({\langle x \rangle}^{4}\right)}^{3}" + assert latex(SingularityFunction(x, a, n)**3) == \ + r"{\left({\langle - a + x \rangle}^{n}\right)}^{3}" + assert latex(SingularityFunction(x, 4, -2)**3) == \ + r"{\left({\langle x - 4 \rangle}^{-2}\right)}^{3}" + assert latex((SingularityFunction(x, 4, -1)**3)**3) == \ + r"{\left({\langle x - 4 \rangle}^{-1}\right)}^{9}" + + +def test_latex_cycle(): + assert latex(Cycle(1, 2, 4)) == r"\left( 1\; 2\; 4\right)" + assert latex(Cycle(1, 2)(4, 5, 6)) == \ + r"\left( 1\; 2\right)\left( 4\; 5\; 6\right)" + assert latex(Cycle()) == r"\left( \right)" + + +def test_latex_permutation(): + assert latex(Permutation(1, 2, 4)) == r"\left( 1\; 2\; 4\right)" + assert latex(Permutation(1, 2)(4, 5, 6)) == \ + r"\left( 1\; 2\right)\left( 4\; 5\; 6\right)" + assert latex(Permutation()) == r"\left( \right)" + assert latex(Permutation(2, 4)*Permutation(5)) == \ + r"\left( 2\; 4\right)\left( 5\right)" + assert latex(Permutation(5)) == r"\left( 5\right)" + + assert latex(Permutation(0, 1), perm_cyclic=False) == \ + r"\begin{pmatrix} 0 & 1 \\ 1 & 0 \end{pmatrix}" + assert latex(Permutation(0, 1)(2, 3), perm_cyclic=False) == \ + r"\begin{pmatrix} 0 & 1 & 2 & 3 \\ 1 & 0 & 3 & 2 \end{pmatrix}" + assert latex(Permutation(), perm_cyclic=False) == \ + r"\left( \right)" + + with warns_deprecated_sympy(): + old_print_cyclic = Permutation.print_cyclic + Permutation.print_cyclic = False + assert latex(Permutation(0, 1)(2, 3)) == \ + r"\begin{pmatrix} 0 & 1 & 2 & 3 \\ 1 & 0 & 3 & 2 \end{pmatrix}" + Permutation.print_cyclic = old_print_cyclic + +def test_latex_Float(): + assert latex(Float(1.0e100)) == r"1.0 \cdot 10^{100}" + assert latex(Float(1.0e-100)) == r"1.0 \cdot 10^{-100}" + assert latex(Float(1.0e-100), mul_symbol="times") == \ + r"1.0 \times 10^{-100}" + assert latex(Float('10000.0'), full_prec=False, min=-2, max=2) == \ + r"1.0 \cdot 10^{4}" + assert latex(Float('10000.0'), full_prec=False, min=-2, max=4) == \ + r"1.0 \cdot 10^{4}" + assert latex(Float('10000.0'), full_prec=False, min=-2, max=5) == \ + r"10000.0" + assert latex(Float('0.099999'), full_prec=True, min=-2, max=5) == \ + r"9.99990000000000 \cdot 10^{-2}" + + +def test_latex_vector_expressions(): + A = CoordSys3D('A') + + assert latex(Cross(A.i, A.j*A.x*3+A.k)) == \ + r"\mathbf{\hat{i}_{A}} \times \left(\left(3 \mathbf{{x}_{A}}\right)\mathbf{\hat{j}_{A}} + \mathbf{\hat{k}_{A}}\right)" + assert latex(Cross(A.i, A.j)) == \ + r"\mathbf{\hat{i}_{A}} \times \mathbf{\hat{j}_{A}}" + assert latex(x*Cross(A.i, A.j)) == \ + r"x \left(\mathbf{\hat{i}_{A}} \times \mathbf{\hat{j}_{A}}\right)" + assert latex(Cross(x*A.i, A.j)) == \ + r'- \mathbf{\hat{j}_{A}} \times \left(\left(x\right)\mathbf{\hat{i}_{A}}\right)' + + assert latex(Curl(3*A.x*A.j)) == \ + r"\nabla\times \left(\left(3 \mathbf{{x}_{A}}\right)\mathbf{\hat{j}_{A}}\right)" + assert latex(Curl(3*A.x*A.j+A.i)) == \ + r"\nabla\times \left(\mathbf{\hat{i}_{A}} + \left(3 \mathbf{{x}_{A}}\right)\mathbf{\hat{j}_{A}}\right)" + assert latex(Curl(3*x*A.x*A.j)) == \ + r"\nabla\times \left(\left(3 \mathbf{{x}_{A}} x\right)\mathbf{\hat{j}_{A}}\right)" + assert latex(x*Curl(3*A.x*A.j)) == \ + r"x \left(\nabla\times \left(\left(3 \mathbf{{x}_{A}}\right)\mathbf{\hat{j}_{A}}\right)\right)" + + assert latex(Divergence(3*A.x*A.j+A.i)) == \ + r"\nabla\cdot \left(\mathbf{\hat{i}_{A}} + \left(3 \mathbf{{x}_{A}}\right)\mathbf{\hat{j}_{A}}\right)" + assert latex(Divergence(3*A.x*A.j)) == \ + r"\nabla\cdot \left(\left(3 \mathbf{{x}_{A}}\right)\mathbf{\hat{j}_{A}}\right)" + assert latex(x*Divergence(3*A.x*A.j)) == \ + r"x \left(\nabla\cdot \left(\left(3 \mathbf{{x}_{A}}\right)\mathbf{\hat{j}_{A}}\right)\right)" + + assert latex(Dot(A.i, A.j*A.x*3+A.k)) == \ + r"\mathbf{\hat{i}_{A}} \cdot \left(\left(3 \mathbf{{x}_{A}}\right)\mathbf{\hat{j}_{A}} + \mathbf{\hat{k}_{A}}\right)" + assert latex(Dot(A.i, A.j)) == \ + r"\mathbf{\hat{i}_{A}} \cdot \mathbf{\hat{j}_{A}}" + assert latex(Dot(x*A.i, A.j)) == \ + r"\mathbf{\hat{j}_{A}} \cdot \left(\left(x\right)\mathbf{\hat{i}_{A}}\right)" + assert latex(x*Dot(A.i, A.j)) == \ + r"x \left(\mathbf{\hat{i}_{A}} \cdot \mathbf{\hat{j}_{A}}\right)" + + assert latex(Gradient(A.x)) == r"\nabla \mathbf{{x}_{A}}" + assert latex(Gradient(A.x + 3*A.y)) == \ + r"\nabla \left(\mathbf{{x}_{A}} + 3 \mathbf{{y}_{A}}\right)" + assert latex(x*Gradient(A.x)) == r"x \left(\nabla \mathbf{{x}_{A}}\right)" + assert latex(Gradient(x*A.x)) == r"\nabla \left(\mathbf{{x}_{A}} x\right)" + + assert latex(Laplacian(A.x)) == r"\Delta \mathbf{{x}_{A}}" + assert latex(Laplacian(A.x + 3*A.y)) == \ + r"\Delta \left(\mathbf{{x}_{A}} + 3 \mathbf{{y}_{A}}\right)" + assert latex(x*Laplacian(A.x)) == r"x \left(\Delta \mathbf{{x}_{A}}\right)" + assert latex(Laplacian(x*A.x)) == r"\Delta \left(\mathbf{{x}_{A}} x\right)" + +def test_latex_symbols(): + Gamma, lmbda, rho = symbols('Gamma, lambda, rho') + tau, Tau, TAU, taU = symbols('tau, Tau, TAU, taU') + assert latex(tau) == r"\tau" + assert latex(Tau) == r"\mathrm{T}" + assert latex(TAU) == r"\tau" + assert latex(taU) == r"\tau" + # Check that all capitalized greek letters are handled explicitly + capitalized_letters = {l.capitalize() for l in greek_letters_set} + assert len(capitalized_letters - set(tex_greek_dictionary.keys())) == 0 + assert latex(Gamma + lmbda) == r"\Gamma + \lambda" + assert latex(Gamma * lmbda) == r"\Gamma \lambda" + assert latex(Symbol('q1')) == r"q_{1}" + assert latex(Symbol('q21')) == r"q_{21}" + assert latex(Symbol('epsilon0')) == r"\epsilon_{0}" + assert latex(Symbol('omega1')) == r"\omega_{1}" + assert latex(Symbol('91')) == r"91" + assert latex(Symbol('alpha_new')) == r"\alpha_{new}" + assert latex(Symbol('C^orig')) == r"C^{orig}" + assert latex(Symbol('x^alpha')) == r"x^{\alpha}" + assert latex(Symbol('beta^alpha')) == r"\beta^{\alpha}" + assert latex(Symbol('e^Alpha')) == r"e^{\mathrm{A}}" + assert latex(Symbol('omega_alpha^beta')) == r"\omega^{\beta}_{\alpha}" + assert latex(Symbol('omega') ** Symbol('beta')) == r"\omega^{\beta}" + + +@XFAIL +def test_latex_symbols_failing(): + rho, mass, volume = symbols('rho, mass, volume') + assert latex( + volume * rho == mass) == r"\rho \mathrm{volume} = \mathrm{mass}" + assert latex(volume / mass * rho == 1) == \ + r"\rho \mathrm{volume} {\mathrm{mass}}^{(-1)} = 1" + assert latex(mass**3 * volume**3) == \ + r"{\mathrm{mass}}^{3} \cdot {\mathrm{volume}}^{3}" + + +@_both_exp_pow +def test_latex_functions(): + assert latex(exp(x)) == r"e^{x}" + assert latex(exp(1) + exp(2)) == r"e + e^{2}" + + f = Function('f') + assert latex(f(x)) == r'f{\left(x \right)}' + assert latex(f) == r'f' + + g = Function('g') + assert latex(g(x, y)) == r'g{\left(x,y \right)}' + assert latex(g) == r'g' + + h = Function('h') + assert latex(h(x, y, z)) == r'h{\left(x,y,z \right)}' + assert latex(h) == r'h' + + Li = Function('Li') + assert latex(Li) == r'\operatorname{Li}' + assert latex(Li(x)) == r'\operatorname{Li}{\left(x \right)}' + + mybeta = Function('beta') + # not to be confused with the beta function + assert latex(mybeta(x, y, z)) == r"\beta{\left(x,y,z \right)}" + assert latex(beta(x, y)) == r'\operatorname{B}\left(x, y\right)' + assert latex(beta(x, evaluate=False)) == r'\operatorname{B}\left(x, x\right)' + assert latex(beta(x, y)**2) == r'\operatorname{B}^{2}\left(x, y\right)' + assert latex(mybeta(x)) == r"\beta{\left(x \right)}" + assert latex(mybeta) == r"\beta" + + g = Function('gamma') + # not to be confused with the gamma function + assert latex(g(x, y, z)) == r"\gamma{\left(x,y,z \right)}" + assert latex(g(x)) == r"\gamma{\left(x \right)}" + assert latex(g) == r"\gamma" + + a_1 = Function('a_1') + assert latex(a_1) == r"a_{1}" + assert latex(a_1(x)) == r"a_{1}{\left(x \right)}" + assert latex(Function('a_1')) == r"a_{1}" + + # Issue #16925 + # multi letter function names + # > simple + assert latex(Function('ab')) == r"\operatorname{ab}" + assert latex(Function('ab1')) == r"\operatorname{ab}_{1}" + assert latex(Function('ab12')) == r"\operatorname{ab}_{12}" + assert latex(Function('ab_1')) == r"\operatorname{ab}_{1}" + assert latex(Function('ab_12')) == r"\operatorname{ab}_{12}" + assert latex(Function('ab_c')) == r"\operatorname{ab}_{c}" + assert latex(Function('ab_cd')) == r"\operatorname{ab}_{cd}" + # > with argument + assert latex(Function('ab')(Symbol('x'))) == r"\operatorname{ab}{\left(x \right)}" + assert latex(Function('ab1')(Symbol('x'))) == r"\operatorname{ab}_{1}{\left(x \right)}" + assert latex(Function('ab12')(Symbol('x'))) == r"\operatorname{ab}_{12}{\left(x \right)}" + assert latex(Function('ab_1')(Symbol('x'))) == r"\operatorname{ab}_{1}{\left(x \right)}" + assert latex(Function('ab_c')(Symbol('x'))) == r"\operatorname{ab}_{c}{\left(x \right)}" + assert latex(Function('ab_cd')(Symbol('x'))) == r"\operatorname{ab}_{cd}{\left(x \right)}" + + # > with power + # does not work on functions without brackets + + # > with argument and power combined + assert latex(Function('ab')()**2) == r"\operatorname{ab}^{2}{\left( \right)}" + assert latex(Function('ab1')()**2) == r"\operatorname{ab}_{1}^{2}{\left( \right)}" + assert latex(Function('ab12')()**2) == r"\operatorname{ab}_{12}^{2}{\left( \right)}" + assert latex(Function('ab_1')()**2) == r"\operatorname{ab}_{1}^{2}{\left( \right)}" + assert latex(Function('ab_12')()**2) == r"\operatorname{ab}_{12}^{2}{\left( \right)}" + assert latex(Function('ab')(Symbol('x'))**2) == r"\operatorname{ab}^{2}{\left(x \right)}" + assert latex(Function('ab1')(Symbol('x'))**2) == r"\operatorname{ab}_{1}^{2}{\left(x \right)}" + assert latex(Function('ab12')(Symbol('x'))**2) == r"\operatorname{ab}_{12}^{2}{\left(x \right)}" + assert latex(Function('ab_1')(Symbol('x'))**2) == r"\operatorname{ab}_{1}^{2}{\left(x \right)}" + assert latex(Function('ab_12')(Symbol('x'))**2) == \ + r"\operatorname{ab}_{12}^{2}{\left(x \right)}" + + # single letter function names + # > simple + assert latex(Function('a')) == r"a" + assert latex(Function('a1')) == r"a_{1}" + assert latex(Function('a12')) == r"a_{12}" + assert latex(Function('a_1')) == r"a_{1}" + assert latex(Function('a_12')) == r"a_{12}" + + # > with argument + assert latex(Function('a')()) == r"a{\left( \right)}" + assert latex(Function('a1')()) == r"a_{1}{\left( \right)}" + assert latex(Function('a12')()) == r"a_{12}{\left( \right)}" + assert latex(Function('a_1')()) == r"a_{1}{\left( \right)}" + assert latex(Function('a_12')()) == r"a_{12}{\left( \right)}" + + # > with power + # does not work on functions without brackets + + # > with argument and power combined + assert latex(Function('a')()**2) == r"a^{2}{\left( \right)}" + assert latex(Function('a1')()**2) == r"a_{1}^{2}{\left( \right)}" + assert latex(Function('a12')()**2) == r"a_{12}^{2}{\left( \right)}" + assert latex(Function('a_1')()**2) == r"a_{1}^{2}{\left( \right)}" + assert latex(Function('a_12')()**2) == r"a_{12}^{2}{\left( \right)}" + assert latex(Function('a')(Symbol('x'))**2) == r"a^{2}{\left(x \right)}" + assert latex(Function('a1')(Symbol('x'))**2) == r"a_{1}^{2}{\left(x \right)}" + assert latex(Function('a12')(Symbol('x'))**2) == r"a_{12}^{2}{\left(x \right)}" + assert latex(Function('a_1')(Symbol('x'))**2) == r"a_{1}^{2}{\left(x \right)}" + assert latex(Function('a_12')(Symbol('x'))**2) == r"a_{12}^{2}{\left(x \right)}" + + assert latex(Function('a')()**32) == r"a^{32}{\left( \right)}" + assert latex(Function('a1')()**32) == r"a_{1}^{32}{\left( \right)}" + assert latex(Function('a12')()**32) == r"a_{12}^{32}{\left( \right)}" + assert latex(Function('a_1')()**32) == r"a_{1}^{32}{\left( \right)}" + assert latex(Function('a_12')()**32) == r"a_{12}^{32}{\left( \right)}" + assert latex(Function('a')(Symbol('x'))**32) == r"a^{32}{\left(x \right)}" + assert latex(Function('a1')(Symbol('x'))**32) == r"a_{1}^{32}{\left(x \right)}" + assert latex(Function('a12')(Symbol('x'))**32) == r"a_{12}^{32}{\left(x \right)}" + assert latex(Function('a_1')(Symbol('x'))**32) == r"a_{1}^{32}{\left(x \right)}" + assert latex(Function('a_12')(Symbol('x'))**32) == r"a_{12}^{32}{\left(x \right)}" + + assert latex(Function('a')()**a) == r"a^{a}{\left( \right)}" + assert latex(Function('a1')()**a) == r"a_{1}^{a}{\left( \right)}" + assert latex(Function('a12')()**a) == r"a_{12}^{a}{\left( \right)}" + assert latex(Function('a_1')()**a) == r"a_{1}^{a}{\left( \right)}" + assert latex(Function('a_12')()**a) == r"a_{12}^{a}{\left( \right)}" + assert latex(Function('a')(Symbol('x'))**a) == r"a^{a}{\left(x \right)}" + assert latex(Function('a1')(Symbol('x'))**a) == r"a_{1}^{a}{\left(x \right)}" + assert latex(Function('a12')(Symbol('x'))**a) == r"a_{12}^{a}{\left(x \right)}" + assert latex(Function('a_1')(Symbol('x'))**a) == r"a_{1}^{a}{\left(x \right)}" + assert latex(Function('a_12')(Symbol('x'))**a) == r"a_{12}^{a}{\left(x \right)}" + + ab = Symbol('ab') + assert latex(Function('a')()**ab) == r"a^{ab}{\left( \right)}" + assert latex(Function('a1')()**ab) == r"a_{1}^{ab}{\left( \right)}" + assert latex(Function('a12')()**ab) == r"a_{12}^{ab}{\left( \right)}" + assert latex(Function('a_1')()**ab) == r"a_{1}^{ab}{\left( \right)}" + assert latex(Function('a_12')()**ab) == r"a_{12}^{ab}{\left( \right)}" + assert latex(Function('a')(Symbol('x'))**ab) == r"a^{ab}{\left(x \right)}" + assert latex(Function('a1')(Symbol('x'))**ab) == r"a_{1}^{ab}{\left(x \right)}" + assert latex(Function('a12')(Symbol('x'))**ab) == r"a_{12}^{ab}{\left(x \right)}" + assert latex(Function('a_1')(Symbol('x'))**ab) == r"a_{1}^{ab}{\left(x \right)}" + assert latex(Function('a_12')(Symbol('x'))**ab) == r"a_{12}^{ab}{\left(x \right)}" + + assert latex(Function('a^12')(x)) == R"a^{12}{\left(x \right)}" + assert latex(Function('a^12')(x) ** ab) == R"\left(a^{12}\right)^{ab}{\left(x \right)}" + assert latex(Function('a__12')(x)) == R"a^{12}{\left(x \right)}" + assert latex(Function('a__12')(x) ** ab) == R"\left(a^{12}\right)^{ab}{\left(x \right)}" + assert latex(Function('a_1__1_2')(x)) == R"a^{1}_{1 2}{\left(x \right)}" + + # issue 5868 + omega1 = Function('omega1') + assert latex(omega1) == r"\omega_{1}" + assert latex(omega1(x)) == r"\omega_{1}{\left(x \right)}" + + assert latex(sin(x)) == r"\sin{\left(x \right)}" + assert latex(sin(x), fold_func_brackets=True) == r"\sin {x}" + assert latex(sin(2*x**2), fold_func_brackets=True) == \ + r"\sin {2 x^{2}}" + assert latex(sin(x**2), fold_func_brackets=True) == \ + r"\sin {x^{2}}" + + assert latex(asin(x)**2) == r"\operatorname{asin}^{2}{\left(x \right)}" + assert latex(asin(x)**2, inv_trig_style="full") == \ + r"\arcsin^{2}{\left(x \right)}" + assert latex(asin(x)**2, inv_trig_style="power") == \ + r"\sin^{-1}{\left(x \right)}^{2}" + assert latex(asin(x**2), inv_trig_style="power", + fold_func_brackets=True) == \ + r"\sin^{-1} {x^{2}}" + assert latex(acsc(x), inv_trig_style="full") == \ + r"\operatorname{arccsc}{\left(x \right)}" + assert latex(asinh(x), inv_trig_style="full") == \ + r"\operatorname{arsinh}{\left(x \right)}" + + assert latex(factorial(k)) == r"k!" + assert latex(factorial(-k)) == r"\left(- k\right)!" + assert latex(factorial(k)**2) == r"k!^{2}" + + assert latex(subfactorial(k)) == r"!k" + assert latex(subfactorial(-k)) == r"!\left(- k\right)" + assert latex(subfactorial(k)**2) == r"\left(!k\right)^{2}" + + assert latex(factorial2(k)) == r"k!!" + assert latex(factorial2(-k)) == r"\left(- k\right)!!" + assert latex(factorial2(k)**2) == r"k!!^{2}" + + assert latex(binomial(2, k)) == r"{\binom{2}{k}}" + assert latex(binomial(2, k)**2) == r"{\binom{2}{k}}^{2}" + + assert latex(FallingFactorial(3, k)) == r"{\left(3\right)}_{k}" + assert latex(RisingFactorial(3, k)) == r"{3}^{\left(k\right)}" + + assert latex(floor(x)) == r"\left\lfloor{x}\right\rfloor" + assert latex(ceiling(x)) == r"\left\lceil{x}\right\rceil" + assert latex(frac(x)) == r"\operatorname{frac}{\left(x\right)}" + assert latex(floor(x)**2) == r"\left\lfloor{x}\right\rfloor^{2}" + assert latex(ceiling(x)**2) == r"\left\lceil{x}\right\rceil^{2}" + assert latex(frac(x)**2) == r"\operatorname{frac}{\left(x\right)}^{2}" + + assert latex(Min(x, 2, x**3)) == r"\min\left(2, x, x^{3}\right)" + assert latex(Min(x, y)**2) == r"\min\left(x, y\right)^{2}" + assert latex(Max(x, 2, x**3)) == r"\max\left(2, x, x^{3}\right)" + assert latex(Max(x, y)**2) == r"\max\left(x, y\right)^{2}" + assert latex(Abs(x)) == r"\left|{x}\right|" + assert latex(Abs(x)**2) == r"\left|{x}\right|^{2}" + assert latex(re(x)) == r"\operatorname{re}{\left(x\right)}" + assert latex(re(x + y)) == \ + r"\operatorname{re}{\left(x\right)} + \operatorname{re}{\left(y\right)}" + assert latex(im(x)) == r"\operatorname{im}{\left(x\right)}" + assert latex(conjugate(x)) == r"\overline{x}" + assert latex(conjugate(x)**2) == r"\overline{x}^{2}" + assert latex(conjugate(x**2)) == r"\overline{x}^{2}" + assert latex(gamma(x)) == r"\Gamma\left(x\right)" + w = Wild('w') + assert latex(gamma(w)) == r"\Gamma\left(w\right)" + assert latex(Order(x)) == r"O\left(x\right)" + assert latex(Order(x, x)) == r"O\left(x\right)" + assert latex(Order(x, (x, 0))) == r"O\left(x\right)" + assert latex(Order(x, (x, oo))) == r"O\left(x; x\rightarrow \infty\right)" + assert latex(Order(x - y, (x, y))) == \ + r"O\left(x - y; x\rightarrow y\right)" + assert latex(Order(x, x, y)) == \ + r"O\left(x; \left( x, \ y\right)\rightarrow \left( 0, \ 0\right)\right)" + assert latex(Order(x, x, y)) == \ + r"O\left(x; \left( x, \ y\right)\rightarrow \left( 0, \ 0\right)\right)" + assert latex(Order(x, (x, oo), (y, oo))) == \ + r"O\left(x; \left( x, \ y\right)\rightarrow \left( \infty, \ \infty\right)\right)" + assert latex(lowergamma(x, y)) == r'\gamma\left(x, y\right)' + assert latex(lowergamma(x, y)**2) == r'\gamma^{2}\left(x, y\right)' + assert latex(uppergamma(x, y)) == r'\Gamma\left(x, y\right)' + assert latex(uppergamma(x, y)**2) == r'\Gamma^{2}\left(x, y\right)' + + assert latex(cot(x)) == r'\cot{\left(x \right)}' + assert latex(coth(x)) == r'\coth{\left(x \right)}' + assert latex(re(x)) == r'\operatorname{re}{\left(x\right)}' + assert latex(im(x)) == r'\operatorname{im}{\left(x\right)}' + assert latex(root(x, y)) == r'x^{\frac{1}{y}}' + assert latex(arg(x)) == r'\arg{\left(x \right)}' + + assert latex(zeta(x)) == r"\zeta\left(x\right)" + assert latex(zeta(x)**2) == r"\zeta^{2}\left(x\right)" + assert latex(zeta(x, y)) == r"\zeta\left(x, y\right)" + assert latex(zeta(x, y)**2) == r"\zeta^{2}\left(x, y\right)" + assert latex(dirichlet_eta(x)) == r"\eta\left(x\right)" + assert latex(dirichlet_eta(x)**2) == r"\eta^{2}\left(x\right)" + assert latex(polylog(x, y)) == r"\operatorname{Li}_{x}\left(y\right)" + assert latex( + polylog(x, y)**2) == r"\operatorname{Li}_{x}^{2}\left(y\right)" + assert latex(lerchphi(x, y, n)) == r"\Phi\left(x, y, n\right)" + assert latex(lerchphi(x, y, n)**2) == r"\Phi^{2}\left(x, y, n\right)" + assert latex(stieltjes(x)) == r"\gamma_{x}" + assert latex(stieltjes(x)**2) == r"\gamma_{x}^{2}" + assert latex(stieltjes(x, y)) == r"\gamma_{x}\left(y\right)" + assert latex(stieltjes(x, y)**2) == r"\gamma_{x}\left(y\right)^{2}" + + assert latex(elliptic_k(z)) == r"K\left(z\right)" + assert latex(elliptic_k(z)**2) == r"K^{2}\left(z\right)" + assert latex(elliptic_f(x, y)) == r"F\left(x\middle| y\right)" + assert latex(elliptic_f(x, y)**2) == r"F^{2}\left(x\middle| y\right)" + assert latex(elliptic_e(x, y)) == r"E\left(x\middle| y\right)" + assert latex(elliptic_e(x, y)**2) == r"E^{2}\left(x\middle| y\right)" + assert latex(elliptic_e(z)) == r"E\left(z\right)" + assert latex(elliptic_e(z)**2) == r"E^{2}\left(z\right)" + assert latex(elliptic_pi(x, y, z)) == r"\Pi\left(x; y\middle| z\right)" + assert latex(elliptic_pi(x, y, z)**2) == \ + r"\Pi^{2}\left(x; y\middle| z\right)" + assert latex(elliptic_pi(x, y)) == r"\Pi\left(x\middle| y\right)" + assert latex(elliptic_pi(x, y)**2) == r"\Pi^{2}\left(x\middle| y\right)" + + assert latex(Ei(x)) == r'\operatorname{Ei}{\left(x \right)}' + assert latex(Ei(x)**2) == r'\operatorname{Ei}^{2}{\left(x \right)}' + assert latex(expint(x, y)) == r'\operatorname{E}_{x}\left(y\right)' + assert latex(expint(x, y)**2) == r'\operatorname{E}_{x}^{2}\left(y\right)' + assert latex(Shi(x)**2) == r'\operatorname{Shi}^{2}{\left(x \right)}' + assert latex(Si(x)**2) == r'\operatorname{Si}^{2}{\left(x \right)}' + assert latex(Ci(x)**2) == r'\operatorname{Ci}^{2}{\left(x \right)}' + assert latex(Chi(x)**2) == r'\operatorname{Chi}^{2}\left(x\right)' + assert latex(Chi(x)) == r'\operatorname{Chi}\left(x\right)' + assert latex(jacobi(n, a, b, x)) == \ + r'P_{n}^{\left(a,b\right)}\left(x\right)' + assert latex(jacobi(n, a, b, x)**2) == \ + r'\left(P_{n}^{\left(a,b\right)}\left(x\right)\right)^{2}' + assert latex(gegenbauer(n, a, x)) == \ + r'C_{n}^{\left(a\right)}\left(x\right)' + assert latex(gegenbauer(n, a, x)**2) == \ + r'\left(C_{n}^{\left(a\right)}\left(x\right)\right)^{2}' + assert latex(chebyshevt(n, x)) == r'T_{n}\left(x\right)' + assert latex(chebyshevt(n, x)**2) == \ + r'\left(T_{n}\left(x\right)\right)^{2}' + assert latex(chebyshevu(n, x)) == r'U_{n}\left(x\right)' + assert latex(chebyshevu(n, x)**2) == \ + r'\left(U_{n}\left(x\right)\right)^{2}' + assert latex(legendre(n, x)) == r'P_{n}\left(x\right)' + assert latex(legendre(n, x)**2) == r'\left(P_{n}\left(x\right)\right)^{2}' + assert latex(assoc_legendre(n, a, x)) == \ + r'P_{n}^{\left(a\right)}\left(x\right)' + assert latex(assoc_legendre(n, a, x)**2) == \ + r'\left(P_{n}^{\left(a\right)}\left(x\right)\right)^{2}' + assert latex(laguerre(n, x)) == r'L_{n}\left(x\right)' + assert latex(laguerre(n, x)**2) == r'\left(L_{n}\left(x\right)\right)^{2}' + assert latex(assoc_laguerre(n, a, x)) == \ + r'L_{n}^{\left(a\right)}\left(x\right)' + assert latex(assoc_laguerre(n, a, x)**2) == \ + r'\left(L_{n}^{\left(a\right)}\left(x\right)\right)^{2}' + assert latex(hermite(n, x)) == r'H_{n}\left(x\right)' + assert latex(hermite(n, x)**2) == r'\left(H_{n}\left(x\right)\right)^{2}' + + theta = Symbol("theta", real=True) + phi = Symbol("phi", real=True) + assert latex(Ynm(n, m, theta, phi)) == r'Y_{n}^{m}\left(\theta,\phi\right)' + assert latex(Ynm(n, m, theta, phi)**3) == \ + r'\left(Y_{n}^{m}\left(\theta,\phi\right)\right)^{3}' + assert latex(Znm(n, m, theta, phi)) == r'Z_{n}^{m}\left(\theta,\phi\right)' + assert latex(Znm(n, m, theta, phi)**3) == \ + r'\left(Z_{n}^{m}\left(\theta,\phi\right)\right)^{3}' + + # Test latex printing of function names with "_" + assert latex(polar_lift(0)) == \ + r"\operatorname{polar\_lift}{\left(0 \right)}" + assert latex(polar_lift(0)**3) == \ + r"\operatorname{polar\_lift}^{3}{\left(0 \right)}" + + assert latex(totient(n)) == r'\phi\left(n\right)' + assert latex(totient(n) ** 2) == r'\left(\phi\left(n\right)\right)^{2}' + + assert latex(reduced_totient(n)) == r'\lambda\left(n\right)' + assert latex(reduced_totient(n) ** 2) == \ + r'\left(\lambda\left(n\right)\right)^{2}' + + assert latex(divisor_sigma(x)) == r"\sigma\left(x\right)" + assert latex(divisor_sigma(x)**2) == r"\sigma^{2}\left(x\right)" + assert latex(divisor_sigma(x, y)) == r"\sigma_y\left(x\right)" + assert latex(divisor_sigma(x, y)**2) == r"\sigma^{2}_y\left(x\right)" + + assert latex(udivisor_sigma(x)) == r"\sigma^*\left(x\right)" + assert latex(udivisor_sigma(x)**2) == r"\sigma^*^{2}\left(x\right)" + assert latex(udivisor_sigma(x, y)) == r"\sigma^*_y\left(x\right)" + assert latex(udivisor_sigma(x, y)**2) == r"\sigma^*^{2}_y\left(x\right)" + + assert latex(primenu(n)) == r'\nu\left(n\right)' + assert latex(primenu(n) ** 2) == r'\left(\nu\left(n\right)\right)^{2}' + + assert latex(primeomega(n)) == r'\Omega\left(n\right)' + assert latex(primeomega(n) ** 2) == \ + r'\left(\Omega\left(n\right)\right)^{2}' + + assert latex(LambertW(n)) == r'W\left(n\right)' + assert latex(LambertW(n, -1)) == r'W_{-1}\left(n\right)' + assert latex(LambertW(n, k)) == r'W_{k}\left(n\right)' + assert latex(LambertW(n) * LambertW(n)) == r"W^{2}\left(n\right)" + assert latex(Pow(LambertW(n), 2)) == r"W^{2}\left(n\right)" + assert latex(LambertW(n)**k) == r"W^{k}\left(n\right)" + assert latex(LambertW(n, k)**p) == r"W^{p}_{k}\left(n\right)" + + assert latex(Mod(x, 7)) == r'x \bmod 7' + assert latex(Mod(x + 1, 7)) == r'\left(x + 1\right) \bmod 7' + assert latex(Mod(7, x + 1)) == r'7 \bmod \left(x + 1\right)' + assert latex(Mod(2 * x, 7)) == r'2 x \bmod 7' + assert latex(Mod(7, 2 * x)) == r'7 \bmod 2 x' + assert latex(Mod(x, 7) + 1) == r'\left(x \bmod 7\right) + 1' + assert latex(2 * Mod(x, 7)) == r'2 \left(x \bmod 7\right)' + assert latex(Mod(7, 2 * x)**n) == r'\left(7 \bmod 2 x\right)^{n}' + + # some unknown function name should get rendered with \operatorname + fjlkd = Function('fjlkd') + assert latex(fjlkd(x)) == r'\operatorname{fjlkd}{\left(x \right)}' + # even when it is referred to without an argument + assert latex(fjlkd) == r'\operatorname{fjlkd}' + + +# test that notation passes to subclasses of the same name only +def test_function_subclass_different_name(): + class mygamma(gamma): + pass + assert latex(mygamma) == r"\operatorname{mygamma}" + assert latex(mygamma(x)) == r"\operatorname{mygamma}{\left(x \right)}" + + +def test_hyper_printing(): + from sympy.abc import x, z + + assert latex(meijerg(Tuple(pi, pi, x), Tuple(1), + (0, 1), Tuple(1, 2, 3/pi), z)) == \ + r'{G_{4, 5}^{2, 3}\left(\begin{matrix} \pi, \pi, x & 1 \\0, 1 & 1, 2, '\ + r'\frac{3}{\pi} \end{matrix} \middle| {z} \right)}' + assert latex(meijerg(Tuple(), Tuple(1), (0,), Tuple(), z)) == \ + r'{G_{1, 1}^{1, 0}\left(\begin{matrix} & 1 \\0 & \end{matrix} \middle| {z} \right)}' + assert latex(hyper((x, 2), (3,), z)) == \ + r'{{}_{2}F_{1}\left(\begin{matrix} 2, x ' \ + r'\\ 3 \end{matrix}\middle| {z} \right)}' + assert latex(hyper(Tuple(), Tuple(1), z)) == \ + r'{{}_{0}F_{1}\left(\begin{matrix} ' \ + r'\\ 1 \end{matrix}\middle| {z} \right)}' + + +def test_latex_bessel(): + from sympy.functions.special.bessel import (besselj, bessely, besseli, + besselk, hankel1, hankel2, + jn, yn, hn1, hn2) + from sympy.abc import z + assert latex(besselj(n, z**2)**k) == r'J^{k}_{n}\left(z^{2}\right)' + assert latex(bessely(n, z)) == r'Y_{n}\left(z\right)' + assert latex(besseli(n, z)) == r'I_{n}\left(z\right)' + assert latex(besselk(n, z)) == r'K_{n}\left(z\right)' + assert latex(hankel1(n, z**2)**2) == \ + r'\left(H^{(1)}_{n}\left(z^{2}\right)\right)^{2}' + assert latex(hankel2(n, z)) == r'H^{(2)}_{n}\left(z\right)' + assert latex(jn(n, z)) == r'j_{n}\left(z\right)' + assert latex(yn(n, z)) == r'y_{n}\left(z\right)' + assert latex(hn1(n, z)) == r'h^{(1)}_{n}\left(z\right)' + assert latex(hn2(n, z)) == r'h^{(2)}_{n}\left(z\right)' + + +def test_latex_fresnel(): + from sympy.functions.special.error_functions import (fresnels, fresnelc) + from sympy.abc import z + assert latex(fresnels(z)) == r'S\left(z\right)' + assert latex(fresnelc(z)) == r'C\left(z\right)' + assert latex(fresnels(z)**2) == r'S^{2}\left(z\right)' + assert latex(fresnelc(z)**2) == r'C^{2}\left(z\right)' + + +def test_latex_brackets(): + assert latex((-1)**x) == r"\left(-1\right)^{x}" + + +def test_latex_indexed(): + Psi_symbol = Symbol('Psi_0', complex=True, real=False) + Psi_indexed = IndexedBase(Symbol('Psi', complex=True, real=False)) + symbol_latex = latex(Psi_symbol * conjugate(Psi_symbol)) + indexed_latex = latex(Psi_indexed[0] * conjugate(Psi_indexed[0])) + # \\overline{{\\Psi}_{0}} {\\Psi}_{0} vs. \\Psi_{0} \\overline{\\Psi_{0}} + assert symbol_latex == r'\Psi_{0} \overline{\Psi_{0}}' + assert indexed_latex == r'\overline{{\Psi}_{0}} {\Psi}_{0}' + + # Symbol('gamma') gives r'\gamma' + interval = '\\mathrel{..}\\nobreak ' + assert latex(Indexed('x1', Symbol('i'))) == r'{x_{1}}_{i}' + assert latex(Indexed('x2', Idx('i'))) == r'{x_{2}}_{i}' + assert latex(Indexed('x3', Idx('i', Symbol('N')))) == r'{x_{3}}_{{i}_{0'+interval+'N - 1}}' + assert latex(Indexed('x3', Idx('i', Symbol('N')+1))) == r'{x_{3}}_{{i}_{0'+interval+'N}}' + assert latex(Indexed('x4', Idx('i', (Symbol('a'),Symbol('b'))))) == r'{x_{4}}_{{i}_{a'+interval+'b}}' + assert latex(IndexedBase('gamma')) == r'\gamma' + assert latex(IndexedBase('a b')) == r'a b' + assert latex(IndexedBase('a_b')) == r'a_{b}' + + +def test_latex_derivatives(): + # regular "d" for ordinary derivatives + assert latex(diff(x**3, x, evaluate=False)) == \ + r"\frac{d}{d x} x^{3}" + assert latex(diff(sin(x) + x**2, x, evaluate=False)) == \ + r"\frac{d}{d x} \left(x^{2} + \sin{\left(x \right)}\right)" + assert latex(diff(diff(sin(x) + x**2, x, evaluate=False), evaluate=False))\ + == \ + r"\frac{d^{2}}{d x^{2}} \left(x^{2} + \sin{\left(x \right)}\right)" + assert latex(diff(diff(diff(sin(x) + x**2, x, evaluate=False), evaluate=False), evaluate=False)) == \ + r"\frac{d^{3}}{d x^{3}} \left(x^{2} + \sin{\left(x \right)}\right)" + + # \partial for partial derivatives + assert latex(diff(sin(x * y), x, evaluate=False)) == \ + r"\frac{\partial}{\partial x} \sin{\left(x y \right)}" + assert latex(diff(sin(x * y) + x**2, x, evaluate=False)) == \ + r"\frac{\partial}{\partial x} \left(x^{2} + \sin{\left(x y \right)}\right)" + assert latex(diff(diff(sin(x*y) + x**2, x, evaluate=False), x, evaluate=False)) == \ + r"\frac{\partial^{2}}{\partial x^{2}} \left(x^{2} + \sin{\left(x y \right)}\right)" + assert latex(diff(diff(diff(sin(x*y) + x**2, x, evaluate=False), x, evaluate=False), x, evaluate=False)) == \ + r"\frac{\partial^{3}}{\partial x^{3}} \left(x^{2} + \sin{\left(x y \right)}\right)" + + # mixed partial derivatives + f = Function("f") + assert latex(diff(diff(f(x, y), x, evaluate=False), y, evaluate=False)) == \ + r"\frac{\partial^{2}}{\partial y\partial x} " + latex(f(x, y)) + + assert latex(diff(diff(diff(f(x, y), x, evaluate=False), x, evaluate=False), y, evaluate=False)) == \ + r"\frac{\partial^{3}}{\partial y\partial x^{2}} " + latex(f(x, y)) + + # for negative nested Derivative + assert latex(diff(-diff(y**2,x,evaluate=False),x,evaluate=False)) == r'\frac{d}{d x} \left(- \frac{d}{d x} y^{2}\right)' + assert latex(diff(diff(-diff(diff(y,x,evaluate=False),x,evaluate=False),x,evaluate=False),x,evaluate=False)) == \ + r'\frac{d^{2}}{d x^{2}} \left(- \frac{d^{2}}{d x^{2}} y\right)' + + # use ordinary d when one of the variables has been integrated out + assert latex(diff(Integral(exp(-x*y), (x, 0, oo)), y, evaluate=False)) == \ + r"\frac{d}{d y} \int\limits_{0}^{\infty} e^{- x y}\, dx" + + # Derivative wrapped in power: + assert latex(diff(x, x, evaluate=False)**2) == \ + r"\left(\frac{d}{d x} x\right)^{2}" + + assert latex(diff(f(x), x)**2) == \ + r"\left(\frac{d}{d x} f{\left(x \right)}\right)^{2}" + + assert latex(diff(f(x), (x, n))) == \ + r"\frac{d^{n}}{d x^{n}} f{\left(x \right)}" + + x1 = Symbol('x1') + x2 = Symbol('x2') + assert latex(diff(f(x1, x2), x1)) == r'\frac{\partial}{\partial x_{1}} f{\left(x_{1},x_{2} \right)}' + + n1 = Symbol('n1') + assert latex(diff(f(x), (x, n1))) == r'\frac{d^{n_{1}}}{d x^{n_{1}}} f{\left(x \right)}' + + n2 = Symbol('n2') + assert latex(diff(f(x), (x, Max(n1, n2)))) == \ + r'\frac{d^{\max\left(n_{1}, n_{2}\right)}}{d x^{\max\left(n_{1}, n_{2}\right)}} f{\left(x \right)}' + + # set diff operator + assert latex(diff(f(x), x), diff_operator="rd") == r'\frac{\mathrm{d}}{\mathrm{d} x} f{\left(x \right)}' + + +def test_latex_subs(): + assert latex(Subs(x*y, (x, y), (1, 2))) == r'\left. x y \right|_{\substack{ x=1\\ y=2 }}' + + +def test_latex_integrals(): + assert latex(Integral(log(x), x)) == r"\int \log{\left(x \right)}\, dx" + assert latex(Integral(x**2, (x, 0, 1))) == \ + r"\int\limits_{0}^{1} x^{2}\, dx" + assert latex(Integral(x**2, (x, 10, 20))) == \ + r"\int\limits_{10}^{20} x^{2}\, dx" + assert latex(Integral(y*x**2, (x, 0, 1), y)) == \ + r"\int\int\limits_{0}^{1} x^{2} y\, dx\, dy" + assert latex(Integral(y*x**2, (x, 0, 1), y), mode='equation*') == \ + r"\begin{equation*}\int\int\limits_{0}^{1} x^{2} y\, dx\, dy\end{equation*}" + assert latex(Integral(y*x**2, (x, 0, 1), y), mode='equation*', itex=True) \ + == r"$$\int\int_{0}^{1} x^{2} y\, dx\, dy$$" + assert latex(Integral(x, (x, 0))) == r"\int\limits^{0} x\, dx" + assert latex(Integral(x*y, x, y)) == r"\iint x y\, dx\, dy" + assert latex(Integral(x*y*z, x, y, z)) == r"\iiint x y z\, dx\, dy\, dz" + assert latex(Integral(x*y*z*t, x, y, z, t)) == \ + r"\iiiint t x y z\, dx\, dy\, dz\, dt" + assert latex(Integral(x, x, x, x, x, x, x)) == \ + r"\int\int\int\int\int\int x\, dx\, dx\, dx\, dx\, dx\, dx" + assert latex(Integral(x, x, y, (z, 0, 1))) == \ + r"\int\limits_{0}^{1}\int\int x\, dx\, dy\, dz" + + # for negative nested Integral + assert latex(Integral(-Integral(y**2,x),x)) == \ + r'\int \left(- \int y^{2}\, dx\right)\, dx' + assert latex(Integral(-Integral(-Integral(y,x),x),x)) == \ + r'\int \left(- \int \left(- \int y\, dx\right)\, dx\right)\, dx' + + # fix issue #10806 + assert latex(Integral(z, z)**2) == r"\left(\int z\, dz\right)^{2}" + assert latex(Integral(x + z, z)) == r"\int \left(x + z\right)\, dz" + assert latex(Integral(x+z/2, z)) == \ + r"\int \left(x + \frac{z}{2}\right)\, dz" + assert latex(Integral(x**y, z)) == r"\int x^{y}\, dz" + + # set diff operator + assert latex(Integral(x, x), diff_operator="rd") == r'\int x\, \mathrm{d}x' + assert latex(Integral(x, (x, 0, 1)), diff_operator="rd") == r'\int\limits_{0}^{1} x\, \mathrm{d}x' + + +def test_latex_sets(): + for s in (frozenset, set): + assert latex(s([x*y, x**2])) == r"\left\{x^{2}, x y\right\}" + assert latex(s(range(1, 6))) == r"\left\{1, 2, 3, 4, 5\right\}" + assert latex(s(range(1, 13))) == \ + r"\left\{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12\right\}" + + s = FiniteSet + assert latex(s(*[x*y, x**2])) == r"\left\{x^{2}, x y\right\}" + assert latex(s(*range(1, 6))) == r"\left\{1, 2, 3, 4, 5\right\}" + assert latex(s(*range(1, 13))) == \ + r"\left\{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12\right\}" + + +def test_latex_SetExpr(): + iv = Interval(1, 3) + se = SetExpr(iv) + assert latex(se) == r"SetExpr\left(\left[1, 3\right]\right)" + + +def test_latex_Range(): + assert latex(Range(1, 51)) == r'\left\{1, 2, \ldots, 50\right\}' + assert latex(Range(1, 4)) == r'\left\{1, 2, 3\right\}' + assert latex(Range(0, 3, 1)) == r'\left\{0, 1, 2\right\}' + assert latex(Range(0, 30, 1)) == r'\left\{0, 1, \ldots, 29\right\}' + assert latex(Range(30, 1, -1)) == r'\left\{30, 29, \ldots, 2\right\}' + assert latex(Range(0, oo, 2)) == r'\left\{0, 2, \ldots\right\}' + assert latex(Range(oo, -2, -2)) == r'\left\{\ldots, 2, 0\right\}' + assert latex(Range(-2, -oo, -1)) == r'\left\{-2, -3, \ldots\right\}' + assert latex(Range(-oo, oo)) == r'\left\{\ldots, -1, 0, 1, \ldots\right\}' + assert latex(Range(oo, -oo, -1)) == r'\left\{\ldots, 1, 0, -1, \ldots\right\}' + + a, b, c = symbols('a:c') + assert latex(Range(a, b, c)) == r'\text{Range}\left(a, b, c\right)' + assert latex(Range(a, 10, 1)) == r'\text{Range}\left(a, 10\right)' + assert latex(Range(0, b, 1)) == r'\text{Range}\left(b\right)' + assert latex(Range(0, 10, c)) == r'\text{Range}\left(0, 10, c\right)' + + i = Symbol('i', integer=True) + n = Symbol('n', negative=True, integer=True) + p = Symbol('p', positive=True, integer=True) + + assert latex(Range(i, i + 3)) == r'\left\{i, i + 1, i + 2\right\}' + assert latex(Range(-oo, n, 2)) == r'\left\{\ldots, n - 4, n - 2\right\}' + assert latex(Range(p, oo)) == r'\left\{p, p + 1, \ldots\right\}' + # The following will work if __iter__ is improved + # assert latex(Range(-3, p + 7)) == r'\left\{-3, -2, \ldots, p + 6\right\}' + # Must have integer assumptions + assert latex(Range(a, a + 3)) == r'\text{Range}\left(a, a + 3\right)' + + +def test_latex_sequences(): + s1 = SeqFormula(a**2, (0, oo)) + s2 = SeqPer((1, 2)) + + latex_str = r'\left[0, 1, 4, 9, \ldots\right]' + assert latex(s1) == latex_str + + latex_str = r'\left[1, 2, 1, 2, \ldots\right]' + assert latex(s2) == latex_str + + s3 = SeqFormula(a**2, (0, 2)) + s4 = SeqPer((1, 2), (0, 2)) + + latex_str = r'\left[0, 1, 4\right]' + assert latex(s3) == latex_str + + latex_str = r'\left[1, 2, 1\right]' + assert latex(s4) == latex_str + + s5 = SeqFormula(a**2, (-oo, 0)) + s6 = SeqPer((1, 2), (-oo, 0)) + + latex_str = r'\left[\ldots, 9, 4, 1, 0\right]' + assert latex(s5) == latex_str + + latex_str = r'\left[\ldots, 2, 1, 2, 1\right]' + assert latex(s6) == latex_str + + latex_str = r'\left[1, 3, 5, 11, \ldots\right]' + assert latex(SeqAdd(s1, s2)) == latex_str + + latex_str = r'\left[1, 3, 5\right]' + assert latex(SeqAdd(s3, s4)) == latex_str + + latex_str = r'\left[\ldots, 11, 5, 3, 1\right]' + assert latex(SeqAdd(s5, s6)) == latex_str + + latex_str = r'\left[0, 2, 4, 18, \ldots\right]' + assert latex(SeqMul(s1, s2)) == latex_str + + latex_str = r'\left[0, 2, 4\right]' + assert latex(SeqMul(s3, s4)) == latex_str + + latex_str = r'\left[\ldots, 18, 4, 2, 0\right]' + assert latex(SeqMul(s5, s6)) == latex_str + + # Sequences with symbolic limits, issue 12629 + s7 = SeqFormula(a**2, (a, 0, x)) + latex_str = r'\left\{a^{2}\right\}_{a=0}^{x}' + assert latex(s7) == latex_str + + b = Symbol('b') + s8 = SeqFormula(b*a**2, (a, 0, 2)) + latex_str = r'\left[0, b, 4 b\right]' + assert latex(s8) == latex_str + + +def test_latex_FourierSeries(): + latex_str = \ + r'2 \sin{\left(x \right)} - \sin{\left(2 x \right)} + \frac{2 \sin{\left(3 x \right)}}{3} + \ldots' + assert latex(fourier_series(x, (x, -pi, pi))) == latex_str + + +def test_latex_FormalPowerSeries(): + latex_str = r'\sum_{k=1}^{\infty} - \frac{\left(-1\right)^{- k} x^{k}}{k}' + assert latex(fps(log(1 + x))) == latex_str + + +def test_latex_intervals(): + a = Symbol('a', real=True) + assert latex(Interval(0, 0)) == r"\left\{0\right\}" + assert latex(Interval(0, a)) == r"\left[0, a\right]" + assert latex(Interval(0, a, False, False)) == r"\left[0, a\right]" + assert latex(Interval(0, a, True, False)) == r"\left(0, a\right]" + assert latex(Interval(0, a, False, True)) == r"\left[0, a\right)" + assert latex(Interval(0, a, True, True)) == r"\left(0, a\right)" + + +def test_latex_AccumuBounds(): + a = Symbol('a', real=True) + assert latex(AccumBounds(0, 1)) == r"\left\langle 0, 1\right\rangle" + assert latex(AccumBounds(0, a)) == r"\left\langle 0, a\right\rangle" + assert latex(AccumBounds(a + 1, a + 2)) == \ + r"\left\langle a + 1, a + 2\right\rangle" + + +def test_latex_emptyset(): + assert latex(S.EmptySet) == r"\emptyset" + + +def test_latex_universalset(): + assert latex(S.UniversalSet) == r"\mathbb{U}" + + +def test_latex_commutator(): + A = Operator('A') + B = Operator('B') + comm = Commutator(B, A) + assert latex(comm.doit()) == r"- (A B - B A)" + + +def test_latex_union(): + assert latex(Union(Interval(0, 1), Interval(2, 3))) == \ + r"\left[0, 1\right] \cup \left[2, 3\right]" + assert latex(Union(Interval(1, 1), Interval(2, 2), Interval(3, 4))) == \ + r"\left\{1, 2\right\} \cup \left[3, 4\right]" + + +def test_latex_intersection(): + assert latex(Intersection(Interval(0, 1), Interval(x, y))) == \ + r"\left[0, 1\right] \cap \left[x, y\right]" + + +def test_latex_symmetric_difference(): + assert latex(SymmetricDifference(Interval(2, 5), Interval(4, 7), + evaluate=False)) == \ + r'\left[2, 5\right] \triangle \left[4, 7\right]' + + +def test_latex_Complement(): + assert latex(Complement(S.Reals, S.Naturals)) == \ + r"\mathbb{R} \setminus \mathbb{N}" + + +def test_latex_productset(): + line = Interval(0, 1) + bigline = Interval(0, 10) + fset = FiniteSet(1, 2, 3) + assert latex(line**2) == r"%s^{2}" % latex(line) + assert latex(line**10) == r"%s^{10}" % latex(line) + assert latex((line * bigline * fset).flatten()) == r"%s \times %s \times %s" % ( + latex(line), latex(bigline), latex(fset)) + + +def test_latex_powerset(): + fset = FiniteSet(1, 2, 3) + assert latex(PowerSet(fset)) == r'\mathcal{P}\left(\left\{1, 2, 3\right\}\right)' + + +def test_latex_ordinals(): + w = OrdinalOmega() + assert latex(w) == r"\omega" + wp = OmegaPower(2, 3) + assert latex(wp) == r'3 \omega^{2}' + assert latex(Ordinal(wp, OmegaPower(1, 1))) == r'3 \omega^{2} + \omega' + assert latex(Ordinal(OmegaPower(2, 1), OmegaPower(1, 2))) == r'\omega^{2} + 2 \omega' + + +def test_set_operators_parenthesis(): + a, b, c, d = symbols('a:d') + A = FiniteSet(a) + B = FiniteSet(b) + C = FiniteSet(c) + D = FiniteSet(d) + + U1 = Union(A, B, evaluate=False) + U2 = Union(C, D, evaluate=False) + I1 = Intersection(A, B, evaluate=False) + I2 = Intersection(C, D, evaluate=False) + C1 = Complement(A, B, evaluate=False) + C2 = Complement(C, D, evaluate=False) + D1 = SymmetricDifference(A, B, evaluate=False) + D2 = SymmetricDifference(C, D, evaluate=False) + # XXX ProductSet does not support evaluate keyword + P1 = ProductSet(A, B) + P2 = ProductSet(C, D) + + assert latex(Intersection(A, U2, evaluate=False)) == \ + r'\left\{a\right\} \cap ' \ + r'\left(\left\{c\right\} \cup \left\{d\right\}\right)' + assert latex(Intersection(U1, U2, evaluate=False)) == \ + r'\left(\left\{a\right\} \cup \left\{b\right\}\right) ' \ + r'\cap \left(\left\{c\right\} \cup \left\{d\right\}\right)' + assert latex(Intersection(C1, C2, evaluate=False)) == \ + r'\left(\left\{a\right\} \setminus ' \ + r'\left\{b\right\}\right) \cap \left(\left\{c\right\} ' \ + r'\setminus \left\{d\right\}\right)' + assert latex(Intersection(D1, D2, evaluate=False)) == \ + r'\left(\left\{a\right\} \triangle ' \ + r'\left\{b\right\}\right) \cap \left(\left\{c\right\} ' \ + r'\triangle \left\{d\right\}\right)' + assert latex(Intersection(P1, P2, evaluate=False)) == \ + r'\left(\left\{a\right\} \times \left\{b\right\}\right) ' \ + r'\cap \left(\left\{c\right\} \times ' \ + r'\left\{d\right\}\right)' + + assert latex(Union(A, I2, evaluate=False)) == \ + r'\left\{a\right\} \cup ' \ + r'\left(\left\{c\right\} \cap \left\{d\right\}\right)' + assert latex(Union(I1, I2, evaluate=False)) == \ + r'\left(\left\{a\right\} \cap \left\{b\right\}\right) ' \ + r'\cup \left(\left\{c\right\} \cap \left\{d\right\}\right)' + assert latex(Union(C1, C2, evaluate=False)) == \ + r'\left(\left\{a\right\} \setminus ' \ + r'\left\{b\right\}\right) \cup \left(\left\{c\right\} ' \ + r'\setminus \left\{d\right\}\right)' + assert latex(Union(D1, D2, evaluate=False)) == \ + r'\left(\left\{a\right\} \triangle ' \ + r'\left\{b\right\}\right) \cup \left(\left\{c\right\} ' \ + r'\triangle \left\{d\right\}\right)' + assert latex(Union(P1, P2, evaluate=False)) == \ + r'\left(\left\{a\right\} \times \left\{b\right\}\right) ' \ + r'\cup \left(\left\{c\right\} \times ' \ + r'\left\{d\right\}\right)' + + assert latex(Complement(A, C2, evaluate=False)) == \ + r'\left\{a\right\} \setminus \left(\left\{c\right\} ' \ + r'\setminus \left\{d\right\}\right)' + assert latex(Complement(U1, U2, evaluate=False)) == \ + r'\left(\left\{a\right\} \cup \left\{b\right\}\right) ' \ + r'\setminus \left(\left\{c\right\} \cup ' \ + r'\left\{d\right\}\right)' + assert latex(Complement(I1, I2, evaluate=False)) == \ + r'\left(\left\{a\right\} \cap \left\{b\right\}\right) ' \ + r'\setminus \left(\left\{c\right\} \cap ' \ + r'\left\{d\right\}\right)' + assert latex(Complement(D1, D2, evaluate=False)) == \ + r'\left(\left\{a\right\} \triangle ' \ + r'\left\{b\right\}\right) \setminus ' \ + r'\left(\left\{c\right\} \triangle \left\{d\right\}\right)' + assert latex(Complement(P1, P2, evaluate=False)) == \ + r'\left(\left\{a\right\} \times \left\{b\right\}\right) '\ + r'\setminus \left(\left\{c\right\} \times '\ + r'\left\{d\right\}\right)' + + assert latex(SymmetricDifference(A, D2, evaluate=False)) == \ + r'\left\{a\right\} \triangle \left(\left\{c\right\} ' \ + r'\triangle \left\{d\right\}\right)' + assert latex(SymmetricDifference(U1, U2, evaluate=False)) == \ + r'\left(\left\{a\right\} \cup \left\{b\right\}\right) ' \ + r'\triangle \left(\left\{c\right\} \cup ' \ + r'\left\{d\right\}\right)' + assert latex(SymmetricDifference(I1, I2, evaluate=False)) == \ + r'\left(\left\{a\right\} \cap \left\{b\right\}\right) ' \ + r'\triangle \left(\left\{c\right\} \cap ' \ + r'\left\{d\right\}\right)' + assert latex(SymmetricDifference(C1, C2, evaluate=False)) == \ + r'\left(\left\{a\right\} \setminus ' \ + r'\left\{b\right\}\right) \triangle ' \ + r'\left(\left\{c\right\} \setminus \left\{d\right\}\right)' + assert latex(SymmetricDifference(P1, P2, evaluate=False)) == \ + r'\left(\left\{a\right\} \times \left\{b\right\}\right) ' \ + r'\triangle \left(\left\{c\right\} \times ' \ + r'\left\{d\right\}\right)' + + # XXX This can be incorrect since cartesian product is not associative + assert latex(ProductSet(A, P2).flatten()) == \ + r'\left\{a\right\} \times \left\{c\right\} \times ' \ + r'\left\{d\right\}' + assert latex(ProductSet(U1, U2)) == \ + r'\left(\left\{a\right\} \cup \left\{b\right\}\right) ' \ + r'\times \left(\left\{c\right\} \cup ' \ + r'\left\{d\right\}\right)' + assert latex(ProductSet(I1, I2)) == \ + r'\left(\left\{a\right\} \cap \left\{b\right\}\right) ' \ + r'\times \left(\left\{c\right\} \cap ' \ + r'\left\{d\right\}\right)' + assert latex(ProductSet(C1, C2)) == \ + r'\left(\left\{a\right\} \setminus ' \ + r'\left\{b\right\}\right) \times \left(\left\{c\right\} ' \ + r'\setminus \left\{d\right\}\right)' + assert latex(ProductSet(D1, D2)) == \ + r'\left(\left\{a\right\} \triangle ' \ + r'\left\{b\right\}\right) \times \left(\left\{c\right\} ' \ + r'\triangle \left\{d\right\}\right)' + + +def test_latex_Complexes(): + assert latex(S.Complexes) == r"\mathbb{C}" + + +def test_latex_Naturals(): + assert latex(S.Naturals) == r"\mathbb{N}" + + +def test_latex_Naturals0(): + assert latex(S.Naturals0) == r"\mathbb{N}_0" + + +def test_latex_Integers(): + assert latex(S.Integers) == r"\mathbb{Z}" + + +def test_latex_ImageSet(): + x = Symbol('x') + assert latex(ImageSet(Lambda(x, x**2), S.Naturals)) == \ + r"\left\{x^{2}\; \middle|\; x \in \mathbb{N}\right\}" + + y = Symbol('y') + imgset = ImageSet(Lambda((x, y), x + y), {1, 2, 3}, {3, 4}) + assert latex(imgset) == \ + r"\left\{x + y\; \middle|\; x \in \left\{1, 2, 3\right\}, y \in \left\{3, 4\right\}\right\}" + + imgset = ImageSet(Lambda(((x, y),), x + y), ProductSet({1, 2, 3}, {3, 4})) + assert latex(imgset) == \ + r"\left\{x + y\; \middle|\; \left( x, \ y\right) \in \left\{1, 2, 3\right\} \times \left\{3, 4\right\}\right\}" + + +def test_latex_ConditionSet(): + x = Symbol('x') + assert latex(ConditionSet(x, Eq(x**2, 1), S.Reals)) == \ + r"\left\{x\; \middle|\; x \in \mathbb{R} \wedge x^{2} = 1 \right\}" + assert latex(ConditionSet(x, Eq(x**2, 1), S.UniversalSet)) == \ + r"\left\{x\; \middle|\; x^{2} = 1 \right\}" + + +def test_latex_ComplexRegion(): + assert latex(ComplexRegion(Interval(3, 5)*Interval(4, 6))) == \ + r"\left\{x + y i\; \middle|\; x, y \in \left[3, 5\right] \times \left[4, 6\right] \right\}" + assert latex(ComplexRegion(Interval(0, 1)*Interval(0, 2*pi), polar=True)) == \ + r"\left\{r \left(i \sin{\left(\theta \right)} + \cos{\left(\theta "\ + r"\right)}\right)\; \middle|\; r, \theta \in \left[0, 1\right] \times \left[0, 2 \pi\right) \right\}" + + +def test_latex_Contains(): + x = Symbol('x') + assert latex(Contains(x, S.Naturals)) == r"x \in \mathbb{N}" + + +def test_latex_sum(): + assert latex(Sum(x*y**2, (x, -2, 2), (y, -5, 5))) == \ + r"\sum_{\substack{-2 \leq x \leq 2\\-5 \leq y \leq 5}} x y^{2}" + assert latex(Sum(x**2, (x, -2, 2))) == \ + r"\sum_{x=-2}^{2} x^{2}" + assert latex(Sum(x**2 + y, (x, -2, 2))) == \ + r"\sum_{x=-2}^{2} \left(x^{2} + y\right)" + assert latex(Sum(x**2 + y, (x, -2, 2))**2) == \ + r"\left(\sum_{x=-2}^{2} \left(x^{2} + y\right)\right)^{2}" + + +def test_latex_product(): + assert latex(Product(x*y**2, (x, -2, 2), (y, -5, 5))) == \ + r"\prod_{\substack{-2 \leq x \leq 2\\-5 \leq y \leq 5}} x y^{2}" + assert latex(Product(x**2, (x, -2, 2))) == \ + r"\prod_{x=-2}^{2} x^{2}" + assert latex(Product(x**2 + y, (x, -2, 2))) == \ + r"\prod_{x=-2}^{2} \left(x^{2} + y\right)" + + assert latex(Product(x, (x, -2, 2))**2) == \ + r"\left(\prod_{x=-2}^{2} x\right)^{2}" + + +def test_latex_limits(): + assert latex(Limit(x, x, oo)) == r"\lim_{x \to \infty} x" + + # issue 8175 + f = Function('f') + assert latex(Limit(f(x), x, 0)) == r"\lim_{x \to 0^+} f{\left(x \right)}" + assert latex(Limit(f(x), x, 0, "-")) == \ + r"\lim_{x \to 0^-} f{\left(x \right)}" + + # issue #10806 + assert latex(Limit(f(x), x, 0)**2) == \ + r"\left(\lim_{x \to 0^+} f{\left(x \right)}\right)^{2}" + # bi-directional limit + assert latex(Limit(f(x), x, 0, dir='+-')) == \ + r"\lim_{x \to 0} f{\left(x \right)}" + + +def test_latex_log(): + assert latex(log(x)) == r"\log{\left(x \right)}" + assert latex(log(x), ln_notation=True) == r"\ln{\left(x \right)}" + assert latex(log(x) + log(y)) == \ + r"\log{\left(x \right)} + \log{\left(y \right)}" + assert latex(log(x) + log(y), ln_notation=True) == \ + r"\ln{\left(x \right)} + \ln{\left(y \right)}" + assert latex(pow(log(x), x)) == r"\log{\left(x \right)}^{x}" + assert latex(pow(log(x), x), ln_notation=True) == \ + r"\ln{\left(x \right)}^{x}" + + +def test_issue_3568(): + beta = Symbol(r'\beta') + y = beta + x + assert latex(y) in [r'\beta + x', r'x + \beta'] + + beta = Symbol(r'beta') + y = beta + x + assert latex(y) in [r'\beta + x', r'x + \beta'] + + +def test_latex(): + assert latex((2*tau)**Rational(7, 2)) == r"8 \sqrt{2} \tau^{\frac{7}{2}}" + assert latex((2*mu)**Rational(7, 2), mode='equation*') == \ + r"\begin{equation*}8 \sqrt{2} \mu^{\frac{7}{2}}\end{equation*}" + assert latex((2*mu)**Rational(7, 2), mode='equation', itex=True) == \ + r"$$8 \sqrt{2} \mu^{\frac{7}{2}}$$" + assert latex([2/x, y]) == r"\left[ \frac{2}{x}, \ y\right]" + + +def test_latex_dict(): + d = {Rational(1): 1, x**2: 2, x: 3, x**3: 4} + assert latex(d) == \ + r'\left\{ 1 : 1, \ x : 3, \ x^{2} : 2, \ x^{3} : 4\right\}' + D = Dict(d) + assert latex(D) == \ + r'\left\{ 1 : 1, \ x : 3, \ x^{2} : 2, \ x^{3} : 4\right\}' + + +def test_latex_list(): + ll = [Symbol('omega1'), Symbol('a'), Symbol('alpha')] + assert latex(ll) == r'\left[ \omega_{1}, \ a, \ \alpha\right]' + + +def test_latex_NumberSymbols(): + assert latex(S.Catalan) == "G" + assert latex(S.EulerGamma) == r"\gamma" + assert latex(S.Exp1) == "e" + assert latex(S.GoldenRatio) == r"\phi" + assert latex(S.Pi) == r"\pi" + assert latex(S.TribonacciConstant) == r"\text{TribonacciConstant}" + + +def test_latex_rational(): + # tests issue 3973 + assert latex(-Rational(1, 2)) == r"- \frac{1}{2}" + assert latex(Rational(-1, 2)) == r"- \frac{1}{2}" + assert latex(Rational(1, -2)) == r"- \frac{1}{2}" + assert latex(-Rational(-1, 2)) == r"\frac{1}{2}" + assert latex(-Rational(1, 2)*x) == r"- \frac{x}{2}" + assert latex(-Rational(1, 2)*x + Rational(-2, 3)*y) == \ + r"- \frac{x}{2} - \frac{2 y}{3}" + + +def test_latex_inverse(): + # tests issue 4129 + assert latex(1/x) == r"\frac{1}{x}" + assert latex(1/(x + y)) == r"\frac{1}{x + y}" + + +def test_latex_DiracDelta(): + assert latex(DiracDelta(x)) == r"\delta\left(x\right)" + assert latex(DiracDelta(x)**2) == r"\left(\delta\left(x\right)\right)^{2}" + assert latex(DiracDelta(x, 0)) == r"\delta\left(x\right)" + assert latex(DiracDelta(x, 5)) == \ + r"\delta^{\left( 5 \right)}\left( x \right)" + assert latex(DiracDelta(x, 5)**2) == \ + r"\left(\delta^{\left( 5 \right)}\left( x \right)\right)^{2}" + + +def test_latex_Heaviside(): + assert latex(Heaviside(x)) == r"\theta\left(x\right)" + assert latex(Heaviside(x)**2) == r"\left(\theta\left(x\right)\right)^{2}" + + +def test_latex_KroneckerDelta(): + assert latex(KroneckerDelta(x, y)) == r"\delta_{x y}" + assert latex(KroneckerDelta(x, y + 1)) == r"\delta_{x, y + 1}" + # issue 6578 + assert latex(KroneckerDelta(x + 1, y)) == r"\delta_{y, x + 1}" + assert latex(Pow(KroneckerDelta(x, y), 2, evaluate=False)) == \ + r"\left(\delta_{x y}\right)^{2}" + + +def test_latex_LeviCivita(): + assert latex(LeviCivita(x, y, z)) == r"\varepsilon_{x y z}" + assert latex(LeviCivita(x, y, z)**2) == \ + r"\left(\varepsilon_{x y z}\right)^{2}" + assert latex(LeviCivita(x, y, z + 1)) == r"\varepsilon_{x, y, z + 1}" + assert latex(LeviCivita(x, y + 1, z)) == r"\varepsilon_{x, y + 1, z}" + assert latex(LeviCivita(x + 1, y, z)) == r"\varepsilon_{x + 1, y, z}" + + +def test_mode(): + expr = x + y + assert latex(expr) == r'x + y' + assert latex(expr, mode='plain') == r'x + y' + assert latex(expr, mode='inline') == r'$x + y$' + assert latex( + expr, mode='equation*') == r'\begin{equation*}x + y\end{equation*}' + assert latex( + expr, mode='equation') == r'\begin{equation}x + y\end{equation}' + raises(ValueError, lambda: latex(expr, mode='foo')) + + +def test_latex_mathieu(): + assert latex(mathieuc(x, y, z)) == r"C\left(x, y, z\right)" + assert latex(mathieus(x, y, z)) == r"S\left(x, y, z\right)" + assert latex(mathieuc(x, y, z)**2) == r"C\left(x, y, z\right)^{2}" + assert latex(mathieus(x, y, z)**2) == r"S\left(x, y, z\right)^{2}" + assert latex(mathieucprime(x, y, z)) == r"C^{\prime}\left(x, y, z\right)" + assert latex(mathieusprime(x, y, z)) == r"S^{\prime}\left(x, y, z\right)" + assert latex(mathieucprime(x, y, z)**2) == r"C^{\prime}\left(x, y, z\right)^{2}" + assert latex(mathieusprime(x, y, z)**2) == r"S^{\prime}\left(x, y, z\right)^{2}" + +def test_latex_Piecewise(): + p = Piecewise((x, x < 1), (x**2, True)) + assert latex(p) == r"\begin{cases} x & \text{for}\: x < 1 \\x^{2} &" \ + r" \text{otherwise} \end{cases}" + assert latex(p, itex=True) == \ + r"\begin{cases} x & \text{for}\: x \lt 1 \\x^{2} &" \ + r" \text{otherwise} \end{cases}" + p = Piecewise((x, x < 0), (0, x >= 0)) + assert latex(p) == r'\begin{cases} x & \text{for}\: x < 0 \\0 &' \ + r' \text{otherwise} \end{cases}' + A, B = symbols("A B", commutative=False) + p = Piecewise((A**2, Eq(A, B)), (A*B, True)) + s = r"\begin{cases} A^{2} & \text{for}\: A = B \\A B & \text{otherwise} \end{cases}" + assert latex(p) == s + assert latex(A*p) == r"A \left(%s\right)" % s + assert latex(p*A) == r"\left(%s\right) A" % s + assert latex(Piecewise((x, x < 1), (x**2, x < 2))) == \ + r'\begin{cases} x & ' \ + r'\text{for}\: x < 1 \\x^{2} & \text{for}\: x < 2 \end{cases}' + + +def test_latex_Matrix(): + M = Matrix([[1 + x, y], [y, x - 1]]) + assert latex(M) == \ + r'\left[\begin{matrix}x + 1 & y\\y & x - 1\end{matrix}\right]' + assert latex(M, mode='inline') == \ + r'$\left[\begin{smallmatrix}x + 1 & y\\' \ + r'y & x - 1\end{smallmatrix}\right]$' + assert latex(M, mat_str='array') == \ + r'\left[\begin{array}{cc}x + 1 & y\\y & x - 1\end{array}\right]' + assert latex(M, mat_str='bmatrix') == \ + r'\left[\begin{bmatrix}x + 1 & y\\y & x - 1\end{bmatrix}\right]' + assert latex(M, mat_delim=None, mat_str='bmatrix') == \ + r'\begin{bmatrix}x + 1 & y\\y & x - 1\end{bmatrix}' + + M2 = Matrix(1, 11, range(11)) + assert latex(M2) == \ + r'\left[\begin{array}{ccccccccccc}' \ + r'0 & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10\end{array}\right]' + + +def test_latex_matrix_with_functions(): + t = symbols('t') + theta1 = symbols('theta1', cls=Function) + + M = Matrix([[sin(theta1(t)), cos(theta1(t))], + [cos(theta1(t).diff(t)), sin(theta1(t).diff(t))]]) + + expected = (r'\left[\begin{matrix}\sin{\left(' + r'\theta_{1}{\left(t \right)} \right)} & ' + r'\cos{\left(\theta_{1}{\left(t \right)} \right)' + r'}\\\cos{\left(\frac{d}{d t} \theta_{1}{\left(t ' + r'\right)} \right)} & \sin{\left(\frac{d}{d t} ' + r'\theta_{1}{\left(t \right)} \right' + r')}\end{matrix}\right]') + + assert latex(M) == expected + + +def test_latex_NDimArray(): + x, y, z, w = symbols("x y z w") + + for ArrayType in (ImmutableDenseNDimArray, ImmutableSparseNDimArray, + MutableDenseNDimArray, MutableSparseNDimArray): + # Basic: scalar array + M = ArrayType(x) + + assert latex(M) == r"x" + + M = ArrayType([[1 / x, y], [z, w]]) + M1 = ArrayType([1 / x, y, z]) + + M2 = tensorproduct(M1, M) + M3 = tensorproduct(M, M) + + assert latex(M) == \ + r'\left[\begin{matrix}\frac{1}{x} & y\\z & w\end{matrix}\right]' + assert latex(M1) == \ + r"\left[\begin{matrix}\frac{1}{x} & y & z\end{matrix}\right]" + assert latex(M2) == \ + r"\left[\begin{matrix}" \ + r"\left[\begin{matrix}\frac{1}{x^{2}} & \frac{y}{x}\\\frac{z}{x} & \frac{w}{x}\end{matrix}\right] & " \ + r"\left[\begin{matrix}\frac{y}{x} & y^{2}\\y z & w y\end{matrix}\right] & " \ + r"\left[\begin{matrix}\frac{z}{x} & y z\\z^{2} & w z\end{matrix}\right]" \ + r"\end{matrix}\right]" + assert latex(M3) == \ + r"""\left[\begin{matrix}"""\ + r"""\left[\begin{matrix}\frac{1}{x^{2}} & \frac{y}{x}\\\frac{z}{x} & \frac{w}{x}\end{matrix}\right] & """\ + r"""\left[\begin{matrix}\frac{y}{x} & y^{2}\\y z & w y\end{matrix}\right]\\"""\ + r"""\left[\begin{matrix}\frac{z}{x} & y z\\z^{2} & w z\end{matrix}\right] & """\ + r"""\left[\begin{matrix}\frac{w}{x} & w y\\w z & w^{2}\end{matrix}\right]"""\ + r"""\end{matrix}\right]""" + + Mrow = ArrayType([[x, y, 1/z]]) + Mcolumn = ArrayType([[x], [y], [1/z]]) + Mcol2 = ArrayType([Mcolumn.tolist()]) + + assert latex(Mrow) == \ + r"\left[\left[\begin{matrix}x & y & \frac{1}{z}\end{matrix}\right]\right]" + assert latex(Mcolumn) == \ + r"\left[\begin{matrix}x\\y\\\frac{1}{z}\end{matrix}\right]" + assert latex(Mcol2) == \ + r'\left[\begin{matrix}\left[\begin{matrix}x\\y\\\frac{1}{z}\end{matrix}\right]\end{matrix}\right]' + + +def test_latex_mul_symbol(): + assert latex(4*4**x, mul_symbol='times') == r"4 \times 4^{x}" + assert latex(4*4**x, mul_symbol='dot') == r"4 \cdot 4^{x}" + assert latex(4*4**x, mul_symbol='ldot') == r"4 \,.\, 4^{x}" + + assert latex(4*x, mul_symbol='times') == r"4 \times x" + assert latex(4*x, mul_symbol='dot') == r"4 \cdot x" + assert latex(4*x, mul_symbol='ldot') == r"4 \,.\, x" + + +def test_latex_issue_4381(): + y = 4*4**log(2) + assert latex(y) == r'4 \cdot 4^{\log{\left(2 \right)}}' + assert latex(1/y) == r'\frac{1}{4 \cdot 4^{\log{\left(2 \right)}}}' + + +def test_latex_issue_4576(): + assert latex(Symbol("beta_13_2")) == r"\beta_{13 2}" + assert latex(Symbol("beta_132_20")) == r"\beta_{132 20}" + assert latex(Symbol("beta_13")) == r"\beta_{13}" + assert latex(Symbol("x_a_b")) == r"x_{a b}" + assert latex(Symbol("x_1_2_3")) == r"x_{1 2 3}" + assert latex(Symbol("x_a_b1")) == r"x_{a b1}" + assert latex(Symbol("x_a_1")) == r"x_{a 1}" + assert latex(Symbol("x_1_a")) == r"x_{1 a}" + assert latex(Symbol("x_1^aa")) == r"x^{aa}_{1}" + assert latex(Symbol("x_1__aa")) == r"x^{aa}_{1}" + assert latex(Symbol("x_11^a")) == r"x^{a}_{11}" + assert latex(Symbol("x_11__a")) == r"x^{a}_{11}" + assert latex(Symbol("x_a_a_a_a")) == r"x_{a a a a}" + assert latex(Symbol("x_a_a^a^a")) == r"x^{a a}_{a a}" + assert latex(Symbol("x_a_a__a__a")) == r"x^{a a}_{a a}" + assert latex(Symbol("alpha_11")) == r"\alpha_{11}" + assert latex(Symbol("alpha_11_11")) == r"\alpha_{11 11}" + assert latex(Symbol("alpha_alpha")) == r"\alpha_{\alpha}" + assert latex(Symbol("alpha^aleph")) == r"\alpha^{\aleph}" + assert latex(Symbol("alpha__aleph")) == r"\alpha^{\aleph}" + + +def test_latex_pow_fraction(): + x = Symbol('x') + # Testing exp + assert r'e^{-x}' in latex(exp(-x)/2).replace(' ', '') # Remove Whitespace + + # Testing e^{-x} in case future changes alter behavior of muls or fracs + # In particular current output is \frac{1}{2}e^{- x} but perhaps this will + # change to \frac{e^{-x}}{2} + + # Testing general, non-exp, power + assert r'3^{-x}' in latex(3**-x/2).replace(' ', '') + + +def test_noncommutative(): + A, B, C = symbols('A,B,C', commutative=False) + + assert latex(A*B*C**-1) == r"A B C^{-1}" + assert latex(C**-1*A*B) == r"C^{-1} A B" + assert latex(A*C**-1*B) == r"A C^{-1} B" + + +def test_latex_order(): + expr = x**3 + x**2*y + y**4 + 3*x*y**3 + + assert latex(expr, order='lex') == r"x^{3} + x^{2} y + 3 x y^{3} + y^{4}" + assert latex( + expr, order='rev-lex') == r"y^{4} + 3 x y^{3} + x^{2} y + x^{3}" + assert latex(expr, order='none') == r"x^{3} + y^{4} + y x^{2} + 3 x y^{3}" + + +def test_latex_Lambda(): + assert latex(Lambda(x, x + 1)) == r"\left( x \mapsto x + 1 \right)" + assert latex(Lambda((x, y), x + 1)) == r"\left( \left( x, \ y\right) \mapsto x + 1 \right)" + assert latex(Lambda(x, x)) == r"\left( x \mapsto x \right)" + +def test_latex_PolyElement(): + Ruv, u, v = ring("u,v", ZZ) + Rxyz, x, y, z = ring("x,y,z", Ruv) + + assert latex(x - x) == r"0" + assert latex(x - 1) == r"x - 1" + assert latex(x + 1) == r"x + 1" + + assert latex((u**2 + 3*u*v + 1)*x**2*y + u + 1) == \ + r"\left({u}^{2} + 3 u v + 1\right) {x}^{2} y + u + 1" + assert latex((u**2 + 3*u*v + 1)*x**2*y + (u + 1)*x) == \ + r"\left({u}^{2} + 3 u v + 1\right) {x}^{2} y + \left(u + 1\right) x" + assert latex((u**2 + 3*u*v + 1)*x**2*y + (u + 1)*x + 1) == \ + r"\left({u}^{2} + 3 u v + 1\right) {x}^{2} y + \left(u + 1\right) x + 1" + assert latex((-u**2 + 3*u*v - 1)*x**2*y - (u + 1)*x - 1) == \ + r"-\left({u}^{2} - 3 u v + 1\right) {x}^{2} y - \left(u + 1\right) x - 1" + + assert latex(-(v**2 + v + 1)*x + 3*u*v + 1) == \ + r"-\left({v}^{2} + v + 1\right) x + 3 u v + 1" + assert latex(-(v**2 + v + 1)*x - 3*u*v + 1) == \ + r"-\left({v}^{2} + v + 1\right) x - 3 u v + 1" + + +def test_latex_FracElement(): + Fuv, u, v = field("u,v", ZZ) + Fxyzt, x, y, z, t = field("x,y,z,t", Fuv) + + assert latex(x - x) == r"0" + assert latex(x - 1) == r"x - 1" + assert latex(x + 1) == r"x + 1" + + assert latex(x/3) == r"\frac{x}{3}" + assert latex(x/z) == r"\frac{x}{z}" + assert latex(x*y/z) == r"\frac{x y}{z}" + assert latex(x/(z*t)) == r"\frac{x}{z t}" + assert latex(x*y/(z*t)) == r"\frac{x y}{z t}" + + assert latex((x - 1)/y) == r"\frac{x - 1}{y}" + assert latex((x + 1)/y) == r"\frac{x + 1}{y}" + assert latex((-x - 1)/y) == r"\frac{-x - 1}{y}" + assert latex((x + 1)/(y*z)) == r"\frac{x + 1}{y z}" + assert latex(-y/(x + 1)) == r"\frac{-y}{x + 1}" + assert latex(y*z/(x + 1)) == r"\frac{y z}{x + 1}" + + assert latex(((u + 1)*x*y + 1)/((v - 1)*z - 1)) == \ + r"\frac{\left(u + 1\right) x y + 1}{\left(v - 1\right) z - 1}" + assert latex(((u + 1)*x*y + 1)/((v - 1)*z - t*u*v - 1)) == \ + r"\frac{\left(u + 1\right) x y + 1}{\left(v - 1\right) z - u v t - 1}" + + +def test_latex_Poly(): + assert latex(Poly(x**2 + 2 * x, x)) == \ + r"\operatorname{Poly}{\left( x^{2} + 2 x, x, domain=\mathbb{Z} \right)}" + assert latex(Poly(x/y, x)) == \ + r"\operatorname{Poly}{\left( \frac{1}{y} x, x, domain=\mathbb{Z}\left(y\right) \right)}" + assert latex(Poly(2.0*x + y)) == \ + r"\operatorname{Poly}{\left( 2.0 x + 1.0 y, x, y, domain=\mathbb{R} \right)}" + + +def test_latex_Poly_order(): + assert latex(Poly([a, 1, b, 2, c, 3], x)) == \ + r'\operatorname{Poly}{\left( a x^{5} + x^{4} + b x^{3} + 2 x^{2} + c'\ + r' x + 3, x, domain=\mathbb{Z}\left[a, b, c\right] \right)}' + assert latex(Poly([a, 1, b+c, 2, 3], x)) == \ + r'\operatorname{Poly}{\left( a x^{4} + x^{3} + \left(b + c\right) '\ + r'x^{2} + 2 x + 3, x, domain=\mathbb{Z}\left[a, b, c\right] \right)}' + assert latex(Poly(a*x**3 + x**2*y - x*y - c*y**3 - b*x*y**2 + y - a*x + b, + (x, y))) == \ + r'\operatorname{Poly}{\left( a x^{3} + x^{2}y - b xy^{2} - xy - '\ + r'a x - c y^{3} + y + b, x, y, domain=\mathbb{Z}\left[a, b, c\right] \right)}' + + +def test_latex_ComplexRootOf(): + assert latex(rootof(x**5 + x + 3, 0)) == \ + r"\operatorname{CRootOf} {\left(x^{5} + x + 3, 0\right)}" + + +def test_latex_RootSum(): + assert latex(RootSum(x**5 + x + 3, sin)) == \ + r"\operatorname{RootSum} {\left(x^{5} + x + 3, \left( x \mapsto \sin{\left(x \right)} \right)\right)}" + + +def test_settings(): + raises(TypeError, lambda: latex(x*y, method="garbage")) + + +def test_latex_numbers(): + assert latex(catalan(n)) == r"C_{n}" + assert latex(catalan(n)**2) == r"C_{n}^{2}" + assert latex(bernoulli(n)) == r"B_{n}" + assert latex(bernoulli(n, x)) == r"B_{n}\left(x\right)" + assert latex(bernoulli(n)**2) == r"B_{n}^{2}" + assert latex(bernoulli(n, x)**2) == r"B_{n}^{2}\left(x\right)" + assert latex(genocchi(n)) == r"G_{n}" + assert latex(genocchi(n, x)) == r"G_{n}\left(x\right)" + assert latex(genocchi(n)**2) == r"G_{n}^{2}" + assert latex(genocchi(n, x)**2) == r"G_{n}^{2}\left(x\right)" + assert latex(bell(n)) == r"B_{n}" + assert latex(bell(n, x)) == r"B_{n}\left(x\right)" + assert latex(bell(n, m, (x, y))) == r"B_{n, m}\left(x, y\right)" + assert latex(bell(n)**2) == r"B_{n}^{2}" + assert latex(bell(n, x)**2) == r"B_{n}^{2}\left(x\right)" + assert latex(bell(n, m, (x, y))**2) == r"B_{n, m}^{2}\left(x, y\right)" + assert latex(fibonacci(n)) == r"F_{n}" + assert latex(fibonacci(n, x)) == r"F_{n}\left(x\right)" + assert latex(fibonacci(n)**2) == r"F_{n}^{2}" + assert latex(fibonacci(n, x)**2) == r"F_{n}^{2}\left(x\right)" + assert latex(lucas(n)) == r"L_{n}" + assert latex(lucas(n)**2) == r"L_{n}^{2}" + assert latex(tribonacci(n)) == r"T_{n}" + assert latex(tribonacci(n, x)) == r"T_{n}\left(x\right)" + assert latex(tribonacci(n)**2) == r"T_{n}^{2}" + assert latex(tribonacci(n, x)**2) == r"T_{n}^{2}\left(x\right)" + assert latex(mobius(n)) == r"\mu\left(n\right)" + assert latex(mobius(n)**2) == r"\mu^{2}\left(n\right)" + + +def test_latex_euler(): + assert latex(euler(n)) == r"E_{n}" + assert latex(euler(n, x)) == r"E_{n}\left(x\right)" + assert latex(euler(n, x)**2) == r"E_{n}^{2}\left(x\right)" + + +def test_lamda(): + assert latex(Symbol('lamda')) == r"\lambda" + assert latex(Symbol('Lamda')) == r"\Lambda" + + +def test_custom_symbol_names(): + x = Symbol('x') + y = Symbol('y') + assert latex(x) == r"x" + assert latex(x, symbol_names={x: "x_i"}) == r"x_i" + assert latex(x + y, symbol_names={x: "x_i"}) == r"x_i + y" + assert latex(x**2, symbol_names={x: "x_i"}) == r"x_i^{2}" + assert latex(x + y, symbol_names={x: "x_i", y: "y_j"}) == r"x_i + y_j" + + +def test_matAdd(): + C = MatrixSymbol('C', 5, 5) + B = MatrixSymbol('B', 5, 5) + + n = symbols("n") + h = MatrixSymbol("h", 1, 1) + + assert latex(C - 2*B) in [r'- 2 B + C', r'C -2 B'] + assert latex(C + 2*B) in [r'2 B + C', r'C + 2 B'] + assert latex(B - 2*C) in [r'B - 2 C', r'- 2 C + B'] + assert latex(B + 2*C) in [r'B + 2 C', r'2 C + B'] + + assert latex(n * h - (-h + h.T) * (h + h.T)) == 'n h - \\left(- h + h^{T}\\right) \\left(h + h^{T}\\right)' + assert latex(MatAdd(MatAdd(h, h), MatAdd(h, h))) == '\\left(h + h\\right) + \\left(h + h\\right)' + assert latex(MatMul(MatMul(h, h), MatMul(h, h))) == '\\left(h h\\right) \\left(h h\\right)' + + +def test_matMul(): + A = MatrixSymbol('A', 5, 5) + B = MatrixSymbol('B', 5, 5) + x = Symbol('x') + assert latex(2*A) == r'2 A' + assert latex(2*x*A) == r'2 x A' + assert latex(-2*A) == r'- 2 A' + assert latex(1.5*A) == r'1.5 A' + assert latex(sqrt(2)*A) == r'\sqrt{2} A' + assert latex(-sqrt(2)*A) == r'- \sqrt{2} A' + assert latex(2*sqrt(2)*x*A) == r'2 \sqrt{2} x A' + assert latex(-2*A*(A + 2*B)) in [r'- 2 A \left(A + 2 B\right)', + r'- 2 A \left(2 B + A\right)'] + + +def test_latex_MatrixSlice(): + n = Symbol('n', integer=True) + x, y, z, w, t, = symbols('x y z w t') + X = MatrixSymbol('X', n, n) + Y = MatrixSymbol('Y', 10, 10) + Z = MatrixSymbol('Z', 10, 10) + + assert latex(MatrixSlice(X, (None, None, None), (None, None, None))) == r'X\left[:, :\right]' + assert latex(X[x:x + 1, y:y + 1]) == r'X\left[x:x + 1, y:y + 1\right]' + assert latex(X[x:x + 1:2, y:y + 1:2]) == r'X\left[x:x + 1:2, y:y + 1:2\right]' + assert latex(X[:x, y:]) == r'X\left[:x, y:\right]' + assert latex(X[:x, y:]) == r'X\left[:x, y:\right]' + assert latex(X[x:, :y]) == r'X\left[x:, :y\right]' + assert latex(X[x:y, z:w]) == r'X\left[x:y, z:w\right]' + assert latex(X[x:y:t, w:t:x]) == r'X\left[x:y:t, w:t:x\right]' + assert latex(X[x::y, t::w]) == r'X\left[x::y, t::w\right]' + assert latex(X[:x:y, :t:w]) == r'X\left[:x:y, :t:w\right]' + assert latex(X[::x, ::y]) == r'X\left[::x, ::y\right]' + assert latex(MatrixSlice(X, (0, None, None), (0, None, None))) == r'X\left[:, :\right]' + assert latex(MatrixSlice(X, (None, n, None), (None, n, None))) == r'X\left[:, :\right]' + assert latex(MatrixSlice(X, (0, n, None), (0, n, None))) == r'X\left[:, :\right]' + assert latex(MatrixSlice(X, (0, n, 2), (0, n, 2))) == r'X\left[::2, ::2\right]' + assert latex(X[1:2:3, 4:5:6]) == r'X\left[1:2:3, 4:5:6\right]' + assert latex(X[1:3:5, 4:6:8]) == r'X\left[1:3:5, 4:6:8\right]' + assert latex(X[1:10:2]) == r'X\left[1:10:2, :\right]' + assert latex(Y[:5, 1:9:2]) == r'Y\left[:5, 1:9:2\right]' + assert latex(Y[:5, 1:10:2]) == r'Y\left[:5, 1::2\right]' + assert latex(Y[5, :5:2]) == r'Y\left[5:6, :5:2\right]' + assert latex(X[0:1, 0:1]) == r'X\left[:1, :1\right]' + assert latex(X[0:1:2, 0:1:2]) == r'X\left[:1:2, :1:2\right]' + assert latex((Y + Z)[2:, 2:]) == r'\left(Y + Z\right)\left[2:, 2:\right]' + + +def test_latex_RandomDomain(): + from sympy.stats import Normal, Die, Exponential, pspace, where + from sympy.stats.rv import RandomDomain + + X = Normal('x1', 0, 1) + assert latex(where(X > 0)) == r"\text{Domain: }0 < x_{1} \wedge x_{1} < \infty" + + D = Die('d1', 6) + assert latex(where(D > 4)) == r"\text{Domain: }d_{1} = 5 \vee d_{1} = 6" + + A = Exponential('a', 1) + B = Exponential('b', 1) + assert latex( + pspace(Tuple(A, B)).domain) == \ + r"\text{Domain: }0 \leq a \wedge 0 \leq b \wedge a < \infty \wedge b < \infty" + + assert latex(RandomDomain(FiniteSet(x), FiniteSet(1, 2))) == \ + r'\text{Domain: }\left\{x\right\} \in \left\{1, 2\right\}' + +def test_PrettyPoly(): + from sympy.polys.domains import QQ + F = QQ.frac_field(x, y) + R = QQ[x, y] + + assert latex(F.convert(x/(x + y))) == latex(x/(x + y)) + assert latex(R.convert(x + y)) == latex(x + y) + + +def test_integral_transforms(): + x = Symbol("x") + k = Symbol("k") + f = Function("f") + a = Symbol("a") + b = Symbol("b") + + assert latex(MellinTransform(f(x), x, k)) == \ + r"\mathcal{M}_{x}\left[f{\left(x \right)}\right]\left(k\right)" + assert latex(InverseMellinTransform(f(k), k, x, a, b)) == \ + r"\mathcal{M}^{-1}_{k}\left[f{\left(k \right)}\right]\left(x\right)" + + assert latex(LaplaceTransform(f(x), x, k)) == \ + r"\mathcal{L}_{x}\left[f{\left(x \right)}\right]\left(k\right)" + assert latex(InverseLaplaceTransform(f(k), k, x, (a, b))) == \ + r"\mathcal{L}^{-1}_{k}\left[f{\left(k \right)}\right]\left(x\right)" + + assert latex(FourierTransform(f(x), x, k)) == \ + r"\mathcal{F}_{x}\left[f{\left(x \right)}\right]\left(k\right)" + assert latex(InverseFourierTransform(f(k), k, x)) == \ + r"\mathcal{F}^{-1}_{k}\left[f{\left(k \right)}\right]\left(x\right)" + + assert latex(CosineTransform(f(x), x, k)) == \ + r"\mathcal{COS}_{x}\left[f{\left(x \right)}\right]\left(k\right)" + assert latex(InverseCosineTransform(f(k), k, x)) == \ + r"\mathcal{COS}^{-1}_{k}\left[f{\left(k \right)}\right]\left(x\right)" + + assert latex(SineTransform(f(x), x, k)) == \ + r"\mathcal{SIN}_{x}\left[f{\left(x \right)}\right]\left(k\right)" + assert latex(InverseSineTransform(f(k), k, x)) == \ + r"\mathcal{SIN}^{-1}_{k}\left[f{\left(k \right)}\right]\left(x\right)" + + +def test_PolynomialRingBase(): + from sympy.polys.domains import QQ + assert latex(QQ.old_poly_ring(x, y)) == r"\mathbb{Q}\left[x, y\right]" + assert latex(QQ.old_poly_ring(x, y, order="ilex")) == \ + r"S_<^{-1}\mathbb{Q}\left[x, y\right]" + + +def test_categories(): + from sympy.categories import (Object, IdentityMorphism, + NamedMorphism, Category, Diagram, + DiagramGrid) + + A1 = Object("A1") + A2 = Object("A2") + A3 = Object("A3") + + f1 = NamedMorphism(A1, A2, "f1") + f2 = NamedMorphism(A2, A3, "f2") + id_A1 = IdentityMorphism(A1) + + K1 = Category("K1") + + assert latex(A1) == r"A_{1}" + assert latex(f1) == r"f_{1}:A_{1}\rightarrow A_{2}" + assert latex(id_A1) == r"id:A_{1}\rightarrow A_{1}" + assert latex(f2*f1) == r"f_{2}\circ f_{1}:A_{1}\rightarrow A_{3}" + + assert latex(K1) == r"\mathbf{K_{1}}" + + d = Diagram() + assert latex(d) == r"\emptyset" + + d = Diagram({f1: "unique", f2: S.EmptySet}) + assert latex(d) == r"\left\{ f_{2}\circ f_{1}:A_{1}" \ + r"\rightarrow A_{3} : \emptyset, \ id:A_{1}\rightarrow " \ + r"A_{1} : \emptyset, \ id:A_{2}\rightarrow A_{2} : " \ + r"\emptyset, \ id:A_{3}\rightarrow A_{3} : \emptyset, " \ + r"\ f_{1}:A_{1}\rightarrow A_{2} : \left\{unique\right\}, " \ + r"\ f_{2}:A_{2}\rightarrow A_{3} : \emptyset\right\}" + + d = Diagram({f1: "unique", f2: S.EmptySet}, {f2 * f1: "unique"}) + assert latex(d) == r"\left\{ f_{2}\circ f_{1}:A_{1}" \ + r"\rightarrow A_{3} : \emptyset, \ id:A_{1}\rightarrow " \ + r"A_{1} : \emptyset, \ id:A_{2}\rightarrow A_{2} : " \ + r"\emptyset, \ id:A_{3}\rightarrow A_{3} : \emptyset, " \ + r"\ f_{1}:A_{1}\rightarrow A_{2} : \left\{unique\right\}," \ + r" \ f_{2}:A_{2}\rightarrow A_{3} : \emptyset\right\}" \ + r"\Longrightarrow \left\{ f_{2}\circ f_{1}:A_{1}" \ + r"\rightarrow A_{3} : \left\{unique\right\}\right\}" + + # A linear diagram. + A = Object("A") + B = Object("B") + C = Object("C") + f = NamedMorphism(A, B, "f") + g = NamedMorphism(B, C, "g") + d = Diagram([f, g]) + grid = DiagramGrid(d) + + assert latex(grid) == r"\begin{array}{cc}" + "\n" \ + r"A & B \\" + "\n" \ + r" & C " + "\n" \ + r"\end{array}" + "\n" + + +def test_Modules(): + from sympy.polys.domains import QQ + from sympy.polys.agca import homomorphism + + R = QQ.old_poly_ring(x, y) + F = R.free_module(2) + M = F.submodule([x, y], [1, x**2]) + + assert latex(F) == r"{\mathbb{Q}\left[x, y\right]}^{2}" + assert latex(M) == \ + r"\left\langle {\left[ {x},{y} \right]},{\left[ {1},{x^{2}} \right]} \right\rangle" + + I = R.ideal(x**2, y) + assert latex(I) == r"\left\langle {x^{2}},{y} \right\rangle" + + Q = F / M + assert latex(Q) == \ + r"\frac{{\mathbb{Q}\left[x, y\right]}^{2}}{\left\langle {\left[ {x},"\ + r"{y} \right]},{\left[ {1},{x^{2}} \right]} \right\rangle}" + assert latex(Q.submodule([1, x**3/2], [2, y])) == \ + r"\left\langle {{\left[ {1},{\frac{x^{3}}{2}} \right]} + {\left"\ + r"\langle {\left[ {x},{y} \right]},{\left[ {1},{x^{2}} \right]} "\ + r"\right\rangle}},{{\left[ {2},{y} \right]} + {\left\langle {\left[ "\ + r"{x},{y} \right]},{\left[ {1},{x^{2}} \right]} \right\rangle}} \right\rangle" + + h = homomorphism(QQ.old_poly_ring(x).free_module(2), + QQ.old_poly_ring(x).free_module(2), [0, 0]) + + assert latex(h) == \ + r"{\left[\begin{matrix}0 & 0\\0 & 0\end{matrix}\right]} : "\ + r"{{\mathbb{Q}\left[x\right]}^{2}} \to {{\mathbb{Q}\left[x\right]}^{2}}" + + +def test_QuotientRing(): + from sympy.polys.domains import QQ + R = QQ.old_poly_ring(x)/[x**2 + 1] + + assert latex(R) == \ + r"\frac{\mathbb{Q}\left[x\right]}{\left\langle {x^{2} + 1} \right\rangle}" + assert latex(R.one) == r"{1} + {\left\langle {x^{2} + 1} \right\rangle}" + + +def test_Tr(): + #TODO: Handle indices + A, B = symbols('A B', commutative=False) + t = Tr(A*B) + assert latex(t) == r'\operatorname{tr}\left(A B\right)' + + +def test_Determinant(): + from sympy.matrices import Determinant, Inverse, BlockMatrix, OneMatrix, ZeroMatrix + m = Matrix(((1, 2), (3, 4))) + assert latex(Determinant(m)) == '\\left|{\\begin{matrix}1 & 2\\\\3 & 4\\end{matrix}}\\right|' + assert latex(Determinant(Inverse(m))) == \ + '\\left|{\\left[\\begin{matrix}1 & 2\\\\3 & 4\\end{matrix}\\right]^{-1}}\\right|' + X = MatrixSymbol('X', 2, 2) + assert latex(Determinant(X)) == '\\left|{X}\\right|' + assert latex(Determinant(X + m)) == \ + '\\left|{\\left[\\begin{matrix}1 & 2\\\\3 & 4\\end{matrix}\\right] + X}\\right|' + assert latex(Determinant(BlockMatrix(((OneMatrix(2, 2), X), + (m, ZeroMatrix(2, 2)))))) == \ + '\\left|{\\begin{matrix}1 & X\\\\\\left[\\begin{matrix}1 & 2\\\\3 & 4\\end{matrix}\\right] & 0\\end{matrix}}\\right|' + + +def test_Adjoint(): + from sympy.matrices import Adjoint, Inverse, Transpose + X = MatrixSymbol('X', 2, 2) + Y = MatrixSymbol('Y', 2, 2) + assert latex(Adjoint(X)) == r'X^{\dagger}' + assert latex(Adjoint(X + Y)) == r'\left(X + Y\right)^{\dagger}' + assert latex(Adjoint(X) + Adjoint(Y)) == r'X^{\dagger} + Y^{\dagger}' + assert latex(Adjoint(X*Y)) == r'\left(X Y\right)^{\dagger}' + assert latex(Adjoint(Y)*Adjoint(X)) == r'Y^{\dagger} X^{\dagger}' + assert latex(Adjoint(X**2)) == r'\left(X^{2}\right)^{\dagger}' + assert latex(Adjoint(X)**2) == r'\left(X^{\dagger}\right)^{2}' + assert latex(Adjoint(Inverse(X))) == r'\left(X^{-1}\right)^{\dagger}' + assert latex(Inverse(Adjoint(X))) == r'\left(X^{\dagger}\right)^{-1}' + assert latex(Adjoint(Transpose(X))) == r'\left(X^{T}\right)^{\dagger}' + assert latex(Transpose(Adjoint(X))) == r'\left(X^{\dagger}\right)^{T}' + assert latex(Transpose(Adjoint(X) + Y)) == r'\left(X^{\dagger} + Y\right)^{T}' + m = Matrix(((1, 2), (3, 4))) + assert latex(Adjoint(m)) == '\\left[\\begin{matrix}1 & 2\\\\3 & 4\\end{matrix}\\right]^{\\dagger}' + assert latex(Adjoint(m+X)) == \ + '\\left(\\left[\\begin{matrix}1 & 2\\\\3 & 4\\end{matrix}\\right] + X\\right)^{\\dagger}' + from sympy.matrices import BlockMatrix, OneMatrix, ZeroMatrix + assert latex(Adjoint(BlockMatrix(((OneMatrix(2, 2), X), + (m, ZeroMatrix(2, 2)))))) == \ + '\\left[\\begin{matrix}1 & X\\\\\\left[\\begin{matrix}1 & 2\\\\3 & 4\\end{matrix}\\right] & 0\\end{matrix}\\right]^{\\dagger}' + # Issue 20959 + Mx = MatrixSymbol('M^x', 2, 2) + assert latex(Adjoint(Mx)) == r'\left(M^{x}\right)^{\dagger}' + + # adjoint style + assert latex(Adjoint(X), adjoint_style="star") == r'X^{\ast}' + assert latex(Adjoint(X + Y), adjoint_style="hermitian") == r'\left(X + Y\right)^{\mathsf{H}}' + assert latex(Adjoint(X) + Adjoint(Y), adjoint_style="dagger") == r'X^{\dagger} + Y^{\dagger}' + assert latex(Adjoint(Y)*Adjoint(X)) == r'Y^{\dagger} X^{\dagger}' + assert latex(Adjoint(X**2), adjoint_style="star") == r'\left(X^{2}\right)^{\ast}' + assert latex(Adjoint(X)**2, adjoint_style="hermitian") == r'\left(X^{\mathsf{H}}\right)^{2}' + +def test_Transpose(): + from sympy.matrices import Transpose, MatPow, HadamardPower + X = MatrixSymbol('X', 2, 2) + Y = MatrixSymbol('Y', 2, 2) + assert latex(Transpose(X)) == r'X^{T}' + assert latex(Transpose(X + Y)) == r'\left(X + Y\right)^{T}' + + assert latex(Transpose(HadamardPower(X, 2))) == r'\left(X^{\circ {2}}\right)^{T}' + assert latex(HadamardPower(Transpose(X), 2)) == r'\left(X^{T}\right)^{\circ {2}}' + assert latex(Transpose(MatPow(X, 2))) == r'\left(X^{2}\right)^{T}' + assert latex(MatPow(Transpose(X), 2)) == r'\left(X^{T}\right)^{2}' + m = Matrix(((1, 2), (3, 4))) + assert latex(Transpose(m)) == '\\left[\\begin{matrix}1 & 2\\\\3 & 4\\end{matrix}\\right]^{T}' + assert latex(Transpose(m+X)) == \ + '\\left(\\left[\\begin{matrix}1 & 2\\\\3 & 4\\end{matrix}\\right] + X\\right)^{T}' + from sympy.matrices import BlockMatrix, OneMatrix, ZeroMatrix + assert latex(Transpose(BlockMatrix(((OneMatrix(2, 2), X), + (m, ZeroMatrix(2, 2)))))) == \ + '\\left[\\begin{matrix}1 & X\\\\\\left[\\begin{matrix}1 & 2\\\\3 & 4\\end{matrix}\\right] & 0\\end{matrix}\\right]^{T}' + # Issue 20959 + Mx = MatrixSymbol('M^x', 2, 2) + assert latex(Transpose(Mx)) == r'\left(M^{x}\right)^{T}' + + +def test_Hadamard(): + from sympy.matrices import HadamardProduct, HadamardPower + from sympy.matrices.expressions import MatAdd, MatMul, MatPow + X = MatrixSymbol('X', 2, 2) + Y = MatrixSymbol('Y', 2, 2) + assert latex(HadamardProduct(X, Y*Y)) == r'X \circ Y^{2}' + assert latex(HadamardProduct(X, Y)*Y) == r'\left(X \circ Y\right) Y' + + assert latex(HadamardPower(X, 2)) == r'X^{\circ {2}}' + assert latex(HadamardPower(X, -1)) == r'X^{\circ \left({-1}\right)}' + assert latex(HadamardPower(MatAdd(X, Y), 2)) == \ + r'\left(X + Y\right)^{\circ {2}}' + assert latex(HadamardPower(MatMul(X, Y), 2)) == \ + r'\left(X Y\right)^{\circ {2}}' + + assert latex(HadamardPower(MatPow(X, -1), -1)) == \ + r'\left(X^{-1}\right)^{\circ \left({-1}\right)}' + assert latex(MatPow(HadamardPower(X, -1), -1)) == \ + r'\left(X^{\circ \left({-1}\right)}\right)^{-1}' + + assert latex(HadamardPower(X, n+1)) == \ + r'X^{\circ \left({n + 1}\right)}' + + +def test_MatPow(): + from sympy.matrices.expressions import MatPow + X = MatrixSymbol('X', 2, 2) + Y = MatrixSymbol('Y', 2, 2) + assert latex(MatPow(X, 2)) == 'X^{2}' + assert latex(MatPow(X*X, 2)) == '\\left(X^{2}\\right)^{2}' + assert latex(MatPow(X*Y, 2)) == '\\left(X Y\\right)^{2}' + assert latex(MatPow(X + Y, 2)) == '\\left(X + Y\\right)^{2}' + assert latex(MatPow(X + X, 2)) == '\\left(2 X\\right)^{2}' + # Issue 20959 + Mx = MatrixSymbol('M^x', 2, 2) + assert latex(MatPow(Mx, 2)) == r'\left(M^{x}\right)^{2}' + + +def test_ElementwiseApplyFunction(): + X = MatrixSymbol('X', 2, 2) + expr = (X.T*X).applyfunc(sin) + assert latex(expr) == r"{\left( d \mapsto \sin{\left(d \right)} \right)}_{\circ}\left({X^{T} X}\right)" + expr = X.applyfunc(Lambda(x, 1/x)) + assert latex(expr) == r'{\left( x \mapsto \frac{1}{x} \right)}_{\circ}\left({X}\right)' + + +def test_ZeroMatrix(): + from sympy.matrices.expressions.special import ZeroMatrix + assert latex(ZeroMatrix(1, 1), mat_symbol_style='plain') == r"0" + assert latex(ZeroMatrix(1, 1), mat_symbol_style='bold') == r"\mathbf{0}" + + +def test_OneMatrix(): + from sympy.matrices.expressions.special import OneMatrix + assert latex(OneMatrix(3, 4), mat_symbol_style='plain') == r"1" + assert latex(OneMatrix(3, 4), mat_symbol_style='bold') == r"\mathbf{1}" + + +def test_Identity(): + from sympy.matrices.expressions.special import Identity + assert latex(Identity(1), mat_symbol_style='plain') == r"\mathbb{I}" + assert latex(Identity(1), mat_symbol_style='bold') == r"\mathbf{I}" + + +def test_latex_DFT_IDFT(): + from sympy.matrices.expressions.fourier import DFT, IDFT + assert latex(DFT(13)) == r"\text{DFT}_{13}" + assert latex(IDFT(x)) == r"\text{IDFT}_{x}" + + +def test_boolean_args_order(): + syms = symbols('a:f') + + expr = And(*syms) + assert latex(expr) == r'a \wedge b \wedge c \wedge d \wedge e \wedge f' + + expr = Or(*syms) + assert latex(expr) == r'a \vee b \vee c \vee d \vee e \vee f' + + expr = Equivalent(*syms) + assert latex(expr) == \ + r'a \Leftrightarrow b \Leftrightarrow c \Leftrightarrow d \Leftrightarrow e \Leftrightarrow f' + + expr = Xor(*syms) + assert latex(expr) == \ + r'a \veebar b \veebar c \veebar d \veebar e \veebar f' + + +def test_imaginary(): + i = sqrt(-1) + assert latex(i) == r'i' + + +def test_builtins_without_args(): + assert latex(sin) == r'\sin' + assert latex(cos) == r'\cos' + assert latex(tan) == r'\tan' + assert latex(log) == r'\log' + assert latex(Ei) == r'\operatorname{Ei}' + assert latex(zeta) == r'\zeta' + + +def test_latex_greek_functions(): + # bug because capital greeks that have roman equivalents should not use + # \Alpha, \Beta, \Eta, etc. + s = Function('Alpha') + assert latex(s) == r'\mathrm{A}' + assert latex(s(x)) == r'\mathrm{A}{\left(x \right)}' + s = Function('Beta') + assert latex(s) == r'\mathrm{B}' + s = Function('Eta') + assert latex(s) == r'\mathrm{H}' + assert latex(s(x)) == r'\mathrm{H}{\left(x \right)}' + + # bug because sympy.core.numbers.Pi is special + p = Function('Pi') + # assert latex(p(x)) == r'\Pi{\left(x \right)}' + assert latex(p) == r'\Pi' + + # bug because not all greeks are included + c = Function('chi') + assert latex(c(x)) == r'\chi{\left(x \right)}' + assert latex(c) == r'\chi' + + +def test_translate(): + s = 'Alpha' + assert translate(s) == r'\mathrm{A}' + s = 'Beta' + assert translate(s) == r'\mathrm{B}' + s = 'Eta' + assert translate(s) == r'\mathrm{H}' + s = 'omicron' + assert translate(s) == r'o' + s = 'Pi' + assert translate(s) == r'\Pi' + s = 'pi' + assert translate(s) == r'\pi' + s = 'LamdaHatDOT' + assert translate(s) == r'\dot{\hat{\Lambda}}' + + +def test_other_symbols(): + from sympy.printing.latex import other_symbols + for s in other_symbols: + assert latex(symbols(s)) == r"" "\\" + s + + +def test_modifiers(): + # Test each modifier individually in the simplest case + # (with funny capitalizations) + assert latex(symbols("xMathring")) == r"\mathring{x}" + assert latex(symbols("xCheck")) == r"\check{x}" + assert latex(symbols("xBreve")) == r"\breve{x}" + assert latex(symbols("xAcute")) == r"\acute{x}" + assert latex(symbols("xGrave")) == r"\grave{x}" + assert latex(symbols("xTilde")) == r"\tilde{x}" + assert latex(symbols("xPrime")) == r"{x}'" + assert latex(symbols("xddDDot")) == r"\ddddot{x}" + assert latex(symbols("xDdDot")) == r"\dddot{x}" + assert latex(symbols("xDDot")) == r"\ddot{x}" + assert latex(symbols("xBold")) == r"\boldsymbol{x}" + assert latex(symbols("xnOrM")) == r"\left\|{x}\right\|" + assert latex(symbols("xAVG")) == r"\left\langle{x}\right\rangle" + assert latex(symbols("xHat")) == r"\hat{x}" + assert latex(symbols("xDot")) == r"\dot{x}" + assert latex(symbols("xBar")) == r"\bar{x}" + assert latex(symbols("xVec")) == r"\vec{x}" + assert latex(symbols("xAbs")) == r"\left|{x}\right|" + assert latex(symbols("xMag")) == r"\left|{x}\right|" + assert latex(symbols("xPrM")) == r"{x}'" + assert latex(symbols("xBM")) == r"\boldsymbol{x}" + # Test strings that are *only* the names of modifiers + assert latex(symbols("Mathring")) == r"Mathring" + assert latex(symbols("Check")) == r"Check" + assert latex(symbols("Breve")) == r"Breve" + assert latex(symbols("Acute")) == r"Acute" + assert latex(symbols("Grave")) == r"Grave" + assert latex(symbols("Tilde")) == r"Tilde" + assert latex(symbols("Prime")) == r"Prime" + assert latex(symbols("DDot")) == r"\dot{D}" + assert latex(symbols("Bold")) == r"Bold" + assert latex(symbols("NORm")) == r"NORm" + assert latex(symbols("AVG")) == r"AVG" + assert latex(symbols("Hat")) == r"Hat" + assert latex(symbols("Dot")) == r"Dot" + assert latex(symbols("Bar")) == r"Bar" + assert latex(symbols("Vec")) == r"Vec" + assert latex(symbols("Abs")) == r"Abs" + assert latex(symbols("Mag")) == r"Mag" + assert latex(symbols("PrM")) == r"PrM" + assert latex(symbols("BM")) == r"BM" + assert latex(symbols("hbar")) == r"\hbar" + # Check a few combinations + assert latex(symbols("xvecdot")) == r"\dot{\vec{x}}" + assert latex(symbols("xDotVec")) == r"\vec{\dot{x}}" + assert latex(symbols("xHATNorm")) == r"\left\|{\hat{x}}\right\|" + # Check a couple big, ugly combinations + assert latex(symbols('xMathringBm_yCheckPRM__zbreveAbs')) == \ + r"\boldsymbol{\mathring{x}}^{\left|{\breve{z}}\right|}_{{\check{y}}'}" + assert latex(symbols('alphadothat_nVECDOT__tTildePrime')) == \ + r"\hat{\dot{\alpha}}^{{\tilde{t}}'}_{\dot{\vec{n}}}" + + +def test_greek_symbols(): + assert latex(Symbol('alpha')) == r'\alpha' + assert latex(Symbol('beta')) == r'\beta' + assert latex(Symbol('gamma')) == r'\gamma' + assert latex(Symbol('delta')) == r'\delta' + assert latex(Symbol('epsilon')) == r'\epsilon' + assert latex(Symbol('zeta')) == r'\zeta' + assert latex(Symbol('eta')) == r'\eta' + assert latex(Symbol('theta')) == r'\theta' + assert latex(Symbol('iota')) == r'\iota' + assert latex(Symbol('kappa')) == r'\kappa' + assert latex(Symbol('lambda')) == r'\lambda' + assert latex(Symbol('mu')) == r'\mu' + assert latex(Symbol('nu')) == r'\nu' + assert latex(Symbol('xi')) == r'\xi' + assert latex(Symbol('omicron')) == r'o' + assert latex(Symbol('pi')) == r'\pi' + assert latex(Symbol('rho')) == r'\rho' + assert latex(Symbol('sigma')) == r'\sigma' + assert latex(Symbol('tau')) == r'\tau' + assert latex(Symbol('upsilon')) == r'\upsilon' + assert latex(Symbol('phi')) == r'\phi' + assert latex(Symbol('chi')) == r'\chi' + assert latex(Symbol('psi')) == r'\psi' + assert latex(Symbol('omega')) == r'\omega' + + assert latex(Symbol('Alpha')) == r'\mathrm{A}' + assert latex(Symbol('Beta')) == r'\mathrm{B}' + assert latex(Symbol('Gamma')) == r'\Gamma' + assert latex(Symbol('Delta')) == r'\Delta' + assert latex(Symbol('Epsilon')) == r'\mathrm{E}' + assert latex(Symbol('Zeta')) == r'\mathrm{Z}' + assert latex(Symbol('Eta')) == r'\mathrm{H}' + assert latex(Symbol('Theta')) == r'\Theta' + assert latex(Symbol('Iota')) == r'\mathrm{I}' + assert latex(Symbol('Kappa')) == r'\mathrm{K}' + assert latex(Symbol('Lambda')) == r'\Lambda' + assert latex(Symbol('Mu')) == r'\mathrm{M}' + assert latex(Symbol('Nu')) == r'\mathrm{N}' + assert latex(Symbol('Xi')) == r'\Xi' + assert latex(Symbol('Omicron')) == r'\mathrm{O}' + assert latex(Symbol('Pi')) == r'\Pi' + assert latex(Symbol('Rho')) == r'\mathrm{P}' + assert latex(Symbol('Sigma')) == r'\Sigma' + assert latex(Symbol('Tau')) == r'\mathrm{T}' + assert latex(Symbol('Upsilon')) == r'\Upsilon' + assert latex(Symbol('Phi')) == r'\Phi' + assert latex(Symbol('Chi')) == r'\mathrm{X}' + assert latex(Symbol('Psi')) == r'\Psi' + assert latex(Symbol('Omega')) == r'\Omega' + + assert latex(Symbol('varepsilon')) == r'\varepsilon' + assert latex(Symbol('varkappa')) == r'\varkappa' + assert latex(Symbol('varphi')) == r'\varphi' + assert latex(Symbol('varpi')) == r'\varpi' + assert latex(Symbol('varrho')) == r'\varrho' + assert latex(Symbol('varsigma')) == r'\varsigma' + assert latex(Symbol('vartheta')) == r'\vartheta' + + +def test_fancyset_symbols(): + assert latex(S.Rationals) == r'\mathbb{Q}' + assert latex(S.Naturals) == r'\mathbb{N}' + assert latex(S.Naturals0) == r'\mathbb{N}_0' + assert latex(S.Integers) == r'\mathbb{Z}' + assert latex(S.Reals) == r'\mathbb{R}' + assert latex(S.Complexes) == r'\mathbb{C}' + + +@XFAIL +def test_builtin_without_args_mismatched_names(): + assert latex(CosineTransform) == r'\mathcal{COS}' + + +def test_builtin_no_args(): + assert latex(Chi) == r'\operatorname{Chi}' + assert latex(beta) == r'\operatorname{B}' + assert latex(gamma) == r'\Gamma' + assert latex(KroneckerDelta) == r'\delta' + assert latex(DiracDelta) == r'\delta' + assert latex(lowergamma) == r'\gamma' + + +def test_issue_6853(): + p = Function('Pi') + assert latex(p(x)) == r"\Pi{\left(x \right)}" + + +def test_Mul(): + e = Mul(-2, x + 1, evaluate=False) + assert latex(e) == r'- 2 \left(x + 1\right)' + e = Mul(2, x + 1, evaluate=False) + assert latex(e) == r'2 \left(x + 1\right)' + e = Mul(S.Half, x + 1, evaluate=False) + assert latex(e) == r'\frac{x + 1}{2}' + e = Mul(y, x + 1, evaluate=False) + assert latex(e) == r'y \left(x + 1\right)' + e = Mul(-y, x + 1, evaluate=False) + assert latex(e) == r'- y \left(x + 1\right)' + e = Mul(-2, x + 1) + assert latex(e) == r'- 2 x - 2' + e = Mul(2, x + 1) + assert latex(e) == r'2 x + 2' + + +def test_Pow(): + e = Pow(2, 2, evaluate=False) + assert latex(e) == r'2^{2}' + assert latex(x**(Rational(-1, 3))) == r'\frac{1}{\sqrt[3]{x}}' + x2 = Symbol(r'x^2') + assert latex(x2**2) == r'\left(x^{2}\right)^{2}' + # Issue 11011 + assert latex(S('1.453e4500')**x) == r'{1.453 \cdot 10^{4500}}^{x}' + + +def test_issue_7180(): + assert latex(Equivalent(x, y)) == r"x \Leftrightarrow y" + assert latex(Not(Equivalent(x, y))) == r"x \not\Leftrightarrow y" + + +def test_issue_8409(): + assert latex(S.Half**n) == r"\left(\frac{1}{2}\right)^{n}" + + +def test_issue_8470(): + from sympy.parsing.sympy_parser import parse_expr + e = parse_expr("-B*A", evaluate=False) + assert latex(e) == r"A \left(- B\right)" + + +def test_issue_15439(): + x = MatrixSymbol('x', 2, 2) + y = MatrixSymbol('y', 2, 2) + assert latex((x * y).subs(y, -y)) == r"x \left(- y\right)" + assert latex((x * y).subs(y, -2*y)) == r"x \left(- 2 y\right)" + assert latex((x * y).subs(x, -x)) == r"\left(- x\right) y" + + +def test_issue_2934(): + assert latex(Symbol(r'\frac{a_1}{b_1}')) == r'\frac{a_1}{b_1}' + + +def test_issue_10489(): + latexSymbolWithBrace = r'C_{x_{0}}' + s = Symbol(latexSymbolWithBrace) + assert latex(s) == latexSymbolWithBrace + assert latex(cos(s)) == r'\cos{\left(C_{x_{0}} \right)}' + + +def test_issue_12886(): + m__1, l__1 = symbols('m__1, l__1') + assert latex(m__1**2 + l__1**2) == \ + r'\left(l^{1}\right)^{2} + \left(m^{1}\right)^{2}' + + +def test_issue_13559(): + from sympy.parsing.sympy_parser import parse_expr + expr = parse_expr('5/1', evaluate=False) + assert latex(expr) == r"\frac{5}{1}" + + +def test_issue_13651(): + expr = c + Mul(-1, a + b, evaluate=False) + assert latex(expr) == r"c - \left(a + b\right)" + + +def test_latex_UnevaluatedExpr(): + x = symbols("x") + he = UnevaluatedExpr(1/x) + assert latex(he) == latex(1/x) == r"\frac{1}{x}" + assert latex(he**2) == r"\left(\frac{1}{x}\right)^{2}" + assert latex(he + 1) == r"1 + \frac{1}{x}" + assert latex(x*he) == r"x \frac{1}{x}" + + +def test_MatrixElement_printing(): + # test cases for issue #11821 + A = MatrixSymbol("A", 1, 3) + B = MatrixSymbol("B", 1, 3) + C = MatrixSymbol("C", 1, 3) + + assert latex(A[0, 0]) == r"{A}_{0,0}" + assert latex(3 * A[0, 0]) == r"3 {A}_{0,0}" + + F = C[0, 0].subs(C, A - B) + assert latex(F) == r"{\left(A - B\right)}_{0,0}" + + i, j, k = symbols("i j k") + M = MatrixSymbol("M", k, k) + N = MatrixSymbol("N", k, k) + assert latex((M*N)[i, j]) == \ + r'\sum_{i_{1}=0}^{k - 1} {M}_{i,i_{1}} {N}_{i_{1},j}' + + X_a = MatrixSymbol('X_a', 3, 3) + assert latex(X_a[0, 0]) == r"{X_{a}}_{0,0}" + + +def test_MatrixSymbol_printing(): + # test cases for issue #14237 + A = MatrixSymbol("A", 3, 3) + B = MatrixSymbol("B", 3, 3) + C = MatrixSymbol("C", 3, 3) + + assert latex(-A) == r"- A" + assert latex(A - A*B - B) == r"A - A B - B" + assert latex(-A*B - A*B*C - B) == r"- A B - A B C - B" + + +def test_DotProduct_printing(): + X = MatrixSymbol('X', 3, 1) + Y = MatrixSymbol('Y', 3, 1) + a = Symbol('a') + assert latex(DotProduct(X, Y)) == r"X \cdot Y" + assert latex(DotProduct(a * X, Y)) == r"a X \cdot Y" + assert latex(a * DotProduct(X, Y)) == r"a \left(X \cdot Y\right)" + + +def test_KroneckerProduct_printing(): + A = MatrixSymbol('A', 3, 3) + B = MatrixSymbol('B', 2, 2) + assert latex(KroneckerProduct(A, B)) == r'A \otimes B' + + +def test_Series_printing(): + tf1 = TransferFunction(x*y**2 - z, y**3 - t**3, y) + tf2 = TransferFunction(x - y, x + y, y) + tf3 = TransferFunction(t*x**2 - t**w*x + w, t - y, y) + assert latex(Series(tf1, tf2)) == \ + r'\left(\frac{x y^{2} - z}{- t^{3} + y^{3}}\right) \left(\frac{x - y}{x + y}\right)' + assert latex(Series(tf1, tf2, tf3)) == \ + r'\left(\frac{x y^{2} - z}{- t^{3} + y^{3}}\right) \left(\frac{x - y}{x + y}\right) \left(\frac{t x^{2} - t^{w} x + w}{t - y}\right)' + assert latex(Series(-tf2, tf1)) == \ + r'\left(\frac{- x + y}{x + y}\right) \left(\frac{x y^{2} - z}{- t^{3} + y^{3}}\right)' + + M_1 = Matrix([[5/s], [5/(2*s)]]) + T_1 = TransferFunctionMatrix.from_Matrix(M_1, s) + M_2 = Matrix([[5, 6*s**3]]) + T_2 = TransferFunctionMatrix.from_Matrix(M_2, s) + # Brackets + assert latex(T_1*(T_2 + T_2)) == \ + r'\left[\begin{matrix}\frac{5}{s}\\\frac{5}{2 s}\end{matrix}\right]_\tau\cdot\left(\left[\begin{matrix}\frac{5}{1} &' \ + r' \frac{6 s^{3}}{1}\end{matrix}\right]_\tau + \left[\begin{matrix}\frac{5}{1} & \frac{6 s^{3}}{1}\end{matrix}\right]_\tau\right)' \ + == latex(MIMOSeries(MIMOParallel(T_2, T_2), T_1)) + # No Brackets + M_3 = Matrix([[5, 6], [6, 5/s]]) + T_3 = TransferFunctionMatrix.from_Matrix(M_3, s) + assert latex(T_1*T_2 + T_3) == r'\left[\begin{matrix}\frac{5}{s}\\\frac{5}{2 s}\end{matrix}\right]_\tau\cdot\left[\begin{matrix}' \ + r'\frac{5}{1} & \frac{6 s^{3}}{1}\end{matrix}\right]_\tau + \left[\begin{matrix}\frac{5}{1} & \frac{6}{1}\\\frac{6}{1} & ' \ + r'\frac{5}{s}\end{matrix}\right]_\tau' == latex(MIMOParallel(MIMOSeries(T_2, T_1), T_3)) + + +def test_TransferFunction_printing(): + tf1 = TransferFunction(x - 1, x + 1, x) + assert latex(tf1) == r"\frac{x - 1}{x + 1}" + tf2 = TransferFunction(x + 1, 2 - y, x) + assert latex(tf2) == r"\frac{x + 1}{2 - y}" + tf3 = TransferFunction(y, y**2 + 2*y + 3, y) + assert latex(tf3) == r"\frac{y}{y^{2} + 2 y + 3}" + + +def test_Parallel_printing(): + tf1 = TransferFunction(x*y**2 - z, y**3 - t**3, y) + tf2 = TransferFunction(x - y, x + y, y) + assert latex(Parallel(tf1, tf2)) == \ + r'\frac{x y^{2} - z}{- t^{3} + y^{3}} + \frac{x - y}{x + y}' + assert latex(Parallel(-tf2, tf1)) == \ + r'\frac{- x + y}{x + y} + \frac{x y^{2} - z}{- t^{3} + y^{3}}' + + M_1 = Matrix([[5, 6], [6, 5/s]]) + T_1 = TransferFunctionMatrix.from_Matrix(M_1, s) + M_2 = Matrix([[5/s, 6], [6, 5/(s - 1)]]) + T_2 = TransferFunctionMatrix.from_Matrix(M_2, s) + M_3 = Matrix([[6, 5/(s*(s - 1))], [5, 6]]) + T_3 = TransferFunctionMatrix.from_Matrix(M_3, s) + assert latex(T_1 + T_2 + T_3) == r'\left[\begin{matrix}\frac{5}{1} & \frac{6}{1}\\\frac{6}{1} & \frac{5}{s}\end{matrix}\right]' \ + r'_\tau + \left[\begin{matrix}\frac{5}{s} & \frac{6}{1}\\\frac{6}{1} & \frac{5}{s - 1}\end{matrix}\right]_\tau + \left[\begin{matrix}' \ + r'\frac{6}{1} & \frac{5}{s \left(s - 1\right)}\\\frac{5}{1} & \frac{6}{1}\end{matrix}\right]_\tau' \ + == latex(MIMOParallel(T_1, T_2, T_3)) == latex(MIMOParallel(T_1, MIMOParallel(T_2, T_3))) == latex(MIMOParallel(MIMOParallel(T_1, T_2), T_3)) + + +def test_TransferFunctionMatrix_printing(): + tf1 = TransferFunction(p, p + x, p) + tf2 = TransferFunction(-s + p, p + s, p) + tf3 = TransferFunction(p, y**2 + 2*y + 3, p) + assert latex(TransferFunctionMatrix([[tf1], [tf2]])) == \ + r'\left[\begin{matrix}\frac{p}{p + x}\\\frac{p - s}{p + s}\end{matrix}\right]_\tau' + assert latex(TransferFunctionMatrix([[tf1, tf2], [tf3, -tf1]])) == \ + r'\left[\begin{matrix}\frac{p}{p + x} & \frac{p - s}{p + s}\\\frac{p}{y^{2} + 2 y + 3} & \frac{\left(-1\right) p}{p + x}\end{matrix}\right]_\tau' + + +def test_Feedback_printing(): + tf1 = TransferFunction(p, p + x, p) + tf2 = TransferFunction(-s + p, p + s, p) + # Negative Feedback (Default) + assert latex(Feedback(tf1, tf2)) == \ + r'\frac{\frac{p}{p + x}}{\frac{1}{1} + \left(\frac{p}{p + x}\right) \left(\frac{p - s}{p + s}\right)}' + assert latex(Feedback(tf1*tf2, TransferFunction(1, 1, p))) == \ + r'\frac{\left(\frac{p}{p + x}\right) \left(\frac{p - s}{p + s}\right)}{\frac{1}{1} + \left(\frac{p}{p + x}\right) \left(\frac{p - s}{p + s}\right)}' + # Positive Feedback + assert latex(Feedback(tf1, tf2, 1)) == \ + r'\frac{\frac{p}{p + x}}{\frac{1}{1} - \left(\frac{p}{p + x}\right) \left(\frac{p - s}{p + s}\right)}' + assert latex(Feedback(tf1*tf2, sign=1)) == \ + r'\frac{\left(\frac{p}{p + x}\right) \left(\frac{p - s}{p + s}\right)}{\frac{1}{1} - \left(\frac{p}{p + x}\right) \left(\frac{p - s}{p + s}\right)}' + + +def test_MIMOFeedback_printing(): + tf1 = TransferFunction(1, s, s) + tf2 = TransferFunction(s, s**2 - 1, s) + tf3 = TransferFunction(s, s - 1, s) + tf4 = TransferFunction(s**2, s**2 - 1, s) + + tfm_1 = TransferFunctionMatrix([[tf1, tf2], [tf3, tf4]]) + tfm_2 = TransferFunctionMatrix([[tf4, tf3], [tf2, tf1]]) + + # Negative Feedback (Default) + assert latex(MIMOFeedback(tfm_1, tfm_2)) == \ + r'\left(I_{\tau} + \left[\begin{matrix}\frac{1}{s} & \frac{s}{s^{2} - 1}\\\frac{s}{s - 1} & \frac{s^{2}}{s^{2} - 1}\end{matrix}\right]_\tau\cdot\left[' \ + r'\begin{matrix}\frac{s^{2}}{s^{2} - 1} & \frac{s}{s - 1}\\\frac{s}{s^{2} - 1} & \frac{1}{s}\end{matrix}\right]_\tau\right)^{-1} \cdot \left[\begin{matrix}' \ + r'\frac{1}{s} & \frac{s}{s^{2} - 1}\\\frac{s}{s - 1} & \frac{s^{2}}{s^{2} - 1}\end{matrix}\right]_\tau' + + # Positive Feedback + assert latex(MIMOFeedback(tfm_1*tfm_2, tfm_1, 1)) == \ + r'\left(I_{\tau} - \left[\begin{matrix}\frac{1}{s} & \frac{s}{s^{2} - 1}\\\frac{s}{s - 1} & \frac{s^{2}}{s^{2} - 1}\end{matrix}\right]_\tau\cdot\left' \ + r'[\begin{matrix}\frac{s^{2}}{s^{2} - 1} & \frac{s}{s - 1}\\\frac{s}{s^{2} - 1} & \frac{1}{s}\end{matrix}\right]_\tau\cdot\left[\begin{matrix}\frac{1}{s} & \frac{s}{s^{2} - 1}' \ + r'\\\frac{s}{s - 1} & \frac{s^{2}}{s^{2} - 1}\end{matrix}\right]_\tau\right)^{-1} \cdot \left[\begin{matrix}\frac{1}{s} & \frac{s}{s^{2} - 1}' \ + r'\\\frac{s}{s - 1} & \frac{s^{2}}{s^{2} - 1}\end{matrix}\right]_\tau\cdot\left[\begin{matrix}\frac{s^{2}}{s^{2} - 1} & \frac{s}{s - 1}\\\frac{s}{s^{2} - 1}' \ + r' & \frac{1}{s}\end{matrix}\right]_\tau' + + +def test_Quaternion_latex_printing(): + q = Quaternion(x, y, z, t) + assert latex(q) == r"x + y i + z j + t k" + q = Quaternion(x, y, z, x*t) + assert latex(q) == r"x + y i + z j + t x k" + q = Quaternion(x, y, z, x + t) + assert latex(q) == r"x + y i + z j + \left(t + x\right) k" + + +def test_TensorProduct_printing(): + from sympy.tensor.functions import TensorProduct + A = MatrixSymbol("A", 3, 3) + B = MatrixSymbol("B", 3, 3) + assert latex(TensorProduct(A, B)) == r"A \otimes B" + + +def test_WedgeProduct_printing(): + from sympy.diffgeom.rn import R2 + from sympy.diffgeom import WedgeProduct + wp = WedgeProduct(R2.dx, R2.dy) + assert latex(wp) == r"\operatorname{d}x \wedge \operatorname{d}y" + + +def test_issue_9216(): + expr_1 = Pow(1, -1, evaluate=False) + assert latex(expr_1) == r"1^{-1}" + + expr_2 = Pow(1, Pow(1, -1, evaluate=False), evaluate=False) + assert latex(expr_2) == r"1^{1^{-1}}" + + expr_3 = Pow(3, -2, evaluate=False) + assert latex(expr_3) == r"\frac{1}{9}" + + expr_4 = Pow(1, -2, evaluate=False) + assert latex(expr_4) == r"1^{-2}" + + +def test_latex_printer_tensor(): + from sympy.tensor.tensor import TensorIndexType, tensor_indices, TensorHead, tensor_heads + L = TensorIndexType("L") + i, j, k, l = tensor_indices("i j k l", L) + i0 = tensor_indices("i_0", L) + A, B, C, D = tensor_heads("A B C D", [L]) + H = TensorHead("H", [L, L]) + K = TensorHead("K", [L, L, L, L]) + + assert latex(i) == r"{}^{i}" + assert latex(-i) == r"{}_{i}" + + expr = A(i) + assert latex(expr) == r"A{}^{i}" + + expr = A(i0) + assert latex(expr) == r"A{}^{i_{0}}" + + expr = A(-i) + assert latex(expr) == r"A{}_{i}" + + expr = -3*A(i) + assert latex(expr) == r"-3A{}^{i}" + + expr = K(i, j, -k, -i0) + assert latex(expr) == r"K{}^{ij}{}_{ki_{0}}" + + expr = K(i, -j, -k, i0) + assert latex(expr) == r"K{}^{i}{}_{jk}{}^{i_{0}}" + + expr = K(i, -j, k, -i0) + assert latex(expr) == r"K{}^{i}{}_{j}{}^{k}{}_{i_{0}}" + + expr = H(i, -j) + assert latex(expr) == r"H{}^{i}{}_{j}" + + expr = H(i, j) + assert latex(expr) == r"H{}^{ij}" + + expr = H(-i, -j) + assert latex(expr) == r"H{}_{ij}" + + expr = (1+x)*A(i) + assert latex(expr) == r"\left(x + 1\right)A{}^{i}" + + expr = H(i, -i) + assert latex(expr) == r"H{}^{L_{0}}{}_{L_{0}}" + + expr = H(i, -j)*A(j)*B(k) + assert latex(expr) == r"H{}^{i}{}_{L_{0}}A{}^{L_{0}}B{}^{k}" + + expr = A(i) + 3*B(i) + assert latex(expr) == r"3B{}^{i} + A{}^{i}" + + # Test ``TensorElement``: + from sympy.tensor.tensor import TensorElement + + expr = TensorElement(K(i, j, k, l), {i: 3, k: 2}) + assert latex(expr) == r'K{}^{i=3,j,k=2,l}' + + expr = TensorElement(K(i, j, k, l), {i: 3}) + assert latex(expr) == r'K{}^{i=3,jkl}' + + expr = TensorElement(K(i, -j, k, l), {i: 3, k: 2}) + assert latex(expr) == r'K{}^{i=3}{}_{j}{}^{k=2,l}' + + expr = TensorElement(K(i, -j, k, -l), {i: 3, k: 2}) + assert latex(expr) == r'K{}^{i=3}{}_{j}{}^{k=2}{}_{l}' + + expr = TensorElement(K(i, j, -k, -l), {i: 3, -k: 2}) + assert latex(expr) == r'K{}^{i=3,j}{}_{k=2,l}' + + expr = TensorElement(K(i, j, -k, -l), {i: 3}) + assert latex(expr) == r'K{}^{i=3,j}{}_{kl}' + + expr = PartialDerivative(A(i), A(i)) + assert latex(expr) == r"\frac{\partial}{\partial {A{}^{L_{0}}}}{A{}^{L_{0}}}" + + expr = PartialDerivative(A(-i), A(-j)) + assert latex(expr) == r"\frac{\partial}{\partial {A{}_{j}}}{A{}_{i}}" + + expr = PartialDerivative(K(i, j, -k, -l), A(m), A(-n)) + assert latex(expr) == r"\frac{\partial^{2}}{\partial {A{}^{m}} \partial {A{}_{n}}}{K{}^{ij}{}_{kl}}" + + expr = PartialDerivative(B(-i) + A(-i), A(-j), A(-n)) + assert latex(expr) == r"\frac{\partial^{2}}{\partial {A{}_{j}} \partial {A{}_{n}}}{\left(A{}_{i} + B{}_{i}\right)}" + + expr = PartialDerivative(3*A(-i), A(-j), A(-n)) + assert latex(expr) == r"\frac{\partial^{2}}{\partial {A{}_{j}} \partial {A{}_{n}}}{\left(3A{}_{i}\right)}" + + +def test_multiline_latex(): + a, b, c, d, e, f = symbols('a b c d e f') + expr = -a + 2*b -3*c +4*d -5*e + expected = r"\begin{eqnarray}" + "\n"\ + r"f & = &- a \nonumber\\" + "\n"\ + r"& & + 2 b \nonumber\\" + "\n"\ + r"& & - 3 c \nonumber\\" + "\n"\ + r"& & + 4 d \nonumber\\" + "\n"\ + r"& & - 5 e " + "\n"\ + r"\end{eqnarray}" + assert multiline_latex(f, expr, environment="eqnarray") == expected + + expected2 = r'\begin{eqnarray}' + '\n'\ + r'f & = &- a + 2 b \nonumber\\' + '\n'\ + r'& & - 3 c + 4 d \nonumber\\' + '\n'\ + r'& & - 5 e ' + '\n'\ + r'\end{eqnarray}' + + assert multiline_latex(f, expr, 2, environment="eqnarray") == expected2 + + expected3 = r'\begin{eqnarray}' + '\n'\ + r'f & = &- a + 2 b - 3 c \nonumber\\'+ '\n'\ + r'& & + 4 d - 5 e ' + '\n'\ + r'\end{eqnarray}' + + assert multiline_latex(f, expr, 3, environment="eqnarray") == expected3 + + expected3dots = r'\begin{eqnarray}' + '\n'\ + r'f & = &- a + 2 b - 3 c \dots\nonumber\\'+ '\n'\ + r'& & + 4 d - 5 e ' + '\n'\ + r'\end{eqnarray}' + + assert multiline_latex(f, expr, 3, environment="eqnarray", use_dots=True) == expected3dots + + expected3align = r'\begin{align*}' + '\n'\ + r'f = &- a + 2 b - 3 c \\'+ '\n'\ + r'& + 4 d - 5 e ' + '\n'\ + r'\end{align*}' + + assert multiline_latex(f, expr, 3) == expected3align + assert multiline_latex(f, expr, 3, environment='align*') == expected3align + + expected2ieee = r'\begin{IEEEeqnarray}{rCl}' + '\n'\ + r'f & = &- a + 2 b \nonumber\\' + '\n'\ + r'& & - 3 c + 4 d \nonumber\\' + '\n'\ + r'& & - 5 e ' + '\n'\ + r'\end{IEEEeqnarray}' + + assert multiline_latex(f, expr, 2, environment="IEEEeqnarray") == expected2ieee + + raises(ValueError, lambda: multiline_latex(f, expr, environment="foo")) + +def test_issue_15353(): + a, x = symbols('a x') + # Obtained from nonlinsolve([(sin(a*x)),cos(a*x)],[x,a]) + sol = ConditionSet( + Tuple(x, a), Eq(sin(a*x), 0) & Eq(cos(a*x), 0), S.Complexes**2) + assert latex(sol) == \ + r'\left\{\left( x, \ a\right)\; \middle|\; \left( x, \ a\right) \in ' \ + r'\mathbb{C}^{2} \wedge \sin{\left(a x \right)} = 0 \wedge ' \ + r'\cos{\left(a x \right)} = 0 \right\}' + + +def test_latex_symbolic_probability(): + mu = symbols("mu") + sigma = symbols("sigma", positive=True) + X = Normal("X", mu, sigma) + assert latex(Expectation(X)) == r'\operatorname{E}\left[X\right]' + assert latex(Variance(X)) == r'\operatorname{Var}\left(X\right)' + assert latex(Probability(X > 0)) == r'\operatorname{P}\left(X > 0\right)' + Y = Normal("Y", mu, sigma) + assert latex(Covariance(X, Y)) == r'\operatorname{Cov}\left(X, Y\right)' + + +def test_trace(): + # Issue 15303 + from sympy.matrices.expressions.trace import trace + A = MatrixSymbol("A", 2, 2) + assert latex(trace(A)) == r"\operatorname{tr}\left(A \right)" + assert latex(trace(A**2)) == r"\operatorname{tr}\left(A^{2} \right)" + + +def test_print_basic(): + # Issue 15303 + from sympy.core.basic import Basic + from sympy.core.expr import Expr + + # dummy class for testing printing where the function is not + # implemented in latex.py + class UnimplementedExpr(Expr): + def __new__(cls, e): + return Basic.__new__(cls, e) + + # dummy function for testing + def unimplemented_expr(expr): + return UnimplementedExpr(expr).doit() + + # override class name to use superscript / subscript + def unimplemented_expr_sup_sub(expr): + result = UnimplementedExpr(expr) + result.__class__.__name__ = 'UnimplementedExpr_x^1' + return result + + assert latex(unimplemented_expr(x)) == r'\operatorname{UnimplementedExpr}\left(x\right)' + assert latex(unimplemented_expr(x**2)) == \ + r'\operatorname{UnimplementedExpr}\left(x^{2}\right)' + assert latex(unimplemented_expr_sup_sub(x)) == \ + r'\operatorname{UnimplementedExpr^{1}_{x}}\left(x\right)' + + +def test_MatrixSymbol_bold(): + # Issue #15871 + from sympy.matrices.expressions.trace import trace + A = MatrixSymbol("A", 2, 2) + assert latex(trace(A), mat_symbol_style='bold') == \ + r"\operatorname{tr}\left(\mathbf{A} \right)" + assert latex(trace(A), mat_symbol_style='plain') == \ + r"\operatorname{tr}\left(A \right)" + + A = MatrixSymbol("A", 3, 3) + B = MatrixSymbol("B", 3, 3) + C = MatrixSymbol("C", 3, 3) + + assert latex(-A, mat_symbol_style='bold') == r"- \mathbf{A}" + assert latex(A - A*B - B, mat_symbol_style='bold') == \ + r"\mathbf{A} - \mathbf{A} \mathbf{B} - \mathbf{B}" + assert latex(-A*B - A*B*C - B, mat_symbol_style='bold') == \ + r"- \mathbf{A} \mathbf{B} - \mathbf{A} \mathbf{B} \mathbf{C} - \mathbf{B}" + + A_k = MatrixSymbol("A_k", 3, 3) + assert latex(A_k, mat_symbol_style='bold') == r"\mathbf{A}_{k}" + + A = MatrixSymbol(r"\nabla_k", 3, 3) + assert latex(A, mat_symbol_style='bold') == r"\mathbf{\nabla}_{k}" + +def test_AppliedPermutation(): + p = Permutation(0, 1, 2) + x = Symbol('x') + assert latex(AppliedPermutation(p, x)) == \ + r'\sigma_{\left( 0\; 1\; 2\right)}(x)' + + +def test_PermutationMatrix(): + p = Permutation(0, 1, 2) + assert latex(PermutationMatrix(p)) == r'P_{\left( 0\; 1\; 2\right)}' + p = Permutation(0, 3)(1, 2) + assert latex(PermutationMatrix(p)) == \ + r'P_{\left( 0\; 3\right)\left( 1\; 2\right)}' + + +def test_issue_21758(): + from sympy.functions.elementary.piecewise import piecewise_fold + from sympy.series.fourier import FourierSeries + x = Symbol('x') + k, n = symbols('k n') + fo = FourierSeries(x, (x, -pi, pi), (0, SeqFormula(0, (k, 1, oo)), SeqFormula( + Piecewise((-2*pi*cos(n*pi)/n + 2*sin(n*pi)/n**2, (n > -oo) & (n < oo) & Ne(n, 0)), + (0, True))*sin(n*x)/pi, (n, 1, oo)))) + assert latex(piecewise_fold(fo)) == '\\begin{cases} 2 \\sin{\\left(x \\right)}' \ + ' - \\sin{\\left(2 x \\right)} + \\frac{2 \\sin{\\left(3 x \\right)}}{3} +' \ + ' \\ldots & \\text{for}\\: n > -\\infty \\wedge n < \\infty \\wedge ' \ + 'n \\neq 0 \\\\0 & \\text{otherwise} \\end{cases}' + assert latex(FourierSeries(x, (x, -pi, pi), (0, SeqFormula(0, (k, 1, oo)), + SeqFormula(0, (n, 1, oo))))) == '0' + + +def test_imaginary_unit(): + assert latex(1 + I) == r'1 + i' + assert latex(1 + I, imaginary_unit='i') == r'1 + i' + assert latex(1 + I, imaginary_unit='j') == r'1 + j' + assert latex(1 + I, imaginary_unit='foo') == r'1 + foo' + assert latex(I, imaginary_unit="ti") == r'\text{i}' + assert latex(I, imaginary_unit="tj") == r'\text{j}' + + +def test_text_re_im(): + assert latex(im(x), gothic_re_im=True) == r'\Im{\left(x\right)}' + assert latex(im(x), gothic_re_im=False) == r'\operatorname{im}{\left(x\right)}' + assert latex(re(x), gothic_re_im=True) == r'\Re{\left(x\right)}' + assert latex(re(x), gothic_re_im=False) == r'\operatorname{re}{\left(x\right)}' + + +def test_latex_diffgeom(): + from sympy.diffgeom import Manifold, Patch, CoordSystem, BaseScalarField, Differential + from sympy.diffgeom.rn import R2 + x,y = symbols('x y', real=True) + m = Manifold('M', 2) + assert latex(m) == r'\text{M}' + p = Patch('P', m) + assert latex(p) == r'\text{P}_{\text{M}}' + rect = CoordSystem('rect', p, [x, y]) + assert latex(rect) == r'\text{rect}^{\text{P}}_{\text{M}}' + b = BaseScalarField(rect, 0) + assert latex(b) == r'\mathbf{x}' + + g = Function('g') + s_field = g(R2.x, R2.y) + assert latex(Differential(s_field)) == \ + r'\operatorname{d}\left(g{\left(\mathbf{x},\mathbf{y} \right)}\right)' + + +def test_unit_printing(): + assert latex(5*meter) == r'5 \text{m}' + assert latex(3*gibibyte) == r'3 \text{gibibyte}' + assert latex(4*microgram/second) == r'\frac{4 \mu\text{g}}{\text{s}}' + assert latex(4*micro*gram/second) == r'\frac{4 \mu \text{g}}{\text{s}}' + assert latex(5*milli*meter) == r'5 \text{m} \text{m}' + assert latex(milli) == r'\text{m}' + + +def test_issue_17092(): + x_star = Symbol('x^*') + assert latex(Derivative(x_star, x_star,2)) == r'\frac{d^{2}}{d \left(x^{*}\right)^{2}} x^{*}' + + +def test_latex_decimal_separator(): + + x, y, z, t = symbols('x y z t') + k, m, n = symbols('k m n', integer=True) + f, g, h = symbols('f g h', cls=Function) + + # comma decimal_separator + assert(latex([1, 2.3, 4.5], decimal_separator='comma') == r'\left[ 1; \ 2{,}3; \ 4{,}5\right]') + assert(latex(FiniteSet(1, 2.3, 4.5), decimal_separator='comma') == r'\left\{1; 2{,}3; 4{,}5\right\}') + assert(latex((1, 2.3, 4.6), decimal_separator = 'comma') == r'\left( 1; \ 2{,}3; \ 4{,}6\right)') + assert(latex((1,), decimal_separator='comma') == r'\left( 1;\right)') + + # period decimal_separator + assert(latex([1, 2.3, 4.5], decimal_separator='period') == r'\left[ 1, \ 2.3, \ 4.5\right]' ) + assert(latex(FiniteSet(1, 2.3, 4.5), decimal_separator='period') == r'\left\{1, 2.3, 4.5\right\}') + assert(latex((1, 2.3, 4.6), decimal_separator = 'period') == r'\left( 1, \ 2.3, \ 4.6\right)') + assert(latex((1,), decimal_separator='period') == r'\left( 1,\right)') + + # default decimal_separator + assert(latex([1, 2.3, 4.5]) == r'\left[ 1, \ 2.3, \ 4.5\right]') + assert(latex(FiniteSet(1, 2.3, 4.5)) == r'\left\{1, 2.3, 4.5\right\}') + assert(latex((1, 2.3, 4.6)) == r'\left( 1, \ 2.3, \ 4.6\right)') + assert(latex((1,)) == r'\left( 1,\right)') + + assert(latex(Mul(3.4,5.3), decimal_separator = 'comma') == r'18{,}02') + assert(latex(3.4*5.3, decimal_separator = 'comma') == r'18{,}02') + x = symbols('x') + y = symbols('y') + z = symbols('z') + assert(latex(x*5.3 + 2**y**3.4 + 4.5 + z, decimal_separator = 'comma') == r'2^{y^{3{,}4}} + 5{,}3 x + z + 4{,}5') + + assert(latex(0.987, decimal_separator='comma') == r'0{,}987') + assert(latex(S(0.987), decimal_separator='comma') == r'0{,}987') + assert(latex(.3, decimal_separator='comma') == r'0{,}3') + assert(latex(S(.3), decimal_separator='comma') == r'0{,}3') + + + assert(latex(5.8*10**(-7), decimal_separator='comma') == r'5{,}8 \cdot 10^{-7}') + assert(latex(S(5.7)*10**(-7), decimal_separator='comma') == r'5{,}7 \cdot 10^{-7}') + assert(latex(S(5.7*10**(-7)), decimal_separator='comma') == r'5{,}7 \cdot 10^{-7}') + + x = symbols('x') + assert(latex(1.2*x+3.4, decimal_separator='comma') == r'1{,}2 x + 3{,}4') + assert(latex(FiniteSet(1, 2.3, 4.5), decimal_separator='period') == r'\left\{1, 2.3, 4.5\right\}') + + # Error Handling tests + raises(ValueError, lambda: latex([1,2.3,4.5], decimal_separator='non_existing_decimal_separator_in_list')) + raises(ValueError, lambda: latex(FiniteSet(1,2.3,4.5), decimal_separator='non_existing_decimal_separator_in_set')) + raises(ValueError, lambda: latex((1,2.3,4.5), decimal_separator='non_existing_decimal_separator_in_tuple')) + +def test_Str(): + from sympy.core.symbol import Str + assert str(Str('x')) == r'x' + +def test_latex_escape(): + assert latex_escape(r"~^\&%$#_{}") == "".join([ + r'\textasciitilde', + r'\textasciicircum', + r'\textbackslash', + r'\&', + r'\%', + r'\$', + r'\#', + r'\_', + r'\{', + r'\}', + ]) + +def test_emptyPrinter(): + class MyObject: + def __repr__(self): + return "" + + # unknown objects are monospaced + assert latex(MyObject()) == r"\mathtt{\text{}}" + + # even if they are nested within other objects + assert latex((MyObject(),)) == r"\left( \mathtt{\text{}},\right)" + +def test_global_settings(): + import inspect + + # settings should be visible in the signature of `latex` + assert inspect.signature(latex).parameters['imaginary_unit'].default == r'i' + assert latex(I) == r'i' + try: + # but changing the defaults... + LatexPrinter.set_global_settings(imaginary_unit='j') + # ... should change the signature + assert inspect.signature(latex).parameters['imaginary_unit'].default == r'j' + assert latex(I) == r'j' + finally: + # there's no public API to undo this, but we need to make sure we do + # so as not to impact other tests + del LatexPrinter._global_settings['imaginary_unit'] + + # check we really did undo it + assert inspect.signature(latex).parameters['imaginary_unit'].default == r'i' + assert latex(I) == r'i' + +def test_pickleable(): + # this tests that the _PrintFunction instance is pickleable + import pickle + assert pickle.loads(pickle.dumps(latex)) is latex + +def test_printing_latex_array_expressions(): + assert latex(ArraySymbol("A", (2, 3, 4))) == "A" + assert latex(ArrayElement("A", (2, 1/(1-x), 0))) == "{{A}_{2, \\frac{1}{1 - x}, 0}}" + M = MatrixSymbol("M", 3, 3) + N = MatrixSymbol("N", 3, 3) + assert latex(ArrayElement(M*N, [x, 0])) == "{{\\left(M N\\right)}_{x, 0}}" + +def test_Array(): + arr = Array(range(10)) + assert latex(arr) == r'\left[\begin{matrix}0 & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9\end{matrix}\right]' + + arr = Array(range(11)) + # fill the empty argument with a bunch of 'c' to avoid latex errors + assert latex(arr) == r'\left[\begin{array}{ccccccccccc}0 & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10\end{array}\right]' + +def test_latex_with_unevaluated(): + with evaluate(False): + assert latex(a * a) == r"a a" + + +def test_latex_disable_split_super_sub(): + assert latex(Symbol('u^a_b')) == 'u^{a}_{b}' + assert latex(Symbol('u^a_b'), disable_split_super_sub=False) == 'u^{a}_{b}' + assert latex(Symbol('u^a_b'), disable_split_super_sub=True) == 'u\\^a\\_b' diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_llvmjit.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_llvmjit.py new file mode 100644 index 0000000000000000000000000000000000000000..709476f1d7517dc629210341594a70dc6f41808f --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_llvmjit.py @@ -0,0 +1,224 @@ +from sympy.external import import_module +from sympy.testing.pytest import raises +import ctypes + + +if import_module('llvmlite'): + import sympy.printing.llvmjitcode as g +else: + disabled = True + +import sympy +from sympy.abc import a, b, n + + +# copied from numpy.isclose documentation +def isclose(a, b): + rtol = 1e-5 + atol = 1e-8 + return abs(a-b) <= atol + rtol*abs(b) + + +def test_simple_expr(): + e = a + 1.0 + f = g.llvm_callable([a], e) + res = float(e.subs({a: 4.0}).evalf()) + jit_res = f(4.0) + + assert isclose(jit_res, res) + + +def test_two_arg(): + e = 4.0*a + b + 3.0 + f = g.llvm_callable([a, b], e) + res = float(e.subs({a: 4.0, b: 3.0}).evalf()) + jit_res = f(4.0, 3.0) + + assert isclose(jit_res, res) + + +def test_func(): + e = 4.0*sympy.exp(-a) + f = g.llvm_callable([a], e) + res = float(e.subs({a: 1.5}).evalf()) + jit_res = f(1.5) + + assert isclose(jit_res, res) + + +def test_two_func(): + e = 4.0*sympy.exp(-a) + sympy.exp(b) + f = g.llvm_callable([a, b], e) + res = float(e.subs({a: 1.5, b: 2.0}).evalf()) + jit_res = f(1.5, 2.0) + + assert isclose(jit_res, res) + + +def test_two_sqrt(): + e = 4.0*sympy.sqrt(a) + sympy.sqrt(b) + f = g.llvm_callable([a, b], e) + res = float(e.subs({a: 1.5, b: 2.0}).evalf()) + jit_res = f(1.5, 2.0) + + assert isclose(jit_res, res) + + +def test_two_pow(): + e = a**1.5 + b**7 + f = g.llvm_callable([a, b], e) + res = float(e.subs({a: 1.5, b: 2.0}).evalf()) + jit_res = f(1.5, 2.0) + + assert isclose(jit_res, res) + + +def test_callback(): + e = a + 1.2 + f = g.llvm_callable([a], e, callback_type='scipy.integrate.test') + m = ctypes.c_int(1) + array_type = ctypes.c_double * 1 + inp = {a: 2.2} + array = array_type(inp[a]) + jit_res = f(m, array) + + res = float(e.subs(inp).evalf()) + + assert isclose(jit_res, res) + + +def test_callback_cubature(): + e = a + 1.2 + f = g.llvm_callable([a], e, callback_type='cubature') + m = ctypes.c_int(1) + array_type = ctypes.c_double * 1 + inp = {a: 2.2} + array = array_type(inp[a]) + out_array = array_type(0.0) + jit_ret = f(m, array, None, m, out_array) + + assert jit_ret == 0 + + res = float(e.subs(inp).evalf()) + + assert isclose(out_array[0], res) + + +def test_callback_two(): + e = 3*a*b + f = g.llvm_callable([a, b], e, callback_type='scipy.integrate.test') + m = ctypes.c_int(2) + array_type = ctypes.c_double * 2 + inp = {a: 0.2, b: 1.7} + array = array_type(inp[a], inp[b]) + jit_res = f(m, array) + + res = float(e.subs(inp).evalf()) + + assert isclose(jit_res, res) + + +def test_callback_alt_two(): + d = sympy.IndexedBase('d') + e = 3*d[0]*d[1] + f = g.llvm_callable([n, d], e, callback_type='scipy.integrate.test') + m = ctypes.c_int(2) + array_type = ctypes.c_double * 2 + inp = {d[0]: 0.2, d[1]: 1.7} + array = array_type(inp[d[0]], inp[d[1]]) + jit_res = f(m, array) + + res = float(e.subs(inp).evalf()) + + assert isclose(jit_res, res) + + +def test_multiple_statements(): + # Match return from CSE + e = [[(b, 4.0*a)], [b + 5]] + f = g.llvm_callable([a], e) + b_val = e[0][0][1].subs({a: 1.5}) + res = float(e[1][0].subs({b: b_val}).evalf()) + jit_res = f(1.5) + assert isclose(jit_res, res) + + f_callback = g.llvm_callable([a], e, callback_type='scipy.integrate.test') + m = ctypes.c_int(1) + array_type = ctypes.c_double * 1 + array = array_type(1.5) + jit_callback_res = f_callback(m, array) + assert isclose(jit_callback_res, res) + + +def test_cse(): + e = a*a + b*b + sympy.exp(-a*a - b*b) + e2 = sympy.cse(e) + f = g.llvm_callable([a, b], e2) + res = float(e.subs({a: 2.3, b: 0.1}).evalf()) + jit_res = f(2.3, 0.1) + + assert isclose(jit_res, res) + + +def eval_cse(e, sub_dict): + tmp_dict = {} + for tmp_name, tmp_expr in e[0]: + e2 = tmp_expr.subs(sub_dict) + e3 = e2.subs(tmp_dict) + tmp_dict[tmp_name] = e3 + return [e.subs(sub_dict).subs(tmp_dict) for e in e[1]] + + +def test_cse_multiple(): + e1 = a*a + e2 = a*a + b*b + e3 = sympy.cse([e1, e2]) + + raises(NotImplementedError, + lambda: g.llvm_callable([a, b], e3, callback_type='scipy.integrate')) + + f = g.llvm_callable([a, b], e3) + jit_res = f(0.1, 1.5) + assert len(jit_res) == 2 + res = eval_cse(e3, {a: 0.1, b: 1.5}) + assert isclose(res[0], jit_res[0]) + assert isclose(res[1], jit_res[1]) + + +def test_callback_cubature_multiple(): + e1 = a*a + e2 = a*a + b*b + e3 = sympy.cse([e1, e2, 4*e2]) + f = g.llvm_callable([a, b], e3, callback_type='cubature') + + # Number of input variables + ndim = 2 + # Number of output expression values + outdim = 3 + + m = ctypes.c_int(ndim) + fdim = ctypes.c_int(outdim) + array_type = ctypes.c_double * ndim + out_array_type = ctypes.c_double * outdim + inp = {a: 0.2, b: 1.5} + array = array_type(inp[a], inp[b]) + out_array = out_array_type() + jit_ret = f(m, array, None, fdim, out_array) + + assert jit_ret == 0 + + res = eval_cse(e3, inp) + + assert isclose(out_array[0], res[0]) + assert isclose(out_array[1], res[1]) + assert isclose(out_array[2], res[2]) + + +def test_symbol_not_found(): + e = a*a + b + raises(LookupError, lambda: g.llvm_callable([a], e)) + + +def test_bad_callback(): + e = a + raises(ValueError, lambda: g.llvm_callable([a], e, callback_type='bad_callback')) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_maple.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_maple.py new file mode 100644 index 0000000000000000000000000000000000000000..9bb4c512ad3203bd64ae56b350e15734b3a6afb0 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_maple.py @@ -0,0 +1,381 @@ +from sympy.core import (S, pi, oo, symbols, Function, Rational, Integer, + Tuple, Symbol, Eq, Ne, Le, Lt, Gt, Ge) +from sympy.core import EulerGamma, GoldenRatio, Catalan, Lambda, Mul, Pow +from sympy.functions import Piecewise, sqrt, ceiling, exp, sin, cos, sinc, lucas +from sympy.testing.pytest import raises +from sympy.utilities.lambdify import implemented_function +from sympy.matrices import (eye, Matrix, MatrixSymbol, Identity, + HadamardProduct, SparseMatrix) +from sympy.functions.special.bessel import besseli + +from sympy.printing.maple import maple_code + +x, y, z = symbols('x,y,z') + + +def test_Integer(): + assert maple_code(Integer(67)) == "67" + assert maple_code(Integer(-1)) == "-1" + + +def test_Rational(): + assert maple_code(Rational(3, 7)) == "3/7" + assert maple_code(Rational(18, 9)) == "2" + assert maple_code(Rational(3, -7)) == "-3/7" + assert maple_code(Rational(-3, -7)) == "3/7" + assert maple_code(x + Rational(3, 7)) == "x + 3/7" + assert maple_code(Rational(3, 7) * x) == '(3/7)*x' + + +def test_Relational(): + assert maple_code(Eq(x, y)) == "x = y" + assert maple_code(Ne(x, y)) == "x <> y" + assert maple_code(Le(x, y)) == "x <= y" + assert maple_code(Lt(x, y)) == "x < y" + assert maple_code(Gt(x, y)) == "x > y" + assert maple_code(Ge(x, y)) == "x >= y" + + +def test_Function(): + assert maple_code(sin(x) ** cos(x)) == "sin(x)^cos(x)" + assert maple_code(abs(x)) == "abs(x)" + assert maple_code(ceiling(x)) == "ceil(x)" + + +def test_Pow(): + assert maple_code(x ** 3) == "x^3" + assert maple_code(x ** (y ** 3)) == "x^(y^3)" + + assert maple_code((x ** 3) ** y) == "(x^3)^y" + assert maple_code(x ** Rational(2, 3)) == 'x^(2/3)' + + g = implemented_function('g', Lambda(x, 2 * x)) + assert maple_code(1 / (g(x) * 3.5) ** (x - y ** x) / (x ** 2 + y)) == \ + "(3.5*2*x)^(-x + y^x)/(x^2 + y)" + # For issue 14160 + assert maple_code(Mul(-2, x, Pow(Mul(y, y, evaluate=False), -1, evaluate=False), + evaluate=False)) == '-2*x/(y*y)' + + +def test_basic_ops(): + assert maple_code(x * y) == "x*y" + assert maple_code(x + y) == "x + y" + assert maple_code(x - y) == "x - y" + assert maple_code(-x) == "-x" + + +def test_1_over_x_and_sqrt(): + # 1.0 and 0.5 would do something different in regular StrPrinter, + # but these are exact in IEEE floating point so no different here. + assert maple_code(1 / x) == '1/x' + assert maple_code(x ** -1) == maple_code(x ** -1.0) == '1/x' + assert maple_code(1 / sqrt(x)) == '1/sqrt(x)' + assert maple_code(x ** -S.Half) == maple_code(x ** -0.5) == '1/sqrt(x)' + assert maple_code(sqrt(x)) == 'sqrt(x)' + assert maple_code(x ** S.Half) == maple_code(x ** 0.5) == 'sqrt(x)' + assert maple_code(1 / pi) == '1/Pi' + assert maple_code(pi ** -1) == maple_code(pi ** -1.0) == '1/Pi' + assert maple_code(pi ** -0.5) == '1/sqrt(Pi)' + + +def test_mix_number_mult_symbols(): + assert maple_code(3 * x) == "3*x" + assert maple_code(pi * x) == "Pi*x" + assert maple_code(3 / x) == "3/x" + assert maple_code(pi / x) == "Pi/x" + assert maple_code(x / 3) == '(1/3)*x' + assert maple_code(x / pi) == "x/Pi" + assert maple_code(x * y) == "x*y" + assert maple_code(3 * x * y) == "3*x*y" + assert maple_code(3 * pi * x * y) == "3*Pi*x*y" + assert maple_code(x / y) == "x/y" + assert maple_code(3 * x / y) == "3*x/y" + assert maple_code(x * y / z) == "x*y/z" + assert maple_code(x / y * z) == "x*z/y" + assert maple_code(1 / x / y) == "1/(x*y)" + assert maple_code(2 * pi * x / y / z) == "2*Pi*x/(y*z)" + assert maple_code(3 * pi / x) == "3*Pi/x" + assert maple_code(S(3) / 5) == "3/5" + assert maple_code(S(3) / 5 * x) == '(3/5)*x' + assert maple_code(x / y / z) == "x/(y*z)" + assert maple_code((x + y) / z) == "(x + y)/z" + assert maple_code((x + y) / (z + x)) == "(x + y)/(x + z)" + assert maple_code((x + y) / EulerGamma) == '(x + y)/gamma' + assert maple_code(x / 3 / pi) == '(1/3)*x/Pi' + assert maple_code(S(3) / 5 * x * y / pi) == '(3/5)*x*y/Pi' + + +def test_mix_number_pow_symbols(): + assert maple_code(pi ** 3) == 'Pi^3' + assert maple_code(x ** 2) == 'x^2' + + assert maple_code(x ** (pi ** 3)) == 'x^(Pi^3)' + assert maple_code(x ** y) == 'x^y' + + assert maple_code(x ** (y ** z)) == 'x^(y^z)' + assert maple_code((x ** y) ** z) == '(x^y)^z' + + +def test_imag(): + I = S('I') + assert maple_code(I) == "I" + assert maple_code(5 * I) == "5*I" + + assert maple_code((S(3) / 2) * I) == "(3/2)*I" + assert maple_code(3 + 4 * I) == "3 + 4*I" + + +def test_constants(): + assert maple_code(pi) == "Pi" + assert maple_code(oo) == "infinity" + assert maple_code(-oo) == "-infinity" + assert maple_code(S.NegativeInfinity) == "-infinity" + assert maple_code(S.NaN) == "undefined" + assert maple_code(S.Exp1) == "exp(1)" + assert maple_code(exp(1)) == "exp(1)" + + +def test_constants_other(): + assert maple_code(2 * GoldenRatio) == '2*(1/2 + (1/2)*sqrt(5))' + assert maple_code(2 * Catalan) == '2*Catalan' + assert maple_code(2 * EulerGamma) == "2*gamma" + + +def test_boolean(): + assert maple_code(x & y) == "x and y" + assert maple_code(x | y) == "x or y" + assert maple_code(~x) == "not x" + assert maple_code(x & y & z) == "x and y and z" + assert maple_code(x | y | z) == "x or y or z" + assert maple_code((x & y) | z) == "z or x and y" + assert maple_code((x | y) & z) == "z and (x or y)" + + +def test_Matrices(): + assert maple_code(Matrix(1, 1, [10])) == \ + 'Matrix([[10]], storage = rectangular)' + + A = Matrix([[1, sin(x / 2), abs(x)], + [0, 1, pi], + [0, exp(1), ceiling(x)]]) + expected = \ + 'Matrix(' \ + '[[1, sin((1/2)*x), abs(x)],' \ + ' [0, 1, Pi],' \ + ' [0, exp(1), ceil(x)]], ' \ + 'storage = rectangular)' + assert maple_code(A) == expected + + # row and columns + assert maple_code(A[:, 0]) == \ + 'Matrix([[1], [0], [0]], storage = rectangular)' + assert maple_code(A[0, :]) == \ + 'Matrix([[1, sin((1/2)*x), abs(x)]], storage = rectangular)' + assert maple_code(Matrix([[x, x - y, -y]])) == \ + 'Matrix([[x, x - y, -y]], storage = rectangular)' + + # empty matrices + assert maple_code(Matrix(0, 0, [])) == \ + 'Matrix([], storage = rectangular)' + assert maple_code(Matrix(0, 3, [])) == \ + 'Matrix([], storage = rectangular)' + +def test_SparseMatrices(): + assert maple_code(SparseMatrix(Identity(2))) == 'Matrix([[1, 0], [0, 1]], storage = sparse)' + + +def test_vector_entries_hadamard(): + # For a row or column, user might to use the other dimension + A = Matrix([[1, sin(2 / x), 3 * pi / x / 5]]) + assert maple_code(A) == \ + 'Matrix([[1, sin(2/x), (3/5)*Pi/x]], storage = rectangular)' + assert maple_code(A.T) == \ + 'Matrix([[1], [sin(2/x)], [(3/5)*Pi/x]], storage = rectangular)' + + +def test_Matrices_entries_not_hadamard(): + A = Matrix([[1, sin(2 / x), 3 * pi / x / 5], [1, 2, x * y]]) + expected = \ + 'Matrix([[1, sin(2/x), (3/5)*Pi/x], [1, 2, x*y]], ' \ + 'storage = rectangular)' + assert maple_code(A) == expected + + +def test_MatrixSymbol(): + n = Symbol('n', integer=True) + A = MatrixSymbol('A', n, n) + B = MatrixSymbol('B', n, n) + assert maple_code(A * B) == "A.B" + assert maple_code(B * A) == "B.A" + assert maple_code(2 * A * B) == "2*A.B" + assert maple_code(B * 2 * A) == "2*B.A" + + assert maple_code( + A * (B + 3 * Identity(n))) == "A.(3*Matrix(n, shape = identity) + B)" + + assert maple_code(A ** (x ** 2)) == "MatrixPower(A, x^2)" + assert maple_code(A ** 3) == "MatrixPower(A, 3)" + assert maple_code(A ** (S.Half)) == "MatrixPower(A, 1/2)" + + +def test_special_matrices(): + assert maple_code(6 * Identity(3)) == "6*Matrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]], storage = sparse)" + assert maple_code(Identity(x)) == 'Matrix(x, shape = identity)' + + +def test_containers(): + assert maple_code([1, 2, 3, [4, 5, [6, 7]], 8, [9, 10], 11]) == \ + "[1, 2, 3, [4, 5, [6, 7]], 8, [9, 10], 11]" + + assert maple_code((1, 2, (3, 4))) == "[1, 2, [3, 4]]" + assert maple_code([1]) == "[1]" + assert maple_code((1,)) == "[1]" + assert maple_code(Tuple(*[1, 2, 3])) == "[1, 2, 3]" + assert maple_code((1, x * y, (3, x ** 2))) == "[1, x*y, [3, x^2]]" + # scalar, matrix, empty matrix and empty list + + assert maple_code((1, eye(3), Matrix(0, 0, []), [])) == \ + "[1, Matrix([[1, 0, 0], [0, 1, 0], [0, 0, 1]], storage = rectangular), Matrix([], storage = rectangular), []]" + + +def test_maple_noninline(): + source = maple_code((x + y)/Catalan, assign_to='me', inline=False) + expected = "me := (x + y)/Catalan" + + assert source == expected + + +def test_maple_matrix_assign_to(): + A = Matrix([[1, 2, 3]]) + assert maple_code(A, assign_to='a') == "a := Matrix([[1, 2, 3]], storage = rectangular)" + A = Matrix([[1, 2], [3, 4]]) + assert maple_code(A, assign_to='A') == "A := Matrix([[1, 2], [3, 4]], storage = rectangular)" + + +def test_maple_matrix_assign_to_more(): + # assigning to Symbol or MatrixSymbol requires lhs/rhs match + A = Matrix([[1, 2, 3]]) + B = MatrixSymbol('B', 1, 3) + C = MatrixSymbol('C', 2, 3) + assert maple_code(A, assign_to=B) == "B := Matrix([[1, 2, 3]], storage = rectangular)" + raises(ValueError, lambda: maple_code(A, assign_to=x)) + raises(ValueError, lambda: maple_code(A, assign_to=C)) + + +def test_maple_matrix_1x1(): + A = Matrix([[3]]) + assert maple_code(A, assign_to='B') == "B := Matrix([[3]], storage = rectangular)" + + +def test_maple_matrix_elements(): + A = Matrix([[x, 2, x * y]]) + + assert maple_code(A[0, 0] ** 2 + A[0, 1] + A[0, 2]) == "x^2 + x*y + 2" + AA = MatrixSymbol('AA', 1, 3) + assert maple_code(AA) == "AA" + + assert maple_code(AA[0, 0] ** 2 + sin(AA[0, 1]) + AA[0, 2]) == \ + "sin(AA[1, 2]) + AA[1, 1]^2 + AA[1, 3]" + assert maple_code(sum(AA)) == "AA[1, 1] + AA[1, 2] + AA[1, 3]" + + +def test_maple_boolean(): + assert maple_code(True) == "true" + assert maple_code(S.true) == "true" + assert maple_code(False) == "false" + assert maple_code(S.false) == "false" + + +def test_sparse(): + M = SparseMatrix(5, 6, {}) + M[2, 2] = 10 + M[1, 2] = 20 + M[1, 3] = 22 + M[0, 3] = 30 + M[3, 0] = x * y + assert maple_code(M) == \ + 'Matrix([[0, 0, 0, 30, 0, 0],' \ + ' [0, 0, 20, 22, 0, 0],' \ + ' [0, 0, 10, 0, 0, 0],' \ + ' [x*y, 0, 0, 0, 0, 0],' \ + ' [0, 0, 0, 0, 0, 0]], ' \ + 'storage = sparse)' + +# Not an important point. +def test_maple_not_supported(): + with raises(NotImplementedError): + maple_code(S.ComplexInfinity) + + +def test_MatrixElement_printing(): + # test cases for issue #11821 + A = MatrixSymbol("A", 1, 3) + B = MatrixSymbol("B", 1, 3) + + assert (maple_code(A[0, 0]) == "A[1, 1]") + assert (maple_code(3 * A[0, 0]) == "3*A[1, 1]") + + F = A-B + + assert (maple_code(F[0,0]) == "A[1, 1] - B[1, 1]") + + +def test_hadamard(): + A = MatrixSymbol('A', 3, 3) + B = MatrixSymbol('B', 3, 3) + v = MatrixSymbol('v', 3, 1) + h = MatrixSymbol('h', 1, 3) + C = HadamardProduct(A, B) + assert maple_code(C) == "A*B" + + assert maple_code(C * v) == "(A*B).v" + # HadamardProduct is higher than dot product. + + assert maple_code(h * C * v) == "h.(A*B).v" + + assert maple_code(C * A) == "(A*B).A" + # mixing Hadamard and scalar strange b/c we vectorize scalars + + assert maple_code(C * x * y) == "x*y*(A*B)" + + +def test_maple_piecewise(): + expr = Piecewise((x, x < 1), (x ** 2, True)) + + assert maple_code(expr) == "piecewise(x < 1, x, x^2)" + assert maple_code(expr, assign_to="r") == ( + "r := piecewise(x < 1, x, x^2)") + + expr = Piecewise((x ** 2, x < 1), (x ** 3, x < 2), (x ** 4, x < 3), (x ** 5, True)) + expected = "piecewise(x < 1, x^2, x < 2, x^3, x < 3, x^4, x^5)" + assert maple_code(expr) == expected + assert maple_code(expr, assign_to="r") == "r := " + expected + + # Check that Piecewise without a True (default) condition error + expr = Piecewise((x, x < 1), (x ** 2, x > 1), (sin(x), x > 0)) + raises(ValueError, lambda: maple_code(expr)) + + +def test_maple_piecewise_times_const(): + pw = Piecewise((x, x < 1), (x ** 2, True)) + + assert maple_code(2 * pw) == "2*piecewise(x < 1, x, x^2)" + assert maple_code(pw / x) == "piecewise(x < 1, x, x^2)/x" + assert maple_code(pw / (x * y)) == "piecewise(x < 1, x, x^2)/(x*y)" + assert maple_code(pw / 3) == "(1/3)*piecewise(x < 1, x, x^2)" + + +def test_maple_derivatives(): + f = Function('f') + assert maple_code(f(x).diff(x)) == 'diff(f(x), x)' + assert maple_code(f(x).diff(x, 2)) == 'diff(f(x), x$2)' + + +def test_automatic_rewrites(): + assert maple_code(lucas(x)) == '(2^(-x)*((1 - sqrt(5))^x + (1 + sqrt(5))^x))' + assert maple_code(sinc(x)) == '(piecewise(x <> 0, sin(x)/x, 1))' + + +def test_specfun(): + assert maple_code('asin(x)') == 'arcsin(x)' + assert maple_code(besseli(x, y)) == 'BesselI(x, y)' diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_mathematica.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_mathematica.py new file mode 100644 index 0000000000000000000000000000000000000000..aaf6b537677442ae59a4f1bbd2b5774d6646f4e2 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_mathematica.py @@ -0,0 +1,287 @@ +from sympy.core import (S, pi, oo, symbols, Function, Rational, Integer, Tuple, + Derivative, Eq, Ne, Le, Lt, Gt, Ge) +from sympy.integrals import Integral +from sympy.concrete import Sum +from sympy.functions import (exp, sin, cos, fresnelc, fresnels, conjugate, Max, + Min, gamma, polygamma, loggamma, erf, erfi, erfc, + erf2, expint, erfinv, erfcinv, Ei, Si, Ci, li, + Shi, Chi, uppergamma, beta, subfactorial, erf2inv, + factorial, factorial2, catalan, RisingFactorial, + FallingFactorial, harmonic, atan2, sec, acsc, + hermite, laguerre, assoc_laguerre, jacobi, + gegenbauer, chebyshevt, chebyshevu, legendre, + assoc_legendre, Li, LambertW) + +from sympy.printing.mathematica import mathematica_code as mcode + +x, y, z, w = symbols('x,y,z,w') +f = Function('f') + + +def test_Integer(): + assert mcode(Integer(67)) == "67" + assert mcode(Integer(-1)) == "-1" + + +def test_Rational(): + assert mcode(Rational(3, 7)) == "3/7" + assert mcode(Rational(18, 9)) == "2" + assert mcode(Rational(3, -7)) == "-3/7" + assert mcode(Rational(-3, -7)) == "3/7" + assert mcode(x + Rational(3, 7)) == "x + 3/7" + assert mcode(Rational(3, 7)*x) == "(3/7)*x" + + +def test_Relational(): + assert mcode(Eq(x, y)) == "x == y" + assert mcode(Ne(x, y)) == "x != y" + assert mcode(Le(x, y)) == "x <= y" + assert mcode(Lt(x, y)) == "x < y" + assert mcode(Gt(x, y)) == "x > y" + assert mcode(Ge(x, y)) == "x >= y" + + +def test_Function(): + assert mcode(f(x, y, z)) == "f[x, y, z]" + assert mcode(sin(x) ** cos(x)) == "Sin[x]^Cos[x]" + assert mcode(sec(x) * acsc(x)) == "ArcCsc[x]*Sec[x]" + assert mcode(atan2(y, x)) == "ArcTan[x, y]" + assert mcode(conjugate(x)) == "Conjugate[x]" + assert mcode(Max(x, y, z)*Min(y, z)) == "Max[x, y, z]*Min[y, z]" + assert mcode(fresnelc(x)) == "FresnelC[x]" + assert mcode(fresnels(x)) == "FresnelS[x]" + assert mcode(gamma(x)) == "Gamma[x]" + assert mcode(uppergamma(x, y)) == "Gamma[x, y]" + assert mcode(polygamma(x, y)) == "PolyGamma[x, y]" + assert mcode(loggamma(x)) == "LogGamma[x]" + assert mcode(erf(x)) == "Erf[x]" + assert mcode(erfc(x)) == "Erfc[x]" + assert mcode(erfi(x)) == "Erfi[x]" + assert mcode(erf2(x, y)) == "Erf[x, y]" + assert mcode(expint(x, y)) == "ExpIntegralE[x, y]" + assert mcode(erfcinv(x)) == "InverseErfc[x]" + assert mcode(erfinv(x)) == "InverseErf[x]" + assert mcode(erf2inv(x, y)) == "InverseErf[x, y]" + assert mcode(Ei(x)) == "ExpIntegralEi[x]" + assert mcode(Ci(x)) == "CosIntegral[x]" + assert mcode(li(x)) == "LogIntegral[x]" + assert mcode(Si(x)) == "SinIntegral[x]" + assert mcode(Shi(x)) == "SinhIntegral[x]" + assert mcode(Chi(x)) == "CoshIntegral[x]" + assert mcode(beta(x, y)) == "Beta[x, y]" + assert mcode(factorial(x)) == "Factorial[x]" + assert mcode(factorial2(x)) == "Factorial2[x]" + assert mcode(subfactorial(x)) == "Subfactorial[x]" + assert mcode(FallingFactorial(x, y)) == "FactorialPower[x, y]" + assert mcode(RisingFactorial(x, y)) == "Pochhammer[x, y]" + assert mcode(catalan(x)) == "CatalanNumber[x]" + assert mcode(harmonic(x)) == "HarmonicNumber[x]" + assert mcode(harmonic(x, y)) == "HarmonicNumber[x, y]" + assert mcode(Li(x)) == "LogIntegral[x] - LogIntegral[2]" + assert mcode(LambertW(x)) == "ProductLog[x]" + assert mcode(LambertW(x, -1)) == "ProductLog[-1, x]" + assert mcode(LambertW(x, y)) == "ProductLog[y, x]" + + +def test_special_polynomials(): + assert mcode(hermite(x, y)) == "HermiteH[x, y]" + assert mcode(laguerre(x, y)) == "LaguerreL[x, y]" + assert mcode(assoc_laguerre(x, y, z)) == "LaguerreL[x, y, z]" + assert mcode(jacobi(x, y, z, w)) == "JacobiP[x, y, z, w]" + assert mcode(gegenbauer(x, y, z)) == "GegenbauerC[x, y, z]" + assert mcode(chebyshevt(x, y)) == "ChebyshevT[x, y]" + assert mcode(chebyshevu(x, y)) == "ChebyshevU[x, y]" + assert mcode(legendre(x, y)) == "LegendreP[x, y]" + assert mcode(assoc_legendre(x, y, z)) == "LegendreP[x, y, z]" + + +def test_Pow(): + assert mcode(x**3) == "x^3" + assert mcode(x**(y**3)) == "x^(y^3)" + assert mcode(1/(f(x)*3.5)**(x - y**x)/(x**2 + y)) == \ + "(3.5*f[x])^(-x + y^x)/(x^2 + y)" + assert mcode(x**-1.0) == 'x^(-1.0)' + assert mcode(x**Rational(2, 3)) == 'x^(2/3)' + + +def test_Mul(): + A, B, C, D = symbols('A B C D', commutative=False) + assert mcode(x*y*z) == "x*y*z" + assert mcode(x*y*A) == "x*y*A" + assert mcode(x*y*A*B) == "x*y*A**B" + assert mcode(x*y*A*B*C) == "x*y*A**B**C" + assert mcode(x*A*B*(C + D)*A*y) == "x*y*A**B**(C + D)**A" + + +def test_constants(): + assert mcode(S.Zero) == "0" + assert mcode(S.One) == "1" + assert mcode(S.NegativeOne) == "-1" + assert mcode(S.Half) == "1/2" + assert mcode(S.ImaginaryUnit) == "I" + + assert mcode(oo) == "Infinity" + assert mcode(S.NegativeInfinity) == "-Infinity" + assert mcode(S.ComplexInfinity) == "ComplexInfinity" + assert mcode(S.NaN) == "Indeterminate" + + assert mcode(S.Exp1) == "E" + assert mcode(pi) == "Pi" + assert mcode(S.GoldenRatio) == "GoldenRatio" + assert mcode(S.TribonacciConstant) == \ + "(1/3 + (1/3)*(19 - 3*33^(1/2))^(1/3) + " \ + "(1/3)*(3*33^(1/2) + 19)^(1/3))" + assert mcode(2*S.TribonacciConstant) == \ + "2*(1/3 + (1/3)*(19 - 3*33^(1/2))^(1/3) + " \ + "(1/3)*(3*33^(1/2) + 19)^(1/3))" + assert mcode(S.EulerGamma) == "EulerGamma" + assert mcode(S.Catalan) == "Catalan" + + +def test_containers(): + assert mcode([1, 2, 3, [4, 5, [6, 7]], 8, [9, 10], 11]) == \ + "{1, 2, 3, {4, 5, {6, 7}}, 8, {9, 10}, 11}" + assert mcode((1, 2, (3, 4))) == "{1, 2, {3, 4}}" + assert mcode([1]) == "{1}" + assert mcode((1,)) == "{1}" + assert mcode(Tuple(*[1, 2, 3])) == "{1, 2, 3}" + + +def test_matrices(): + from sympy.matrices import MutableDenseMatrix, MutableSparseMatrix, \ + ImmutableDenseMatrix, ImmutableSparseMatrix + A = MutableDenseMatrix( + [[1, -1, 0, 0], + [0, 1, -1, 0], + [0, 0, 1, -1], + [0, 0, 0, 1]] + ) + B = MutableSparseMatrix(A) + C = ImmutableDenseMatrix(A) + D = ImmutableSparseMatrix(A) + + assert mcode(C) == mcode(A) == \ + "{{1, -1, 0, 0}, " \ + "{0, 1, -1, 0}, " \ + "{0, 0, 1, -1}, " \ + "{0, 0, 0, 1}}" + + assert mcode(D) == mcode(B) == \ + "SparseArray[{" \ + "{1, 1} -> 1, {1, 2} -> -1, {2, 2} -> 1, {2, 3} -> -1, " \ + "{3, 3} -> 1, {3, 4} -> -1, {4, 4} -> 1" \ + "}, {4, 4}]" + + # Trivial cases of matrices + assert mcode(MutableDenseMatrix(0, 0, [])) == '{}' + assert mcode(MutableSparseMatrix(0, 0, [])) == 'SparseArray[{}, {0, 0}]' + assert mcode(MutableDenseMatrix(0, 3, [])) == '{}' + assert mcode(MutableSparseMatrix(0, 3, [])) == 'SparseArray[{}, {0, 3}]' + assert mcode(MutableDenseMatrix(3, 0, [])) == '{{}, {}, {}}' + assert mcode(MutableSparseMatrix(3, 0, [])) == 'SparseArray[{}, {3, 0}]' + +def test_NDArray(): + from sympy.tensor.array import ( + MutableDenseNDimArray, ImmutableDenseNDimArray, + MutableSparseNDimArray, ImmutableSparseNDimArray) + + example = MutableDenseNDimArray( + [[[1, 2, 3, 4], + [5, 6, 7, 8], + [9, 10, 11, 12]], + [[13, 14, 15, 16], + [17, 18, 19, 20], + [21, 22, 23, 24]]] + ) + + assert mcode(example) == \ + "{{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}, " \ + "{{13, 14, 15, 16}, {17, 18, 19, 20}, {21, 22, 23, 24}}}" + + example = ImmutableDenseNDimArray(example) + + assert mcode(example) == \ + "{{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}, " \ + "{{13, 14, 15, 16}, {17, 18, 19, 20}, {21, 22, 23, 24}}}" + + example = MutableSparseNDimArray(example) + + assert mcode(example) == \ + "SparseArray[{" \ + "{1, 1, 1} -> 1, {1, 1, 2} -> 2, {1, 1, 3} -> 3, " \ + "{1, 1, 4} -> 4, {1, 2, 1} -> 5, {1, 2, 2} -> 6, " \ + "{1, 2, 3} -> 7, {1, 2, 4} -> 8, {1, 3, 1} -> 9, " \ + "{1, 3, 2} -> 10, {1, 3, 3} -> 11, {1, 3, 4} -> 12, " \ + "{2, 1, 1} -> 13, {2, 1, 2} -> 14, {2, 1, 3} -> 15, " \ + "{2, 1, 4} -> 16, {2, 2, 1} -> 17, {2, 2, 2} -> 18, " \ + "{2, 2, 3} -> 19, {2, 2, 4} -> 20, {2, 3, 1} -> 21, " \ + "{2, 3, 2} -> 22, {2, 3, 3} -> 23, {2, 3, 4} -> 24" \ + "}, {2, 3, 4}]" + + example = ImmutableSparseNDimArray(example) + + assert mcode(example) == \ + "SparseArray[{" \ + "{1, 1, 1} -> 1, {1, 1, 2} -> 2, {1, 1, 3} -> 3, " \ + "{1, 1, 4} -> 4, {1, 2, 1} -> 5, {1, 2, 2} -> 6, " \ + "{1, 2, 3} -> 7, {1, 2, 4} -> 8, {1, 3, 1} -> 9, " \ + "{1, 3, 2} -> 10, {1, 3, 3} -> 11, {1, 3, 4} -> 12, " \ + "{2, 1, 1} -> 13, {2, 1, 2} -> 14, {2, 1, 3} -> 15, " \ + "{2, 1, 4} -> 16, {2, 2, 1} -> 17, {2, 2, 2} -> 18, " \ + "{2, 2, 3} -> 19, {2, 2, 4} -> 20, {2, 3, 1} -> 21, " \ + "{2, 3, 2} -> 22, {2, 3, 3} -> 23, {2, 3, 4} -> 24" \ + "}, {2, 3, 4}]" + + +def test_Integral(): + assert mcode(Integral(sin(sin(x)), x)) == "Hold[Integrate[Sin[Sin[x]], x]]" + assert mcode(Integral(exp(-x**2 - y**2), + (x, -oo, oo), + (y, -oo, oo))) == \ + "Hold[Integrate[Exp[-x^2 - y^2], {x, -Infinity, Infinity}, " \ + "{y, -Infinity, Infinity}]]" + + +def test_Derivative(): + assert mcode(Derivative(sin(x), x)) == "Hold[D[Sin[x], x]]" + assert mcode(Derivative(x, x)) == "Hold[D[x, x]]" + assert mcode(Derivative(sin(x)*y**4, x, 2)) == "Hold[D[y^4*Sin[x], {x, 2}]]" + assert mcode(Derivative(sin(x)*y**4, x, y, x)) == "Hold[D[y^4*Sin[x], x, y, x]]" + assert mcode(Derivative(sin(x)*y**4, x, y, 3, x)) == "Hold[D[y^4*Sin[x], x, {y, 3}, x]]" + + +def test_Sum(): + assert mcode(Sum(sin(x), (x, 0, 10))) == "Hold[Sum[Sin[x], {x, 0, 10}]]" + assert mcode(Sum(exp(-x**2 - y**2), + (x, -oo, oo), + (y, -oo, oo))) == \ + "Hold[Sum[Exp[-x^2 - y^2], {x, -Infinity, Infinity}, " \ + "{y, -Infinity, Infinity}]]" + + +def test_comment(): + from sympy.printing.mathematica import MCodePrinter + assert MCodePrinter()._get_comment("Hello World") == \ + "(* Hello World *)" + + +def test_userfuncs(): + # Dictionary mutation test + some_function = symbols("some_function", cls=Function) + my_user_functions = {"some_function": "SomeFunction"} + assert mcode( + some_function(z), + user_functions=my_user_functions) == \ + 'SomeFunction[z]' + assert mcode( + some_function(z), + user_functions=my_user_functions) == \ + 'SomeFunction[z]' + + # List argument test + my_user_functions = \ + {"some_function": [(lambda x: True, "SomeOtherFunction")]} + assert mcode( + some_function(z), + user_functions=my_user_functions) == \ + 'SomeOtherFunction[z]' diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_mathml.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_mathml.py new file mode 100644 index 0000000000000000000000000000000000000000..4e7c2253c98fb1a4e99375774ad158df9b80b439 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_mathml.py @@ -0,0 +1,2048 @@ +from sympy.calculus.accumulationbounds import AccumBounds +from sympy.concrete.summations import Sum +from sympy.core.basic import Basic +from sympy.core.containers import Tuple +from sympy.core.function import Derivative, Lambda, diff, Function +from sympy.core.numbers import (zoo, Float, Integer, I, oo, pi, E, + Rational) +from sympy.core.relational import Lt, Ge, Ne, Eq +from sympy.core.singleton import S +from sympy.core.symbol import symbols, Symbol +from sympy.core.sympify import sympify +from sympy.functions.combinatorial.factorials import (factorial2, + binomial, factorial) +from sympy.functions.combinatorial.numbers import (lucas, bell, + catalan, euler, tribonacci, fibonacci, bernoulli, primenu, primeomega, + totient, reduced_totient) +from sympy.functions.elementary.complexes import re, im, conjugate, Abs +from sympy.functions.elementary.exponential import exp, LambertW, log +from sympy.functions.elementary.hyperbolic import (tanh, acoth, atanh, + coth, asinh, acsch, asech, acosh, csch, sinh, cosh, sech) +from sympy.functions.elementary.integers import ceiling, floor +from sympy.functions.elementary.miscellaneous import Max, Min +from sympy.functions.elementary.trigonometric import (csc, sec, tan, + atan, sin, asec, cot, cos, acot, acsc, asin, acos) +from sympy.functions.special.delta_functions import Heaviside +from sympy.functions.special.elliptic_integrals import (elliptic_pi, + elliptic_f, elliptic_k, elliptic_e) +from sympy.functions.special.error_functions import (fresnelc, + fresnels, Ei, expint) +from sympy.functions.special.gamma_functions import (gamma, uppergamma, + lowergamma) +from sympy.functions.special.mathieu_functions import (mathieusprime, + mathieus, mathieucprime, mathieuc) +from sympy.functions.special.polynomials import (jacobi, chebyshevu, + chebyshevt, hermite, assoc_legendre, gegenbauer, assoc_laguerre, + legendre, laguerre) +from sympy.functions.special.singularity_functions import SingularityFunction +from sympy.functions.special.zeta_functions import (polylog, stieltjes, + lerchphi, dirichlet_eta, zeta) +from sympy.integrals.integrals import Integral +from sympy.logic.boolalg import (Xor, Or, false, true, And, Equivalent, + Implies, Not) +from sympy.matrices.dense import Matrix +from sympy.matrices.expressions.determinant import Determinant +from sympy.matrices.expressions.matexpr import MatrixSymbol +from sympy.physics.quantum import (ComplexSpace, FockSpace, hbar, + HilbertSpace, Dagger) +from sympy.printing.mathml import (MathMLPresentationPrinter, + MathMLPrinter, MathMLContentPrinter, mathml) +from sympy.series.limits import Limit +from sympy.sets.contains import Contains +from sympy.sets.fancysets import Range +from sympy.sets.sets import (Interval, Union, SymmetricDifference, + Complement, FiniteSet, Intersection, ProductSet) +from sympy.stats.rv import RandomSymbol +from sympy.tensor.indexed import IndexedBase +from sympy.vector import (Divergence, CoordSys3D, Cross, Curl, Dot, + Laplacian, Gradient) +from sympy.testing.pytest import raises, XFAIL + +x, y, z, a, b, c, d, e, n = symbols('x:z a:e n') +mp = MathMLContentPrinter() +mpp = MathMLPresentationPrinter() + + +def test_mathml_printer(): + m = MathMLPrinter() + assert m.doprint(1+x) == mp.doprint(1+x) + + +def test_content_printmethod(): + assert mp.doprint(1 + x) == 'x1' + + +def test_content_mathml_core(): + mml_1 = mp._print(1 + x) + assert mml_1.nodeName == 'apply' + nodes = mml_1.childNodes + assert len(nodes) == 3 + assert nodes[0].nodeName == 'plus' + assert nodes[0].hasChildNodes() is False + assert nodes[0].nodeValue is None + assert nodes[1].nodeName in ['cn', 'ci'] + if nodes[1].nodeName == 'cn': + assert nodes[1].childNodes[0].nodeValue == '1' + assert nodes[2].childNodes[0].nodeValue == 'x' + else: + assert nodes[1].childNodes[0].nodeValue == 'x' + assert nodes[2].childNodes[0].nodeValue == '1' + + mml_2 = mp._print(x**2) + assert mml_2.nodeName == 'apply' + nodes = mml_2.childNodes + assert nodes[1].childNodes[0].nodeValue == 'x' + assert nodes[2].childNodes[0].nodeValue == '2' + + mml_3 = mp._print(2*x) + assert mml_3.nodeName == 'apply' + nodes = mml_3.childNodes + assert nodes[0].nodeName == 'times' + assert nodes[1].childNodes[0].nodeValue == '2' + assert nodes[2].childNodes[0].nodeValue == 'x' + + mml = mp._print(Float(1.0, 2)*x) + assert mml.nodeName == 'apply' + nodes = mml.childNodes + assert nodes[0].nodeName == 'times' + assert nodes[1].childNodes[0].nodeValue == '1.0' + assert nodes[2].childNodes[0].nodeValue == 'x' + + +def test_content_mathml_functions(): + mml_1 = mp._print(sin(x)) + assert mml_1.nodeName == 'apply' + assert mml_1.childNodes[0].nodeName == 'sin' + assert mml_1.childNodes[1].nodeName == 'ci' + + mml_2 = mp._print(diff(sin(x), x, evaluate=False)) + assert mml_2.nodeName == 'apply' + assert mml_2.childNodes[0].nodeName == 'diff' + assert mml_2.childNodes[1].nodeName == 'bvar' + assert mml_2.childNodes[1].childNodes[ + 0].nodeName == 'ci' # below bvar there's x/ci> + + mml_3 = mp._print(diff(cos(x*y), x, evaluate=False)) + assert mml_3.nodeName == 'apply' + assert mml_3.childNodes[0].nodeName == 'partialdiff' + assert mml_3.childNodes[1].nodeName == 'bvar' + assert mml_3.childNodes[1].childNodes[ + 0].nodeName == 'ci' # below bvar there's x/ci> + + mml_4 = mp._print(Lambda((x, y), x * y)) + assert mml_4.nodeName == 'lambda' + assert mml_4.childNodes[0].nodeName == 'bvar' + assert mml_4.childNodes[0].childNodes[ + 0].nodeName == 'ci' # below bvar there's x/ci> + assert mml_4.childNodes[1].nodeName == 'bvar' + assert mml_4.childNodes[1].childNodes[ + 0].nodeName == 'ci' # below bvar there's y/ci> + assert mml_4.childNodes[2].nodeName == 'apply' + + +def test_content_mathml_limits(): + # XXX No unevaluated limits + lim_fun = sin(x)/x + mml_1 = mp._print(Limit(lim_fun, x, 0)) + assert mml_1.childNodes[0].nodeName == 'limit' + assert mml_1.childNodes[1].nodeName == 'bvar' + assert mml_1.childNodes[2].nodeName == 'lowlimit' + assert mml_1.childNodes[3].toxml() == mp._print(lim_fun).toxml() + + +def test_content_mathml_integrals(): + integrand = x + mml_1 = mp._print(Integral(integrand, (x, 0, 1))) + assert mml_1.childNodes[0].nodeName == 'int' + assert mml_1.childNodes[1].nodeName == 'bvar' + assert mml_1.childNodes[2].nodeName == 'lowlimit' + assert mml_1.childNodes[3].nodeName == 'uplimit' + assert mml_1.childNodes[4].toxml() == mp._print(integrand).toxml() + + +def test_content_mathml_matrices(): + A = Matrix([1, 2, 3]) + B = Matrix([[0, 5, 4], [2, 3, 1], [9, 7, 9]]) + mll_1 = mp._print(A) + assert mll_1.childNodes[0].nodeName == 'matrixrow' + assert mll_1.childNodes[0].childNodes[0].nodeName == 'cn' + assert mll_1.childNodes[0].childNodes[0].childNodes[0].nodeValue == '1' + assert mll_1.childNodes[1].nodeName == 'matrixrow' + assert mll_1.childNodes[1].childNodes[0].nodeName == 'cn' + assert mll_1.childNodes[1].childNodes[0].childNodes[0].nodeValue == '2' + assert mll_1.childNodes[2].nodeName == 'matrixrow' + assert mll_1.childNodes[2].childNodes[0].nodeName == 'cn' + assert mll_1.childNodes[2].childNodes[0].childNodes[0].nodeValue == '3' + mll_2 = mp._print(B) + assert mll_2.childNodes[0].nodeName == 'matrixrow' + assert mll_2.childNodes[0].childNodes[0].nodeName == 'cn' + assert mll_2.childNodes[0].childNodes[0].childNodes[0].nodeValue == '0' + assert mll_2.childNodes[0].childNodes[1].nodeName == 'cn' + assert mll_2.childNodes[0].childNodes[1].childNodes[0].nodeValue == '5' + assert mll_2.childNodes[0].childNodes[2].nodeName == 'cn' + assert mll_2.childNodes[0].childNodes[2].childNodes[0].nodeValue == '4' + assert mll_2.childNodes[1].nodeName == 'matrixrow' + assert mll_2.childNodes[1].childNodes[0].nodeName == 'cn' + assert mll_2.childNodes[1].childNodes[0].childNodes[0].nodeValue == '2' + assert mll_2.childNodes[1].childNodes[1].nodeName == 'cn' + assert mll_2.childNodes[1].childNodes[1].childNodes[0].nodeValue == '3' + assert mll_2.childNodes[1].childNodes[2].nodeName == 'cn' + assert mll_2.childNodes[1].childNodes[2].childNodes[0].nodeValue == '1' + assert mll_2.childNodes[2].nodeName == 'matrixrow' + assert mll_2.childNodes[2].childNodes[0].nodeName == 'cn' + assert mll_2.childNodes[2].childNodes[0].childNodes[0].nodeValue == '9' + assert mll_2.childNodes[2].childNodes[1].nodeName == 'cn' + assert mll_2.childNodes[2].childNodes[1].childNodes[0].nodeValue == '7' + assert mll_2.childNodes[2].childNodes[2].nodeName == 'cn' + assert mll_2.childNodes[2].childNodes[2].childNodes[0].nodeValue == '9' + + +def test_content_mathml_sums(): + summand = x + mml_1 = mp._print(Sum(summand, (x, 1, 10))) + assert mml_1.childNodes[0].nodeName == 'sum' + assert mml_1.childNodes[1].nodeName == 'bvar' + assert mml_1.childNodes[2].nodeName == 'lowlimit' + assert mml_1.childNodes[3].nodeName == 'uplimit' + assert mml_1.childNodes[4].toxml() == mp._print(summand).toxml() + + +def test_content_mathml_tuples(): + mml_1 = mp._print([2]) + assert mml_1.nodeName == 'list' + assert mml_1.childNodes[0].nodeName == 'cn' + assert len(mml_1.childNodes) == 1 + + mml_2 = mp._print([2, Integer(1)]) + assert mml_2.nodeName == 'list' + assert mml_2.childNodes[0].nodeName == 'cn' + assert mml_2.childNodes[1].nodeName == 'cn' + assert len(mml_2.childNodes) == 2 + + +def test_content_mathml_add(): + mml = mp._print(x**5 - x**4 + x) + assert mml.childNodes[0].nodeName == 'plus' + assert mml.childNodes[1].childNodes[0].nodeName == 'minus' + assert mml.childNodes[1].childNodes[1].nodeName == 'apply' + + +def test_content_mathml_Rational(): + mml_1 = mp._print(Rational(1, 1)) + """should just return a number""" + assert mml_1.nodeName == 'cn' + + mml_2 = mp._print(Rational(2, 5)) + assert mml_2.childNodes[0].nodeName == 'divide' + + +def test_content_mathml_constants(): + mml = mp._print(I) + assert mml.nodeName == 'imaginaryi' + + mml = mp._print(E) + assert mml.nodeName == 'exponentiale' + + mml = mp._print(oo) + assert mml.nodeName == 'infinity' + + mml = mp._print(pi) + assert mml.nodeName == 'pi' + + assert mathml(hbar) == '' + assert mathml(S.TribonacciConstant) == '' + assert mathml(S.GoldenRatio) == 'φ' + mml = mathml(S.EulerGamma) + assert mml == '' + + mml = mathml(S.EmptySet) + assert mml == '' + + mml = mathml(S.true) + assert mml == '' + + mml = mathml(S.false) + assert mml == '' + + mml = mathml(S.NaN) + assert mml == '' + + +def test_content_mathml_trig(): + mml = mp._print(sin(x)) + assert mml.childNodes[0].nodeName == 'sin' + + mml = mp._print(cos(x)) + assert mml.childNodes[0].nodeName == 'cos' + + mml = mp._print(tan(x)) + assert mml.childNodes[0].nodeName == 'tan' + + mml = mp._print(cot(x)) + assert mml.childNodes[0].nodeName == 'cot' + + mml = mp._print(csc(x)) + assert mml.childNodes[0].nodeName == 'csc' + + mml = mp._print(sec(x)) + assert mml.childNodes[0].nodeName == 'sec' + + mml = mp._print(asin(x)) + assert mml.childNodes[0].nodeName == 'arcsin' + + mml = mp._print(acos(x)) + assert mml.childNodes[0].nodeName == 'arccos' + + mml = mp._print(atan(x)) + assert mml.childNodes[0].nodeName == 'arctan' + + mml = mp._print(acot(x)) + assert mml.childNodes[0].nodeName == 'arccot' + + mml = mp._print(acsc(x)) + assert mml.childNodes[0].nodeName == 'arccsc' + + mml = mp._print(asec(x)) + assert mml.childNodes[0].nodeName == 'arcsec' + + mml = mp._print(sinh(x)) + assert mml.childNodes[0].nodeName == 'sinh' + + mml = mp._print(cosh(x)) + assert mml.childNodes[0].nodeName == 'cosh' + + mml = mp._print(tanh(x)) + assert mml.childNodes[0].nodeName == 'tanh' + + mml = mp._print(coth(x)) + assert mml.childNodes[0].nodeName == 'coth' + + mml = mp._print(csch(x)) + assert mml.childNodes[0].nodeName == 'csch' + + mml = mp._print(sech(x)) + assert mml.childNodes[0].nodeName == 'sech' + + mml = mp._print(asinh(x)) + assert mml.childNodes[0].nodeName == 'arcsinh' + + mml = mp._print(atanh(x)) + assert mml.childNodes[0].nodeName == 'arctanh' + + mml = mp._print(acosh(x)) + assert mml.childNodes[0].nodeName == 'arccosh' + + mml = mp._print(acoth(x)) + assert mml.childNodes[0].nodeName == 'arccoth' + + mml = mp._print(acsch(x)) + assert mml.childNodes[0].nodeName == 'arccsch' + + mml = mp._print(asech(x)) + assert mml.childNodes[0].nodeName == 'arcsech' + + +def test_content_mathml_relational(): + mml_1 = mp._print(Eq(x, 1)) + assert mml_1.nodeName == 'apply' + assert mml_1.childNodes[0].nodeName == 'eq' + assert mml_1.childNodes[1].nodeName == 'ci' + assert mml_1.childNodes[1].childNodes[0].nodeValue == 'x' + assert mml_1.childNodes[2].nodeName == 'cn' + assert mml_1.childNodes[2].childNodes[0].nodeValue == '1' + + mml_2 = mp._print(Ne(1, x)) + assert mml_2.nodeName == 'apply' + assert mml_2.childNodes[0].nodeName == 'neq' + assert mml_2.childNodes[1].nodeName == 'cn' + assert mml_2.childNodes[1].childNodes[0].nodeValue == '1' + assert mml_2.childNodes[2].nodeName == 'ci' + assert mml_2.childNodes[2].childNodes[0].nodeValue == 'x' + + mml_3 = mp._print(Ge(1, x)) + assert mml_3.nodeName == 'apply' + assert mml_3.childNodes[0].nodeName == 'geq' + assert mml_3.childNodes[1].nodeName == 'cn' + assert mml_3.childNodes[1].childNodes[0].nodeValue == '1' + assert mml_3.childNodes[2].nodeName == 'ci' + assert mml_3.childNodes[2].childNodes[0].nodeValue == 'x' + + mml_4 = mp._print(Lt(1, x)) + assert mml_4.nodeName == 'apply' + assert mml_4.childNodes[0].nodeName == 'lt' + assert mml_4.childNodes[1].nodeName == 'cn' + assert mml_4.childNodes[1].childNodes[0].nodeValue == '1' + assert mml_4.childNodes[2].nodeName == 'ci' + assert mml_4.childNodes[2].childNodes[0].nodeValue == 'x' + + +def test_content_symbol(): + mml = mp._print(x) + assert mml.nodeName == 'ci' + assert mml.childNodes[0].nodeValue == 'x' + del mml + + mml = mp._print(Symbol("x^2")) + assert mml.nodeName == 'ci' + assert mml.childNodes[0].nodeName == 'mml:msup' + assert mml.childNodes[0].childNodes[0].nodeName == 'mml:mi' + assert mml.childNodes[0].childNodes[0].childNodes[0].nodeValue == 'x' + assert mml.childNodes[0].childNodes[1].nodeName == 'mml:mi' + assert mml.childNodes[0].childNodes[1].childNodes[0].nodeValue == '2' + del mml + + mml = mp._print(Symbol("x__2")) + assert mml.nodeName == 'ci' + assert mml.childNodes[0].nodeName == 'mml:msup' + assert mml.childNodes[0].childNodes[0].nodeName == 'mml:mi' + assert mml.childNodes[0].childNodes[0].childNodes[0].nodeValue == 'x' + assert mml.childNodes[0].childNodes[1].nodeName == 'mml:mi' + assert mml.childNodes[0].childNodes[1].childNodes[0].nodeValue == '2' + del mml + + mml = mp._print(Symbol("x_2")) + assert mml.nodeName == 'ci' + assert mml.childNodes[0].nodeName == 'mml:msub' + assert mml.childNodes[0].childNodes[0].nodeName == 'mml:mi' + assert mml.childNodes[0].childNodes[0].childNodes[0].nodeValue == 'x' + assert mml.childNodes[0].childNodes[1].nodeName == 'mml:mi' + assert mml.childNodes[0].childNodes[1].childNodes[0].nodeValue == '2' + del mml + + mml = mp._print(Symbol("x^3_2")) + assert mml.nodeName == 'ci' + assert mml.childNodes[0].nodeName == 'mml:msubsup' + assert mml.childNodes[0].childNodes[0].nodeName == 'mml:mi' + assert mml.childNodes[0].childNodes[0].childNodes[0].nodeValue == 'x' + assert mml.childNodes[0].childNodes[1].nodeName == 'mml:mi' + assert mml.childNodes[0].childNodes[1].childNodes[0].nodeValue == '2' + assert mml.childNodes[0].childNodes[2].nodeName == 'mml:mi' + assert mml.childNodes[0].childNodes[2].childNodes[0].nodeValue == '3' + del mml + + mml = mp._print(Symbol("x__3_2")) + assert mml.nodeName == 'ci' + assert mml.childNodes[0].nodeName == 'mml:msubsup' + assert mml.childNodes[0].childNodes[0].nodeName == 'mml:mi' + assert mml.childNodes[0].childNodes[0].childNodes[0].nodeValue == 'x' + assert mml.childNodes[0].childNodes[1].nodeName == 'mml:mi' + assert mml.childNodes[0].childNodes[1].childNodes[0].nodeValue == '2' + assert mml.childNodes[0].childNodes[2].nodeName == 'mml:mi' + assert mml.childNodes[0].childNodes[2].childNodes[0].nodeValue == '3' + del mml + + mml = mp._print(Symbol("x_2_a")) + assert mml.nodeName == 'ci' + assert mml.childNodes[0].nodeName == 'mml:msub' + assert mml.childNodes[0].childNodes[0].nodeName == 'mml:mi' + assert mml.childNodes[0].childNodes[0].childNodes[0].nodeValue == 'x' + assert mml.childNodes[0].childNodes[1].nodeName == 'mml:mrow' + assert mml.childNodes[0].childNodes[1].childNodes[0].nodeName == 'mml:mi' + assert mml.childNodes[0].childNodes[1].childNodes[0].childNodes[ + 0].nodeValue == '2' + assert mml.childNodes[0].childNodes[1].childNodes[1].nodeName == 'mml:mo' + assert mml.childNodes[0].childNodes[1].childNodes[1].childNodes[ + 0].nodeValue == ' ' + assert mml.childNodes[0].childNodes[1].childNodes[2].nodeName == 'mml:mi' + assert mml.childNodes[0].childNodes[1].childNodes[2].childNodes[ + 0].nodeValue == 'a' + del mml + + mml = mp._print(Symbol("x^2^a")) + assert mml.nodeName == 'ci' + assert mml.childNodes[0].nodeName == 'mml:msup' + assert mml.childNodes[0].childNodes[0].nodeName == 'mml:mi' + assert mml.childNodes[0].childNodes[0].childNodes[0].nodeValue == 'x' + assert mml.childNodes[0].childNodes[1].nodeName == 'mml:mrow' + assert mml.childNodes[0].childNodes[1].childNodes[0].nodeName == 'mml:mi' + assert mml.childNodes[0].childNodes[1].childNodes[0].childNodes[ + 0].nodeValue == '2' + assert mml.childNodes[0].childNodes[1].childNodes[1].nodeName == 'mml:mo' + assert mml.childNodes[0].childNodes[1].childNodes[1].childNodes[ + 0].nodeValue == ' ' + assert mml.childNodes[0].childNodes[1].childNodes[2].nodeName == 'mml:mi' + assert mml.childNodes[0].childNodes[1].childNodes[2].childNodes[ + 0].nodeValue == 'a' + del mml + + mml = mp._print(Symbol("x__2__a")) + assert mml.nodeName == 'ci' + assert mml.childNodes[0].nodeName == 'mml:msup' + assert mml.childNodes[0].childNodes[0].nodeName == 'mml:mi' + assert mml.childNodes[0].childNodes[0].childNodes[0].nodeValue == 'x' + assert mml.childNodes[0].childNodes[1].nodeName == 'mml:mrow' + assert mml.childNodes[0].childNodes[1].childNodes[0].nodeName == 'mml:mi' + assert mml.childNodes[0].childNodes[1].childNodes[0].childNodes[ + 0].nodeValue == '2' + assert mml.childNodes[0].childNodes[1].childNodes[1].nodeName == 'mml:mo' + assert mml.childNodes[0].childNodes[1].childNodes[1].childNodes[ + 0].nodeValue == ' ' + assert mml.childNodes[0].childNodes[1].childNodes[2].nodeName == 'mml:mi' + assert mml.childNodes[0].childNodes[1].childNodes[2].childNodes[ + 0].nodeValue == 'a' + del mml + + +def test_content_mathml_greek(): + mml = mp._print(Symbol('alpha')) + assert mml.nodeName == 'ci' + assert mml.childNodes[0].nodeValue == '\N{GREEK SMALL LETTER ALPHA}' + + assert mp.doprint(Symbol('alpha')) == 'α' + assert mp.doprint(Symbol('beta')) == 'β' + assert mp.doprint(Symbol('gamma')) == 'γ' + assert mp.doprint(Symbol('delta')) == 'δ' + assert mp.doprint(Symbol('epsilon')) == 'ε' + assert mp.doprint(Symbol('zeta')) == 'ζ' + assert mp.doprint(Symbol('eta')) == 'η' + assert mp.doprint(Symbol('theta')) == 'θ' + assert mp.doprint(Symbol('iota')) == 'ι' + assert mp.doprint(Symbol('kappa')) == 'κ' + assert mp.doprint(Symbol('lambda')) == 'λ' + assert mp.doprint(Symbol('mu')) == 'μ' + assert mp.doprint(Symbol('nu')) == 'ν' + assert mp.doprint(Symbol('xi')) == 'ξ' + assert mp.doprint(Symbol('omicron')) == 'ο' + assert mp.doprint(Symbol('pi')) == 'π' + assert mp.doprint(Symbol('rho')) == 'ρ' + assert mp.doprint(Symbol('varsigma')) == 'ς' + assert mp.doprint(Symbol('sigma')) == 'σ' + assert mp.doprint(Symbol('tau')) == 'τ' + assert mp.doprint(Symbol('upsilon')) == 'υ' + assert mp.doprint(Symbol('phi')) == 'φ' + assert mp.doprint(Symbol('chi')) == 'χ' + assert mp.doprint(Symbol('psi')) == 'ψ' + assert mp.doprint(Symbol('omega')) == 'ω' + + assert mp.doprint(Symbol('Alpha')) == 'Α' + assert mp.doprint(Symbol('Beta')) == 'Β' + assert mp.doprint(Symbol('Gamma')) == 'Γ' + assert mp.doprint(Symbol('Delta')) == 'Δ' + assert mp.doprint(Symbol('Epsilon')) == 'Ε' + assert mp.doprint(Symbol('Zeta')) == 'Ζ' + assert mp.doprint(Symbol('Eta')) == 'Η' + assert mp.doprint(Symbol('Theta')) == 'Θ' + assert mp.doprint(Symbol('Iota')) == 'Ι' + assert mp.doprint(Symbol('Kappa')) == 'Κ' + assert mp.doprint(Symbol('Lambda')) == 'Λ' + assert mp.doprint(Symbol('Mu')) == 'Μ' + assert mp.doprint(Symbol('Nu')) == 'Ν' + assert mp.doprint(Symbol('Xi')) == 'Ξ' + assert mp.doprint(Symbol('Omicron')) == 'Ο' + assert mp.doprint(Symbol('Pi')) == 'Π' + assert mp.doprint(Symbol('Rho')) == 'Ρ' + assert mp.doprint(Symbol('Sigma')) == 'Σ' + assert mp.doprint(Symbol('Tau')) == 'Τ' + assert mp.doprint(Symbol('Upsilon')) == 'Υ' + assert mp.doprint(Symbol('Phi')) == 'Φ' + assert mp.doprint(Symbol('Chi')) == 'Χ' + assert mp.doprint(Symbol('Psi')) == 'Ψ' + assert mp.doprint(Symbol('Omega')) == 'Ω' + + +def test_content_mathml_order(): + expr = x**3 + x**2*y + 3*x*y**3 + y**4 + + mp = MathMLContentPrinter({'order': 'lex'}) + mml = mp._print(expr) + + assert mml.childNodes[1].childNodes[0].nodeName == 'power' + assert mml.childNodes[1].childNodes[1].childNodes[0].data == 'x' + assert mml.childNodes[1].childNodes[2].childNodes[0].data == '3' + + assert mml.childNodes[4].childNodes[0].nodeName == 'power' + assert mml.childNodes[4].childNodes[1].childNodes[0].data == 'y' + assert mml.childNodes[4].childNodes[2].childNodes[0].data == '4' + + mp = MathMLContentPrinter({'order': 'rev-lex'}) + mml = mp._print(expr) + + assert mml.childNodes[1].childNodes[0].nodeName == 'power' + assert mml.childNodes[1].childNodes[1].childNodes[0].data == 'y' + assert mml.childNodes[1].childNodes[2].childNodes[0].data == '4' + + assert mml.childNodes[4].childNodes[0].nodeName == 'power' + assert mml.childNodes[4].childNodes[1].childNodes[0].data == 'x' + assert mml.childNodes[4].childNodes[2].childNodes[0].data == '3' + + +def test_content_settings(): + raises(TypeError, lambda: mathml(x, method="garbage")) + + +def test_content_mathml_logic(): + assert mathml(And(x, y)) == 'xy' + assert mathml(Or(x, y)) == 'xy' + assert mathml(Xor(x, y)) == 'xy' + assert mathml(Implies(x, y)) == 'xy' + assert mathml(Not(x)) == 'x' + + +def test_content_finite_sets(): + assert mathml(FiniteSet(a)) == 'a' + assert mathml(FiniteSet(a, b)) == 'ab' + assert mathml(FiniteSet(FiniteSet(a, b), c)) == \ + 'cab' + + A = FiniteSet(a) + B = FiniteSet(b) + C = FiniteSet(c) + D = FiniteSet(d) + + U1 = Union(A, B, evaluate=False) + U2 = Union(C, D, evaluate=False) + I1 = Intersection(A, B, evaluate=False) + I2 = Intersection(C, D, evaluate=False) + C1 = Complement(A, B, evaluate=False) + C2 = Complement(C, D, evaluate=False) + # XXX ProductSet does not support evaluate keyword + P1 = ProductSet(A, B) + P2 = ProductSet(C, D) + + assert mathml(U1) == \ + 'ab' + assert mathml(I1) == \ + 'ab' \ + '' + assert mathml(C1) == \ + 'ab' + assert mathml(P1) == \ + 'ab' \ + '' + + assert mathml(Intersection(A, U2, evaluate=False)) == \ + 'a' \ + 'cd' + assert mathml(Intersection(U1, U2, evaluate=False)) == \ + 'a' \ + 'bc' \ + 'd' + + # XXX Does the parenthesis appear correctly for these examples in mathjax? + assert mathml(Intersection(C1, C2, evaluate=False)) == \ + 'a' \ + 'bc' \ + 'd' + assert mathml(Intersection(P1, P2, evaluate=False)) == \ + 'a' \ + 'b' \ + 'cd' + + assert mathml(Union(A, I2, evaluate=False)) == \ + 'a' \ + 'cd' + assert mathml(Union(I1, I2, evaluate=False)) == \ + 'a' \ + 'bc' \ + 'd' + assert mathml(Union(C1, C2, evaluate=False)) == \ + 'a' \ + 'bc' \ + 'd' + assert mathml(Union(P1, P2, evaluate=False)) == \ + 'a' \ + 'b' \ + 'cd' + + assert mathml(Complement(A, C2, evaluate=False)) == \ + 'a' \ + 'cd' + assert mathml(Complement(U1, U2, evaluate=False)) == \ + 'a' \ + 'bc' \ + 'd' + assert mathml(Complement(I1, I2, evaluate=False)) == \ + 'a' \ + 'bc' \ + 'd' + assert mathml(Complement(P1, P2, evaluate=False)) == \ + 'a' \ + 'b' \ + 'cd' + + assert mathml(ProductSet(A, P2)) == \ + 'a' \ + 'c' \ + 'd' + assert mathml(ProductSet(U1, U2)) == \ + 'a' \ + 'bc' \ + 'd' + assert mathml(ProductSet(I1, I2)) == \ + 'a' \ + 'b' \ + 'cd' + assert mathml(ProductSet(C1, C2)) == \ + 'a' \ + 'b' \ + 'cd' + + +def test_presentation_printmethod(): + assert mpp.doprint(1 + x) == 'x+1' + assert mpp.doprint(x**2) == 'x2' + assert mpp.doprint(x**-1) == '1x' + assert mpp.doprint(x**-2) == \ + '1x2' + assert mpp.doprint(2*x) == \ + '2x' + + +def test_presentation_mathml_core(): + mml_1 = mpp._print(1 + x) + assert mml_1.nodeName == 'mrow' + nodes = mml_1.childNodes + assert len(nodes) == 3 + assert nodes[0].nodeName in ['mi', 'mn'] + assert nodes[1].nodeName == 'mo' + if nodes[0].nodeName == 'mn': + assert nodes[0].childNodes[0].nodeValue == '1' + assert nodes[2].childNodes[0].nodeValue == 'x' + else: + assert nodes[0].childNodes[0].nodeValue == 'x' + assert nodes[2].childNodes[0].nodeValue == '1' + + mml_2 = mpp._print(x**2) + assert mml_2.nodeName == 'msup' + nodes = mml_2.childNodes + assert nodes[0].childNodes[0].nodeValue == 'x' + assert nodes[1].childNodes[0].nodeValue == '2' + + mml_3 = mpp._print(2*x) + assert mml_3.nodeName == 'mrow' + nodes = mml_3.childNodes + assert nodes[0].childNodes[0].nodeValue == '2' + assert nodes[1].childNodes[0].nodeValue == '⁢' + assert nodes[2].childNodes[0].nodeValue == 'x' + + mml = mpp._print(Float(1.0, 2)*x) + assert mml.nodeName == 'mrow' + nodes = mml.childNodes + assert nodes[0].childNodes[0].nodeValue == '1.0' + assert nodes[1].childNodes[0].nodeValue == '⁢' + assert nodes[2].childNodes[0].nodeValue == 'x' + + +def test_presentation_mathml_functions(): + mml_1 = mpp._print(sin(x)) + assert mml_1.childNodes[0].childNodes[0 + ].nodeValue == 'sin' + assert mml_1.childNodes[1].childNodes[1 + ].childNodes[0].nodeValue == 'x' + + mml_2 = mpp._print(diff(sin(x), x, evaluate=False)) + assert mml_2.nodeName == 'mrow' + assert mml_2.childNodes[0].childNodes[0 + ].childNodes[0].childNodes[0].nodeValue == 'ⅆ' + assert mml_2.childNodes[1].childNodes[1 + ].nodeName == 'mrow' + assert mml_2.childNodes[0].childNodes[1 + ].childNodes[0].childNodes[0].nodeValue == 'ⅆ' + + mml_3 = mpp._print(diff(cos(x*y), x, evaluate=False)) + assert mml_3.childNodes[0].nodeName == 'mfrac' + assert mml_3.childNodes[0].childNodes[0 + ].childNodes[0].childNodes[0].nodeValue == '∂' + assert mml_3.childNodes[1].childNodes[0 + ].childNodes[0].nodeValue == 'cos' + + +def test_print_derivative(): + f = Function('f') + d = Derivative(f(x, y, z), x, z, x, z, z, y) + assert mathml(d) == \ + 'yz2xzxxyz' + assert mathml(d, printer='presentation') == \ + '6y2zxzxf(x,y,z)' + + +def test_presentation_mathml_limits(): + lim_fun = sin(x)/x + mml_1 = mpp._print(Limit(lim_fun, x, 0)) + assert mml_1.childNodes[0].nodeName == 'munder' + assert mml_1.childNodes[0].childNodes[0 + ].childNodes[0].nodeValue == 'lim' + assert mml_1.childNodes[0].childNodes[1 + ].childNodes[0].childNodes[0 + ].nodeValue == 'x' + assert mml_1.childNodes[0].childNodes[1 + ].childNodes[1].childNodes[0 + ].nodeValue == '→' + assert mml_1.childNodes[0].childNodes[1 + ].childNodes[2].childNodes[0 + ].nodeValue == '0' + + +def test_presentation_mathml_integrals(): + assert mpp.doprint(Integral(x, (x, 0, 1))) == \ + '01'\ + 'xx' + assert mpp.doprint(Integral(log(x), x)) == \ + 'log(x' \ + ')x' + assert mpp.doprint(Integral(x*y, x, y)) == \ + 'x'\ + 'yyx' + z, w = symbols('z w') + assert mpp.doprint(Integral(x*y*z, x, y, z)) == \ + 'x'\ + 'yz'\ + 'zyx' + assert mpp.doprint(Integral(x*y*z*w, x, y, z, w)) == \ + ''\ + 'w'\ + 'xy'\ + 'zw'\ + 'zyx' + assert mpp.doprint(Integral(x, x, y, (z, 0, 1))) == \ + '01'\ + 'xz'\ + 'yx' + assert mpp.doprint(Integral(x, (x, 0))) == \ + '0x'\ + 'x' + + +def test_presentation_mathml_matrices(): + A = Matrix([1, 2, 3]) + B = Matrix([[0, 5, 4], [2, 3, 1], [9, 7, 9]]) + mll_1 = mpp._print(A) + assert mll_1.childNodes[1].nodeName == 'mtable' + assert mll_1.childNodes[1].childNodes[0].nodeName == 'mtr' + assert len(mll_1.childNodes[1].childNodes) == 3 + assert mll_1.childNodes[1].childNodes[0].childNodes[0].nodeName == 'mtd' + assert len(mll_1.childNodes[1].childNodes[0].childNodes) == 1 + assert mll_1.childNodes[1].childNodes[0].childNodes[0 + ].childNodes[0].childNodes[0].nodeValue == '1' + assert mll_1.childNodes[1].childNodes[1].childNodes[0 + ].childNodes[0].childNodes[0].nodeValue == '2' + assert mll_1.childNodes[1].childNodes[2].childNodes[0 + ].childNodes[0].childNodes[0].nodeValue == '3' + mll_2 = mpp._print(B) + assert mll_2.childNodes[1].nodeName == 'mtable' + assert mll_2.childNodes[1].childNodes[0].nodeName == 'mtr' + assert len(mll_2.childNodes[1].childNodes) == 3 + assert mll_2.childNodes[1].childNodes[0].childNodes[0].nodeName == 'mtd' + assert len(mll_2.childNodes[1].childNodes[0].childNodes) == 3 + assert mll_2.childNodes[1].childNodes[0].childNodes[0 + ].childNodes[0].childNodes[0].nodeValue == '0' + assert mll_2.childNodes[1].childNodes[0].childNodes[1 + ].childNodes[0].childNodes[0].nodeValue == '5' + assert mll_2.childNodes[1].childNodes[0].childNodes[2 + ].childNodes[0].childNodes[0].nodeValue == '4' + assert mll_2.childNodes[1].childNodes[1].childNodes[0 + ].childNodes[0].childNodes[0].nodeValue == '2' + assert mll_2.childNodes[1].childNodes[1].childNodes[1 + ].childNodes[0].childNodes[0].nodeValue == '3' + assert mll_2.childNodes[1].childNodes[1].childNodes[2 + ].childNodes[0].childNodes[0].nodeValue == '1' + assert mll_2.childNodes[1].childNodes[2].childNodes[0 + ].childNodes[0].childNodes[0].nodeValue == '9' + assert mll_2.childNodes[1].childNodes[2].childNodes[1 + ].childNodes[0].childNodes[0].nodeValue == '7' + assert mll_2.childNodes[1].childNodes[2].childNodes[2 + ].childNodes[0].childNodes[0].nodeValue == '9' + + +def test_presentation_mathml_sums(): + mml_1 = mpp._print(Sum(x, (x, 1, 10))) + assert mml_1.childNodes[0].nodeName == 'munderover' + assert len(mml_1.childNodes[0].childNodes) == 3 + assert mml_1.childNodes[0].childNodes[0].childNodes[0 + ].nodeValue == '∑' + assert len(mml_1.childNodes[0].childNodes[1].childNodes) == 3 + assert mml_1.childNodes[0].childNodes[2].childNodes[0 + ].nodeValue == '10' + assert mml_1.childNodes[1].childNodes[0].nodeValue == 'x' + + assert mpp.doprint(Sum(x, (x, 1, 10))) == \ + 'x=110x' + assert mpp.doprint(Sum(x + y, (x, 1, 10))) == \ + 'x=110(x+y)' + + +def test_presentation_mathml_add(): + mml = mpp._print(x**5 - x**4 + x) + assert len(mml.childNodes) == 5 + assert mml.childNodes[0].childNodes[0].childNodes[0 + ].nodeValue == 'x' + assert mml.childNodes[0].childNodes[1].childNodes[0 + ].nodeValue == '5' + assert mml.childNodes[1].childNodes[0].nodeValue == '-' + assert mml.childNodes[2].childNodes[0].childNodes[0 + ].nodeValue == 'x' + assert mml.childNodes[2].childNodes[1].childNodes[0 + ].nodeValue == '4' + assert mml.childNodes[3].childNodes[0].nodeValue == '+' + assert mml.childNodes[4].childNodes[0].nodeValue == 'x' + + +def test_presentation_mathml_Rational(): + mml_1 = mpp._print(Rational(1, 1)) + assert mml_1.nodeName == 'mn' + + mml_2 = mpp._print(Rational(2, 5)) + assert mml_2.nodeName == 'mfrac' + assert mml_2.childNodes[0].childNodes[0].nodeValue == '2' + assert mml_2.childNodes[1].childNodes[0].nodeValue == '5' + + +def test_presentation_mathml_constants(): + mml = mpp._print(I) + assert mml.childNodes[0].nodeValue == 'ⅈ' + + mml = mpp._print(E) + assert mml.childNodes[0].nodeValue == 'ⅇ' + + mml = mpp._print(oo) + assert mml.childNodes[0].nodeValue == '∞' + + mml = mpp._print(pi) + assert mml.childNodes[0].nodeValue == 'π' + + assert mathml(hbar, printer='presentation') == '' + assert mathml(S.TribonacciConstant, printer='presentation' + ) == 'TribonacciConstant' + assert mathml(S.EulerGamma, printer='presentation' + ) == 'γ' + assert mathml(S.GoldenRatio, printer='presentation' + ) == 'Φ' + + assert mathml(zoo, printer='presentation') == \ + '~' + + assert mathml(S.NaN, printer='presentation') == 'NaN' + +def test_presentation_mathml_trig(): + mml = mpp._print(sin(x)) + assert mml.childNodes[0].childNodes[0].nodeValue == 'sin' + + mml = mpp._print(cos(x)) + assert mml.childNodes[0].childNodes[0].nodeValue == 'cos' + + mml = mpp._print(tan(x)) + assert mml.childNodes[0].childNodes[0].nodeValue == 'tan' + + mml = mpp._print(asin(x)) + assert mml.childNodes[0].childNodes[0].nodeValue == 'arcsin' + + mml = mpp._print(acos(x)) + assert mml.childNodes[0].childNodes[0].nodeValue == 'arccos' + + mml = mpp._print(atan(x)) + assert mml.childNodes[0].childNodes[0].nodeValue == 'arctan' + + mml = mpp._print(sinh(x)) + assert mml.childNodes[0].childNodes[0].nodeValue == 'sinh' + + mml = mpp._print(cosh(x)) + assert mml.childNodes[0].childNodes[0].nodeValue == 'cosh' + + mml = mpp._print(tanh(x)) + assert mml.childNodes[0].childNodes[0].nodeValue == 'tanh' + + mml = mpp._print(asinh(x)) + assert mml.childNodes[0].childNodes[0].nodeValue == 'arcsinh' + + mml = mpp._print(atanh(x)) + assert mml.childNodes[0].childNodes[0].nodeValue == 'arctanh' + + mml = mpp._print(acosh(x)) + assert mml.childNodes[0].childNodes[0].nodeValue == 'arccosh' + + +def test_presentation_mathml_relational(): + mml_1 = mpp._print(Eq(x, 1)) + assert len(mml_1.childNodes) == 3 + assert mml_1.childNodes[0].nodeName == 'mi' + assert mml_1.childNodes[0].childNodes[0].nodeValue == 'x' + assert mml_1.childNodes[1].nodeName == 'mo' + assert mml_1.childNodes[1].childNodes[0].nodeValue == '=' + assert mml_1.childNodes[2].nodeName == 'mn' + assert mml_1.childNodes[2].childNodes[0].nodeValue == '1' + + mml_2 = mpp._print(Ne(1, x)) + assert len(mml_2.childNodes) == 3 + assert mml_2.childNodes[0].nodeName == 'mn' + assert mml_2.childNodes[0].childNodes[0].nodeValue == '1' + assert mml_2.childNodes[1].nodeName == 'mo' + assert mml_2.childNodes[1].childNodes[0].nodeValue == '≠' + assert mml_2.childNodes[2].nodeName == 'mi' + assert mml_2.childNodes[2].childNodes[0].nodeValue == 'x' + + mml_3 = mpp._print(Ge(1, x)) + assert len(mml_3.childNodes) == 3 + assert mml_3.childNodes[0].nodeName == 'mn' + assert mml_3.childNodes[0].childNodes[0].nodeValue == '1' + assert mml_3.childNodes[1].nodeName == 'mo' + assert mml_3.childNodes[1].childNodes[0].nodeValue == '≥' + assert mml_3.childNodes[2].nodeName == 'mi' + assert mml_3.childNodes[2].childNodes[0].nodeValue == 'x' + + mml_4 = mpp._print(Lt(1, x)) + assert len(mml_4.childNodes) == 3 + assert mml_4.childNodes[0].nodeName == 'mn' + assert mml_4.childNodes[0].childNodes[0].nodeValue == '1' + assert mml_4.childNodes[1].nodeName == 'mo' + assert mml_4.childNodes[1].childNodes[0].nodeValue == '<' + assert mml_4.childNodes[2].nodeName == 'mi' + assert mml_4.childNodes[2].childNodes[0].nodeValue == 'x' + + +def test_presentation_symbol(): + mml = mpp._print(x) + assert mml.nodeName == 'mi' + assert mml.childNodes[0].nodeValue == 'x' + del mml + + mml = mpp._print(Symbol("x^2")) + assert mml.nodeName == 'msup' + assert mml.childNodes[0].nodeName == 'mi' + assert mml.childNodes[0].childNodes[0].nodeValue == 'x' + assert mml.childNodes[1].nodeName == 'mi' + assert mml.childNodes[1].childNodes[0].nodeValue == '2' + del mml + + mml = mpp._print(Symbol("x__2")) + assert mml.nodeName == 'msup' + assert mml.childNodes[0].nodeName == 'mi' + assert mml.childNodes[0].childNodes[0].nodeValue == 'x' + assert mml.childNodes[1].nodeName == 'mi' + assert mml.childNodes[1].childNodes[0].nodeValue == '2' + del mml + + mml = mpp._print(Symbol("x_2")) + assert mml.nodeName == 'msub' + assert mml.childNodes[0].nodeName == 'mi' + assert mml.childNodes[0].childNodes[0].nodeValue == 'x' + assert mml.childNodes[1].nodeName == 'mi' + assert mml.childNodes[1].childNodes[0].nodeValue == '2' + del mml + + mml = mpp._print(Symbol("x^3_2")) + assert mml.nodeName == 'msubsup' + assert mml.childNodes[0].nodeName == 'mi' + assert mml.childNodes[0].childNodes[0].nodeValue == 'x' + assert mml.childNodes[1].nodeName == 'mi' + assert mml.childNodes[1].childNodes[0].nodeValue == '2' + assert mml.childNodes[2].nodeName == 'mi' + assert mml.childNodes[2].childNodes[0].nodeValue == '3' + del mml + + mml = mpp._print(Symbol("x__3_2")) + assert mml.nodeName == 'msubsup' + assert mml.childNodes[0].nodeName == 'mi' + assert mml.childNodes[0].childNodes[0].nodeValue == 'x' + assert mml.childNodes[1].nodeName == 'mi' + assert mml.childNodes[1].childNodes[0].nodeValue == '2' + assert mml.childNodes[2].nodeName == 'mi' + assert mml.childNodes[2].childNodes[0].nodeValue == '3' + del mml + + mml = mpp._print(Symbol("x_2_a")) + assert mml.nodeName == 'msub' + assert mml.childNodes[0].nodeName == 'mi' + assert mml.childNodes[0].childNodes[0].nodeValue == 'x' + assert mml.childNodes[1].nodeName == 'mrow' + assert mml.childNodes[1].childNodes[0].nodeName == 'mi' + assert mml.childNodes[1].childNodes[0].childNodes[0].nodeValue == '2' + assert mml.childNodes[1].childNodes[1].nodeName == 'mo' + assert mml.childNodes[1].childNodes[1].childNodes[0].nodeValue == ' ' + assert mml.childNodes[1].childNodes[2].nodeName == 'mi' + assert mml.childNodes[1].childNodes[2].childNodes[0].nodeValue == 'a' + del mml + + mml = mpp._print(Symbol("x^2^a")) + assert mml.nodeName == 'msup' + assert mml.childNodes[0].nodeName == 'mi' + assert mml.childNodes[0].childNodes[0].nodeValue == 'x' + assert mml.childNodes[1].nodeName == 'mrow' + assert mml.childNodes[1].childNodes[0].nodeName == 'mi' + assert mml.childNodes[1].childNodes[0].childNodes[0].nodeValue == '2' + assert mml.childNodes[1].childNodes[1].nodeName == 'mo' + assert mml.childNodes[1].childNodes[1].childNodes[0].nodeValue == ' ' + assert mml.childNodes[1].childNodes[2].nodeName == 'mi' + assert mml.childNodes[1].childNodes[2].childNodes[0].nodeValue == 'a' + del mml + + mml = mpp._print(Symbol("x__2__a")) + assert mml.nodeName == 'msup' + assert mml.childNodes[0].nodeName == 'mi' + assert mml.childNodes[0].childNodes[0].nodeValue == 'x' + assert mml.childNodes[1].nodeName == 'mrow' + assert mml.childNodes[1].childNodes[0].nodeName == 'mi' + assert mml.childNodes[1].childNodes[0].childNodes[0].nodeValue == '2' + assert mml.childNodes[1].childNodes[1].nodeName == 'mo' + assert mml.childNodes[1].childNodes[1].childNodes[0].nodeValue == ' ' + assert mml.childNodes[1].childNodes[2].nodeName == 'mi' + assert mml.childNodes[1].childNodes[2].childNodes[0].nodeValue == 'a' + del mml + + +def test_presentation_mathml_greek(): + mml = mpp._print(Symbol('alpha')) + assert mml.nodeName == 'mi' + assert mml.childNodes[0].nodeValue == '\N{GREEK SMALL LETTER ALPHA}' + + assert mpp.doprint(Symbol('alpha')) == 'α' + assert mpp.doprint(Symbol('beta')) == 'β' + assert mpp.doprint(Symbol('gamma')) == 'γ' + assert mpp.doprint(Symbol('delta')) == 'δ' + assert mpp.doprint(Symbol('epsilon')) == 'ε' + assert mpp.doprint(Symbol('zeta')) == 'ζ' + assert mpp.doprint(Symbol('eta')) == 'η' + assert mpp.doprint(Symbol('theta')) == 'θ' + assert mpp.doprint(Symbol('iota')) == 'ι' + assert mpp.doprint(Symbol('kappa')) == 'κ' + assert mpp.doprint(Symbol('lambda')) == 'λ' + assert mpp.doprint(Symbol('mu')) == 'μ' + assert mpp.doprint(Symbol('nu')) == 'ν' + assert mpp.doprint(Symbol('xi')) == 'ξ' + assert mpp.doprint(Symbol('omicron')) == 'ο' + assert mpp.doprint(Symbol('pi')) == 'π' + assert mpp.doprint(Symbol('rho')) == 'ρ' + assert mpp.doprint(Symbol('varsigma')) == 'ς' + assert mpp.doprint(Symbol('sigma')) == 'σ' + assert mpp.doprint(Symbol('tau')) == 'τ' + assert mpp.doprint(Symbol('upsilon')) == 'υ' + assert mpp.doprint(Symbol('phi')) == 'φ' + assert mpp.doprint(Symbol('chi')) == 'χ' + assert mpp.doprint(Symbol('psi')) == 'ψ' + assert mpp.doprint(Symbol('omega')) == 'ω' + + assert mpp.doprint(Symbol('Alpha')) == 'Α' + assert mpp.doprint(Symbol('Beta')) == 'Β' + assert mpp.doprint(Symbol('Gamma')) == 'Γ' + assert mpp.doprint(Symbol('Delta')) == 'Δ' + assert mpp.doprint(Symbol('Epsilon')) == 'Ε' + assert mpp.doprint(Symbol('Zeta')) == 'Ζ' + assert mpp.doprint(Symbol('Eta')) == 'Η' + assert mpp.doprint(Symbol('Theta')) == 'Θ' + assert mpp.doprint(Symbol('Iota')) == 'Ι' + assert mpp.doprint(Symbol('Kappa')) == 'Κ' + assert mpp.doprint(Symbol('Lambda')) == 'Λ' + assert mpp.doprint(Symbol('Mu')) == 'Μ' + assert mpp.doprint(Symbol('Nu')) == 'Ν' + assert mpp.doprint(Symbol('Xi')) == 'Ξ' + assert mpp.doprint(Symbol('Omicron')) == 'Ο' + assert mpp.doprint(Symbol('Pi')) == 'Π' + assert mpp.doprint(Symbol('Rho')) == 'Ρ' + assert mpp.doprint(Symbol('Sigma')) == 'Σ' + assert mpp.doprint(Symbol('Tau')) == 'Τ' + assert mpp.doprint(Symbol('Upsilon')) == 'Υ' + assert mpp.doprint(Symbol('Phi')) == 'Φ' + assert mpp.doprint(Symbol('Chi')) == 'Χ' + assert mpp.doprint(Symbol('Psi')) == 'Ψ' + assert mpp.doprint(Symbol('Omega')) == 'Ω' + + +def test_presentation_mathml_order(): + expr = x**3 + x**2*y + 3*x*y**3 + y**4 + + mp = MathMLPresentationPrinter({'order': 'lex'}) + mml = mp._print(expr) + assert mml.childNodes[0].nodeName == 'msup' + assert mml.childNodes[0].childNodes[0].childNodes[0].nodeValue == 'x' + assert mml.childNodes[0].childNodes[1].childNodes[0].nodeValue == '3' + + assert mml.childNodes[6].nodeName == 'msup' + assert mml.childNodes[6].childNodes[0].childNodes[0].nodeValue == 'y' + assert mml.childNodes[6].childNodes[1].childNodes[0].nodeValue == '4' + + mp = MathMLPresentationPrinter({'order': 'rev-lex'}) + mml = mp._print(expr) + + assert mml.childNodes[0].nodeName == 'msup' + assert mml.childNodes[0].childNodes[0].childNodes[0].nodeValue == 'y' + assert mml.childNodes[0].childNodes[1].childNodes[0].nodeValue == '4' + + assert mml.childNodes[6].nodeName == 'msup' + assert mml.childNodes[6].childNodes[0].childNodes[0].nodeValue == 'x' + assert mml.childNodes[6].childNodes[1].childNodes[0].nodeValue == '3' + + +def test_print_intervals(): + a = Symbol('a', real=True) + assert mpp.doprint(Interval(0, a)) == \ + '[0,a]' + assert mpp.doprint(Interval(0, a, False, False)) == \ + '[0,a]' + assert mpp.doprint(Interval(0, a, True, False)) == \ + '(0,a]' + assert mpp.doprint(Interval(0, a, False, True)) == \ + '[0,a)' + assert mpp.doprint(Interval(0, a, True, True)) == \ + '(0,a)' + + +def test_print_tuples(): + assert mpp.doprint(Tuple(0,)) == \ + '(0)' + assert mpp.doprint(Tuple(0, a)) == \ + '(0,a)' + assert mpp.doprint(Tuple(0, a, a)) == \ + '(0,a,a)' + assert mpp.doprint(Tuple(0, 1, 2, 3, 4)) == \ + '(0,1,2,3,4)' + assert mpp.doprint(Tuple(0, 1, Tuple(2, 3, 4))) == \ + '(0,1,(2,3'\ + ',4))' + + +def test_print_re_im(): + assert mpp.doprint(re(x)) == \ + '(x)' + assert mpp.doprint(im(x)) == \ + '(x)' + assert mpp.doprint(re(x + 1, evaluate=False)) == \ + '(x+1)' + assert mpp.doprint(im(x + 1, evaluate=False)) == \ + '(x+1)' + + +def test_print_Abs(): + assert mpp.doprint(Abs(x)) == \ + '|x|' + assert mpp.doprint(Abs(x + 1)) == \ + '|x+1|' + + +def test_print_Determinant(): + assert mpp.doprint(Determinant(Matrix([[1, 2], [3, 4]]))) == \ + '|[1234]|' + + +def test_presentation_settings(): + raises(TypeError, lambda: mathml(x, printer='presentation', + method="garbage")) + + +def test_print_domains(): + from sympy.sets import Integers, Naturals, Naturals0, Reals, Complexes + + assert mpp.doprint(Complexes) == '' + assert mpp.doprint(Integers) == '' + assert mpp.doprint(Naturals) == '' + assert mpp.doprint(Naturals0) == \ + '0' + assert mpp.doprint(Reals) == '' + + +def test_print_expression_with_minus(): + assert mpp.doprint(-x) == '-x' + assert mpp.doprint(-x/y) == \ + '-xy' + assert mpp.doprint(-Rational(1, 2)) == \ + '-12' + + +def test_print_AssocOp(): + from sympy.core.operations import AssocOp + + class TestAssocOp(AssocOp): + identity = 0 + + expr = TestAssocOp(1, 2) + assert mpp.doprint(expr) == \ + 'testassocop12' + + +def test_print_basic(): + expr = Basic(S(1), S(2)) + assert mpp.doprint(expr) == \ + 'basic(1,2)' + assert mp.doprint(expr) == '12' + + +def test_mat_delim_print(): + expr = Matrix([[1, 2], [3, 4]]) + assert mathml(expr, printer='presentation', mat_delim='[') == \ + '[1'\ + '234'\ + ']' + assert mathml(expr, printer='presentation', mat_delim='(') == \ + '(12'\ + '34)' + assert mathml(expr, printer='presentation', mat_delim='') == \ + '12'\ + '34' + + +def test_ln_notation_print(): + expr = log(x) + assert mathml(expr, printer='presentation') == \ + 'log(x)' + assert mathml(expr, printer='presentation', ln_notation=False) == \ + 'log(x)' + assert mathml(expr, printer='presentation', ln_notation=True) == \ + 'ln(x)' + + +def test_mul_symbol_print(): + expr = x * y + assert mathml(expr, printer='presentation') == \ + 'xy' + assert mathml(expr, printer='presentation', mul_symbol=None) == \ + 'xy' + assert mathml(expr, printer='presentation', mul_symbol='dot') == \ + 'x·y' + assert mathml(expr, printer='presentation', mul_symbol='ldot') == \ + 'xy' + assert mathml(expr, printer='presentation', mul_symbol='times') == \ + 'x×y' + + +def test_print_lerchphi(): + assert mpp.doprint(lerchphi(1, 2, 3)) == \ + 'Φ(1,2,3)' + + +def test_print_polylog(): + assert mp.doprint(polylog(x, y)) == \ + 'xy' + assert mpp.doprint(polylog(x, y)) == \ + 'Lix(y)' + + +def test_print_set_frozenset(): + f = frozenset({1, 5, 3}) + assert mpp.doprint(f) == \ + '{1,3,5}' + s = set({1, 2, 3}) + assert mpp.doprint(s) == \ + '{1,2,3}' + + +def test_print_FiniteSet(): + f1 = FiniteSet(x, 1, 3) + assert mpp.doprint(f1) == \ + '{1,3,x}' + + +def test_print_LambertW(): + assert mpp.doprint(LambertW(x)) == 'W(x)' + assert mpp.doprint(LambertW(x, y)) == 'W(x,y)' + + +def test_print_EmptySet(): + assert mpp.doprint(S.EmptySet) == '' + + +def test_print_UniversalSet(): + assert mpp.doprint(S.UniversalSet) == '𝕌' + + +def test_print_spaces(): + assert mpp.doprint(HilbertSpace()) == '' + assert mpp.doprint(ComplexSpace(2)) == '𝒞2' + assert mpp.doprint(FockSpace()) == '' + + +def test_print_constants(): + assert mpp.doprint(hbar) == '' + assert mpp.doprint(S.TribonacciConstant) == 'TribonacciConstant' + assert mpp.doprint(S.GoldenRatio) == 'Φ' + assert mpp.doprint(S.EulerGamma) == 'γ' + + +def test_print_Contains(): + assert mpp.doprint(Contains(x, S.Naturals)) == \ + 'x' + + +def test_print_Dagger(): + x = symbols('x', commutative=False) + assert mpp.doprint(Dagger(x)) == 'x' + + +def test_print_SetOp(): + f1 = FiniteSet(x, 1, 3) + f2 = FiniteSet(y, 2, 4) + + prntr = lambda x: mathml(x, printer='presentation') + + assert prntr(Union(f1, f2, evaluate=False)) == \ + '{1,3,x'\ + '}{2,'\ + '4,y}' + assert prntr(Intersection(f1, f2, evaluate=False)) == \ + '{1,3,x'\ + '}{2'\ + ',4,y}' + assert prntr(Complement(f1, f2, evaluate=False)) == \ + '{1,3,x'\ + '}{2'\ + ',4,y}' + assert prntr(SymmetricDifference(f1, f2, evaluate=False)) == \ + '{1,3,x'\ + '}{2'\ + ',4,y}' + + A = FiniteSet(a) + C = FiniteSet(c) + D = FiniteSet(d) + + U1 = Union(C, D, evaluate=False) + I1 = Intersection(C, D, evaluate=False) + C1 = Complement(C, D, evaluate=False) + D1 = SymmetricDifference(C, D, evaluate=False) + # XXX ProductSet does not support evaluate keyword + P1 = ProductSet(C, D) + + assert prntr(Union(A, I1, evaluate=False)) == \ + '{a}' \ + '({' \ + 'c}{' \ + 'd})' + assert prntr(Intersection(A, C1, evaluate=False)) == \ + '{a}' \ + '({' \ + 'c}{' \ + 'd})' + assert prntr(Complement(A, D1, evaluate=False)) == \ + '{a}' \ + '({' \ + 'c}{' \ + 'd})' + assert prntr(SymmetricDifference(A, P1, evaluate=False)) == \ + '{a}' \ + '({' \ + 'c}×{' \ + 'd})' + assert prntr(ProductSet(A, U1)) == \ + '{a}' \ + '×({' \ + 'c}{' \ + 'd})' + + +def test_print_logic(): + assert mpp.doprint(And(x, y)) == \ + 'xy' + assert mpp.doprint(Or(x, y)) == \ + 'xy' + assert mpp.doprint(Xor(x, y)) == \ + 'xy' + assert mpp.doprint(Implies(x, y)) == \ + 'xy' + assert mpp.doprint(Equivalent(x, y)) == \ + 'xy' + + assert mpp.doprint(And(Eq(x, y), x > 4)) == \ + 'x=y'\ + 'x>4' + assert mpp.doprint(And(Eq(x, 3), y < 3, x > y + 1)) == \ + 'x=3'\ + 'x>y+1'\ + 'y<3' + assert mpp.doprint(Or(Eq(x, y), x > 4)) == \ + 'x=y'\ + 'x>4' + assert mpp.doprint(And(Eq(x, 3), Or(y < 3, x > y + 1))) == \ + 'x=3'\ + '(x>'\ + 'y+1'\ + 'y<3)' + + assert mpp.doprint(Not(x)) == '¬x' + assert mpp.doprint(Not(And(x, y))) == \ + '¬(xy)' + + +def test_root_notation_print(): + assert mathml(x**(S.One/3), printer='presentation') == \ + 'x3' + assert mathml(x**(S.One/3), printer='presentation', root_notation=False) ==\ + 'x13' + assert mathml(x**(S.One/3), printer='content') == \ + '3x' + assert mathml(x**(S.One/3), printer='content', root_notation=False) == \ + 'x13' + assert mathml(x**(Rational(-1, 3)), printer='presentation') == \ + '1x3' + assert mathml(x**(Rational(-1, 3)), printer='presentation', root_notation=False) \ + == '1x13' + + +def test_fold_frac_powers_print(): + expr = x ** Rational(5, 2) + assert mathml(expr, printer='presentation') == \ + 'x52' + assert mathml(expr, printer='presentation', fold_frac_powers=True) == \ + 'x52' + assert mathml(expr, printer='presentation', fold_frac_powers=False) == \ + 'x52' + + +def test_fold_short_frac_print(): + expr = Rational(2, 5) + assert mathml(expr, printer='presentation') == \ + '25' + assert mathml(expr, printer='presentation', fold_short_frac=True) == \ + '25' + assert mathml(expr, printer='presentation', fold_short_frac=False) == \ + '25' + + +def test_print_factorials(): + assert mpp.doprint(factorial(x)) == 'x!' + assert mpp.doprint(factorial(x + 1)) == \ + '(x+1)!' + assert mpp.doprint(factorial2(x)) == 'x!!' + assert mpp.doprint(factorial2(x + 1)) == \ + '(x+1)!!' + assert mpp.doprint(binomial(x, y)) == \ + '(xy)' + assert mpp.doprint(binomial(4, x + y)) == \ + '(4x'\ + '+y)' + + +def test_print_floor(): + expr = floor(x) + assert mathml(expr, printer='presentation') == \ + 'x' + + +def test_print_ceiling(): + expr = ceiling(x) + assert mathml(expr, printer='presentation') == \ + 'x' + + +def test_print_Lambda(): + expr = Lambda(x, x+1) + assert mathml(expr, printer='presentation') == \ + '(xx+1)' + expr = Lambda((x, y), x + y) + assert mathml(expr, printer='presentation') == \ + '((x,y)x+y)' + + +def test_print_conjugate(): + assert mpp.doprint(conjugate(x)) == \ + 'x' + assert mpp.doprint(conjugate(x + 1)) == \ + 'x+1' + + +def test_print_AccumBounds(): + a = Symbol('a', real=True) + assert mpp.doprint(AccumBounds(0, 1)) == '0,1' + assert mpp.doprint(AccumBounds(0, a)) == '0,a' + assert mpp.doprint(AccumBounds(a + 1, a + 2)) == 'a+1,a+2' + + +def test_print_Float(): + assert mpp.doprint(Float(1e100)) == '1.0·10100' + assert mpp.doprint(Float(1e-100)) == '1.0·10-100' + assert mpp.doprint(Float(-1e100)) == '-1.0·10100' + assert mpp.doprint(Float(1.0*oo)) == '' + assert mpp.doprint(Float(-1.0*oo)) == '-' + + +def test_print_different_functions(): + assert mpp.doprint(gamma(x)) == 'Γ(x)' + assert mpp.doprint(lowergamma(x, y)) == 'γ(x,y)' + assert mpp.doprint(uppergamma(x, y)) == 'Γ(x,y)' + assert mpp.doprint(zeta(x)) == 'ζ(x)' + assert mpp.doprint(zeta(x, y)) == 'ζ(x,y)' + assert mpp.doprint(dirichlet_eta(x)) == 'η(x)' + assert mpp.doprint(elliptic_k(x)) == 'Κ(x)' + assert mpp.doprint(totient(x)) == 'ϕ(x)' + assert mpp.doprint(reduced_totient(x)) == 'λ(x)' + assert mpp.doprint(primenu(x)) == 'ν(x)' + assert mpp.doprint(primeomega(x)) == 'Ω(x)' + assert mpp.doprint(fresnels(x)) == 'S(x)' + assert mpp.doprint(fresnelc(x)) == 'C(x)' + assert mpp.doprint(Heaviside(x)) == 'Θ(x,12)' + + +def test_mathml_builtins(): + assert mpp.doprint(None) == 'None' + assert mpp.doprint(true) == 'True' + assert mpp.doprint(false) == 'False' + + +def test_mathml_Range(): + assert mpp.doprint(Range(1, 51)) == \ + '{1,2,,50}' + assert mpp.doprint(Range(1, 4)) == \ + '{1,2,3}' + assert mpp.doprint(Range(0, 3, 1)) == \ + '{0,1,2}' + assert mpp.doprint(Range(0, 30, 1)) == \ + '{0,1,,29}' + assert mpp.doprint(Range(30, 1, -1)) == \ + '{30,29,,2}' + assert mpp.doprint(Range(0, oo, 2)) == \ + '{0,2,}' + assert mpp.doprint(Range(oo, -2, -2)) == \ + '{,2,0}' + assert mpp.doprint(Range(-2, -oo, -1)) == \ + '{-2,-3,}' + + +def test_print_exp(): + assert mpp.doprint(exp(x)) == \ + 'x' + assert mpp.doprint(exp(1) + exp(2)) == \ + '+2' + + +def test_print_MinMax(): + assert mpp.doprint(Min(x, y)) == \ + 'min(x,y)' + assert mpp.doprint(Min(x, 2, x**3)) == \ + 'min(2,x,x3)' + assert mpp.doprint(Max(x, y)) == \ + 'max(x,y)' + assert mpp.doprint(Max(x, 2, x**3)) == \ + 'max(2,x,x3)' + + +def test_mathml_presentation_numbers(): + n = Symbol('n') + assert mathml(catalan(n), printer='presentation') == \ + 'Cn' + assert mathml(bernoulli(n), printer='presentation') == \ + 'Bn' + assert mathml(bell(n), printer='presentation') == \ + 'Bn' + assert mathml(euler(n), printer='presentation') == \ + 'En' + assert mathml(fibonacci(n), printer='presentation') == \ + 'Fn' + assert mathml(lucas(n), printer='presentation') == \ + 'Ln' + assert mathml(tribonacci(n), printer='presentation') == \ + 'Tn' + assert mathml(bernoulli(n, x), printer='presentation') == \ + mathml(bell(n, x), printer='presentation') == \ + 'Bn(x)' + assert mathml(euler(n, x), printer='presentation') == \ + 'En(x)' + assert mathml(fibonacci(n, x), printer='presentation') == \ + 'Fn(x)' + assert mathml(tribonacci(n, x), printer='presentation') == \ + 'Tn(x)' + + +def test_mathml_presentation_mathieu(): + assert mathml(mathieuc(x, y, z), printer='presentation') == \ + 'C(x,y,z)' + assert mathml(mathieus(x, y, z), printer='presentation') == \ + 'S(x,y,z)' + assert mathml(mathieucprime(x, y, z), printer='presentation') == \ + 'C′(x,y,z)' + assert mathml(mathieusprime(x, y, z), printer='presentation') == \ + 'S′(x,y,z)' + + +def test_mathml_presentation_stieltjes(): + assert mathml(stieltjes(n), printer='presentation') == \ + 'γn' + assert mathml(stieltjes(n, x), printer='presentation') == \ + 'γn(x)' + + +def test_print_matrix_symbol(): + A = MatrixSymbol('A', 1, 2) + assert mpp.doprint(A) == 'A' + assert mp.doprint(A) == 'A' + assert mathml(A, printer='presentation', mat_symbol_style="bold") == \ + 'A' + # No effect in content printer + assert mathml(A, mat_symbol_style="bold") == 'A' + + +def test_print_hadamard(): + from sympy.matrices.expressions import HadamardProduct + from sympy.matrices.expressions import Transpose + + X = MatrixSymbol('X', 2, 2) + Y = MatrixSymbol('Y', 2, 2) + + assert mathml(HadamardProduct(X, Y*Y), printer="presentation") == \ + '' \ + 'X' \ + '' \ + 'Y2' \ + '' + + assert mathml(HadamardProduct(X, Y)*Y, printer="presentation") == \ + '' \ + '(' \ + 'XY' \ + ')' \ + 'Y' \ + '' + + assert mathml(HadamardProduct(X, Y, Y), printer="presentation") == \ + '' \ + 'X' \ + 'Y' \ + 'Y' \ + '' + + assert mathml( + Transpose(HadamardProduct(X, Y)), printer="presentation") == \ + '' \ + '(' \ + 'XY' \ + ')' \ + 'T' \ + '' + + +def test_print_random_symbol(): + R = RandomSymbol(Symbol('R')) + assert mpp.doprint(R) == 'R' + assert mp.doprint(R) == 'R' + + +def test_print_IndexedBase(): + assert mathml(IndexedBase(a)[b], printer='presentation') == \ + 'ab' + assert mathml(IndexedBase(a)[b, c, d], printer='presentation') == \ + 'a(b,c,d)' + assert mathml(IndexedBase(a)[b]*IndexedBase(c)[d]*IndexedBase(e), + printer='presentation') == \ + 'ab⁢'\ + 'cde' + + +def test_print_Indexed(): + assert mathml(IndexedBase(a), printer='presentation') == 'a' + assert mathml(IndexedBase(a/b), printer='presentation') == \ + 'ab' + assert mathml(IndexedBase((a, b)), printer='presentation') == \ + '(a,b)' + +def test_print_MatrixElement(): + i, j = symbols('i j') + A = MatrixSymbol('A', i, j) + assert mathml(A[0,0],printer = 'presentation') == \ + 'A0,0' + assert mathml(A[i,j], printer = 'presentation') == \ + 'Ai,j' + assert mathml(A[i*j,0], printer = 'presentation') == \ + 'Aij,0' + + +def test_print_Vector(): + ACS = CoordSys3D('A') + assert mathml(Cross(ACS.i, ACS.j*ACS.x*3 + ACS.k), printer='presentation') == \ + 'i^'\ + 'A×('\ + '(3'\ + 'xA'\ + ')'\ + 'j^'\ + 'A+'\ + 'k^'\ + 'A)' + assert mathml(Cross(ACS.i, ACS.j), printer='presentation') == \ + 'i^'\ + 'A×'\ + 'j^'\ + 'A' + assert mathml(x*Cross(ACS.i, ACS.j), printer='presentation') == \ + 'x('\ + 'i^'\ + 'A×'\ + 'j^'\ + 'A)' + assert mathml(Cross(x*ACS.i, ACS.j), printer='presentation') == \ + '-j'\ + '^A'\ + '×((x)'\ + 'i'\ + '^A'\ + ')' + assert mathml(Curl(3*ACS.x*ACS.j), printer='presentation') == \ + '×(('\ + '3x'\ + 'A)'\ + 'j^'\ + 'A)' + assert mathml(Curl(3*x*ACS.x*ACS.j), printer='presentation') == \ + '×(('\ + '3x'\ + 'A'\ + 'x)'\ + 'j^'\ + 'A)' + assert mathml(x*Curl(3*ACS.x*ACS.j), printer='presentation') == \ + 'x('\ + '×((3'\ + 'x'\ + 'A)'\ + 'j'\ + '^A)'\ + ')' + assert mathml(Curl(3*x*ACS.x*ACS.j + ACS.i), printer='presentation') == \ + '×('\ + 'i^'\ + 'A+('\ + '3x'\ + 'A'\ + 'x)'\ + 'j^'\ + 'A)' + assert mathml(Divergence(3*ACS.x*ACS.j), printer='presentation') == \ + '·(('\ + '3x'\ + 'A)'\ + 'j'\ + '^A)' + assert mathml(x*Divergence(3*ACS.x*ACS.j), printer='presentation') == \ + 'x('\ + '·((3'\ + 'x'\ + 'A)'\ + 'j'\ + '^A'\ + '))' + assert mathml(Divergence(3*x*ACS.x*ACS.j + ACS.i), printer='presentation') == \ + '·('\ + 'i^'\ + 'A+('\ + '3'\ + 'xA'\ + 'x)'\ + 'j'\ + '^A'\ + ')' + assert mathml(Dot(ACS.i, ACS.j*ACS.x*3+ACS.k), printer='presentation') == \ + 'i^'\ + 'A·('\ + '(3'\ + 'xA'\ + ')'\ + 'j^'\ + 'A+'\ + 'k^'\ + 'A)' + assert mathml(Dot(ACS.i, ACS.j), printer='presentation') == \ + 'i^'\ + 'A·'\ + 'j^'\ + 'A' + assert mathml(Dot(x*ACS.i, ACS.j), printer='presentation') == \ + 'j^'\ + 'A·('\ + '(x)'\ + 'i^'\ + 'A)' + assert mathml(x*Dot(ACS.i, ACS.j), printer='presentation') == \ + 'x('\ + 'i^'\ + 'A·'\ + 'j^'\ + 'A)' + assert mathml(Gradient(ACS.x), printer='presentation') == \ + 'x'\ + 'A' + assert mathml(Gradient(ACS.x + 3*ACS.y), printer='presentation') == \ + '('\ + 'xA+3'\ + 'y'\ + 'A)' + assert mathml(x*Gradient(ACS.x), printer='presentation') == \ + 'x('\ + 'xA'\ + ')' + assert mathml(Gradient(x*ACS.x), printer='presentation') == \ + '('\ + 'xA'\ + 'x)' + assert mathml(Cross(ACS.z, ACS.x), printer='presentation') == \ + '-x'\ + 'A×'\ + 'zA' + assert mathml(Laplacian(ACS.x), printer='presentation') == \ + 'x'\ + 'A' + assert mathml(Laplacian(ACS.x + 3*ACS.y), printer='presentation') == \ + '('\ + 'xA+3'\ + 'y'\ + 'A)' + assert mathml(x*Laplacian(ACS.x), printer='presentation') == \ + 'x('\ + 'xA'\ + ')' + assert mathml(Laplacian(x*ACS.x), printer='presentation') == \ + '('\ + 'xA'\ + 'x)' + +@XFAIL +def test_vector_cross_xfail(): + ACS = CoordSys3D('A') + assert mathml(Cross(ACS.x, ACS.z) + Cross(ACS.z, ACS.x), printer='presentation') == \ + '0^' + +def test_print_elliptic_f(): + assert mathml(elliptic_f(x, y), printer = 'presentation') == \ + '𝖥(x|y)' + assert mathml(elliptic_f(x/y, y), printer = 'presentation') == \ + '𝖥(xy|y)' + +def test_print_elliptic_e(): + assert mathml(elliptic_e(x), printer = 'presentation') == \ + '𝖤(x)' + assert mathml(elliptic_e(x, y), printer = 'presentation') == \ + '𝖤(x|y)' + +def test_print_elliptic_pi(): + assert mathml(elliptic_pi(x, y), printer = 'presentation') == \ + '𝛱(x|y)' + assert mathml(elliptic_pi(x, y, z), printer = 'presentation') == \ + '𝛱(x;y|z)' + +def test_print_Ei(): + assert mathml(Ei(x), printer = 'presentation') == \ + 'Ei(x)' + assert mathml(Ei(x**y), printer = 'presentation') == \ + 'Ei(xy)' + +def test_print_expint(): + assert mathml(expint(x, y), printer = 'presentation') == \ + 'Ex(y)' + assert mathml(expint(IndexedBase(x)[1], IndexedBase(x)[2]), printer = 'presentation') == \ + 'Ex1(x2)' + +def test_print_jacobi(): + assert mathml(jacobi(n, a, b, x), printer = 'presentation') == \ + 'Pn(a,b)(x)' + +def test_print_gegenbauer(): + assert mathml(gegenbauer(n, a, x), printer = 'presentation') == \ + 'Cn(a)(x)' + +def test_print_chebyshevt(): + assert mathml(chebyshevt(n, x), printer = 'presentation') == \ + 'Tn(x)' + +def test_print_chebyshevu(): + assert mathml(chebyshevu(n, x), printer = 'presentation') == \ + 'Un(x)' + +def test_print_legendre(): + assert mathml(legendre(n, x), printer = 'presentation') == \ + 'Pn(x)' + +def test_print_assoc_legendre(): + assert mathml(assoc_legendre(n, a, x), printer = 'presentation') == \ + 'Pn(a)(x)' + +def test_print_laguerre(): + assert mathml(laguerre(n, x), printer = 'presentation') == \ + 'Ln(x)' + +def test_print_assoc_laguerre(): + assert mathml(assoc_laguerre(n, a, x), printer = 'presentation') == \ + 'Ln(a)(x)' + +def test_print_hermite(): + assert mathml(hermite(n, x), printer = 'presentation') == \ + 'Hn(x)' + +def test_mathml_SingularityFunction(): + assert mathml(SingularityFunction(x, 4, 5), printer='presentation') == \ + 'x-45' + assert mathml(SingularityFunction(x, -3, 4), printer='presentation') == \ + 'x+34' + assert mathml(SingularityFunction(x, 0, 4), printer='presentation') == \ + 'x4' + assert mathml(SingularityFunction(x, a, n), printer='presentation') == \ + '-a+xn' + assert mathml(SingularityFunction(x, 4, -2), printer='presentation') == \ + 'x-4-2' + assert mathml(SingularityFunction(x, 4, -1), printer='presentation') == \ + 'x-4-1' + + +def test_mathml_matrix_functions(): + from sympy.matrices import Adjoint, Inverse, Transpose + X = MatrixSymbol('X', 2, 2) + Y = MatrixSymbol('Y', 2, 2) + assert mathml(Adjoint(X), printer='presentation') == \ + 'X' + assert mathml(Adjoint(X + Y), printer='presentation') == \ + '(X+Y)' + assert mathml(Adjoint(X) + Adjoint(Y), printer='presentation') == \ + 'X+' \ + 'Y' + assert mathml(Adjoint(X*Y), printer='presentation') == \ + '(X' \ + 'Y)' + assert mathml(Adjoint(Y)*Adjoint(X), printer='presentation') == \ + 'Y⁢' \ + 'X' + assert mathml(Adjoint(X**2), printer='presentation') == \ + '(X2)' + assert mathml(Adjoint(X)**2, printer='presentation') == \ + '(X)2' + assert mathml(Adjoint(Inverse(X)), printer='presentation') == \ + '(X-1)' + assert mathml(Inverse(Adjoint(X)), printer='presentation') == \ + '(X)-1' + assert mathml(Adjoint(Transpose(X)), printer='presentation') == \ + '(XT)' + assert mathml(Transpose(Adjoint(X)), printer='presentation') == \ + '(X)T' + assert mathml(Transpose(Adjoint(X) + Y), printer='presentation') == \ + '(X' \ + '+Y)T' + assert mathml(Transpose(X), printer='presentation') == \ + 'XT' + assert mathml(Transpose(X + Y), printer='presentation') == \ + '(X+Y)T' + + +def test_mathml_special_matrices(): + from sympy.matrices import Identity, ZeroMatrix, OneMatrix + assert mathml(Identity(4), printer='presentation') == '𝕀' + assert mathml(ZeroMatrix(2, 2), printer='presentation') == '𝟘' + assert mathml(OneMatrix(2, 2), printer='presentation') == '𝟙' + +def test_mathml_piecewise(): + from sympy.functions.elementary.piecewise import Piecewise + # Content MathML + assert mathml(Piecewise((x, x <= 1), (x**2, True))) == \ + 'xx1x2' + + raises(ValueError, lambda: mathml(Piecewise((x, x <= 1)))) + + +def test_issue_17857(): + assert mathml(Range(-oo, oo), printer='presentation') == \ + '{,-1,0,1,}' + assert mathml(Range(oo, -oo, -1), printer='presentation') == \ + '{,1,0,-1,}' + + +def test_float_roundtrip(): + x = sympify(0.8975979010256552) + y = float(mp.doprint(x).strip('')) + assert x == y + + +def test_content_mathml_disable_split_super_sub(): + mp = MathMLContentPrinter() + assert mp.doprint(Symbol('u_b')) == 'ub' + mp = MathMLContentPrinter({'disable_split_super_sub': False}) + assert mp.doprint(Symbol('u_b')) == 'ub' + mp = MathMLContentPrinter({'disable_split_super_sub': True}) + assert mp.doprint(Symbol('u_b')) == 'u_b' + +def test_presentation_mathml_disable_split_super_sub(): + mpp = MathMLPresentationPrinter() + assert mpp.doprint(Symbol('u_b')) == 'ub' + mpp = MathMLPresentationPrinter({'disable_split_super_sub': False}) + assert mpp.doprint(Symbol('u_b')) == 'ub' + mpp = MathMLPresentationPrinter({'disable_split_super_sub': True}) + assert mpp.doprint(Symbol('u_b')) == 'u_b' diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_numpy.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_numpy.py new file mode 100644 index 0000000000000000000000000000000000000000..fee1c6bd95e54790a048220f37b8e5de79017d2f --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_numpy.py @@ -0,0 +1,381 @@ +from sympy.concrete.summations import Sum +from sympy.core.mod import Mod +from sympy.core.relational import (Equality, Unequality) +from sympy.core.symbol import Symbol +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.piecewise import Piecewise +from sympy.functions.special.gamma_functions import polygamma +from sympy.functions.special.error_functions import (Si, Ci) +from sympy.matrices import Matrix +from sympy.matrices.expressions.blockmatrix import BlockMatrix +from sympy.matrices.expressions.matexpr import MatrixSymbol +from sympy.matrices.expressions.special import Identity +from sympy.utilities.lambdify import lambdify +from sympy import symbols, Min, Max + +from sympy.abc import x, i, j, a, b, c, d +from sympy.core import Pow +from sympy.codegen.matrix_nodes import MatrixSolve +from sympy.codegen.numpy_nodes import logaddexp, logaddexp2 +from sympy.codegen.cfunctions import log1p, expm1, hypot, log10, exp2, log2, Sqrt +from sympy.tensor.array import Array +from sympy.tensor.array.expressions.array_expressions import ArrayTensorProduct, ArrayAdd, \ + PermuteDims, ArrayDiagonal +from sympy.printing.numpy import NumPyPrinter, SciPyPrinter, _numpy_known_constants, \ + _numpy_known_functions, _scipy_known_constants, _scipy_known_functions +from sympy.tensor.array.expressions.from_matrix_to_array import convert_matrix_to_array + +from sympy.testing.pytest import skip, raises +from sympy.external import import_module + +np = import_module('numpy') +jax = import_module('jax') + +if np: + deafult_float_info = np.finfo(np.array([]).dtype) + NUMPY_DEFAULT_EPSILON = deafult_float_info.eps + +def test_numpy_piecewise_regression(): + """ + NumPyPrinter needs to print Piecewise()'s choicelist as a list to avoid + breaking compatibility with numpy 1.8. This is not necessary in numpy 1.9+. + See gh-9747 and gh-9749 for details. + """ + printer = NumPyPrinter() + p = Piecewise((1, x < 0), (0, True)) + assert printer.doprint(p) == \ + 'numpy.select([numpy.less(x, 0),True], [1,0], default=numpy.nan)' + assert printer.module_imports == {'numpy': {'select', 'less', 'nan'}} + +def test_numpy_logaddexp(): + lae = logaddexp(a, b) + assert NumPyPrinter().doprint(lae) == 'numpy.logaddexp(a, b)' + lae2 = logaddexp2(a, b) + assert NumPyPrinter().doprint(lae2) == 'numpy.logaddexp2(a, b)' + + +def test_sum(): + if not np: + skip("NumPy not installed") + + s = Sum(x ** i, (i, a, b)) + f = lambdify((a, b, x), s, 'numpy') + + a_, b_ = 0, 10 + x_ = np.linspace(-1, +1, 10) + assert np.allclose(f(a_, b_, x_), sum(x_ ** i_ for i_ in range(a_, b_ + 1))) + + s = Sum(i * x, (i, a, b)) + f = lambdify((a, b, x), s, 'numpy') + + a_, b_ = 0, 10 + x_ = np.linspace(-1, +1, 10) + assert np.allclose(f(a_, b_, x_), sum(i_ * x_ for i_ in range(a_, b_ + 1))) + + +def test_multiple_sums(): + if not np: + skip("NumPy not installed") + + s = Sum((x + j) * i, (i, a, b), (j, c, d)) + f = lambdify((a, b, c, d, x), s, 'numpy') + + a_, b_ = 0, 10 + c_, d_ = 11, 21 + x_ = np.linspace(-1, +1, 10) + assert np.allclose(f(a_, b_, c_, d_, x_), + sum((x_ + j_) * i_ for i_ in range(a_, b_ + 1) for j_ in range(c_, d_ + 1))) + + +def test_codegen_einsum(): + if not np: + skip("NumPy not installed") + + M = MatrixSymbol("M", 2, 2) + N = MatrixSymbol("N", 2, 2) + + cg = convert_matrix_to_array(M * N) + f = lambdify((M, N), cg, 'numpy') + + ma = np.array([[1, 2], [3, 4]]) + mb = np.array([[1,-2], [-1, 3]]) + assert (f(ma, mb) == np.matmul(ma, mb)).all() + + +def test_codegen_extra(): + if not np: + skip("NumPy not installed") + + M = MatrixSymbol("M", 2, 2) + N = MatrixSymbol("N", 2, 2) + P = MatrixSymbol("P", 2, 2) + Q = MatrixSymbol("Q", 2, 2) + ma = np.array([[1, 2], [3, 4]]) + mb = np.array([[1,-2], [-1, 3]]) + mc = np.array([[2, 0], [1, 2]]) + md = np.array([[1,-1], [4, 7]]) + + cg = ArrayTensorProduct(M, N) + f = lambdify((M, N), cg, 'numpy') + assert (f(ma, mb) == np.einsum(ma, [0, 1], mb, [2, 3])).all() + + cg = ArrayAdd(M, N) + f = lambdify((M, N), cg, 'numpy') + assert (f(ma, mb) == ma+mb).all() + + cg = ArrayAdd(M, N, P) + f = lambdify((M, N, P), cg, 'numpy') + assert (f(ma, mb, mc) == ma+mb+mc).all() + + cg = ArrayAdd(M, N, P, Q) + f = lambdify((M, N, P, Q), cg, 'numpy') + assert (f(ma, mb, mc, md) == ma+mb+mc+md).all() + + cg = PermuteDims(M, [1, 0]) + f = lambdify((M,), cg, 'numpy') + assert (f(ma) == ma.T).all() + + cg = PermuteDims(ArrayTensorProduct(M, N), [1, 2, 3, 0]) + f = lambdify((M, N), cg, 'numpy') + assert (f(ma, mb) == np.transpose(np.einsum(ma, [0, 1], mb, [2, 3]), (1, 2, 3, 0))).all() + + cg = ArrayDiagonal(ArrayTensorProduct(M, N), (1, 2)) + f = lambdify((M, N), cg, 'numpy') + assert (f(ma, mb) == np.diagonal(np.einsum(ma, [0, 1], mb, [2, 3]), axis1=1, axis2=2)).all() + + +def test_relational(): + if not np: + skip("NumPy not installed") + + e = Equality(x, 1) + + f = lambdify((x,), e) + x_ = np.array([0, 1, 2]) + assert np.array_equal(f(x_), [False, True, False]) + + e = Unequality(x, 1) + + f = lambdify((x,), e) + x_ = np.array([0, 1, 2]) + assert np.array_equal(f(x_), [True, False, True]) + + e = (x < 1) + + f = lambdify((x,), e) + x_ = np.array([0, 1, 2]) + assert np.array_equal(f(x_), [True, False, False]) + + e = (x <= 1) + + f = lambdify((x,), e) + x_ = np.array([0, 1, 2]) + assert np.array_equal(f(x_), [True, True, False]) + + e = (x > 1) + + f = lambdify((x,), e) + x_ = np.array([0, 1, 2]) + assert np.array_equal(f(x_), [False, False, True]) + + e = (x >= 1) + + f = lambdify((x,), e) + x_ = np.array([0, 1, 2]) + assert np.array_equal(f(x_), [False, True, True]) + + +def test_mod(): + if not np: + skip("NumPy not installed") + + e = Mod(a, b) + f = lambdify((a, b), e) + + a_ = np.array([0, 1, 2, 3]) + b_ = 2 + assert np.array_equal(f(a_, b_), [0, 1, 0, 1]) + + a_ = np.array([0, 1, 2, 3]) + b_ = np.array([2, 2, 2, 2]) + assert np.array_equal(f(a_, b_), [0, 1, 0, 1]) + + a_ = np.array([2, 3, 4, 5]) + b_ = np.array([2, 3, 4, 5]) + assert np.array_equal(f(a_, b_), [0, 0, 0, 0]) + + +def test_pow(): + if not np: + skip('NumPy not installed') + + expr = Pow(2, -1, evaluate=False) + f = lambdify([], expr, 'numpy') + assert f() == 0.5 + + +def test_expm1(): + if not np: + skip("NumPy not installed") + + f = lambdify((a,), expm1(a), 'numpy') + assert abs(f(1e-10) - 1e-10 - 5e-21) <= 1e-10 * NUMPY_DEFAULT_EPSILON + + +def test_log1p(): + if not np: + skip("NumPy not installed") + + f = lambdify((a,), log1p(a), 'numpy') + assert abs(f(1e-99) - 1e-99) <= 1e-99 * NUMPY_DEFAULT_EPSILON + +def test_hypot(): + if not np: + skip("NumPy not installed") + assert abs(lambdify((a, b), hypot(a, b), 'numpy')(3, 4) - 5) <= NUMPY_DEFAULT_EPSILON + +def test_log10(): + if not np: + skip("NumPy not installed") + assert abs(lambdify((a,), log10(a), 'numpy')(100) - 2) <= NUMPY_DEFAULT_EPSILON + + +def test_exp2(): + if not np: + skip("NumPy not installed") + assert abs(lambdify((a,), exp2(a), 'numpy')(5) - 32) <= NUMPY_DEFAULT_EPSILON + + +def test_log2(): + if not np: + skip("NumPy not installed") + assert abs(lambdify((a,), log2(a), 'numpy')(256) - 8) <= NUMPY_DEFAULT_EPSILON + + +def test_Sqrt(): + if not np: + skip("NumPy not installed") + assert abs(lambdify((a,), Sqrt(a), 'numpy')(4) - 2) <= NUMPY_DEFAULT_EPSILON + + +def test_sqrt(): + if not np: + skip("NumPy not installed") + assert abs(lambdify((a,), sqrt(a), 'numpy')(4) - 2) <= NUMPY_DEFAULT_EPSILON + + +def test_matsolve(): + if not np: + skip("NumPy not installed") + + M = MatrixSymbol("M", 3, 3) + x = MatrixSymbol("x", 3, 1) + + expr = M**(-1) * x + x + matsolve_expr = MatrixSolve(M, x) + x + + f = lambdify((M, x), expr) + f_matsolve = lambdify((M, x), matsolve_expr) + + m0 = np.array([[1, 2, 3], [3, 2, 5], [5, 6, 7]]) + assert np.linalg.matrix_rank(m0) == 3 + + x0 = np.array([3, 4, 5]) + + assert np.allclose(f_matsolve(m0, x0), f(m0, x0)) + + +def test_16857(): + if not np: + skip("NumPy not installed") + + a_1 = MatrixSymbol('a_1', 10, 3) + a_2 = MatrixSymbol('a_2', 10, 3) + a_3 = MatrixSymbol('a_3', 10, 3) + a_4 = MatrixSymbol('a_4', 10, 3) + A = BlockMatrix([[a_1, a_2], [a_3, a_4]]) + assert A.shape == (20, 6) + + printer = NumPyPrinter() + assert printer.doprint(A) == 'numpy.block([[a_1, a_2], [a_3, a_4]])' + + +def test_issue_17006(): + if not np: + skip("NumPy not installed") + + M = MatrixSymbol("M", 2, 2) + + f = lambdify(M, M + Identity(2)) + ma = np.array([[1, 2], [3, 4]]) + mr = np.array([[2, 2], [3, 5]]) + + assert (f(ma) == mr).all() + + from sympy.core.symbol import symbols + n = symbols('n', integer=True) + N = MatrixSymbol("M", n, n) + raises(NotImplementedError, lambda: lambdify(N, N + Identity(n))) + +def test_jax_tuple_compatibility(): + if not jax: + skip("Jax not installed") + + x, y, z = symbols('x y z') + expr = Max(x, y, z) + Min(x, y, z) + func = lambdify((x, y, z), expr, 'jax') + input_tuple1, input_tuple2 = (1, 2, 3), (4, 5, 6) + input_array1, input_array2 = jax.numpy.asarray(input_tuple1), jax.numpy.asarray(input_tuple2) + assert np.allclose(func(*input_tuple1), func(*input_array1)) + assert np.allclose(func(*input_tuple2), func(*input_array2)) + +def test_numpy_array(): + p = NumPyPrinter() + assert p.doprint(Array([[1, 2], [3, 5]])) == 'numpy.array([[1, 2], [3, 5]])' + assert p.doprint(Array([1, 2])) == 'numpy.array([1, 2])' + assert p.doprint(Array([[[1, 2, 3]]])) == 'numpy.array([[[1, 2, 3]]])' + assert p.doprint(Array([], (0,))) == 'numpy.zeros((0,))' + assert p.doprint(Array([], (0, 0))) == 'numpy.zeros((0, 0))' + assert p.doprint(Array([], (0, 1))) == 'numpy.zeros((0, 1))' + assert p.doprint(Array([], (1, 0))) == 'numpy.zeros((1, 0))' + assert p.doprint(Array([1], ())) == 'numpy.array(1)' + +def test_numpy_matrix(): + p = NumPyPrinter() + assert p.doprint(Matrix([[1, 2], [3, 5]])) == 'numpy.array([[1, 2], [3, 5]])' + assert p.doprint(Matrix([1, 2])) == 'numpy.array([[1], [2]])' + assert p.doprint(Matrix(0, 0, [])) == 'numpy.zeros((0, 0))' + assert p.doprint(Matrix(0, 1, [])) == 'numpy.zeros((0, 1))' + assert p.doprint(Matrix(1, 0, [])) == 'numpy.zeros((1, 0))' + +def test_numpy_known_funcs_consts(): + assert _numpy_known_constants['NaN'] == 'numpy.nan' + assert _numpy_known_constants['EulerGamma'] == 'numpy.euler_gamma' + + assert _numpy_known_functions['acos'] == 'numpy.arccos' + assert _numpy_known_functions['log'] == 'numpy.log' + +def test_scipy_known_funcs_consts(): + assert _scipy_known_constants['GoldenRatio'] == 'scipy.constants.golden_ratio' + assert _scipy_known_constants['Pi'] == 'scipy.constants.pi' + + assert _scipy_known_functions['erf'] == 'scipy.special.erf' + assert _scipy_known_functions['factorial'] == 'scipy.special.factorial' + +def test_numpy_print_methods(): + prntr = NumPyPrinter() + assert hasattr(prntr, '_print_acos') + assert hasattr(prntr, '_print_log') + +def test_scipy_print_methods(): + prntr = SciPyPrinter() + assert hasattr(prntr, '_print_acos') + assert hasattr(prntr, '_print_log') + assert hasattr(prntr, '_print_erf') + assert hasattr(prntr, '_print_factorial') + assert hasattr(prntr, '_print_chebyshevt') + k = Symbol('k', integer=True, nonnegative=True) + x = Symbol('x', real=True) + assert prntr.doprint(polygamma(k, x)) == "scipy.special.polygamma(k, x)" + assert prntr.doprint(Si(x)) == "scipy.special.sici(x)[0]" + assert prntr.doprint(Ci(x)) == "scipy.special.sici(x)[1]" diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_octave.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_octave.py new file mode 100644 index 0000000000000000000000000000000000000000..1aba318f873c48ec702f1b4e3a6cc047f75d647d --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_octave.py @@ -0,0 +1,515 @@ +from sympy.core import (S, pi, oo, symbols, Function, Rational, Integer, + Tuple, Symbol, EulerGamma, GoldenRatio, Catalan, + Lambda, Mul, Pow, Mod, Eq, Ne, Le, Lt, Gt, Ge) +from sympy.codegen.matrix_nodes import MatrixSolve +from sympy.functions import (arg, atan2, bernoulli, beta, ceiling, chebyshevu, + chebyshevt, conjugate, DiracDelta, exp, expint, + factorial, floor, harmonic, Heaviside, im, + laguerre, LambertW, log, Max, Min, Piecewise, + polylog, re, RisingFactorial, sign, sinc, sqrt, + zeta, binomial, legendre, dirichlet_eta, + riemann_xi) +from sympy.functions import (sin, cos, tan, cot, sec, csc, asin, acos, acot, + atan, asec, acsc, sinh, cosh, tanh, coth, csch, + sech, asinh, acosh, atanh, acoth, asech, acsch) +from sympy.testing.pytest import raises, XFAIL +from sympy.utilities.lambdify import implemented_function +from sympy.matrices import (eye, Matrix, MatrixSymbol, Identity, + HadamardProduct, SparseMatrix, HadamardPower) +from sympy.functions.special.bessel import (jn, yn, besselj, bessely, besseli, + besselk, hankel1, hankel2, airyai, + airybi, airyaiprime, airybiprime) +from sympy.functions.special.gamma_functions import (gamma, lowergamma, + uppergamma, loggamma, + polygamma) +from sympy.functions.special.error_functions import (Chi, Ci, erf, erfc, erfi, + erfcinv, erfinv, fresnelc, + fresnels, li, Shi, Si, Li, + erf2, Ei) +from sympy.printing.octave import octave_code, octave_code as mcode + +x, y, z = symbols('x,y,z') + + +def test_Integer(): + assert mcode(Integer(67)) == "67" + assert mcode(Integer(-1)) == "-1" + + +def test_Rational(): + assert mcode(Rational(3, 7)) == "3/7" + assert mcode(Rational(18, 9)) == "2" + assert mcode(Rational(3, -7)) == "-3/7" + assert mcode(Rational(-3, -7)) == "3/7" + assert mcode(x + Rational(3, 7)) == "x + 3/7" + assert mcode(Rational(3, 7)*x) == "3*x/7" + + +def test_Relational(): + assert mcode(Eq(x, y)) == "x == y" + assert mcode(Ne(x, y)) == "x != y" + assert mcode(Le(x, y)) == "x <= y" + assert mcode(Lt(x, y)) == "x < y" + assert mcode(Gt(x, y)) == "x > y" + assert mcode(Ge(x, y)) == "x >= y" + + +def test_Function(): + assert mcode(sin(x) ** cos(x)) == "sin(x).^cos(x)" + assert mcode(sign(x)) == "sign(x)" + assert mcode(exp(x)) == "exp(x)" + assert mcode(log(x)) == "log(x)" + assert mcode(factorial(x)) == "factorial(x)" + assert mcode(floor(x)) == "floor(x)" + assert mcode(atan2(y, x)) == "atan2(y, x)" + assert mcode(beta(x, y)) == 'beta(x, y)' + assert mcode(polylog(x, y)) == 'polylog(x, y)' + assert mcode(harmonic(x)) == 'harmonic(x)' + assert mcode(bernoulli(x)) == "bernoulli(x)" + assert mcode(bernoulli(x, y)) == "bernoulli(x, y)" + assert mcode(legendre(x, y)) == "legendre(x, y)" + + +def test_Function_change_name(): + assert mcode(abs(x)) == "abs(x)" + assert mcode(ceiling(x)) == "ceil(x)" + assert mcode(arg(x)) == "angle(x)" + assert mcode(im(x)) == "imag(x)" + assert mcode(re(x)) == "real(x)" + assert mcode(conjugate(x)) == "conj(x)" + assert mcode(chebyshevt(y, x)) == "chebyshevT(y, x)" + assert mcode(chebyshevu(y, x)) == "chebyshevU(y, x)" + assert mcode(laguerre(x, y)) == "laguerreL(x, y)" + assert mcode(Chi(x)) == "coshint(x)" + assert mcode(Shi(x)) == "sinhint(x)" + assert mcode(Ci(x)) == "cosint(x)" + assert mcode(Si(x)) == "sinint(x)" + assert mcode(li(x)) == "logint(x)" + assert mcode(loggamma(x)) == "gammaln(x)" + assert mcode(polygamma(x, y)) == "psi(x, y)" + assert mcode(RisingFactorial(x, y)) == "pochhammer(x, y)" + assert mcode(DiracDelta(x)) == "dirac(x)" + assert mcode(DiracDelta(x, 3)) == "dirac(3, x)" + assert mcode(Heaviside(x)) == "heaviside(x, 1/2)" + assert mcode(Heaviside(x, y)) == "heaviside(x, y)" + assert mcode(binomial(x, y)) == "bincoeff(x, y)" + assert mcode(Mod(x, y)) == "mod(x, y)" + + +def test_minmax(): + assert mcode(Max(x, y) + Min(x, y)) == "max(x, y) + min(x, y)" + assert mcode(Max(x, y, z)) == "max(x, max(y, z))" + assert mcode(Min(x, y, z)) == "min(x, min(y, z))" + + +def test_Pow(): + assert mcode(x**3) == "x.^3" + assert mcode(x**(y**3)) == "x.^(y.^3)" + assert mcode(x**Rational(2, 3)) == 'x.^(2/3)' + g = implemented_function('g', Lambda(x, 2*x)) + assert mcode(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ + "(3.5*2*x).^(-x + y.^x)./(x.^2 + y)" + # For issue 14160 + assert mcode(Mul(-2, x, Pow(Mul(y,y,evaluate=False), -1, evaluate=False), + evaluate=False)) == '-2*x./(y.*y)' + + +def test_basic_ops(): + assert mcode(x*y) == "x.*y" + assert mcode(x + y) == "x + y" + assert mcode(x - y) == "x - y" + assert mcode(-x) == "-x" + + +def test_1_over_x_and_sqrt(): + # 1.0 and 0.5 would do something different in regular StrPrinter, + # but these are exact in IEEE floating point so no different here. + assert mcode(1/x) == '1./x' + assert mcode(x**-1) == mcode(x**-1.0) == '1./x' + assert mcode(1/sqrt(x)) == '1./sqrt(x)' + assert mcode(x**-S.Half) == mcode(x**-0.5) == '1./sqrt(x)' + assert mcode(sqrt(x)) == 'sqrt(x)' + assert mcode(x**S.Half) == mcode(x**0.5) == 'sqrt(x)' + assert mcode(1/pi) == '1/pi' + assert mcode(pi**-1) == mcode(pi**-1.0) == '1/pi' + assert mcode(pi**-0.5) == '1/sqrt(pi)' + + +def test_mix_number_mult_symbols(): + assert mcode(3*x) == "3*x" + assert mcode(pi*x) == "pi*x" + assert mcode(3/x) == "3./x" + assert mcode(pi/x) == "pi./x" + assert mcode(x/3) == "x/3" + assert mcode(x/pi) == "x/pi" + assert mcode(x*y) == "x.*y" + assert mcode(3*x*y) == "3*x.*y" + assert mcode(3*pi*x*y) == "3*pi*x.*y" + assert mcode(x/y) == "x./y" + assert mcode(3*x/y) == "3*x./y" + assert mcode(x*y/z) == "x.*y./z" + assert mcode(x/y*z) == "x.*z./y" + assert mcode(1/x/y) == "1./(x.*y)" + assert mcode(2*pi*x/y/z) == "2*pi*x./(y.*z)" + assert mcode(3*pi/x) == "3*pi./x" + assert mcode(S(3)/5) == "3/5" + assert mcode(S(3)/5*x) == "3*x/5" + assert mcode(x/y/z) == "x./(y.*z)" + assert mcode((x+y)/z) == "(x + y)./z" + assert mcode((x+y)/(z+x)) == "(x + y)./(x + z)" + assert mcode((x+y)/EulerGamma) == "(x + y)/%s" % EulerGamma.evalf(17) + assert mcode(x/3/pi) == "x/(3*pi)" + assert mcode(S(3)/5*x*y/pi) == "3*x.*y/(5*pi)" + + +def test_mix_number_pow_symbols(): + assert mcode(pi**3) == 'pi^3' + assert mcode(x**2) == 'x.^2' + assert mcode(x**(pi**3)) == 'x.^(pi^3)' + assert mcode(x**y) == 'x.^y' + assert mcode(x**(y**z)) == 'x.^(y.^z)' + assert mcode((x**y)**z) == '(x.^y).^z' + + +def test_imag(): + I = S('I') + assert mcode(I) == "1i" + assert mcode(5*I) == "5i" + assert mcode((S(3)/2)*I) == "3*1i/2" + assert mcode(3+4*I) == "3 + 4i" + assert mcode(sqrt(3)*I) == "sqrt(3)*1i" + + +def test_constants(): + assert mcode(pi) == "pi" + assert mcode(oo) == "inf" + assert mcode(-oo) == "-inf" + assert mcode(S.NegativeInfinity) == "-inf" + assert mcode(S.NaN) == "NaN" + assert mcode(S.Exp1) == "exp(1)" + assert mcode(exp(1)) == "exp(1)" + + +def test_constants_other(): + assert mcode(2*GoldenRatio) == "2*(1+sqrt(5))/2" + assert mcode(2*Catalan) == "2*%s" % Catalan.evalf(17) + assert mcode(2*EulerGamma) == "2*%s" % EulerGamma.evalf(17) + + +def test_boolean(): + assert mcode(x & y) == "x & y" + assert mcode(x | y) == "x | y" + assert mcode(~x) == "~x" + assert mcode(x & y & z) == "x & y & z" + assert mcode(x | y | z) == "x | y | z" + assert mcode((x & y) | z) == "z | x & y" + assert mcode((x | y) & z) == "z & (x | y)" + + +def test_KroneckerDelta(): + from sympy.functions import KroneckerDelta + assert mcode(KroneckerDelta(x, y)) == "double(x == y)" + assert mcode(KroneckerDelta(x, y + 1)) == "double(x == (y + 1))" + assert mcode(KroneckerDelta(2**x, y)) == "double((2.^x) == y)" + + +def test_Matrices(): + assert mcode(Matrix(1, 1, [10])) == "10" + A = Matrix([[1, sin(x/2), abs(x)], + [0, 1, pi], + [0, exp(1), ceiling(x)]]) + expected = "[1 sin(x/2) abs(x); 0 1 pi; 0 exp(1) ceil(x)]" + assert mcode(A) == expected + # row and columns + assert mcode(A[:,0]) == "[1; 0; 0]" + assert mcode(A[0,:]) == "[1 sin(x/2) abs(x)]" + # empty matrices + assert mcode(Matrix(0, 0, [])) == '[]' + assert mcode(Matrix(0, 3, [])) == 'zeros(0, 3)' + # annoying to read but correct + assert mcode(Matrix([[x, x - y, -y]])) == "[x x - y -y]" + + +def test_vector_entries_hadamard(): + # For a row or column, user might to use the other dimension + A = Matrix([[1, sin(2/x), 3*pi/x/5]]) + assert mcode(A) == "[1 sin(2./x) 3*pi./(5*x)]" + assert mcode(A.T) == "[1; sin(2./x); 3*pi./(5*x)]" + + +@XFAIL +def test_Matrices_entries_not_hadamard(): + # For Matrix with col >= 2, row >= 2, they need to be scalars + # FIXME: is it worth worrying about this? Its not wrong, just + # leave it user's responsibility to put scalar data for x. + A = Matrix([[1, sin(2/x), 3*pi/x/5], [1, 2, x*y]]) + expected = ("[1 sin(2/x) 3*pi/(5*x);\n" + "1 2 x*y]") # <- we give x.*y + assert mcode(A) == expected + + +def test_MatrixSymbol(): + n = Symbol('n', integer=True) + A = MatrixSymbol('A', n, n) + B = MatrixSymbol('B', n, n) + assert mcode(A*B) == "A*B" + assert mcode(B*A) == "B*A" + assert mcode(2*A*B) == "2*A*B" + assert mcode(B*2*A) == "2*B*A" + assert mcode(A*(B + 3*Identity(n))) == "A*(3*eye(n) + B)" + assert mcode(A**(x**2)) == "A^(x.^2)" + assert mcode(A**3) == "A^3" + assert mcode(A**S.Half) == "A^(1/2)" + + +def test_MatrixSolve(): + n = Symbol('n', integer=True) + A = MatrixSymbol('A', n, n) + x = MatrixSymbol('x', n, 1) + assert mcode(MatrixSolve(A, x)) == "A \\ x" + +def test_special_matrices(): + assert mcode(6*Identity(3)) == "6*eye(3)" + + +def test_containers(): + assert mcode([1, 2, 3, [4, 5, [6, 7]], 8, [9, 10], 11]) == \ + "{1, 2, 3, {4, 5, {6, 7}}, 8, {9, 10}, 11}" + assert mcode((1, 2, (3, 4))) == "{1, 2, {3, 4}}" + assert mcode([1]) == "{1}" + assert mcode((1,)) == "{1}" + assert mcode(Tuple(*[1, 2, 3])) == "{1, 2, 3}" + assert mcode((1, x*y, (3, x**2))) == "{1, x.*y, {3, x.^2}}" + # scalar, matrix, empty matrix and empty list + assert mcode((1, eye(3), Matrix(0, 0, []), [])) == "{1, [1 0 0; 0 1 0; 0 0 1], [], {}}" + + +def test_octave_noninline(): + source = mcode((x+y)/Catalan, assign_to='me', inline=False) + expected = ( + "Catalan = %s;\n" + "me = (x + y)/Catalan;" + ) % Catalan.evalf(17) + assert source == expected + + +def test_octave_piecewise(): + expr = Piecewise((x, x < 1), (x**2, True)) + assert mcode(expr) == "((x < 1).*(x) + (~(x < 1)).*(x.^2))" + assert mcode(expr, assign_to="r") == ( + "r = ((x < 1).*(x) + (~(x < 1)).*(x.^2));") + assert mcode(expr, assign_to="r", inline=False) == ( + "if (x < 1)\n" + " r = x;\n" + "else\n" + " r = x.^2;\n" + "end") + expr = Piecewise((x**2, x < 1), (x**3, x < 2), (x**4, x < 3), (x**5, True)) + expected = ("((x < 1).*(x.^2) + (~(x < 1)).*( ...\n" + "(x < 2).*(x.^3) + (~(x < 2)).*( ...\n" + "(x < 3).*(x.^4) + (~(x < 3)).*(x.^5))))") + assert mcode(expr) == expected + assert mcode(expr, assign_to="r") == "r = " + expected + ";" + assert mcode(expr, assign_to="r", inline=False) == ( + "if (x < 1)\n" + " r = x.^2;\n" + "elseif (x < 2)\n" + " r = x.^3;\n" + "elseif (x < 3)\n" + " r = x.^4;\n" + "else\n" + " r = x.^5;\n" + "end") + # Check that Piecewise without a True (default) condition error + expr = Piecewise((x, x < 1), (x**2, x > 1), (sin(x), x > 0)) + raises(ValueError, lambda: mcode(expr)) + + +def test_octave_piecewise_times_const(): + pw = Piecewise((x, x < 1), (x**2, True)) + assert mcode(2*pw) == "2*((x < 1).*(x) + (~(x < 1)).*(x.^2))" + assert mcode(pw/x) == "((x < 1).*(x) + (~(x < 1)).*(x.^2))./x" + assert mcode(pw/(x*y)) == "((x < 1).*(x) + (~(x < 1)).*(x.^2))./(x.*y)" + assert mcode(pw/3) == "((x < 1).*(x) + (~(x < 1)).*(x.^2))/3" + + +def test_octave_matrix_assign_to(): + A = Matrix([[1, 2, 3]]) + assert mcode(A, assign_to='a') == "a = [1 2 3];" + A = Matrix([[1, 2], [3, 4]]) + assert mcode(A, assign_to='A') == "A = [1 2; 3 4];" + + +def test_octave_matrix_assign_to_more(): + # assigning to Symbol or MatrixSymbol requires lhs/rhs match + A = Matrix([[1, 2, 3]]) + B = MatrixSymbol('B', 1, 3) + C = MatrixSymbol('C', 2, 3) + assert mcode(A, assign_to=B) == "B = [1 2 3];" + raises(ValueError, lambda: mcode(A, assign_to=x)) + raises(ValueError, lambda: mcode(A, assign_to=C)) + + +def test_octave_matrix_1x1(): + A = Matrix([[3]]) + B = MatrixSymbol('B', 1, 1) + C = MatrixSymbol('C', 1, 2) + assert mcode(A, assign_to=B) == "B = 3;" + # FIXME? + #assert mcode(A, assign_to=x) == "x = 3;" + raises(ValueError, lambda: mcode(A, assign_to=C)) + + +def test_octave_matrix_elements(): + A = Matrix([[x, 2, x*y]]) + assert mcode(A[0, 0]**2 + A[0, 1] + A[0, 2]) == "x.^2 + x.*y + 2" + A = MatrixSymbol('AA', 1, 3) + assert mcode(A) == "AA" + assert mcode(A[0, 0]**2 + sin(A[0,1]) + A[0,2]) == \ + "sin(AA(1, 2)) + AA(1, 1).^2 + AA(1, 3)" + assert mcode(sum(A)) == "AA(1, 1) + AA(1, 2) + AA(1, 3)" + + +def test_octave_boolean(): + assert mcode(True) == "true" + assert mcode(S.true) == "true" + assert mcode(False) == "false" + assert mcode(S.false) == "false" + + +def test_octave_not_supported(): + with raises(NotImplementedError): + mcode(S.ComplexInfinity) + f = Function('f') + assert mcode(f(x).diff(x), strict=False) == ( + "% Not supported in Octave:\n" + "% Derivative\n" + "Derivative(f(x), x)" + ) + + +def test_octave_not_supported_not_on_whitelist(): + from sympy.functions.special.polynomials import assoc_laguerre + with raises(NotImplementedError): + mcode(assoc_laguerre(x, y, z)) + + +def test_octave_expint(): + assert mcode(expint(1, x)) == "expint(x)" + with raises(NotImplementedError): + mcode(expint(2, x)) + assert mcode(expint(y, x), strict=False) == ( + "% Not supported in Octave:\n" + "% expint\n" + "expint(y, x)" + ) + + +def test_trick_indent_with_end_else_words(): + # words starting with "end" or "else" do not confuse the indenter + t1 = S('endless') + t2 = S('elsewhere') + pw = Piecewise((t1, x < 0), (t2, x <= 1), (1, True)) + assert mcode(pw, inline=False) == ( + "if (x < 0)\n" + " endless\n" + "elseif (x <= 1)\n" + " elsewhere\n" + "else\n" + " 1\n" + "end") + + +def test_hadamard(): + A = MatrixSymbol('A', 3, 3) + B = MatrixSymbol('B', 3, 3) + v = MatrixSymbol('v', 3, 1) + h = MatrixSymbol('h', 1, 3) + C = HadamardProduct(A, B) + n = Symbol('n') + assert mcode(C) == "A.*B" + assert mcode(C*v) == "(A.*B)*v" + assert mcode(h*C*v) == "h*(A.*B)*v" + assert mcode(C*A) == "(A.*B)*A" + # mixing Hadamard and scalar strange b/c we vectorize scalars + assert mcode(C*x*y) == "(x.*y)*(A.*B)" + + # Testing HadamardPower: + assert mcode(HadamardPower(A, n)) == "A.**n" + assert mcode(HadamardPower(A, 1+n)) == "A.**(n + 1)" + assert mcode(HadamardPower(A*B.T, 1+n)) == "(A*B.T).**(n + 1)" + + +def test_sparse(): + M = SparseMatrix(5, 6, {}) + M[2, 2] = 10 + M[1, 2] = 20 + M[1, 3] = 22 + M[0, 3] = 30 + M[3, 0] = x*y + assert mcode(M) == ( + "sparse([4 2 3 1 2], [1 3 3 4 4], [x.*y 20 10 30 22], 5, 6)" + ) + + +def test_sinc(): + assert mcode(sinc(x)) == 'sinc(x/pi)' + assert mcode(sinc(x + 3)) == 'sinc((x + 3)/pi)' + assert mcode(sinc(pi*(x + 3))) == 'sinc(x + 3)' + + +def test_trigfun(): + for f in (sin, cos, tan, cot, sec, csc, asin, acos, acot, atan, asec, acsc, + sinh, cosh, tanh, coth, csch, sech, asinh, acosh, atanh, acoth, + asech, acsch): + assert octave_code(f(x) == f.__name__ + '(x)') + + +def test_specfun(): + n = Symbol('n') + for f in [besselj, bessely, besseli, besselk]: + assert octave_code(f(n, x)) == f.__name__ + '(n, x)' + for f in (erfc, erfi, erf, erfinv, erfcinv, fresnelc, fresnels, gamma): + assert octave_code(f(x)) == f.__name__ + '(x)' + assert octave_code(hankel1(n, x)) == 'besselh(n, 1, x)' + assert octave_code(hankel2(n, x)) == 'besselh(n, 2, x)' + assert octave_code(airyai(x)) == 'airy(0, x)' + assert octave_code(airyaiprime(x)) == 'airy(1, x)' + assert octave_code(airybi(x)) == 'airy(2, x)' + assert octave_code(airybiprime(x)) == 'airy(3, x)' + assert octave_code(uppergamma(n, x)) == '(gammainc(x, n, \'upper\').*gamma(n))' + assert octave_code(lowergamma(n, x)) == '(gammainc(x, n).*gamma(n))' + assert octave_code(z**lowergamma(n, x)) == 'z.^(gammainc(x, n).*gamma(n))' + assert octave_code(jn(n, x)) == 'sqrt(2)*sqrt(pi)*sqrt(1./x).*besselj(n + 1/2, x)/2' + assert octave_code(yn(n, x)) == 'sqrt(2)*sqrt(pi)*sqrt(1./x).*bessely(n + 1/2, x)/2' + assert octave_code(LambertW(x)) == 'lambertw(x)' + assert octave_code(LambertW(x, n)) == 'lambertw(n, x)' + + # Automatic rewrite + assert octave_code(Ei(x)) == '(logint(exp(x)))' + assert octave_code(dirichlet_eta(x)) == '(((x == 1).*(log(2)) + (~(x == 1)).*((1 - 2.^(1 - x)).*zeta(x))))' + assert octave_code(riemann_xi(x)) == '(pi.^(-x/2).*x.*(x - 1).*gamma(x/2).*zeta(x)/2)' + + +def test_MatrixElement_printing(): + # test cases for issue #11821 + A = MatrixSymbol("A", 1, 3) + B = MatrixSymbol("B", 1, 3) + C = MatrixSymbol("C", 1, 3) + + assert mcode(A[0, 0]) == "A(1, 1)" + assert mcode(3 * A[0, 0]) == "3*A(1, 1)" + + F = C[0, 0].subs(C, A - B) + assert mcode(F) == "(A - B)(1, 1)" + + +def test_zeta_printing_issue_14820(): + assert octave_code(zeta(x)) == 'zeta(x)' + with raises(NotImplementedError): + octave_code(zeta(x, y)) + + +def test_automatic_rewrite(): + assert octave_code(Li(x)) == '(logint(x) - logint(2))' + assert octave_code(erf2(x, y)) == '(-erf(x) + erf(y))' diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_precedence.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_precedence.py new file mode 100644 index 0000000000000000000000000000000000000000..d08ea07483857e8c2ee7f930aa53d2dacdc58193 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_precedence.py @@ -0,0 +1,128 @@ +from sympy.concrete.products import Product +from sympy.concrete.summations import Sum +from sympy.core.function import Derivative, Function +from sympy.core.numbers import Integer, Rational, Float, oo +from sympy.core.relational import Rel +from sympy.core.symbol import symbols +from sympy.functions import sin +from sympy.integrals.integrals import Integral +from sympy.series.order import Order + +from sympy.printing.precedence import precedence, PRECEDENCE + +x, y = symbols("x,y") + + +def test_Add(): + assert precedence(x + y) == PRECEDENCE["Add"] + assert precedence(x*y + 1) == PRECEDENCE["Add"] + + +def test_Function(): + assert precedence(sin(x)) == PRECEDENCE["Func"] + +def test_Derivative(): + assert precedence(Derivative(x, y)) == PRECEDENCE["Atom"] + +def test_Integral(): + assert precedence(Integral(x, y)) == PRECEDENCE["Atom"] + + +def test_Mul(): + assert precedence(x*y) == PRECEDENCE["Mul"] + assert precedence(-x*y) == PRECEDENCE["Add"] + + +def test_Number(): + assert precedence(Integer(0)) == PRECEDENCE["Atom"] + assert precedence(Integer(1)) == PRECEDENCE["Atom"] + assert precedence(Integer(-1)) == PRECEDENCE["Add"] + assert precedence(Integer(10)) == PRECEDENCE["Atom"] + assert precedence(Rational(5, 2)) == PRECEDENCE["Mul"] + assert precedence(Rational(-5, 2)) == PRECEDENCE["Add"] + assert precedence(Float(5)) == PRECEDENCE["Atom"] + assert precedence(Float(-5)) == PRECEDENCE["Add"] + assert precedence(oo) == PRECEDENCE["Atom"] + assert precedence(-oo) == PRECEDENCE["Add"] + + +def test_Order(): + assert precedence(Order(x)) == PRECEDENCE["Atom"] + + +def test_Pow(): + assert precedence(x**y) == PRECEDENCE["Pow"] + assert precedence(-x**y) == PRECEDENCE["Add"] + assert precedence(x**-y) == PRECEDENCE["Pow"] + + +def test_Product(): + assert precedence(Product(x, (x, y, y + 1))) == PRECEDENCE["Atom"] + + +def test_Relational(): + assert precedence(Rel(x + y, y, "<")) == PRECEDENCE["Relational"] + + +def test_Sum(): + assert precedence(Sum(x, (x, y, y + 1))) == PRECEDENCE["Atom"] + + +def test_Symbol(): + assert precedence(x) == PRECEDENCE["Atom"] + + +def test_And_Or(): + # precedence relations between logical operators, ... + assert precedence(x & y) > precedence(x | y) + assert precedence(~y) > precedence(x & y) + # ... and with other operators (cfr. other programming languages) + assert precedence(x + y) > precedence(x | y) + assert precedence(x + y) > precedence(x & y) + assert precedence(x*y) > precedence(x | y) + assert precedence(x*y) > precedence(x & y) + assert precedence(~y) > precedence(x*y) + assert precedence(~y) > precedence(x - y) + # double checks + assert precedence(x & y) == PRECEDENCE["And"] + assert precedence(x | y) == PRECEDENCE["Or"] + assert precedence(~y) == PRECEDENCE["Not"] + + +def test_custom_function_precedence_comparison(): + """ + Test cases for custom functions with different precedence values, + specifically handling: + 1. Functions with precedence < PRECEDENCE["Mul"] (50) + 2. Functions with precedence = Func (70) + + Key distinction: + 1. Lower precedence functions (45) need parentheses: -2*(x F y) + 2. Higher precedence functions (70) don't: -2*x F y + """ + class LowPrecedenceF(Function): + precedence = PRECEDENCE["Mul"] - 5 + def _sympystr(self, printer): + return f"{printer._print(self.args[0])} F {printer._print(self.args[1])}" + + class HighPrecedenceF(Function): + precedence = PRECEDENCE["Func"] + def _sympystr(self, printer): + return f"{printer._print(self.args[0])} F {printer._print(self.args[1])}" + + def test_low_precedence(): + expr1 = 2 * LowPrecedenceF(x, y) + assert str(expr1) == "2*(x F y)" + + expr2 = -2 * LowPrecedenceF(x, y) + assert str(expr2) == "-2*(x F y)" + + def test_high_precedence(): + expr1 = 2 * HighPrecedenceF(x, y) + assert str(expr1) == "2*x F y" + + expr2 = -2 * HighPrecedenceF(x, y) + assert str(expr2) == "-2*x F y" + + test_low_precedence() + test_high_precedence() diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_preview.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_preview.py new file mode 100644 index 0000000000000000000000000000000000000000..91771ceb0466d6b0fee00570426713d02da14872 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_preview.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- + +from sympy.core.relational import Eq +from sympy.core.symbol import Symbol +from sympy.functions.elementary.piecewise import Piecewise +from sympy.printing.preview import preview + +from io import BytesIO + + +def test_preview(): + x = Symbol('x') + obj = BytesIO() + try: + preview(x, output='png', viewer='BytesIO', outputbuffer=obj) + except RuntimeError: + pass # latex not installed on CI server + + +def test_preview_unicode_symbol(): + # issue 9107 + a = Symbol('α') + obj = BytesIO() + try: + preview(a, output='png', viewer='BytesIO', outputbuffer=obj) + except RuntimeError: + pass # latex not installed on CI server + + +def test_preview_latex_construct_in_expr(): + # see PR 9801 + x = Symbol('x') + pw = Piecewise((1, Eq(x, 0)), (0, True)) + obj = BytesIO() + try: + preview(pw, output='png', viewer='BytesIO', outputbuffer=obj) + except RuntimeError: + pass # latex not installed on CI server diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_pycode.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_pycode.py new file mode 100644 index 0000000000000000000000000000000000000000..2c38fe81d830149cdce6b55f15e6e07513fdd146 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_pycode.py @@ -0,0 +1,493 @@ +from sympy import Not +from sympy.codegen import Assignment +from sympy.codegen.ast import none +from sympy.codegen.cfunctions import expm1, log1p +from sympy.codegen.scipy_nodes import cosm1 +from sympy.codegen.matrix_nodes import MatrixSolve +from sympy.core import Expr, Mod, symbols, Eq, Le, Gt, zoo, oo, Rational, Pow +from sympy.core.function import Derivative +from sympy.core.numbers import pi +from sympy.core.singleton import S +from sympy.functions import acos, KroneckerDelta, Piecewise, sign, sqrt, Min, Max, cot, acsch, asec, coth, sec, log, sin, cos, tan, asin, atan, sinh, cosh, tanh, asinh, acosh, atanh +from sympy.functions.elementary.trigonometric import atan2 +from sympy.logic import And, Or +from sympy.matrices import SparseMatrix, MatrixSymbol, Identity +from sympy.printing.codeprinter import PrintMethodNotImplementedError +from sympy.printing.pycode import ( + MpmathPrinter, CmathPrinter, PythonCodePrinter, pycode, SymPyPrinter +) +from sympy.printing.tensorflow import TensorflowPrinter +from sympy.printing.numpy import NumPyPrinter, SciPyPrinter +from sympy.testing.pytest import raises, skip +from sympy.tensor import IndexedBase, Idx +from sympy.tensor.array.expressions.array_expressions import ArraySymbol, ArrayDiagonal, ArrayContraction, ZeroArray, OneArray +from sympy.external import import_module +from sympy.functions.special.gamma_functions import loggamma + + + +x, y, z = symbols('x y z') +p = IndexedBase("p") + + +def test_PythonCodePrinter(): + prntr = PythonCodePrinter() + + assert not prntr.module_imports + + assert prntr.doprint(x**y) == 'x**y' + assert prntr.doprint(Mod(x, 2)) == 'x % 2' + assert prntr.doprint(-Mod(x, y)) == '-(x % y)' + assert prntr.doprint(Mod(-x, y)) == '(-x) % y' + assert prntr.doprint(And(x, y)) == 'x and y' + assert prntr.doprint(Or(x, y)) == 'x or y' + assert prntr.doprint(1/(x+y)) == '1/(x + y)' + assert prntr.doprint(Not(x)) == 'not x' + assert not prntr.module_imports + + assert prntr.doprint(pi) == 'math.pi' + assert prntr.module_imports == {'math': {'pi'}} + + assert prntr.doprint(x**Rational(1, 2)) == 'math.sqrt(x)' + assert prntr.doprint(sqrt(x)) == 'math.sqrt(x)' + assert prntr.module_imports == {'math': {'pi', 'sqrt'}} + + assert prntr.doprint(acos(x)) == 'math.acos(x)' + assert prntr.doprint(cot(x)) == '(1/math.tan(x))' + assert prntr.doprint(coth(x)) == '((math.exp(x) + math.exp(-x))/(math.exp(x) - math.exp(-x)))' + assert prntr.doprint(asec(x)) == '(math.acos(1/x))' + assert prntr.doprint(acsch(x)) == '(math.log(math.sqrt(1 + x**(-2)) + 1/x))' + + assert prntr.doprint(Assignment(x, 2)) == 'x = 2' + assert prntr.doprint(Piecewise((1, Eq(x, 0)), + (2, x>6))) == '((1) if (x == 0) else (2) if (x > 6) else None)' + assert prntr.doprint(Piecewise((2, Le(x, 0)), + (3, Gt(x, 0)), evaluate=False)) == '((2) if (x <= 0) else'\ + ' (3) if (x > 0) else None)' + assert prntr.doprint(sign(x)) == '(0.0 if x == 0 else math.copysign(1, x))' + assert prntr.doprint(p[0, 1]) == 'p[0, 1]' + assert prntr.doprint(KroneckerDelta(x,y)) == '(1 if x == y else 0)' + + assert prntr.doprint((2,3)) == "(2, 3)" + assert prntr.doprint([2,3]) == "[2, 3]" + + assert prntr.doprint(Min(x, y)) == "min(x, y)" + assert prntr.doprint(Max(x, y)) == "max(x, y)" + + +def test_PythonCodePrinter_standard(): + prntr = PythonCodePrinter() + + assert prntr.standard == 'python3' + + raises(ValueError, lambda: PythonCodePrinter({'standard':'python4'})) + + +def test_CmathPrinter(): + p = CmathPrinter() + + assert p.doprint(sqrt(x)) == 'cmath.sqrt(x)' + assert p.doprint(log(x)) == 'cmath.log(x)' + + assert p.doprint(sin(x)) == 'cmath.sin(x)' + assert p.doprint(cos(x)) == 'cmath.cos(x)' + assert p.doprint(tan(x)) == 'cmath.tan(x)' + + assert p.doprint(asin(x)) == 'cmath.asin(x)' + assert p.doprint(acos(x)) == 'cmath.acos(x)' + assert p.doprint(atan(x)) == 'cmath.atan(x)' + + assert p.doprint(sinh(x)) == 'cmath.sinh(x)' + assert p.doprint(cosh(x)) == 'cmath.cosh(x)' + assert p.doprint(tanh(x)) == 'cmath.tanh(x)' + + assert p.doprint(asinh(x)) == 'cmath.asinh(x)' + assert p.doprint(acosh(x)) == 'cmath.acosh(x)' + assert p.doprint(atanh(x)) == 'cmath.atanh(x)' + + +def test_MpmathPrinter(): + p = MpmathPrinter() + assert p.doprint(sign(x)) == 'mpmath.sign(x)' + assert p.doprint(Rational(1, 2)) == 'mpmath.mpf(1)/mpmath.mpf(2)' + + assert p.doprint(S.Exp1) == 'mpmath.e' + assert p.doprint(S.Pi) == 'mpmath.pi' + assert p.doprint(S.GoldenRatio) == 'mpmath.phi' + assert p.doprint(S.EulerGamma) == 'mpmath.euler' + assert p.doprint(S.NaN) == 'mpmath.nan' + assert p.doprint(S.Infinity) == 'mpmath.inf' + assert p.doprint(S.NegativeInfinity) == 'mpmath.ninf' + assert p.doprint(loggamma(x)) == 'mpmath.loggamma(x)' + + +def test_NumPyPrinter(): + from sympy.core.function import Lambda + from sympy.matrices.expressions.adjoint import Adjoint + from sympy.matrices.expressions.diagonal import (DiagMatrix, DiagonalMatrix, DiagonalOf) + from sympy.matrices.expressions.funcmatrix import FunctionMatrix + from sympy.matrices.expressions.hadamard import HadamardProduct + from sympy.matrices.expressions.kronecker import KroneckerProduct + from sympy.matrices.expressions.special import (OneMatrix, ZeroMatrix) + from sympy.abc import a, b + p = NumPyPrinter() + assert p.doprint(sign(x)) == 'numpy.sign(x)' + A = MatrixSymbol("A", 2, 2) + B = MatrixSymbol("B", 2, 2) + C = MatrixSymbol("C", 1, 5) + D = MatrixSymbol("D", 3, 4) + assert p.doprint(A**(-1)) == "numpy.linalg.inv(A)" + assert p.doprint(A**5) == "numpy.linalg.matrix_power(A, 5)" + assert p.doprint(Identity(3)) == "numpy.eye(3)" + + u = MatrixSymbol('x', 2, 1) + v = MatrixSymbol('y', 2, 1) + assert p.doprint(MatrixSolve(A, u)) == 'numpy.linalg.solve(A, x)' + assert p.doprint(MatrixSolve(A, u) + v) == 'numpy.linalg.solve(A, x) + y' + + assert p.doprint(ZeroMatrix(2, 3)) == "numpy.zeros((2, 3))" + assert p.doprint(OneMatrix(2, 3)) == "numpy.ones((2, 3))" + assert p.doprint(FunctionMatrix(4, 5, Lambda((a, b), a + b))) == \ + "numpy.fromfunction(lambda a, b: a + b, (4, 5))" + assert p.doprint(HadamardProduct(A, B)) == "numpy.multiply(A, B)" + assert p.doprint(KroneckerProduct(A, B)) == "numpy.kron(A, B)" + assert p.doprint(Adjoint(A)) == "numpy.conjugate(numpy.transpose(A))" + assert p.doprint(DiagonalOf(A)) == "numpy.reshape(numpy.diag(A), (-1, 1))" + assert p.doprint(DiagMatrix(C)) == "numpy.diagflat(C)" + assert p.doprint(DiagonalMatrix(D)) == "numpy.multiply(D, numpy.eye(3, 4))" + + # Workaround for numpy negative integer power errors + assert p.doprint(x**-1) == 'x**(-1.0)' + assert p.doprint(x**-2) == 'x**(-2.0)' + + expr = Pow(2, -1, evaluate=False) + assert p.doprint(expr) == "2**(-1.0)" + + assert p.doprint(S.Exp1) == 'numpy.e' + assert p.doprint(S.Pi) == 'numpy.pi' + assert p.doprint(S.EulerGamma) == 'numpy.euler_gamma' + assert p.doprint(S.NaN) == 'numpy.nan' + assert p.doprint(S.Infinity) == 'numpy.inf' + assert p.doprint(S.NegativeInfinity) == '-numpy.inf' + + # Function rewriting operator precedence fix + assert p.doprint(sec(x)**2) == '(numpy.cos(x)**(-1.0))**2' + + +def test_issue_18770(): + numpy = import_module('numpy') + if not numpy: + skip("numpy not installed.") + + from sympy.functions.elementary.miscellaneous import (Max, Min) + from sympy.utilities.lambdify import lambdify + + expr1 = Min(0.1*x + 3, x + 1, 0.5*x + 1) + func = lambdify(x, expr1, "numpy") + assert (func(numpy.linspace(0, 3, 3)) == [1.0, 1.75, 2.5 ]).all() + assert func(4) == 3 + + expr1 = Max(x**2, x**3) + func = lambdify(x,expr1, "numpy") + assert (func(numpy.linspace(-1, 2, 4)) == [1, 0, 1, 8] ).all() + assert func(4) == 64 + + +def test_SciPyPrinter(): + p = SciPyPrinter() + expr = acos(x) + assert 'numpy' not in p.module_imports + assert p.doprint(expr) == 'numpy.arccos(x)' + assert 'numpy' in p.module_imports + assert not any(m.startswith('scipy') for m in p.module_imports) + smat = SparseMatrix(2, 5, {(0, 1): 3}) + assert p.doprint(smat) == \ + 'scipy.sparse.coo_matrix(([3], ([0], [1])), shape=(2, 5))' + assert 'scipy.sparse' in p.module_imports + + assert p.doprint(S.GoldenRatio) == 'scipy.constants.golden_ratio' + assert p.doprint(S.Pi) == 'scipy.constants.pi' + assert p.doprint(S.Exp1) == 'numpy.e' + + +def test_pycode_reserved_words(): + s1, s2 = symbols('if else') + raises(ValueError, lambda: pycode(s1 + s2, error_on_reserved=True)) + py_str = pycode(s1 + s2) + assert py_str in ('else_ + if_', 'if_ + else_') + + +def test_issue_20762(): + # Make sure pycode removes curly braces from subscripted variables + a_b, b, a_11 = symbols('a_{b} b a_{11}') + expr = a_b*b + assert pycode(expr) == 'a_b*b' + expr = a_11*b + assert pycode(expr) == 'a_11*b' + + +def test_sqrt(): + prntr = PythonCodePrinter() + assert prntr._print_Pow(sqrt(x), rational=False) == 'math.sqrt(x)' + assert prntr._print_Pow(1/sqrt(x), rational=False) == '1/math.sqrt(x)' + + prntr = PythonCodePrinter({'standard' : 'python3'}) + assert prntr._print_Pow(sqrt(x), rational=True) == 'x**(1/2)' + assert prntr._print_Pow(1/sqrt(x), rational=True) == 'x**(-1/2)' + + prntr = MpmathPrinter() + assert prntr._print_Pow(sqrt(x), rational=False) == 'mpmath.sqrt(x)' + assert prntr._print_Pow(sqrt(x), rational=True) == \ + "x**(mpmath.mpf(1)/mpmath.mpf(2))" + + prntr = NumPyPrinter() + assert prntr._print_Pow(sqrt(x), rational=False) == 'numpy.sqrt(x)' + assert prntr._print_Pow(sqrt(x), rational=True) == 'x**(1/2)' + + prntr = SciPyPrinter() + assert prntr._print_Pow(sqrt(x), rational=False) == 'numpy.sqrt(x)' + assert prntr._print_Pow(sqrt(x), rational=True) == 'x**(1/2)' + + prntr = SymPyPrinter() + assert prntr._print_Pow(sqrt(x), rational=False) == 'sympy.sqrt(x)' + assert prntr._print_Pow(sqrt(x), rational=True) == 'x**(1/2)' + + +def test_frac(): + from sympy.functions.elementary.integers import frac + + expr = frac(x) + prntr = NumPyPrinter() + assert prntr.doprint(expr) == 'numpy.mod(x, 1)' + + prntr = SciPyPrinter() + assert prntr.doprint(expr) == 'numpy.mod(x, 1)' + + prntr = PythonCodePrinter() + assert prntr.doprint(expr) == 'x % 1' + + prntr = MpmathPrinter() + assert prntr.doprint(expr) == 'mpmath.frac(x)' + + prntr = SymPyPrinter() + assert prntr.doprint(expr) == 'sympy.functions.elementary.integers.frac(x)' + + +class CustomPrintedObject(Expr): + def _numpycode(self, printer): + return 'numpy' + + def _mpmathcode(self, printer): + return 'mpmath' + + +def test_printmethod(): + obj = CustomPrintedObject() + assert NumPyPrinter().doprint(obj) == 'numpy' + assert MpmathPrinter().doprint(obj) == 'mpmath' + + +def test_codegen_ast_nodes(): + assert pycode(none) == 'None' + + +def test_issue_14283(): + prntr = PythonCodePrinter() + + assert prntr.doprint(zoo) == "math.nan" + assert prntr.doprint(-oo) == "float('-inf')" + + +def test_NumPyPrinter_print_seq(): + n = NumPyPrinter() + + assert n._print_seq(range(2)) == '(0, 1,)' + + +def test_issue_16535_16536(): + from sympy.functions.special.gamma_functions import (lowergamma, uppergamma) + + a = symbols('a') + expr1 = lowergamma(a, x) + expr2 = uppergamma(a, x) + + prntr = SciPyPrinter() + assert prntr.doprint(expr1) == 'scipy.special.gamma(a)*scipy.special.gammainc(a, x)' + assert prntr.doprint(expr2) == 'scipy.special.gamma(a)*scipy.special.gammaincc(a, x)' + + p_numpy = NumPyPrinter() + p_pycode = PythonCodePrinter({'strict': False}) + + for expr in [expr1, expr2]: + with raises(NotImplementedError): + p_numpy.doprint(expr1) + assert "Not supported" in p_pycode.doprint(expr) + + +def test_Integral(): + from sympy.functions.elementary.exponential import exp + from sympy.integrals.integrals import Integral + + single = Integral(exp(-x), (x, 0, oo)) + double = Integral(x**2*exp(x*y), (x, -z, z), (y, 0, z)) + indefinite = Integral(x**2, x) + evaluateat = Integral(x**2, (x, 1)) + + prntr = SciPyPrinter() + assert prntr.doprint(single) == 'scipy.integrate.quad(lambda x: numpy.exp(-x), 0, numpy.inf)[0]' + assert prntr.doprint(double) == 'scipy.integrate.nquad(lambda x, y: x**2*numpy.exp(x*y), ((-z, z), (0, z)))[0]' + raises(NotImplementedError, lambda: prntr.doprint(indefinite)) + raises(NotImplementedError, lambda: prntr.doprint(evaluateat)) + + prntr = MpmathPrinter() + assert prntr.doprint(single) == 'mpmath.quad(lambda x: mpmath.exp(-x), (0, mpmath.inf))' + assert prntr.doprint(double) == 'mpmath.quad(lambda x, y: x**2*mpmath.exp(x*y), (-z, z), (0, z))' + raises(NotImplementedError, lambda: prntr.doprint(indefinite)) + raises(NotImplementedError, lambda: prntr.doprint(evaluateat)) + + +def test_fresnel_integrals(): + from sympy.functions.special.error_functions import (fresnelc, fresnels) + + expr1 = fresnelc(x) + expr2 = fresnels(x) + + prntr = SciPyPrinter() + assert prntr.doprint(expr1) == 'scipy.special.fresnel(x)[1]' + assert prntr.doprint(expr2) == 'scipy.special.fresnel(x)[0]' + + p_numpy = NumPyPrinter() + p_pycode = PythonCodePrinter() + p_mpmath = MpmathPrinter() + for expr in [expr1, expr2]: + with raises(NotImplementedError): + p_numpy.doprint(expr) + with raises(NotImplementedError): + p_pycode.doprint(expr) + + assert p_mpmath.doprint(expr1) == 'mpmath.fresnelc(x)' + assert p_mpmath.doprint(expr2) == 'mpmath.fresnels(x)' + + +def test_beta(): + from sympy.functions.special.beta_functions import beta + + expr = beta(x, y) + + prntr = SciPyPrinter() + assert prntr.doprint(expr) == 'scipy.special.beta(x, y)' + + prntr = NumPyPrinter() + assert prntr.doprint(expr) == '(math.gamma(x)*math.gamma(y)/math.gamma(x + y))' + + prntr = PythonCodePrinter() + assert prntr.doprint(expr) == '(math.gamma(x)*math.gamma(y)/math.gamma(x + y))' + + prntr = PythonCodePrinter({'allow_unknown_functions': True}) + assert prntr.doprint(expr) == '(math.gamma(x)*math.gamma(y)/math.gamma(x + y))' + + prntr = MpmathPrinter() + assert prntr.doprint(expr) == 'mpmath.beta(x, y)' + +def test_airy(): + from sympy.functions.special.bessel import (airyai, airybi) + + expr1 = airyai(x) + expr2 = airybi(x) + + prntr = SciPyPrinter() + assert prntr.doprint(expr1) == 'scipy.special.airy(x)[0]' + assert prntr.doprint(expr2) == 'scipy.special.airy(x)[2]' + + prntr = NumPyPrinter({'strict': False}) + assert "Not supported" in prntr.doprint(expr1) + assert "Not supported" in prntr.doprint(expr2) + + prntr = PythonCodePrinter({'strict': False}) + assert "Not supported" in prntr.doprint(expr1) + assert "Not supported" in prntr.doprint(expr2) + +def test_airy_prime(): + from sympy.functions.special.bessel import (airyaiprime, airybiprime) + + expr1 = airyaiprime(x) + expr2 = airybiprime(x) + + prntr = SciPyPrinter() + assert prntr.doprint(expr1) == 'scipy.special.airy(x)[1]' + assert prntr.doprint(expr2) == 'scipy.special.airy(x)[3]' + + prntr = NumPyPrinter({'strict': False}) + assert "Not supported" in prntr.doprint(expr1) + assert "Not supported" in prntr.doprint(expr2) + + prntr = PythonCodePrinter({'strict': False}) + assert "Not supported" in prntr.doprint(expr1) + assert "Not supported" in prntr.doprint(expr2) + + +def test_numerical_accuracy_functions(): + prntr = SciPyPrinter() + assert prntr.doprint(expm1(x)) == 'numpy.expm1(x)' + assert prntr.doprint(log1p(x)) == 'numpy.log1p(x)' + assert prntr.doprint(cosm1(x)) == 'scipy.special.cosm1(x)' + +def test_array_printer(): + A = ArraySymbol('A', (4,4,6,6,6)) + I = IndexedBase('I') + i,j,k = Idx('i', (0,1)), Idx('j', (2,3)), Idx('k', (4,5)) + + prntr = NumPyPrinter() + assert prntr.doprint(ZeroArray(5)) == 'numpy.zeros((5,))' + assert prntr.doprint(OneArray(5)) == 'numpy.ones((5,))' + assert prntr.doprint(ArrayContraction(A, [2,3])) == 'numpy.einsum("abccd->abd", A)' + assert prntr.doprint(I) == 'I' + assert prntr.doprint(ArrayDiagonal(A, [2,3,4])) == 'numpy.einsum("abccc->abc", A)' + assert prntr.doprint(ArrayDiagonal(A, [0,1], [2,3])) == 'numpy.einsum("aabbc->cab", A)' + assert prntr.doprint(ArrayContraction(A, [2], [3])) == 'numpy.einsum("abcde->abe", A)' + assert prntr.doprint(Assignment(I[i,j,k], I[i,j,k])) == 'I = I' + + prntr = TensorflowPrinter() + assert prntr.doprint(ZeroArray(5)) == 'tensorflow.zeros((5,))' + assert prntr.doprint(OneArray(5)) == 'tensorflow.ones((5,))' + assert prntr.doprint(ArrayContraction(A, [2,3])) == 'tensorflow.linalg.einsum("abccd->abd", A)' + assert prntr.doprint(I) == 'I' + assert prntr.doprint(ArrayDiagonal(A, [2,3,4])) == 'tensorflow.linalg.einsum("abccc->abc", A)' + assert prntr.doprint(ArrayDiagonal(A, [0,1], [2,3])) == 'tensorflow.linalg.einsum("aabbc->cab", A)' + assert prntr.doprint(ArrayContraction(A, [2], [3])) == 'tensorflow.linalg.einsum("abcde->abe", A)' + assert prntr.doprint(Assignment(I[i,j,k], I[i,j,k])) == 'I = I' + + +def test_custom_Derivative_methods(): + class MyPrinter(SciPyPrinter): + def _print_Derivative_cosm1(self, args, seq_orders): + arg, = args + order, = seq_orders + return 'my_custom_cosm1(%s, deriv_order=%d)' % (self._print(arg), order) + + def _print_Derivative_atan2(self, args, seq_orders): + arg1, arg2 = args + ord1, ord2 = seq_orders + return 'my_custom_atan2(%s, %s, deriv1=%d, deriv2=%d)' % ( + self._print(arg1), self._print(arg2), ord1, ord2 + ) + + p = MyPrinter() + cosm1_1 = cosm1(x).diff(x, evaluate=False) + assert p.doprint(cosm1_1) == 'my_custom_cosm1(x, deriv_order=1)' + atan2_2_3 = atan2(x, y).diff(x, 2, y, 3, evaluate=False) + assert p.doprint(atan2_2_3) == 'my_custom_atan2(x, y, deriv1=2, deriv2=3)' + + try: + p.doprint(expm1(x).diff(x, evaluate=False)) + except PrintMethodNotImplementedError as e: + assert '_print_Derivative_expm1' in repr(e) + else: + assert False # should have thrown + + try: + p.doprint(Derivative(cosm1(x**2),x)) + except ValueError as e: + assert '_print_Derivative(' in repr(e) + else: + assert False # should have thrown diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_python.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_python.py new file mode 100644 index 0000000000000000000000000000000000000000..fb94a662be90934a672d08b3de44a22e2580d8b6 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_python.py @@ -0,0 +1,203 @@ +from sympy.core.function import (Derivative, Function) +from sympy.core.numbers import (I, Rational, oo, pi) +from sympy.core.relational import (Eq, Ge, Gt, Le, Lt, Ne) +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.elementary.complexes import (Abs, conjugate) +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import sin +from sympy.integrals.integrals import Integral +from sympy.matrices.dense import Matrix +from sympy.series.limits import limit + +from sympy.printing.python import python + +from sympy.testing.pytest import raises, XFAIL + +x, y = symbols('x,y') +th = Symbol('theta') +ph = Symbol('phi') + + +def test_python_basic(): + # Simple numbers/symbols + assert python(-Rational(1)/2) == "e = Rational(-1, 2)" + assert python(-Rational(13)/22) == "e = Rational(-13, 22)" + assert python(oo) == "e = oo" + + # Powers + assert python(x**2) == "x = Symbol(\'x\')\ne = x**2" + assert python(1/x) == "x = Symbol('x')\ne = 1/x" + assert python(y*x**-2) == "y = Symbol('y')\nx = Symbol('x')\ne = y/x**2" + assert python( + x**Rational(-5, 2)) == "x = Symbol('x')\ne = x**Rational(-5, 2)" + + # Sums of terms + assert python(x**2 + x + 1) in [ + "x = Symbol('x')\ne = 1 + x + x**2", + "x = Symbol('x')\ne = x + x**2 + 1", + "x = Symbol('x')\ne = x**2 + x + 1", ] + assert python(1 - x) in [ + "x = Symbol('x')\ne = 1 - x", + "x = Symbol('x')\ne = -x + 1"] + assert python(1 - 2*x) in [ + "x = Symbol('x')\ne = 1 - 2*x", + "x = Symbol('x')\ne = -2*x + 1"] + assert python(1 - Rational(3, 2)*y/x) in [ + "y = Symbol('y')\nx = Symbol('x')\ne = 1 - 3/2*y/x", + "y = Symbol('y')\nx = Symbol('x')\ne = -3/2*y/x + 1", + "y = Symbol('y')\nx = Symbol('x')\ne = 1 - 3*y/(2*x)"] + + # Multiplication + assert python(x/y) == "x = Symbol('x')\ny = Symbol('y')\ne = x/y" + assert python(-x/y) == "x = Symbol('x')\ny = Symbol('y')\ne = -x/y" + assert python((x + 2)/y) in [ + "y = Symbol('y')\nx = Symbol('x')\ne = 1/y*(2 + x)", + "y = Symbol('y')\nx = Symbol('x')\ne = 1/y*(x + 2)", + "x = Symbol('x')\ny = Symbol('y')\ne = 1/y*(2 + x)", + "x = Symbol('x')\ny = Symbol('y')\ne = (2 + x)/y", + "x = Symbol('x')\ny = Symbol('y')\ne = (x + 2)/y"] + assert python((1 + x)*y) in [ + "y = Symbol('y')\nx = Symbol('x')\ne = y*(1 + x)", + "y = Symbol('y')\nx = Symbol('x')\ne = y*(x + 1)", ] + + # Check for proper placement of negative sign + assert python(-5*x/(x + 10)) == "x = Symbol('x')\ne = -5*x/(x + 10)" + assert python(1 - Rational(3, 2)*(x + 1)) in [ + "x = Symbol('x')\ne = Rational(-3, 2)*x + Rational(-1, 2)", + "x = Symbol('x')\ne = -3*x/2 + Rational(-1, 2)", + "x = Symbol('x')\ne = -3*x/2 + Rational(-1, 2)" + ] + + +def test_python_keyword_symbol_name_escaping(): + # Check for escaping of keywords + assert python( + 5*Symbol("lambda")) == "lambda_ = Symbol('lambda')\ne = 5*lambda_" + assert (python(5*Symbol("lambda") + 7*Symbol("lambda_")) == + "lambda__ = Symbol('lambda')\nlambda_ = Symbol('lambda_')\ne = 7*lambda_ + 5*lambda__") + assert (python(5*Symbol("for") + Function("for_")(8)) == + "for__ = Symbol('for')\nfor_ = Function('for_')\ne = 5*for__ + for_(8)") + + +def test_python_keyword_function_name_escaping(): + assert python( + 5*Function("for")(8)) == "for_ = Function('for')\ne = 5*for_(8)" + + +def test_python_relational(): + assert python(Eq(x, y)) == "x = Symbol('x')\ny = Symbol('y')\ne = Eq(x, y)" + assert python(Ge(x, y)) == "x = Symbol('x')\ny = Symbol('y')\ne = x >= y" + assert python(Le(x, y)) == "x = Symbol('x')\ny = Symbol('y')\ne = x <= y" + assert python(Gt(x, y)) == "x = Symbol('x')\ny = Symbol('y')\ne = x > y" + assert python(Lt(x, y)) == "x = Symbol('x')\ny = Symbol('y')\ne = x < y" + assert python(Ne(x/(y + 1), y**2)) in [ + "x = Symbol('x')\ny = Symbol('y')\ne = Ne(x/(1 + y), y**2)", + "x = Symbol('x')\ny = Symbol('y')\ne = Ne(x/(y + 1), y**2)"] + + +def test_python_functions(): + # Simple + assert python(2*x + exp(x)) in "x = Symbol('x')\ne = 2*x + exp(x)" + assert python(sqrt(2)) == 'e = sqrt(2)' + assert python(2**Rational(1, 3)) == 'e = 2**Rational(1, 3)' + assert python(sqrt(2 + pi)) == 'e = sqrt(2 + pi)' + assert python((2 + pi)**Rational(1, 3)) == 'e = (2 + pi)**Rational(1, 3)' + assert python(2**Rational(1, 4)) == 'e = 2**Rational(1, 4)' + assert python(Abs(x)) == "x = Symbol('x')\ne = Abs(x)" + assert python( + Abs(x/(x**2 + 1))) in ["x = Symbol('x')\ne = Abs(x/(1 + x**2))", + "x = Symbol('x')\ne = Abs(x/(x**2 + 1))"] + + # Univariate/Multivariate functions + f = Function('f') + assert python(f(x)) == "x = Symbol('x')\nf = Function('f')\ne = f(x)" + assert python(f(x, y)) == "x = Symbol('x')\ny = Symbol('y')\nf = Function('f')\ne = f(x, y)" + assert python(f(x/(y + 1), y)) in [ + "x = Symbol('x')\ny = Symbol('y')\nf = Function('f')\ne = f(x/(1 + y), y)", + "x = Symbol('x')\ny = Symbol('y')\nf = Function('f')\ne = f(x/(y + 1), y)"] + + # Nesting of square roots + assert python(sqrt((sqrt(x + 1)) + 1)) in [ + "x = Symbol('x')\ne = sqrt(1 + sqrt(1 + x))", + "x = Symbol('x')\ne = sqrt(sqrt(x + 1) + 1)"] + + # Nesting of powers + assert python((((x + 1)**Rational(1, 3)) + 1)**Rational(1, 3)) in [ + "x = Symbol('x')\ne = (1 + (1 + x)**Rational(1, 3))**Rational(1, 3)", + "x = Symbol('x')\ne = ((x + 1)**Rational(1, 3) + 1)**Rational(1, 3)"] + + # Function powers + assert python(sin(x)**2) == "x = Symbol('x')\ne = sin(x)**2" + + +@XFAIL +def test_python_functions_conjugates(): + a, b = map(Symbol, 'ab') + assert python( conjugate(a + b*I) ) == '_ _\na - I*b' + assert python( conjugate(exp(a + b*I)) ) == ' _ _\n a - I*b\ne ' + + +def test_python_derivatives(): + # Simple + f_1 = Derivative(log(x), x, evaluate=False) + assert python(f_1) == "x = Symbol('x')\ne = Derivative(log(x), x)" + + f_2 = Derivative(log(x), x, evaluate=False) + x + assert python(f_2) == "x = Symbol('x')\ne = x + Derivative(log(x), x)" + + # Multiple symbols + f_3 = Derivative(log(x) + x**2, x, y, evaluate=False) + assert python(f_3) == \ + "x = Symbol('x')\ny = Symbol('y')\ne = Derivative(x**2 + log(x), x, y)" + + f_4 = Derivative(2*x*y, y, x, evaluate=False) + x**2 + assert python(f_4) in [ + "x = Symbol('x')\ny = Symbol('y')\ne = x**2 + Derivative(2*x*y, y, x)", + "x = Symbol('x')\ny = Symbol('y')\ne = Derivative(2*x*y, y, x) + x**2"] + + +def test_python_integrals(): + # Simple + f_1 = Integral(log(x), x) + assert python(f_1) == "x = Symbol('x')\ne = Integral(log(x), x)" + + f_2 = Integral(x**2, x) + assert python(f_2) == "x = Symbol('x')\ne = Integral(x**2, x)" + + # Double nesting of pow + f_3 = Integral(x**(2**x), x) + assert python(f_3) == "x = Symbol('x')\ne = Integral(x**(2**x), x)" + + # Definite integrals + f_4 = Integral(x**2, (x, 1, 2)) + assert python(f_4) == "x = Symbol('x')\ne = Integral(x**2, (x, 1, 2))" + + f_5 = Integral(x**2, (x, Rational(1, 2), 10)) + assert python( + f_5) == "x = Symbol('x')\ne = Integral(x**2, (x, Rational(1, 2), 10))" + + # Nested integrals + f_6 = Integral(x**2*y**2, x, y) + assert python(f_6) == "x = Symbol('x')\ny = Symbol('y')\ne = Integral(x**2*y**2, x, y)" + + +def test_python_matrix(): + p = python(Matrix([[x**2+1, 1], [y, x+y]])) + s = "x = Symbol('x')\ny = Symbol('y')\ne = MutableDenseMatrix([[x**2 + 1, 1], [y, x + y]])" + assert p == s + +def test_python_limits(): + assert python(limit(x, x, oo)) == 'e = oo' + assert python(limit(x**2, x, 0)) == 'e = 0' + +def test_issue_20762(): + # Make sure Python removes curly braces from subscripted variables + a_b = Symbol('a_{b}') + b = Symbol('b') + expr = a_b*b + assert python(expr) == "a_b = Symbol('a_{b}')\nb = Symbol('b')\ne = a_b*b" + + +def test_settings(): + raises(TypeError, lambda: python(x, method="garbage")) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_rcode.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_rcode.py new file mode 100644 index 0000000000000000000000000000000000000000..a83235b0654c6bf24c30846dbf68678d29cd3c80 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_rcode.py @@ -0,0 +1,476 @@ +from sympy.core import (S, pi, oo, Symbol, symbols, Rational, Integer, + GoldenRatio, EulerGamma, Catalan, Lambda, Dummy) +from sympy.functions import (Piecewise, sin, cos, Abs, exp, ceiling, sqrt, + gamma, sign, Max, Min, factorial, beta) +from sympy.core.relational import (Eq, Ge, Gt, Le, Lt, Ne) +from sympy.sets import Range +from sympy.logic import ITE +from sympy.codegen import For, aug_assign, Assignment +from sympy.testing.pytest import raises +from sympy.printing.rcode import RCodePrinter +from sympy.utilities.lambdify import implemented_function +from sympy.tensor import IndexedBase, Idx +from sympy.matrices import Matrix, MatrixSymbol + +from sympy.printing.rcode import rcode + +x, y, z = symbols('x,y,z') + + +def test_printmethod(): + class fabs(Abs): + def _rcode(self, printer): + return "abs(%s)" % printer._print(self.args[0]) + + assert rcode(fabs(x)) == "abs(x)" + + +def test_rcode_sqrt(): + assert rcode(sqrt(x)) == "sqrt(x)" + assert rcode(x**0.5) == "sqrt(x)" + assert rcode(sqrt(x)) == "sqrt(x)" + + +def test_rcode_Pow(): + assert rcode(x**3) == "x^3" + assert rcode(x**(y**3)) == "x^(y^3)" + g = implemented_function('g', Lambda(x, 2*x)) + assert rcode(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ + "(3.5*2*x)^(-x + y^x)/(x^2 + y)" + assert rcode(x**-1.0) == '1.0/x' + assert rcode(x**Rational(2, 3)) == 'x^(2.0/3.0)' + _cond_cfunc = [(lambda base, exp: exp.is_integer, "dpowi"), + (lambda base, exp: not exp.is_integer, "pow")] + assert rcode(x**3, user_functions={'Pow': _cond_cfunc}) == 'dpowi(x, 3)' + assert rcode(x**3.2, user_functions={'Pow': _cond_cfunc}) == 'pow(x, 3.2)' + + +def test_rcode_Max(): + # Test for gh-11926 + assert rcode(Max(x,x*x),user_functions={"Max":"my_max", "Pow":"my_pow"}) == 'my_max(x, my_pow(x, 2))' + + +def test_rcode_constants_mathh(): + assert rcode(exp(1)) == "exp(1)" + assert rcode(pi) == "pi" + assert rcode(oo) == "Inf" + assert rcode(-oo) == "-Inf" + + +def test_rcode_constants_other(): + assert rcode(2*GoldenRatio) == "GoldenRatio = 1.61803398874989;\n2*GoldenRatio" + assert rcode( + 2*Catalan) == "Catalan = 0.915965594177219;\n2*Catalan" + assert rcode(2*EulerGamma) == "EulerGamma = 0.577215664901533;\n2*EulerGamma" + + +def test_rcode_Rational(): + assert rcode(Rational(3, 7)) == "3.0/7.0" + assert rcode(Rational(18, 9)) == "2" + assert rcode(Rational(3, -7)) == "-3.0/7.0" + assert rcode(Rational(-3, -7)) == "3.0/7.0" + assert rcode(x + Rational(3, 7)) == "x + 3.0/7.0" + assert rcode(Rational(3, 7)*x) == "(3.0/7.0)*x" + + +def test_rcode_Integer(): + assert rcode(Integer(67)) == "67" + assert rcode(Integer(-1)) == "-1" + + +def test_rcode_functions(): + assert rcode(sin(x) ** cos(x)) == "sin(x)^cos(x)" + assert rcode(factorial(x) + gamma(y)) == "factorial(x) + gamma(y)" + assert rcode(beta(Min(x, y), Max(x, y))) == "beta(min(x, y), max(x, y))" + + +def test_rcode_inline_function(): + x = symbols('x') + g = implemented_function('g', Lambda(x, 2*x)) + assert rcode(g(x)) == "2*x" + g = implemented_function('g', Lambda(x, 2*x/Catalan)) + assert rcode( + g(x)) == "Catalan = %s;\n2*x/Catalan" % Catalan.n() + A = IndexedBase('A') + i = Idx('i', symbols('n', integer=True)) + g = implemented_function('g', Lambda(x, x*(1 + x)*(2 + x))) + res=rcode(g(A[i]), assign_to=A[i]) + ref=( + "for (i in 1:n){\n" + " A[i] = (A[i] + 1)*(A[i] + 2)*A[i];\n" + "}" + ) + assert res == ref + + +def test_rcode_exceptions(): + assert rcode(ceiling(x)) == "ceiling(x)" + assert rcode(Abs(x)) == "abs(x)" + assert rcode(gamma(x)) == "gamma(x)" + + +def test_rcode_user_functions(): + x = symbols('x', integer=False) + n = symbols('n', integer=True) + custom_functions = { + "ceiling": "myceil", + "Abs": [(lambda x: not x.is_integer, "fabs"), (lambda x: x.is_integer, "abs")], + } + assert rcode(ceiling(x), user_functions=custom_functions) == "myceil(x)" + assert rcode(Abs(x), user_functions=custom_functions) == "fabs(x)" + assert rcode(Abs(n), user_functions=custom_functions) == "abs(n)" + + +def test_rcode_boolean(): + assert rcode(True) == "True" + assert rcode(S.true) == "True" + assert rcode(False) == "False" + assert rcode(S.false) == "False" + assert rcode(x & y) == "x & y" + assert rcode(x | y) == "x | y" + assert rcode(~x) == "!x" + assert rcode(x & y & z) == "x & y & z" + assert rcode(x | y | z) == "x | y | z" + assert rcode((x & y) | z) == "z | x & y" + assert rcode((x | y) & z) == "z & (x | y)" + +def test_rcode_Relational(): + assert rcode(Eq(x, y)) == "x == y" + assert rcode(Ne(x, y)) == "x != y" + assert rcode(Le(x, y)) == "x <= y" + assert rcode(Lt(x, y)) == "x < y" + assert rcode(Gt(x, y)) == "x > y" + assert rcode(Ge(x, y)) == "x >= y" + + +def test_rcode_Piecewise(): + expr = Piecewise((x, x < 1), (x**2, True)) + res=rcode(expr) + ref="ifelse(x < 1,x,x^2)" + assert res == ref + tau=Symbol("tau") + res=rcode(expr,tau) + ref="tau = ifelse(x < 1,x,x^2);" + assert res == ref + + expr = 2*Piecewise((x, x < 1), (x**2, x<2), (x**3,True)) + assert rcode(expr) == "2*ifelse(x < 1,x,ifelse(x < 2,x^2,x^3))" + res = rcode(expr, assign_to='c') + assert res == "c = 2*ifelse(x < 1,x,ifelse(x < 2,x^2,x^3));" + + # Check that Piecewise without a True (default) condition error + #expr = Piecewise((x, x < 1), (x**2, x > 1), (sin(x), x > 0)) + #raises(ValueError, lambda: rcode(expr)) + expr = 2*Piecewise((x, x < 1), (x**2, x<2)) + assert(rcode(expr))== "2*ifelse(x < 1,x,ifelse(x < 2,x^2,NA))" + + +def test_rcode_sinc(): + from sympy.functions.elementary.trigonometric import sinc + expr = sinc(x) + res = rcode(expr) + ref = "(ifelse(x != 0,sin(x)/x,1))" + assert res == ref + + +def test_rcode_Piecewise_deep(): + p = rcode(2*Piecewise((x, x < 1), (x + 1, x < 2), (x**2, True))) + assert p == "2*ifelse(x < 1,x,ifelse(x < 2,x + 1,x^2))" + expr = x*y*z + x**2 + y**2 + Piecewise((0, x < 0.5), (1, True)) + cos(z) - 1 + p = rcode(expr) + ref="x^2 + x*y*z + y^2 + ifelse(x < 0.5,0,1) + cos(z) - 1" + assert p == ref + + ref="c = x^2 + x*y*z + y^2 + ifelse(x < 0.5,0,1) + cos(z) - 1;" + p = rcode(expr, assign_to='c') + assert p == ref + + +def test_rcode_ITE(): + expr = ITE(x < 1, y, z) + p = rcode(expr) + ref="ifelse(x < 1,y,z)" + assert p == ref + + +def test_rcode_settings(): + raises(TypeError, lambda: rcode(sin(x), method="garbage")) + + +def test_rcode_Indexed(): + n, m, o = symbols('n m o', integer=True) + i, j, k = Idx('i', n), Idx('j', m), Idx('k', o) + p = RCodePrinter() + p._not_r = set() + + x = IndexedBase('x')[j] + assert p._print_Indexed(x) == 'x[j]' + A = IndexedBase('A')[i, j] + assert p._print_Indexed(A) == 'A[i, j]' + B = IndexedBase('B')[i, j, k] + assert p._print_Indexed(B) == 'B[i, j, k]' + + assert p._not_r == set() + +def test_rcode_Indexed_without_looking_for_contraction(): + len_y = 5 + y = IndexedBase('y', shape=(len_y,)) + x = IndexedBase('x', shape=(len_y,)) + Dy = IndexedBase('Dy', shape=(len_y-1,)) + i = Idx('i', len_y-1) + e=Eq(Dy[i], (y[i+1]-y[i])/(x[i+1]-x[i])) + code0 = rcode(e.rhs, assign_to=e.lhs, contract=False) + assert code0 == 'Dy[i] = (y[%s] - y[i])/(x[%s] - x[i]);' % (i + 1, i + 1) + + +def test_rcode_loops_matrix_vector(): + n, m = symbols('n m', integer=True) + A = IndexedBase('A') + x = IndexedBase('x') + y = IndexedBase('y') + i = Idx('i', m) + j = Idx('j', n) + + s = ( + 'for (i in 1:m){\n' + ' y[i] = 0;\n' + '}\n' + 'for (i in 1:m){\n' + ' for (j in 1:n){\n' + ' y[i] = A[i, j]*x[j] + y[i];\n' + ' }\n' + '}' + ) + c = rcode(A[i, j]*x[j], assign_to=y[i]) + assert c == s + + +def test_dummy_loops(): + # the following line could also be + # [Dummy(s, integer=True) for s in 'im'] + # or [Dummy(integer=True) for s in 'im'] + i, m = symbols('i m', integer=True, cls=Dummy) + x = IndexedBase('x') + y = IndexedBase('y') + i = Idx(i, m) + + expected = ( + 'for (i_%(icount)i in 1:m_%(mcount)i){\n' + ' y[i_%(icount)i] = x[i_%(icount)i];\n' + '}' + ) % {'icount': i.label.dummy_index, 'mcount': m.dummy_index} + code = rcode(x[i], assign_to=y[i]) + assert code == expected + + +def test_rcode_loops_add(): + n, m = symbols('n m', integer=True) + A = IndexedBase('A') + x = IndexedBase('x') + y = IndexedBase('y') + z = IndexedBase('z') + i = Idx('i', m) + j = Idx('j', n) + + s = ( + 'for (i in 1:m){\n' + ' y[i] = x[i] + z[i];\n' + '}\n' + 'for (i in 1:m){\n' + ' for (j in 1:n){\n' + ' y[i] = A[i, j]*x[j] + y[i];\n' + ' }\n' + '}' + ) + c = rcode(A[i, j]*x[j] + x[i] + z[i], assign_to=y[i]) + assert c == s + + +def test_rcode_loops_multiple_contractions(): + n, m, o, p = symbols('n m o p', integer=True) + a = IndexedBase('a') + b = IndexedBase('b') + y = IndexedBase('y') + i = Idx('i', m) + j = Idx('j', n) + k = Idx('k', o) + l = Idx('l', p) + + s = ( + 'for (i in 1:m){\n' + ' y[i] = 0;\n' + '}\n' + 'for (i in 1:m){\n' + ' for (j in 1:n){\n' + ' for (k in 1:o){\n' + ' for (l in 1:p){\n' + ' y[i] = a[i, j, k, l]*b[j, k, l] + y[i];\n' + ' }\n' + ' }\n' + ' }\n' + '}' + ) + c = rcode(b[j, k, l]*a[i, j, k, l], assign_to=y[i]) + assert c == s + + +def test_rcode_loops_addfactor(): + n, m, o, p = symbols('n m o p', integer=True) + a = IndexedBase('a') + b = IndexedBase('b') + c = IndexedBase('c') + y = IndexedBase('y') + i = Idx('i', m) + j = Idx('j', n) + k = Idx('k', o) + l = Idx('l', p) + + s = ( + 'for (i in 1:m){\n' + ' y[i] = 0;\n' + '}\n' + 'for (i in 1:m){\n' + ' for (j in 1:n){\n' + ' for (k in 1:o){\n' + ' for (l in 1:p){\n' + ' y[i] = (a[i, j, k, l] + b[i, j, k, l])*c[j, k, l] + y[i];\n' + ' }\n' + ' }\n' + ' }\n' + '}' + ) + c = rcode((a[i, j, k, l] + b[i, j, k, l])*c[j, k, l], assign_to=y[i]) + assert c == s + + +def test_rcode_loops_multiple_terms(): + n, m, o, p = symbols('n m o p', integer=True) + a = IndexedBase('a') + b = IndexedBase('b') + c = IndexedBase('c') + y = IndexedBase('y') + i = Idx('i', m) + j = Idx('j', n) + k = Idx('k', o) + + s0 = ( + 'for (i in 1:m){\n' + ' y[i] = 0;\n' + '}\n' + ) + s1 = ( + 'for (i in 1:m){\n' + ' for (j in 1:n){\n' + ' for (k in 1:o){\n' + ' y[i] = b[j]*b[k]*c[i, j, k] + y[i];\n' + ' }\n' + ' }\n' + '}\n' + ) + s2 = ( + 'for (i in 1:m){\n' + ' for (k in 1:o){\n' + ' y[i] = a[i, k]*b[k] + y[i];\n' + ' }\n' + '}\n' + ) + s3 = ( + 'for (i in 1:m){\n' + ' for (j in 1:n){\n' + ' y[i] = a[i, j]*b[j] + y[i];\n' + ' }\n' + '}\n' + ) + c = rcode( + b[j]*a[i, j] + b[k]*a[i, k] + b[j]*b[k]*c[i, j, k], assign_to=y[i]) + + ref={} + ref[0] = s0 + s1 + s2 + s3[:-1] + ref[1] = s0 + s1 + s3 + s2[:-1] + ref[2] = s0 + s2 + s1 + s3[:-1] + ref[3] = s0 + s2 + s3 + s1[:-1] + ref[4] = s0 + s3 + s1 + s2[:-1] + ref[5] = s0 + s3 + s2 + s1[:-1] + + assert (c == ref[0] or + c == ref[1] or + c == ref[2] or + c == ref[3] or + c == ref[4] or + c == ref[5]) + + +def test_dereference_printing(): + expr = x + y + sin(z) + z + assert rcode(expr, dereference=[z]) == "x + y + (*z) + sin((*z))" + + +def test_Matrix_printing(): + # Test returning a Matrix + mat = Matrix([x*y, Piecewise((2 + x, y>0), (y, True)), sin(z)]) + A = MatrixSymbol('A', 3, 1) + p = rcode(mat, A) + assert p == ( + "A[0] = x*y;\n" + "A[1] = ifelse(y > 0,x + 2,y);\n" + "A[2] = sin(z);") + # Test using MatrixElements in expressions + expr = Piecewise((2*A[2, 0], x > 0), (A[2, 0], True)) + sin(A[1, 0]) + A[0, 0] + p = rcode(expr) + assert p == ("ifelse(x > 0,2*A[2],A[2]) + sin(A[1]) + A[0]") + # Test using MatrixElements in a Matrix + q = MatrixSymbol('q', 5, 1) + M = MatrixSymbol('M', 3, 3) + m = Matrix([[sin(q[1,0]), 0, cos(q[2,0])], + [q[1,0] + q[2,0], q[3, 0], 5], + [2*q[4, 0]/q[1,0], sqrt(q[0,0]) + 4, 0]]) + assert rcode(m, M) == ( + "M[0] = sin(q[1]);\n" + "M[1] = 0;\n" + "M[2] = cos(q[2]);\n" + "M[3] = q[1] + q[2];\n" + "M[4] = q[3];\n" + "M[5] = 5;\n" + "M[6] = 2*q[4]/q[1];\n" + "M[7] = sqrt(q[0]) + 4;\n" + "M[8] = 0;") + + +def test_rcode_sgn(): + + expr = sign(x) * y + assert rcode(expr) == 'y*sign(x)' + p = rcode(expr, 'z') + assert p == 'z = y*sign(x);' + + p = rcode(sign(2 * x + x**2) * x + x**2) + assert p == "x^2 + x*sign(x^2 + 2*x)" + + expr = sign(cos(x)) + p = rcode(expr) + assert p == 'sign(cos(x))' + +def test_rcode_Assignment(): + assert rcode(Assignment(x, y + z)) == 'x = y + z;' + assert rcode(aug_assign(x, '+', y + z)) == 'x += y + z;' + + +def test_rcode_For(): + f = For(x, Range(0, 10, 2), [aug_assign(y, '*', x)]) + sol = rcode(f) + assert sol == ("for(x in seq(from=0, to=9, by=2){\n" + " y *= x;\n" + "}") + + +def test_MatrixElement_printing(): + # test cases for issue #11821 + A = MatrixSymbol("A", 1, 3) + B = MatrixSymbol("B", 1, 3) + C = MatrixSymbol("C", 1, 3) + + assert(rcode(A[0, 0]) == "A[0]") + assert(rcode(3 * A[0, 0]) == "3*A[0]") + + F = C[0, 0].subs(C, A - B) + assert(rcode(F) == "(A - B)[0]") diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_repr.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_repr.py new file mode 100644 index 0000000000000000000000000000000000000000..da58883b4fb027ed82db842a0a1ce5f76a49a8bb --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_repr.py @@ -0,0 +1,382 @@ +from __future__ import annotations +from typing import Any + +from sympy.external.gmpy import GROUND_TYPES +from sympy.testing.pytest import raises, warns_deprecated_sympy +from sympy.assumptions.ask import Q +from sympy.core.function import (Function, WildFunction) +from sympy.core.numbers import (AlgebraicNumber, Float, Integer, Rational) +from sympy.core.singleton import S +from sympy.core.symbol import (Dummy, Symbol, Wild, symbols) +from sympy.core.sympify import sympify +from sympy.functions.elementary.complexes import Abs +from sympy.functions.elementary.miscellaneous import (root, sqrt) +from sympy.functions.elementary.trigonometric import sin +from sympy.functions.special.delta_functions import Heaviside +from sympy.logic.boolalg import (false, true) +from sympy.matrices.dense import (Matrix, ones) +from sympy.matrices.expressions.matexpr import MatrixSymbol +from sympy.matrices.immutable import ImmutableDenseMatrix +from sympy.combinatorics import Cycle, Permutation +from sympy.core.symbol import Str +from sympy.geometry import Point, Ellipse +from sympy.printing import srepr +from sympy.polys import ring, field, ZZ, QQ, lex, grlex, Poly +from sympy.polys.polyclasses import DMP +from sympy.polys.agca.extensions import FiniteExtension + +x, y = symbols('x,y') + +# eval(srepr(expr)) == expr has to succeed in the right environment. The right +# environment is the scope of "from sympy import *" for most cases. +ENV: dict[str, Any] = {"Str": Str} +exec("from sympy import *", ENV) + + +def sT(expr, string, import_stmt=None, **kwargs): + """ + sT := sreprTest + + Tests that srepr delivers the expected string and that + the condition eval(srepr(expr))==expr holds. + """ + if import_stmt is None: + ENV2 = ENV + else: + ENV2 = ENV.copy() + exec(import_stmt, ENV2) + + assert srepr(expr, **kwargs) == string + assert eval(string, ENV2) == expr + + +def test_printmethod(): + class R(Abs): + def _sympyrepr(self, printer): + return "foo(%s)" % printer._print(self.args[0]) + assert srepr(R(x)) == "foo(Symbol('x'))" + + +def test_Add(): + sT(x + y, "Add(Symbol('x'), Symbol('y'))") + assert srepr(x**2 + 1, order='lex') == "Add(Pow(Symbol('x'), Integer(2)), Integer(1))" + assert srepr(x**2 + 1, order='old') == "Add(Integer(1), Pow(Symbol('x'), Integer(2)))" + assert srepr(sympify('x + 3 - 2', evaluate=False), order='none') == "Add(Symbol('x'), Integer(3), Mul(Integer(-1), Integer(2)))" + + +def test_more_than_255_args_issue_10259(): + from sympy.core.add import Add + from sympy.core.mul import Mul + for op in (Add, Mul): + expr = op(*symbols('x:256')) + assert eval(srepr(expr)) == expr + + +def test_Function(): + sT(Function("f")(x), "Function('f')(Symbol('x'))") + # test unapplied Function + sT(Function('f'), "Function('f')") + + sT(sin(x), "sin(Symbol('x'))") + sT(sin, "sin") + + +def test_Heaviside(): + sT(Heaviside(x), "Heaviside(Symbol('x'))") + sT(Heaviside(x, 1), "Heaviside(Symbol('x'), Integer(1))") + + +def test_Geometry(): + sT(Point(0, 0), "Point2D(Integer(0), Integer(0))") + sT(Ellipse(Point(0, 0), 5, 1), + "Ellipse(Point2D(Integer(0), Integer(0)), Integer(5), Integer(1))") + # TODO more tests + + +def test_Singletons(): + sT(S.Catalan, 'Catalan') + sT(S.ComplexInfinity, 'zoo') + sT(S.EulerGamma, 'EulerGamma') + sT(S.Exp1, 'E') + sT(S.GoldenRatio, 'GoldenRatio') + sT(S.TribonacciConstant, 'TribonacciConstant') + sT(S.Half, 'Rational(1, 2)') + sT(S.ImaginaryUnit, 'I') + sT(S.Infinity, 'oo') + sT(S.NaN, 'nan') + sT(S.NegativeInfinity, '-oo') + sT(S.NegativeOne, 'Integer(-1)') + sT(S.One, 'Integer(1)') + sT(S.Pi, 'pi') + sT(S.Zero, 'Integer(0)') + sT(S.Complexes, 'Complexes') + sT(S.EmptySequence, 'EmptySequence') + sT(S.EmptySet, 'EmptySet') + # sT(S.IdentityFunction, 'Lambda(_x, _x)') + sT(S.Naturals, 'Naturals') + sT(S.Naturals0, 'Naturals0') + sT(S.Rationals, 'Rationals') + sT(S.Reals, 'Reals') + sT(S.UniversalSet, 'UniversalSet') + + +def test_Integer(): + sT(Integer(4), "Integer(4)") + + +def test_list(): + sT([x, Integer(4)], "[Symbol('x'), Integer(4)]") + + +def test_Matrix(): + for cls, name in [(Matrix, "MutableDenseMatrix"), (ImmutableDenseMatrix, "ImmutableDenseMatrix")]: + sT(cls([[x**+1, 1], [y, x + y]]), + "%s([[Symbol('x'), Integer(1)], [Symbol('y'), Add(Symbol('x'), Symbol('y'))]])" % name) + + sT(cls(), "%s([])" % name) + + sT(cls([[x**+1, 1], [y, x + y]]), "%s([[Symbol('x'), Integer(1)], [Symbol('y'), Add(Symbol('x'), Symbol('y'))]])" % name) + + +def test_empty_Matrix(): + sT(ones(0, 3), "MutableDenseMatrix(0, 3, [])") + sT(ones(4, 0), "MutableDenseMatrix(4, 0, [])") + sT(ones(0, 0), "MutableDenseMatrix([])") + + +def test_Rational(): + sT(Rational(1, 3), "Rational(1, 3)") + sT(Rational(-1, 3), "Rational(-1, 3)") + + +def test_Float(): + sT(Float('1.23', dps=3), "Float('1.22998', precision=13)") + sT(Float('1.23456789', dps=9), "Float('1.23456788994', precision=33)") + sT(Float('1.234567890123456789', dps=19), + "Float('1.234567890123456789013', precision=66)") + sT(Float('0.60038617995049726', dps=15), + "Float('0.60038617995049726', precision=53)") + + sT(Float('1.23', precision=13), "Float('1.22998', precision=13)") + sT(Float('1.23456789', precision=33), + "Float('1.23456788994', precision=33)") + sT(Float('1.234567890123456789', precision=66), + "Float('1.234567890123456789013', precision=66)") + sT(Float('0.60038617995049726', precision=53), + "Float('0.60038617995049726', precision=53)") + + sT(Float('0.60038617995049726', 15), + "Float('0.60038617995049726', precision=53)") + + +def test_Symbol(): + sT(x, "Symbol('x')") + sT(y, "Symbol('y')") + sT(Symbol('x', negative=True), "Symbol('x', negative=True)") + + +def test_Symbol_two_assumptions(): + x = Symbol('x', negative=0, integer=1) + # order could vary + s1 = "Symbol('x', integer=True, negative=False)" + s2 = "Symbol('x', negative=False, integer=True)" + assert srepr(x) in (s1, s2) + assert eval(srepr(x), ENV) == x + + +def test_Symbol_no_special_commutative_treatment(): + sT(Symbol('x'), "Symbol('x')") + sT(Symbol('x', commutative=False), "Symbol('x', commutative=False)") + sT(Symbol('x', commutative=0), "Symbol('x', commutative=False)") + sT(Symbol('x', commutative=True), "Symbol('x', commutative=True)") + sT(Symbol('x', commutative=1), "Symbol('x', commutative=True)") + + +def test_Wild(): + sT(Wild('x', even=True), "Wild('x', even=True)") + + +def test_Dummy(): + d = Dummy('d') + sT(d, "Dummy('d', dummy_index=%s)" % str(d.dummy_index)) + + +def test_Dummy_assumption(): + d = Dummy('d', nonzero=True) + assert d == eval(srepr(d)) + s1 = "Dummy('d', dummy_index=%s, nonzero=True)" % str(d.dummy_index) + s2 = "Dummy('d', nonzero=True, dummy_index=%s)" % str(d.dummy_index) + assert srepr(d) in (s1, s2) + + +def test_Dummy_from_Symbol(): + # should not get the full dictionary of assumptions + n = Symbol('n', integer=True) + d = n.as_dummy() + assert srepr(d + ) == "Dummy('n', dummy_index=%s)" % str(d.dummy_index) + + +def test_tuple(): + sT((x,), "(Symbol('x'),)") + sT((x, y), "(Symbol('x'), Symbol('y'))") + + +def test_WildFunction(): + sT(WildFunction('w'), "WildFunction('w')") + + +def test_settins(): + raises(TypeError, lambda: srepr(x, method="garbage")) + + +def test_Mul(): + sT(3*x**3*y, "Mul(Integer(3), Pow(Symbol('x'), Integer(3)), Symbol('y'))") + assert srepr(3*x**3*y, order='old') == "Mul(Integer(3), Symbol('y'), Pow(Symbol('x'), Integer(3)))" + assert srepr(sympify('(x+4)*2*x*7', evaluate=False), order='none') == "Mul(Add(Symbol('x'), Integer(4)), Integer(2), Symbol('x'), Integer(7))" + + +def test_AlgebraicNumber(): + a = AlgebraicNumber(sqrt(2)) + sT(a, "AlgebraicNumber(Pow(Integer(2), Rational(1, 2)), [Integer(1), Integer(0)])") + a = AlgebraicNumber(root(-2, 3)) + sT(a, "AlgebraicNumber(Pow(Integer(-2), Rational(1, 3)), [Integer(1), Integer(0)])") + + +def test_PolyRing(): + assert srepr(ring("x", ZZ, lex)[0]) == "PolyRing((Symbol('x'),), ZZ, lex)" + assert srepr(ring("x,y", QQ, grlex)[0]) == "PolyRing((Symbol('x'), Symbol('y')), QQ, grlex)" + assert srepr(ring("x,y,z", ZZ["t"], lex)[0]) == "PolyRing((Symbol('x'), Symbol('y'), Symbol('z')), ZZ[t], lex)" + + +def test_FracField(): + assert srepr(field("x", ZZ, lex)[0]) == "FracField((Symbol('x'),), ZZ, lex)" + assert srepr(field("x,y", QQ, grlex)[0]) == "FracField((Symbol('x'), Symbol('y')), QQ, grlex)" + assert srepr(field("x,y,z", ZZ["t"], lex)[0]) == "FracField((Symbol('x'), Symbol('y'), Symbol('z')), ZZ[t], lex)" + + +def test_PolyElement(): + R, x, y = ring("x,y", ZZ) + assert srepr(3*x**2*y + 1) == "PolyElement(PolyRing((Symbol('x'), Symbol('y')), ZZ, lex), [((2, 1), 3), ((0, 0), 1)])" + + +def test_FracElement(): + F, x, y = field("x,y", ZZ) + assert srepr((3*x**2*y + 1)/(x - y**2)) == "FracElement(FracField((Symbol('x'), Symbol('y')), ZZ, lex), [((2, 1), 3), ((0, 0), 1)], [((1, 0), 1), ((0, 2), -1)])" + + +def test_FractionField(): + assert srepr(QQ.frac_field(x)) == \ + "FractionField(FracField((Symbol('x'),), QQ, lex))" + assert srepr(QQ.frac_field(x, y, order=grlex)) == \ + "FractionField(FracField((Symbol('x'), Symbol('y')), QQ, grlex))" + + +def test_PolynomialRingBase(): + assert srepr(ZZ.old_poly_ring(x)) == \ + "GlobalPolynomialRing(ZZ, Symbol('x'))" + assert srepr(ZZ[x].old_poly_ring(y)) == \ + "GlobalPolynomialRing(ZZ[x], Symbol('y'))" + assert srepr(QQ.frac_field(x).old_poly_ring(y)) == \ + "GlobalPolynomialRing(FractionField(FracField((Symbol('x'),), QQ, lex)), Symbol('y'))" + + +def test_DMP(): + p1 = DMP([1, 2], ZZ) + p2 = ZZ.old_poly_ring(x)([1, 2]) + if GROUND_TYPES != 'flint': + assert srepr(p1) == "DMP_Python([1, 2], ZZ)" + assert srepr(p2) == "DMP_Python([1, 2], ZZ)" + else: + assert srepr(p1) == "DUP_Flint([1, 2], ZZ)" + assert srepr(p2) == "DUP_Flint([1, 2], ZZ)" + + +def test_FiniteExtension(): + assert srepr(FiniteExtension(Poly(x**2 + 1, x))) == \ + "FiniteExtension(Poly(x**2 + 1, x, domain='ZZ'))" + + +def test_ExtensionElement(): + A = FiniteExtension(Poly(x**2 + 1, x)) + if GROUND_TYPES != 'flint': + ans = "ExtElem(DMP_Python([1, 0], ZZ), FiniteExtension(Poly(x**2 + 1, x, domain='ZZ')))" + else: + ans = "ExtElem(DUP_Flint([1, 0], ZZ), FiniteExtension(Poly(x**2 + 1, x, domain='ZZ')))" + assert srepr(A.generator) == ans + +def test_BooleanAtom(): + assert srepr(true) == "true" + assert srepr(false) == "false" + + +def test_Integers(): + sT(S.Integers, "Integers") + + +def test_Naturals(): + sT(S.Naturals, "Naturals") + + +def test_Naturals0(): + sT(S.Naturals0, "Naturals0") + + +def test_Reals(): + sT(S.Reals, "Reals") + + +def test_matrix_expressions(): + n = symbols('n', integer=True) + A = MatrixSymbol("A", n, n) + B = MatrixSymbol("B", n, n) + sT(A, "MatrixSymbol(Str('A'), Symbol('n', integer=True), Symbol('n', integer=True))") + sT(A*B, "MatMul(MatrixSymbol(Str('A'), Symbol('n', integer=True), Symbol('n', integer=True)), MatrixSymbol(Str('B'), Symbol('n', integer=True), Symbol('n', integer=True)))") + sT(A + B, "MatAdd(MatrixSymbol(Str('A'), Symbol('n', integer=True), Symbol('n', integer=True)), MatrixSymbol(Str('B'), Symbol('n', integer=True), Symbol('n', integer=True)))") + + +def test_Cycle(): + # FIXME: sT fails because Cycle is not immutable and calling srepr(Cycle(1, 2)) + # adds keys to the Cycle dict (GH-17661) + #import_stmt = "from sympy.combinatorics import Cycle" + #sT(Cycle(1, 2), "Cycle(1, 2)", import_stmt) + assert srepr(Cycle(1, 2)) == "Cycle(1, 2)" + + +def test_Permutation(): + import_stmt = "from sympy.combinatorics import Permutation" + sT(Permutation(1, 2)(3, 4), "Permutation([0, 2, 1, 4, 3])", import_stmt, perm_cyclic=False) + sT(Permutation(1, 2)(3, 4), "Permutation(1, 2)(3, 4)", import_stmt, perm_cyclic=True) + + with warns_deprecated_sympy(): + old_print_cyclic = Permutation.print_cyclic + Permutation.print_cyclic = False + sT(Permutation(1, 2)(3, 4), "Permutation([0, 2, 1, 4, 3])", import_stmt) + Permutation.print_cyclic = old_print_cyclic + +def test_dict(): + from sympy.abc import x, y, z + d = {} + assert srepr(d) == "{}" + d = {x: y} + assert srepr(d) == "{Symbol('x'): Symbol('y')}" + d = {x: y, y: z} + assert srepr(d) in ( + "{Symbol('x'): Symbol('y'), Symbol('y'): Symbol('z')}", + "{Symbol('y'): Symbol('z'), Symbol('x'): Symbol('y')}", + ) + d = {x: {y: z}} + assert srepr(d) == "{Symbol('x'): {Symbol('y'): Symbol('z')}}" + +def test_set(): + from sympy.abc import x, y + s = set() + assert srepr(s) == "set()" + s = {x, y} + assert srepr(s) in ("{Symbol('x'), Symbol('y')}", "{Symbol('y'), Symbol('x')}") + +def test_Predicate(): + sT(Q.even, "Q.even") + +def test_AppliedPredicate(): + sT(Q.even(Symbol('z')), "AppliedPredicate(Q.even, Symbol('z'))") diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_rust.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_rust.py new file mode 100644 index 0000000000000000000000000000000000000000..c81d592faca0d4a31e5a9618a48d67cb19ca94d8 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_rust.py @@ -0,0 +1,363 @@ +from sympy.core import (S, pi, oo, symbols, Rational, Integer, + GoldenRatio, EulerGamma, Catalan, Lambda, Dummy, + Eq, Ne, Le, Lt, Gt, Ge, Mod) +from sympy.functions import (Piecewise, sin, cos, Abs, exp, ceiling, sqrt, + sign, floor) +from sympy.logic import ITE +from sympy.testing.pytest import raises +from sympy.utilities.lambdify import implemented_function +from sympy.tensor import IndexedBase, Idx +from sympy.matrices import MatrixSymbol, SparseMatrix, Matrix + +from sympy.printing.codeprinter import rust_code + +x, y, z = symbols('x,y,z', integer=False, real=True) +k, m, n = symbols('k,m,n', integer=True) + + +def test_Integer(): + assert rust_code(Integer(42)) == "42" + assert rust_code(Integer(-56)) == "-56" + + +def test_Relational(): + assert rust_code(Eq(x, y)) == "x == y" + assert rust_code(Ne(x, y)) == "x != y" + assert rust_code(Le(x, y)) == "x <= y" + assert rust_code(Lt(x, y)) == "x < y" + assert rust_code(Gt(x, y)) == "x > y" + assert rust_code(Ge(x, y)) == "x >= y" + + +def test_Rational(): + assert rust_code(Rational(3, 7)) == "3_f64/7.0" + assert rust_code(Rational(18, 9)) == "2" + assert rust_code(Rational(3, -7)) == "-3_f64/7.0" + assert rust_code(Rational(-3, -7)) == "3_f64/7.0" + assert rust_code(x + Rational(3, 7)) == "x + 3_f64/7.0" + assert rust_code(Rational(3, 7)*x) == "(3_f64/7.0)*x" + + +def test_basic_ops(): + assert rust_code(x + y) == "x + y" + assert rust_code(x - y) == "x - y" + assert rust_code(x * y) == "x*y" + assert rust_code(x / y) == "x*y.recip()" + assert rust_code(-x) == "-x" + assert rust_code(2 * x) == "2.0*x" + assert rust_code(y + 2) == "y + 2.0" + assert rust_code(x + n) == "n as f64 + x" + +def test_printmethod(): + class fabs(Abs): + def _rust_code(self, printer): + return "%s.fabs()" % printer._print(self.args[0]) + assert rust_code(fabs(x)) == "x.fabs()" + a = MatrixSymbol("a", 1, 3) + assert rust_code(a[0,0]) == 'a[0]' + + +def test_Functions(): + assert rust_code(sin(x) ** cos(x)) == "x.sin().powf(x.cos())" + assert rust_code(abs(x)) == "x.abs()" + assert rust_code(ceiling(x)) == "x.ceil()" + assert rust_code(floor(x)) == "x.floor()" + + # Automatic rewrite + assert rust_code(Mod(x, 3)) == 'x - 3.0*((1_f64/3.0)*x).floor()' + + +def test_Pow(): + assert rust_code(1/x) == "x.recip()" + assert rust_code(x**-1) == rust_code(x**-1.0) == "x.recip()" + assert rust_code(sqrt(x)) == "x.sqrt()" + assert rust_code(x**S.Half) == rust_code(x**0.5) == "x.sqrt()" + + assert rust_code(1/sqrt(x)) == "x.sqrt().recip()" + assert rust_code(x**-S.Half) == rust_code(x**-0.5) == "x.sqrt().recip()" + + assert rust_code(1/pi) == "PI.recip()" + assert rust_code(pi**-1) == rust_code(pi**-1.0) == "PI.recip()" + assert rust_code(pi**-0.5) == "PI.sqrt().recip()" + + assert rust_code(x**Rational(1, 3)) == "x.cbrt()" + assert rust_code(2**x) == "x.exp2()" + assert rust_code(exp(x)) == "x.exp()" + assert rust_code(x**3) == "x.powi(3)" + assert rust_code(x**(y**3)) == "x.powf(y.powi(3))" + assert rust_code(x**Rational(2, 3)) == "x.powf(2_f64/3.0)" + + g = implemented_function('g', Lambda(x, 2*x)) + assert rust_code(1/(g(x)*3.5)**(x - y**x)/(x**2 + y)) == \ + "(3.5*2.0*x).powf(-x + y.powf(x))/(x.powi(2) + y)" + _cond_cfunc = [(lambda base, exp: exp.is_integer, "dpowi", 1), + (lambda base, exp: not exp.is_integer, "pow", 1)] + assert rust_code(x**3, user_functions={'Pow': _cond_cfunc}) == 'x.dpowi(3)' + assert rust_code(x**3.2, user_functions={'Pow': _cond_cfunc}) == 'x.pow(3.2)' + + +def test_constants(): + assert rust_code(pi) == "PI" + assert rust_code(oo) == "INFINITY" + assert rust_code(S.Infinity) == "INFINITY" + assert rust_code(-oo) == "NEG_INFINITY" + assert rust_code(S.NegativeInfinity) == "NEG_INFINITY" + assert rust_code(S.NaN) == "NAN" + assert rust_code(exp(1)) == "E" + assert rust_code(S.Exp1) == "E" + + +def test_constants_other(): + assert rust_code(2*GoldenRatio) == "const GoldenRatio: f64 = %s;\n2.0*GoldenRatio" % GoldenRatio.evalf(17) + assert rust_code( + 2*Catalan) == "const Catalan: f64 = %s;\n2.0*Catalan" % Catalan.evalf(17) + assert rust_code(2*EulerGamma) == "const EulerGamma: f64 = %s;\n2.0*EulerGamma" % EulerGamma.evalf(17) + + +def test_boolean(): + assert rust_code(True) == "true" + assert rust_code(S.true) == "true" + assert rust_code(False) == "false" + assert rust_code(S.false) == "false" + assert rust_code(k & m) == "k && m" + assert rust_code(k | m) == "k || m" + assert rust_code(~k) == "!k" + assert rust_code(k & m & n) == "k && m && n" + assert rust_code(k | m | n) == "k || m || n" + assert rust_code((k & m) | n) == "n || k && m" + assert rust_code((k | m) & n) == "n && (k || m)" + + +def test_Piecewise(): + expr = Piecewise((x, x < 1), (x + 2, True)) + assert rust_code(expr) == ( + "if (x < 1.0) {\n" + " x\n" + "} else {\n" + " x + 2.0\n" + "}") + assert rust_code(expr, assign_to="r") == ( + "r = if (x < 1.0) {\n" + " x\n" + "} else {\n" + " x + 2.0\n" + "};") + assert rust_code(expr, assign_to="r", inline=True) == ( + "r = if (x < 1.0) { x } else { x + 2.0 };") + expr = Piecewise((x, x < 1), (x + 1, x < 5), (x + 2, True)) + assert rust_code(expr, inline=True) == ( + "if (x < 1.0) { x } else if (x < 5.0) { x + 1.0 } else { x + 2.0 }") + assert rust_code(expr, assign_to="r", inline=True) == ( + "r = if (x < 1.0) { x } else if (x < 5.0) { x + 1.0 } else { x + 2.0 };") + assert rust_code(expr, assign_to="r") == ( + "r = if (x < 1.0) {\n" + " x\n" + "} else if (x < 5.0) {\n" + " x + 1.0\n" + "} else {\n" + " x + 2.0\n" + "};") + expr = 2*Piecewise((x, x < 1), (x + 1, x < 5), (x + 2, True)) + assert rust_code(expr, inline=True) == ( + "2.0*if (x < 1.0) { x } else if (x < 5.0) { x + 1.0 } else { x + 2.0 }") + expr = 2*Piecewise((x, x < 1), (x + 1, x < 5), (x + 2, True)) - 42 + assert rust_code(expr, inline=True) == ( + "2.0*if (x < 1.0) { x } else if (x < 5.0) { x + 1.0 } else { x + 2.0 } - 42.0") + # Check that Piecewise without a True (default) condition error + expr = Piecewise((x, x < 1), (x**2, x > 1), (sin(x), x > 0)) + raises(ValueError, lambda: rust_code(expr)) + + +def test_dereference_printing(): + expr = x + y + sin(z) + z + assert rust_code(expr, dereference=[z]) == "x + y + (*z) + (*z).sin()" + + +def test_sign(): + expr = sign(x) * y + assert rust_code(expr) == "y*(if (x == 0.0) { 0.0 } else { (x).signum() }) as f64" + assert rust_code(expr, assign_to='r') == "r = y*(if (x == 0.0) { 0.0 } else { (x).signum() }) as f64;" + + expr = sign(x + y) + 42 + assert rust_code(expr) == "(if (x + y == 0.0) { 0.0 } else { (x + y).signum() }) + 42" + assert rust_code(expr, assign_to='r') == "r = (if (x + y == 0.0) { 0.0 } else { (x + y).signum() }) + 42;" + + expr = sign(cos(x)) + assert rust_code(expr) == "(if (x.cos() == 0.0) { 0.0 } else { (x.cos()).signum() })" + + +def test_reserved_words(): + + x, y = symbols("x if") + + expr = sin(y) + assert rust_code(expr) == "if_.sin()" + assert rust_code(expr, dereference=[y]) == "(*if_).sin()" + assert rust_code(expr, reserved_word_suffix='_unreserved') == "if_unreserved.sin()" + + with raises(ValueError): + rust_code(expr, error_on_reserved=True) + + +def test_ITE(): + ekpr = ITE(k < 1, m, n) + assert rust_code(ekpr) == ( + "if (k < 1) {\n" + " m\n" + "} else {\n" + " n\n" + "}") + + +def test_Indexed(): + n, m, o = symbols('n m o', integer=True) + i, j, k = Idx('i', n), Idx('j', m), Idx('k', o) + + x = IndexedBase('x')[j] + assert rust_code(x) == "x[j]" + + A = IndexedBase('A')[i, j] + assert rust_code(A) == "A[m*i + j]" + + B = IndexedBase('B')[i, j, k] + assert rust_code(B) == "B[m*o*i + o*j + k]" + + +def test_dummy_loops(): + i, m = symbols('i m', integer=True, cls=Dummy) + x = IndexedBase('x') + y = IndexedBase('y') + i = Idx(i, m) + + assert rust_code(x[i], assign_to=y[i]) == ( + "for i in 0..m {\n" + " y[i] = x[i];\n" + "}") + + +def test_loops(): + m, n = symbols('m n', integer=True) + A = IndexedBase('A') + x = IndexedBase('x') + y = IndexedBase('y') + z = IndexedBase('z') + i = Idx('i', m) + j = Idx('j', n) + + assert rust_code(A[i, j]*x[j], assign_to=y[i]) == ( + "for i in 0..m {\n" + " y[i] = 0;\n" + "}\n" + "for i in 0..m {\n" + " for j in 0..n {\n" + " y[i] = A[n*i + j]*x[j] + y[i];\n" + " }\n" + "}") + + assert rust_code(A[i, j]*x[j] + x[i] + z[i], assign_to=y[i]) == ( + "for i in 0..m {\n" + " y[i] = x[i] + z[i];\n" + "}\n" + "for i in 0..m {\n" + " for j in 0..n {\n" + " y[i] = A[n*i + j]*x[j] + y[i];\n" + " }\n" + "}") + + +def test_loops_multiple_contractions(): + n, m, o, p = symbols('n m o p', integer=True) + a = IndexedBase('a') + b = IndexedBase('b') + y = IndexedBase('y') + i = Idx('i', m) + j = Idx('j', n) + k = Idx('k', o) + l = Idx('l', p) + + assert rust_code(b[j, k, l]*a[i, j, k, l], assign_to=y[i]) == ( + "for i in 0..m {\n" + " y[i] = 0;\n" + "}\n" + "for i in 0..m {\n" + " for j in 0..n {\n" + " for k in 0..o {\n" + " for l in 0..p {\n" + " y[i] = a[%s]*b[%s] + y[i];\n" % (i*n*o*p + j*o*p + k*p + l, j*o*p + k*p + l) +\ + " }\n" + " }\n" + " }\n" + "}") + + +def test_loops_addfactor(): + m, n, o, p = symbols('m n o p', integer=True) + a = IndexedBase('a') + b = IndexedBase('b') + c = IndexedBase('c') + y = IndexedBase('y') + i = Idx('i', m) + j = Idx('j', n) + k = Idx('k', o) + l = Idx('l', p) + + code = rust_code((a[i, j, k, l] + b[i, j, k, l])*c[j, k, l], assign_to=y[i]) + assert code == ( + "for i in 0..m {\n" + " y[i] = 0;\n" + "}\n" + "for i in 0..m {\n" + " for j in 0..n {\n" + " for k in 0..o {\n" + " for l in 0..p {\n" + " y[i] = (a[%s] + b[%s])*c[%s] + y[i];\n" % (i*n*o*p + j*o*p + k*p + l, i*n*o*p + j*o*p + k*p + l, j*o*p + k*p + l) +\ + " }\n" + " }\n" + " }\n" + "}") + + +def test_settings(): + raises(TypeError, lambda: rust_code(sin(x), method="garbage")) + + +def test_inline_function(): + x = symbols('x') + g = implemented_function('g', Lambda(x, 2*x)) + assert rust_code(g(x)) == "2*x" + + g = implemented_function('g', Lambda(x, 2*x/Catalan)) + assert rust_code(g(x)) == ( + "const Catalan: f64 = %s;\n2.0*x/Catalan" % Catalan.evalf(17)) + + A = IndexedBase('A') + i = Idx('i', symbols('n', integer=True)) + g = implemented_function('g', Lambda(x, x*(1 + x)*(2 + x))) + assert rust_code(g(A[i]), assign_to=A[i]) == ( + "for i in 0..n {\n" + " A[i] = (A[i] + 1)*(A[i] + 2)*A[i];\n" + "}") + + +def test_user_functions(): + x = symbols('x', integer=False) + n = symbols('n', integer=True) + custom_functions = { + "ceiling": "ceil", + "Abs": [(lambda x: not x.is_integer, "fabs", 4), (lambda x: x.is_integer, "abs", 4)], + } + assert rust_code(ceiling(x), user_functions=custom_functions) == "x.ceil()" + assert rust_code(Abs(x), user_functions=custom_functions) == "fabs(x)" + assert rust_code(Abs(n), user_functions=custom_functions) == "abs(n)" + + +def test_matrix(): + assert rust_code(Matrix([1, 2, 3])) == '[1, 2, 3]' + with raises(ValueError): + rust_code(Matrix([[1, 2, 3]])) + + +def test_sparse_matrix(): + # gh-15791 + with raises(NotImplementedError): + rust_code(SparseMatrix([[1, 2, 3]])) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_smtlib.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_smtlib.py new file mode 100644 index 0000000000000000000000000000000000000000..48ff3d432d9042bf178f4e52dc46c787059937a3 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_smtlib.py @@ -0,0 +1,553 @@ +import contextlib +import itertools +import re +import typing +from enum import Enum +from typing import Callable + +import sympy +from sympy import Add, Implies, sqrt +from sympy.core import Mul, Pow +from sympy.core import (S, pi, symbols, Function, Rational, Integer, + Symbol, Eq, Ne, Le, Lt, Gt, Ge) +from sympy.functions import Piecewise, exp, sin, cos +from sympy.assumptions.ask import Q +from sympy.printing.smtlib import smtlib_code +from sympy.testing.pytest import raises, Failed + +x, y, z = symbols('x,y,z') + + +class _W(Enum): + DEFAULTING_TO_FLOAT = re.compile("Could not infer type of `.+`. Defaulting to float.", re.IGNORECASE) + WILL_NOT_DECLARE = re.compile("Non-Symbol/Function `.+` will not be declared.", re.IGNORECASE) + WILL_NOT_ASSERT = re.compile("Non-Boolean expression `.+` will not be asserted. Converting to SMTLib verbatim.", re.IGNORECASE) + + +@contextlib.contextmanager +def _check_warns(expected: typing.Iterable[_W]): + warns: typing.List[str] = [] + log_warn = warns.append + yield log_warn + + errors = [] + for i, (w, e) in enumerate(itertools.zip_longest(warns, expected)): + if not e: + errors += [f"[{i}] Received unexpected warning `{w}`."] + elif not w: + errors += [f"[{i}] Did not receive expected warning `{e.name}`."] + elif not e.value.match(w): + errors += [f"[{i}] Warning `{w}` does not match expected {e.name}."] + + if errors: raise Failed('\n'.join(errors)) + + +def test_Integer(): + with _check_warns([_W.WILL_NOT_ASSERT] * 2) as w: + assert smtlib_code(Integer(67), log_warn=w) == "67" + assert smtlib_code(Integer(-1), log_warn=w) == "-1" + with _check_warns([]) as w: + assert smtlib_code(Integer(67)) == "67" + assert smtlib_code(Integer(-1)) == "-1" + + +def test_Rational(): + with _check_warns([_W.WILL_NOT_ASSERT] * 4) as w: + assert smtlib_code(Rational(3, 7), log_warn=w) == "(/ 3 7)" + assert smtlib_code(Rational(18, 9), log_warn=w) == "2" + assert smtlib_code(Rational(3, -7), log_warn=w) == "(/ -3 7)" + assert smtlib_code(Rational(-3, -7), log_warn=w) == "(/ 3 7)" + + with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT] * 2) as w: + assert smtlib_code(x + Rational(3, 7), auto_declare=False, log_warn=w) == "(+ (/ 3 7) x)" + assert smtlib_code(Rational(3, 7) * x, log_warn=w) == "(declare-const x Real)\n" \ + "(* (/ 3 7) x)" + + +def test_Relational(): + with _check_warns([_W.DEFAULTING_TO_FLOAT] * 12) as w: + assert smtlib_code(Eq(x, y), auto_declare=False, log_warn=w) == "(assert (= x y))" + assert smtlib_code(Ne(x, y), auto_declare=False, log_warn=w) == "(assert (not (= x y)))" + assert smtlib_code(Le(x, y), auto_declare=False, log_warn=w) == "(assert (<= x y))" + assert smtlib_code(Lt(x, y), auto_declare=False, log_warn=w) == "(assert (< x y))" + assert smtlib_code(Gt(x, y), auto_declare=False, log_warn=w) == "(assert (> x y))" + assert smtlib_code(Ge(x, y), auto_declare=False, log_warn=w) == "(assert (>= x y))" + + +def test_AppliedBinaryRelation(): + with _check_warns([_W.DEFAULTING_TO_FLOAT] * 12) as w: + assert smtlib_code(Q.eq(x, y), auto_declare=False, log_warn=w) == "(assert (= x y))" + assert smtlib_code(Q.ne(x, y), auto_declare=False, log_warn=w) == "(assert (not (= x y)))" + assert smtlib_code(Q.lt(x, y), auto_declare=False, log_warn=w) == "(assert (< x y))" + assert smtlib_code(Q.le(x, y), auto_declare=False, log_warn=w) == "(assert (<= x y))" + assert smtlib_code(Q.gt(x, y), auto_declare=False, log_warn=w) == "(assert (> x y))" + assert smtlib_code(Q.ge(x, y), auto_declare=False, log_warn=w) == "(assert (>= x y))" + + raises(ValueError, lambda: smtlib_code(Q.complex(x), log_warn=w)) + + +def test_AppliedPredicate(): + with _check_warns([_W.DEFAULTING_TO_FLOAT] * 6) as w: + assert smtlib_code(Q.positive(x), auto_declare=False, log_warn=w) == "(assert (> x 0))" + assert smtlib_code(Q.negative(x), auto_declare=False, log_warn=w) == "(assert (< x 0))" + assert smtlib_code(Q.zero(x), auto_declare=False, log_warn=w) == "(assert (= x 0))" + assert smtlib_code(Q.nonpositive(x), auto_declare=False, log_warn=w) == "(assert (<= x 0))" + assert smtlib_code(Q.nonnegative(x), auto_declare=False, log_warn=w) == "(assert (>= x 0))" + assert smtlib_code(Q.nonzero(x), auto_declare=False, log_warn=w) == "(assert (not (= x 0)))" + +def test_Function(): + with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w: + assert smtlib_code(sin(x) ** cos(x), auto_declare=False, log_warn=w) == "(pow (sin x) (cos x))" + + with _check_warns([_W.WILL_NOT_ASSERT]) as w: + assert smtlib_code( + abs(x), + symbol_table={x: int, y: bool}, + known_types={int: "INTEGER_TYPE"}, + known_functions={sympy.Abs: "ABSOLUTE_VALUE_OF"}, + log_warn=w + ) == "(declare-const x INTEGER_TYPE)\n" \ + "(ABSOLUTE_VALUE_OF x)" + + my_fun1 = Function('f1') + with _check_warns([_W.WILL_NOT_ASSERT]) as w: + assert smtlib_code( + my_fun1(x), + symbol_table={my_fun1: Callable[[bool], float]}, + log_warn=w + ) == "(declare-const x Bool)\n" \ + "(declare-fun f1 (Bool) Real)\n" \ + "(f1 x)" + + with _check_warns([]) as w: + assert smtlib_code( + my_fun1(x), + symbol_table={my_fun1: Callable[[bool], bool]}, + log_warn=w + ) == "(declare-const x Bool)\n" \ + "(declare-fun f1 (Bool) Bool)\n" \ + "(assert (f1 x))" + + assert smtlib_code( + Eq(my_fun1(x, z), y), + symbol_table={my_fun1: Callable[[int, bool], bool]}, + log_warn=w + ) == "(declare-const x Int)\n" \ + "(declare-const y Bool)\n" \ + "(declare-const z Bool)\n" \ + "(declare-fun f1 (Int Bool) Bool)\n" \ + "(assert (= (f1 x z) y))" + + assert smtlib_code( + Eq(my_fun1(x, z), y), + symbol_table={my_fun1: Callable[[int, bool], bool]}, + known_functions={my_fun1: "MY_KNOWN_FUN", Eq: '=='}, + log_warn=w + ) == "(declare-const x Int)\n" \ + "(declare-const y Bool)\n" \ + "(declare-const z Bool)\n" \ + "(assert (== (MY_KNOWN_FUN x z) y))" + + with _check_warns([_W.DEFAULTING_TO_FLOAT] * 3) as w: + assert smtlib_code( + Eq(my_fun1(x, z), y), + known_functions={my_fun1: "MY_KNOWN_FUN", Eq: '=='}, + log_warn=w + ) == "(declare-const x Real)\n" \ + "(declare-const y Real)\n" \ + "(declare-const z Real)\n" \ + "(assert (== (MY_KNOWN_FUN x z) y))" + + +def test_Pow(): + with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w: + assert smtlib_code(x ** 3, auto_declare=False, log_warn=w) == "(pow x 3)" + with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w: + assert smtlib_code(x ** (y ** 3), auto_declare=False, log_warn=w) == "(pow x (pow y 3))" + with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w: + assert smtlib_code(x ** Rational(2, 3), auto_declare=False, log_warn=w) == '(pow x (/ 2 3))' + + a = Symbol('a', integer=True) + b = Symbol('b', real=True) + c = Symbol('c') + + def g(x): return 2 * x + + # if x=1, y=2, then expr=2.333... + expr = 1 / (g(a) * 3.5) ** (a - b ** a) / (a ** 2 + b) + + with _check_warns([]) as w: + assert smtlib_code( + [ + Eq(a < 2, c), + Eq(b > a, c), + c & True, + Eq(expr, 2 + Rational(1, 3)) + ], + log_warn=w + ) == '(declare-const a Int)\n' \ + '(declare-const b Real)\n' \ + '(declare-const c Bool)\n' \ + '(assert (= (< a 2) c))\n' \ + '(assert (= (> b a) c))\n' \ + '(assert c)\n' \ + '(assert (= ' \ + '(* (pow (* 7.0 a) (+ (pow b a) (* -1 a))) (pow (+ b (pow a 2)) -1)) ' \ + '(/ 7 3)' \ + '))' + + with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w: + assert smtlib_code( + Mul(-2, c, Pow(Mul(b, b, evaluate=False), -1, evaluate=False), evaluate=False), + log_warn=w + ) == '(declare-const b Real)\n' \ + '(declare-const c Real)\n' \ + '(* -2 c (pow (* b b) -1))' + + +def test_basic_ops(): + with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w: + assert smtlib_code(x * y, auto_declare=False, log_warn=w) == "(* x y)" + + with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w: + assert smtlib_code(x + y, auto_declare=False, log_warn=w) == "(+ x y)" + + # with _check_warns([_SmtlibWarnings.DEFAULTING_TO_FLOAT, _SmtlibWarnings.DEFAULTING_TO_FLOAT, _SmtlibWarnings.WILL_NOT_ASSERT]) as w: + # todo: implement re-write, currently does '(+ x (* -1 y))' instead + # assert smtlib_code(x - y, auto_declare=False, log_warn=w) == "(- x y)" + + with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w: + assert smtlib_code(-x, auto_declare=False, log_warn=w) == "(* -1 x)" + + +def test_quantifier_extensions(): + from sympy.logic.boolalg import Boolean + from sympy import Interval, Tuple, sympify + + # start For-all quantifier class example + class ForAll(Boolean): + def _smtlib(self, printer): + bound_symbol_declarations = [ + printer._s_expr(sym.name, [ + printer._known_types[printer.symbol_table[sym]], + Interval(start, end) + ]) for sym, start, end in self.limits + ] + return printer._s_expr('forall', [ + printer._s_expr('', bound_symbol_declarations), + self.function + ]) + + @property + def bound_symbols(self): + return {s for s, _, _ in self.limits} + + @property + def free_symbols(self): + bound_symbol_names = {s.name for s in self.bound_symbols} + return { + s for s in self.function.free_symbols + if s.name not in bound_symbol_names + } + + def __new__(cls, *args): + limits = [sympify(a) for a in args if isinstance(a, (tuple, Tuple))] + function = [sympify(a) for a in args if isinstance(a, Boolean)] + assert len(limits) + len(function) == len(args) + assert len(function) == 1 + function = function[0] + + if isinstance(function, ForAll): return ForAll.__new__( + ForAll, *(limits + function.limits), function.function + ) + inst = Boolean.__new__(cls) + inst._args = tuple(limits + [function]) + inst.limits = limits + inst.function = function + return inst + + # end For-All Quantifier class example + + f = Function('f') + with _check_warns([_W.DEFAULTING_TO_FLOAT]) as w: + assert smtlib_code( + ForAll((x, -42, +21), Eq(f(x), f(x))), + symbol_table={f: Callable[[float], float]}, + log_warn=w + ) == '(assert (forall ( (x Real [-42, 21])) true))' + + with _check_warns([_W.DEFAULTING_TO_FLOAT] * 2) as w: + assert smtlib_code( + ForAll( + (x, -42, +21), (y, -100, 3), + Implies(Eq(x, y), Eq(f(x), f(y))) + ), + symbol_table={f: Callable[[float], float]}, + log_warn=w + ) == '(declare-fun f (Real) Real)\n' \ + '(assert (' \ + 'forall ( (x Real [-42, 21]) (y Real [-100, 3])) ' \ + '(=> (= x y) (= (f x) (f y)))' \ + '))' + + a = Symbol('a', integer=True) + b = Symbol('b', real=True) + c = Symbol('c') + + with _check_warns([]) as w: + assert smtlib_code( + ForAll( + (a, 2, 100), ForAll( + (b, 2, 100), + Implies(a < b, sqrt(a) < b) | c + )), + log_warn=w + ) == '(declare-const c Bool)\n' \ + '(assert (forall ( (a Int [2, 100]) (b Real [2, 100])) ' \ + '(or c (=> (< a b) (< (pow a (/ 1 2)) b)))' \ + '))' + + +def test_mix_number_mult_symbols(): + with _check_warns([_W.WILL_NOT_ASSERT]) as w: + assert smtlib_code( + 1 / pi, + known_constants={pi: "MY_PI"}, + log_warn=w + ) == '(pow MY_PI -1)' + + with _check_warns([_W.WILL_NOT_ASSERT]) as w: + assert smtlib_code( + [ + Eq(pi, 3.14, evaluate=False), + 1 / pi, + ], + known_constants={pi: "MY_PI"}, + log_warn=w + ) == '(assert (= MY_PI 3.14))\n' \ + '(pow MY_PI -1)' + + with _check_warns([_W.WILL_NOT_ASSERT]) as w: + assert smtlib_code( + Add(S.Zero, S.One, S.NegativeOne, S.Half, + S.Exp1, S.Pi, S.GoldenRatio, evaluate=False), + known_constants={ + S.Pi: 'p', S.GoldenRatio: 'g', + S.Exp1: 'e' + }, + known_functions={ + Add: 'plus', + exp: 'exp' + }, + precision=3, + log_warn=w + ) == '(plus 0 1 -1 (/ 1 2) (exp 1) p g)' + + with _check_warns([_W.WILL_NOT_ASSERT]) as w: + assert smtlib_code( + Add(S.Zero, S.One, S.NegativeOne, S.Half, + S.Exp1, S.Pi, S.GoldenRatio, evaluate=False), + known_constants={ + S.Pi: 'p' + }, + known_functions={ + Add: 'plus', + exp: 'exp' + }, + precision=3, + log_warn=w + ) == '(plus 0 1 -1 (/ 1 2) (exp 1) p 1.62)' + + with _check_warns([_W.WILL_NOT_ASSERT]) as w: + assert smtlib_code( + Add(S.Zero, S.One, S.NegativeOne, S.Half, + S.Exp1, S.Pi, S.GoldenRatio, evaluate=False), + known_functions={Add: 'plus'}, + precision=3, + log_warn=w + ) == '(plus 0 1 -1 (/ 1 2) 2.72 3.14 1.62)' + + with _check_warns([_W.WILL_NOT_ASSERT]) as w: + assert smtlib_code( + Add(S.Zero, S.One, S.NegativeOne, S.Half, + S.Exp1, S.Pi, S.GoldenRatio, evaluate=False), + known_constants={S.Exp1: 'e'}, + known_functions={Add: 'plus'}, + precision=3, + log_warn=w + ) == '(plus 0 1 -1 (/ 1 2) e 3.14 1.62)' + + +def test_boolean(): + with _check_warns([]) as w: + assert smtlib_code(x & y, log_warn=w) == '(declare-const x Bool)\n' \ + '(declare-const y Bool)\n' \ + '(assert (and x y))' + assert smtlib_code(x | y, log_warn=w) == '(declare-const x Bool)\n' \ + '(declare-const y Bool)\n' \ + '(assert (or x y))' + assert smtlib_code(~x, log_warn=w) == '(declare-const x Bool)\n' \ + '(assert (not x))' + assert smtlib_code(x & y & z, log_warn=w) == '(declare-const x Bool)\n' \ + '(declare-const y Bool)\n' \ + '(declare-const z Bool)\n' \ + '(assert (and x y z))' + + with _check_warns([_W.DEFAULTING_TO_FLOAT]) as w: + assert smtlib_code((x & ~y) | (z > 3), log_warn=w) == '(declare-const x Bool)\n' \ + '(declare-const y Bool)\n' \ + '(declare-const z Real)\n' \ + '(assert (or (> z 3) (and x (not y))))' + + f = Function('f') + g = Function('g') + h = Function('h') + with _check_warns([_W.DEFAULTING_TO_FLOAT]) as w: + assert smtlib_code( + [Gt(f(x), y), + Lt(y, g(z))], + symbol_table={ + f: Callable[[bool], int], g: Callable[[bool], int], + }, log_warn=w + ) == '(declare-const x Bool)\n' \ + '(declare-const y Real)\n' \ + '(declare-const z Bool)\n' \ + '(declare-fun f (Bool) Int)\n' \ + '(declare-fun g (Bool) Int)\n' \ + '(assert (> (f x) y))\n' \ + '(assert (< y (g z)))' + + with _check_warns([]) as w: + assert smtlib_code( + [Eq(f(x), y), + Lt(y, g(z))], + symbol_table={ + f: Callable[[bool], int], g: Callable[[bool], int], + }, log_warn=w + ) == '(declare-const x Bool)\n' \ + '(declare-const y Int)\n' \ + '(declare-const z Bool)\n' \ + '(declare-fun f (Bool) Int)\n' \ + '(declare-fun g (Bool) Int)\n' \ + '(assert (= (f x) y))\n' \ + '(assert (< y (g z)))' + + with _check_warns([]) as w: + assert smtlib_code( + [Eq(f(x), y), + Eq(g(f(x)), z), + Eq(h(g(f(x))), x)], + symbol_table={ + f: Callable[[float], int], + g: Callable[[int], bool], + h: Callable[[bool], float] + }, + log_warn=w + ) == '(declare-const x Real)\n' \ + '(declare-const y Int)\n' \ + '(declare-const z Bool)\n' \ + '(declare-fun f (Real) Int)\n' \ + '(declare-fun g (Int) Bool)\n' \ + '(declare-fun h (Bool) Real)\n' \ + '(assert (= (f x) y))\n' \ + '(assert (= (g (f x)) z))\n' \ + '(assert (= (h (g (f x))) x))' + + +# todo: make smtlib_code support arrays +# def test_containers(): +# assert julia_code([1, 2, 3, [4, 5, [6, 7]], 8, [9, 10], 11]) == \ +# "Any[1, 2, 3, Any[4, 5, Any[6, 7]], 8, Any[9, 10], 11]" +# assert julia_code((1, 2, (3, 4))) == "(1, 2, (3, 4))" +# assert julia_code([1]) == "Any[1]" +# assert julia_code((1,)) == "(1,)" +# assert julia_code(Tuple(*[1, 2, 3])) == "(1, 2, 3)" +# assert julia_code((1, x * y, (3, x ** 2))) == "(1, x .* y, (3, x .^ 2))" +# # scalar, matrix, empty matrix and empty list +# assert julia_code((1, eye(3), Matrix(0, 0, []), [])) == "(1, [1 0 0;\n0 1 0;\n0 0 1], zeros(0, 0), Any[])" + +def test_smtlib_piecewise(): + with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w: + assert smtlib_code( + Piecewise((x, x < 1), + (x ** 2, True)), + auto_declare=False, + log_warn=w + ) == '(ite (< x 1) x (pow x 2))' + + with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w: + assert smtlib_code( + Piecewise((x ** 2, x < 1), + (x ** 3, x < 2), + (x ** 4, x < 3), + (x ** 5, True)), + auto_declare=False, + log_warn=w + ) == '(ite (< x 1) (pow x 2) ' \ + '(ite (< x 2) (pow x 3) ' \ + '(ite (< x 3) (pow x 4) ' \ + '(pow x 5))))' + + # Check that Piecewise without a True (default) condition error + expr = Piecewise((x, x < 1), (x ** 2, x > 1), (sin(x), x > 0)) + with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w: + raises(AssertionError, lambda: smtlib_code(expr, log_warn=w)) + + +def test_smtlib_piecewise_times_const(): + pw = Piecewise((x, x < 1), (x ** 2, True)) + with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w: + assert smtlib_code(2 * pw, log_warn=w) == '(declare-const x Real)\n(* 2 (ite (< x 1) x (pow x 2)))' + with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w: + assert smtlib_code(pw / x, log_warn=w) == '(declare-const x Real)\n(* (pow x -1) (ite (< x 1) x (pow x 2)))' + with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w: + assert smtlib_code(pw / (x * y), log_warn=w) == '(declare-const x Real)\n(declare-const y Real)\n(* (pow x -1) (pow y -1) (ite (< x 1) x (pow x 2)))' + with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w: + assert smtlib_code(pw / 3, log_warn=w) == '(declare-const x Real)\n(* (/ 1 3) (ite (< x 1) x (pow x 2)))' + + +# todo: make smtlib_code support arrays / matrices ? +# def test_smtlib_matrix_assign_to(): +# A = Matrix([[1, 2, 3]]) +# assert smtlib_code(A, assign_to='a') == "a = [1 2 3]" +# A = Matrix([[1, 2], [3, 4]]) +# assert smtlib_code(A, assign_to='A') == "A = [1 2;\n3 4]" + +# def test_julia_matrix_1x1(): +# A = Matrix([[3]]) +# B = MatrixSymbol('B', 1, 1) +# C = MatrixSymbol('C', 1, 2) +# assert julia_code(A, assign_to=B) == "B = [3]" +# raises(ValueError, lambda: julia_code(A, assign_to=C)) + +# def test_julia_matrix_elements(): +# A = Matrix([[x, 2, x * y]]) +# assert julia_code(A[0, 0] ** 2 + A[0, 1] + A[0, 2]) == "x .^ 2 + x .* y + 2" +# A = MatrixSymbol('AA', 1, 3) +# assert julia_code(A) == "AA" +# assert julia_code(A[0, 0] ** 2 + sin(A[0, 1]) + A[0, 2]) == \ +# "sin(AA[1,2]) + AA[1,1] .^ 2 + AA[1,3]" +# assert julia_code(sum(A)) == "AA[1,1] + AA[1,2] + AA[1,3]" + +def test_smtlib_boolean(): + with _check_warns([]) as w: + assert smtlib_code(True, auto_assert=False, log_warn=w) == 'true' + assert smtlib_code(True, log_warn=w) == '(assert true)' + assert smtlib_code(S.true, log_warn=w) == '(assert true)' + assert smtlib_code(S.false, log_warn=w) == '(assert false)' + assert smtlib_code(False, log_warn=w) == '(assert false)' + assert smtlib_code(False, auto_assert=False, log_warn=w) == 'false' + + +def test_not_supported(): + f = Function('f') + with _check_warns([_W.DEFAULTING_TO_FLOAT, _W.WILL_NOT_ASSERT]) as w: + raises(KeyError, lambda: smtlib_code(f(x).diff(x), symbol_table={f: Callable[[float], float]}, log_warn=w)) + with _check_warns([_W.WILL_NOT_ASSERT]) as w: + raises(KeyError, lambda: smtlib_code(S.ComplexInfinity, log_warn=w)) + + +def test_Float(): + assert smtlib_code(0.0) == "0.0" + assert smtlib_code(0.000000000000000003) == '(* 3.0 (pow 10 -18))' + assert smtlib_code(5.3) == "5.3" diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_str.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_str.py new file mode 100644 index 0000000000000000000000000000000000000000..675212964b03bf9a9806088225c28d7f70971ca7 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_str.py @@ -0,0 +1,1206 @@ +from sympy import MatAdd +from sympy.algebras.quaternion import Quaternion +from sympy.assumptions.ask import Q +from sympy.calculus.accumulationbounds import AccumBounds +from sympy.combinatorics.partitions import Partition +from sympy.concrete.summations import (Sum, summation) +from sympy.core.add import Add +from sympy.core.containers import (Dict, Tuple) +from sympy.core.expr import UnevaluatedExpr, Expr +from sympy.core.function import (Derivative, Function, Lambda, Subs, WildFunction) +from sympy.core.mul import Mul +from sympy.core import (Catalan, EulerGamma, GoldenRatio, TribonacciConstant) +from sympy.core.numbers import (E, Float, I, Integer, Rational, nan, oo, pi, zoo) +from sympy.core.parameters import _exp_is_pow +from sympy.core.power import Pow +from sympy.core.relational import (Eq, Rel, Ne) +from sympy.core.singleton import S +from sympy.core.symbol import (Dummy, Symbol, Wild, symbols) +from sympy.functions.combinatorial.factorials import (factorial, factorial2, subfactorial) +from sympy.functions.elementary.complexes import Abs +from sympy.functions.elementary.exponential import exp +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.functions.special.delta_functions import Heaviside +from sympy.functions.special.zeta_functions import zeta +from sympy.integrals.integrals import Integral +from sympy.logic.boolalg import (Equivalent, false, true, Xor) +from sympy.matrices.dense import Matrix +from sympy.matrices.expressions.matexpr import MatrixSymbol +from sympy.matrices.expressions import Identity +from sympy.matrices.expressions.slice import MatrixSlice +from sympy.matrices import SparseMatrix +from sympy.polys.polytools import factor +from sympy.series.limits import Limit +from sympy.series.order import O +from sympy.sets.sets import (Complement, FiniteSet, Interval, SymmetricDifference) +from sympy.stats import (Covariance, Expectation, Probability, Variance) +from sympy.stats.rv import RandomSymbol +from sympy.external import import_module +from sympy.physics.control.lti import TransferFunction, Series, Parallel, \ + Feedback, TransferFunctionMatrix, MIMOSeries, MIMOParallel, MIMOFeedback +from sympy.physics.units import second, joule +from sympy.polys import (Poly, rootof, RootSum, groebner, ring, field, ZZ, QQ, + ZZ_I, QQ_I, lex, grlex) +from sympy.geometry import Point, Circle, Polygon, Ellipse, Triangle +from sympy.tensor import NDimArray +from sympy.tensor.array.expressions.array_expressions import ArraySymbol, ArrayElement + +from sympy.testing.pytest import raises, warns_deprecated_sympy + +from sympy.printing import sstr, sstrrepr, StrPrinter +from sympy.physics.quantum.trace import Tr + +x, y, z, w, t = symbols('x,y,z,w,t') +d = Dummy('d') + + +def test_printmethod(): + class R(Abs): + def _sympystr(self, printer): + return "foo(%s)" % printer._print(self.args[0]) + assert sstr(R(x)) == "foo(x)" + + class R(Abs): + def _sympystr(self, printer): + return "foo" + assert sstr(R(x)) == "foo" + + +def test_Abs(): + assert str(Abs(x)) == "Abs(x)" + assert str(Abs(Rational(1, 6))) == "1/6" + assert str(Abs(Rational(-1, 6))) == "1/6" + + +def test_Add(): + assert str(x + y) == "x + y" + assert str(x + 1) == "x + 1" + assert str(x + x**2) == "x**2 + x" + assert str(Add(0, 1, evaluate=False)) == "0 + 1" + assert str(Add(0, 0, 1, evaluate=False)) == "0 + 0 + 1" + assert str(1.0*x) == "1.0*x" + assert str(5 + x + y + x*y + x**2 + y**2) == "x**2 + x*y + x + y**2 + y + 5" + assert str(1 + x + x**2/2 + x**3/3) == "x**3/3 + x**2/2 + x + 1" + assert str(2*x - 7*x**2 + 2 + 3*y) == "-7*x**2 + 2*x + 3*y + 2" + assert str(x - y) == "x - y" + assert str(2 - x) == "2 - x" + assert str(x - 2) == "x - 2" + assert str(x - y - z - w) == "-w + x - y - z" + assert str(x - z*y**2*z*w) == "-w*y**2*z**2 + x" + assert str(x - 1*y*x*y) == "-x*y**2 + x" + assert str(sin(x).series(x, 0, 15)) == "x - x**3/6 + x**5/120 - x**7/5040 + x**9/362880 - x**11/39916800 + x**13/6227020800 + O(x**15)" + assert str(Add(Add(-w, x, evaluate=False), Add(-y, z, evaluate=False), evaluate=False)) == "(-w + x) + (-y + z)" + assert str(Add(Add(-x, -y, evaluate=False), -z, evaluate=False)) == "-z + (-x - y)" + assert str(Add(Add(Add(-x, -y, evaluate=False), -z, evaluate=False), -t, evaluate=False)) == "-t + (-z + (-x - y))" + + +def test_Catalan(): + assert str(Catalan) == "Catalan" + + +def test_ComplexInfinity(): + assert str(zoo) == "zoo" + + +def test_Derivative(): + assert str(Derivative(x, y)) == "Derivative(x, y)" + assert str(Derivative(x**2, x, evaluate=False)) == "Derivative(x**2, x)" + assert str(Derivative( + x**2/y, x, y, evaluate=False)) == "Derivative(x**2/y, x, y)" + + +def test_dict(): + assert str({1: 1 + x}) == sstr({1: 1 + x}) == "{1: x + 1}" + assert str({1: x**2, 2: y*x}) in ("{1: x**2, 2: x*y}", "{2: x*y, 1: x**2}") + assert sstr({1: x**2, 2: y*x}) == "{1: x**2, 2: x*y}" + + +def test_Dict(): + assert str(Dict({1: 1 + x})) == sstr({1: 1 + x}) == "{1: x + 1}" + assert str(Dict({1: x**2, 2: y*x})) in ( + "{1: x**2, 2: x*y}", "{2: x*y, 1: x**2}") + assert sstr(Dict({1: x**2, 2: y*x})) == "{1: x**2, 2: x*y}" + + +def test_Dummy(): + assert str(d) == "_d" + assert str(d + x) == "_d + x" + + +def test_EulerGamma(): + assert str(EulerGamma) == "EulerGamma" + + +def test_Exp(): + assert str(E) == "E" + with _exp_is_pow(True): + assert str(exp(x)) == "E**x" + + +def test_factorial(): + n = Symbol('n', integer=True) + assert str(factorial(-2)) == "zoo" + assert str(factorial(0)) == "1" + assert str(factorial(7)) == "5040" + assert str(factorial(n)) == "factorial(n)" + assert str(factorial(2*n)) == "factorial(2*n)" + assert str(factorial(factorial(n))) == 'factorial(factorial(n))' + assert str(factorial(factorial2(n))) == 'factorial(factorial2(n))' + assert str(factorial2(factorial(n))) == 'factorial2(factorial(n))' + assert str(factorial2(factorial2(n))) == 'factorial2(factorial2(n))' + assert str(subfactorial(3)) == "2" + assert str(subfactorial(n)) == "subfactorial(n)" + assert str(subfactorial(2*n)) == "subfactorial(2*n)" + + +def test_Function(): + f = Function('f') + fx = f(x) + w = WildFunction('w') + assert str(f) == "f" + assert str(fx) == "f(x)" + assert str(w) == "w_" + + +def test_Geometry(): + assert sstr(Point(0, 0)) == 'Point2D(0, 0)' + assert sstr(Circle(Point(0, 0), 3)) == 'Circle(Point2D(0, 0), 3)' + assert sstr(Ellipse(Point(1, 2), 3, 4)) == 'Ellipse(Point2D(1, 2), 3, 4)' + assert sstr(Triangle(Point(1, 1), Point(7, 8), Point(0, -1))) == \ + 'Triangle(Point2D(1, 1), Point2D(7, 8), Point2D(0, -1))' + assert sstr(Polygon(Point(5, 6), Point(-2, -3), Point(0, 0), Point(4, 7))) == \ + 'Polygon(Point2D(5, 6), Point2D(-2, -3), Point2D(0, 0), Point2D(4, 7))' + assert sstr(Triangle(Point(0, 0), Point(1, 0), Point(0, 1)), sympy_integers=True) == \ + 'Triangle(Point2D(S(0), S(0)), Point2D(S(1), S(0)), Point2D(S(0), S(1)))' + assert sstr(Ellipse(Point(1, 2), 3, 4), sympy_integers=True) == \ + 'Ellipse(Point2D(S(1), S(2)), S(3), S(4))' + + +def test_GoldenRatio(): + assert str(GoldenRatio) == "GoldenRatio" + + +def test_Heaviside(): + assert str(Heaviside(x)) == str(Heaviside(x, S.Half)) == "Heaviside(x)" + assert str(Heaviside(x, 1)) == "Heaviside(x, 1)" + + +def test_TribonacciConstant(): + assert str(TribonacciConstant) == "TribonacciConstant" + + +def test_ImaginaryUnit(): + assert str(I) == "I" + + +def test_Infinity(): + assert str(oo) == "oo" + assert str(oo*I) == "oo*I" + + +def test_Integer(): + assert str(Integer(-1)) == "-1" + assert str(Integer(1)) == "1" + assert str(Integer(-3)) == "-3" + assert str(Integer(0)) == "0" + assert str(Integer(25)) == "25" + + +def test_Integral(): + assert str(Integral(sin(x), y)) == "Integral(sin(x), y)" + assert str(Integral(sin(x), (y, 0, 1))) == "Integral(sin(x), (y, 0, 1))" + + +def test_Interval(): + n = (S.NegativeInfinity, 1, 2, S.Infinity) + for i in range(len(n)): + for j in range(i + 1, len(n)): + for l in (True, False): + for r in (True, False): + ival = Interval(n[i], n[j], l, r) + assert S(str(ival)) == ival + + +def test_AccumBounds(): + a = Symbol('a', real=True) + assert str(AccumBounds(0, a)) == "AccumBounds(0, a)" + assert str(AccumBounds(0, 1)) == "AccumBounds(0, 1)" + + +def test_Lambda(): + assert str(Lambda(d, d**2)) == "Lambda(_d, _d**2)" + # issue 2908 + assert str(Lambda((), 1)) == "Lambda((), 1)" + assert str(Lambda((), x)) == "Lambda((), x)" + assert str(Lambda((x, y), x+y)) == "Lambda((x, y), x + y)" + assert str(Lambda(((x, y),), x+y)) == "Lambda(((x, y),), x + y)" + + +def test_Limit(): + assert str(Limit(sin(x)/x, x, y)) == "Limit(sin(x)/x, x, y, dir='+')" + assert str(Limit(1/x, x, 0)) == "Limit(1/x, x, 0, dir='+')" + assert str( + Limit(sin(x)/x, x, y, dir="-")) == "Limit(sin(x)/x, x, y, dir='-')" + + +def test_list(): + assert str([x]) == sstr([x]) == "[x]" + assert str([x**2, x*y + 1]) == sstr([x**2, x*y + 1]) == "[x**2, x*y + 1]" + assert str([x**2, [y + x]]) == sstr([x**2, [y + x]]) == "[x**2, [x + y]]" + + +def test_Matrix_str(): + M = Matrix([[x**+1, 1], [y, x + y]]) + assert str(M) == "Matrix([[x, 1], [y, x + y]])" + assert sstr(M) == "Matrix([\n[x, 1],\n[y, x + y]])" + M = Matrix([[1]]) + assert str(M) == sstr(M) == "Matrix([[1]])" + M = Matrix([[1, 2]]) + assert str(M) == sstr(M) == "Matrix([[1, 2]])" + M = Matrix() + assert str(M) == sstr(M) == "Matrix(0, 0, [])" + M = Matrix(0, 1, lambda i, j: 0) + assert str(M) == sstr(M) == "Matrix(0, 1, [])" + + +def test_Mul(): + assert str(x/y) == "x/y" + assert str(y/x) == "y/x" + assert str(x/y/z) == "x/(y*z)" + assert str((x + 1)/(y + 2)) == "(x + 1)/(y + 2)" + assert str(2*x/3) == '2*x/3' + assert str(-2*x/3) == '-2*x/3' + assert str(-1.0*x) == '-1.0*x' + assert str(1.0*x) == '1.0*x' + assert str(Mul(0, 1, evaluate=False)) == '0*1' + assert str(Mul(1, 0, evaluate=False)) == '1*0' + assert str(Mul(1, 1, evaluate=False)) == '1*1' + assert str(Mul(1, 1, 1, evaluate=False)) == '1*1*1' + assert str(Mul(1, 2, evaluate=False)) == '1*2' + assert str(Mul(1, S.Half, evaluate=False)) == '1*(1/2)' + assert str(Mul(1, 1, S.Half, evaluate=False)) == '1*1*(1/2)' + assert str(Mul(1, 1, 2, 3, x, evaluate=False)) == '1*1*2*3*x' + assert str(Mul(1, -1, evaluate=False)) == '1*(-1)' + assert str(Mul(-1, 1, evaluate=False)) == '-1*1' + assert str(Mul(4, 3, 2, 1, 0, y, x, evaluate=False)) == '4*3*2*1*0*y*x' + assert str(Mul(4, 3, 2, 1+z, 0, y, x, evaluate=False)) == '4*3*2*(z + 1)*0*y*x' + assert str(Mul(Rational(2, 3), Rational(5, 7), evaluate=False)) == '(2/3)*(5/7)' + # For issue 14160 + assert str(Mul(-2, x, Pow(Mul(y,y,evaluate=False), -1, evaluate=False), + evaluate=False)) == '-2*x/(y*y)' + # issue 21537 + assert str(Mul(x, Pow(1/y, -1, evaluate=False), evaluate=False)) == 'x/(1/y)' + + # Issue 24108 + from sympy.core.parameters import evaluate + with evaluate(False): + assert str(Mul(Pow(Integer(2), Integer(-1)), Add(Integer(-1), Mul(Integer(-1), Integer(1))))) == "(-1 - 1*1)/2" + + class CustomClass1(Expr): + is_commutative = True + + class CustomClass2(Expr): + is_commutative = True + cc1 = CustomClass1() + cc2 = CustomClass2() + assert str(Rational(2)*cc1) == '2*CustomClass1()' + assert str(cc1*Rational(2)) == '2*CustomClass1()' + assert str(cc1*Float("1.5")) == '1.5*CustomClass1()' + assert str(cc2*Rational(2)) == '2*CustomClass2()' + assert str(cc2*Rational(2)*cc1) == '2*CustomClass1()*CustomClass2()' + assert str(cc1*Rational(2)*cc2) == '2*CustomClass1()*CustomClass2()' + + +def test_NaN(): + assert str(nan) == "nan" + + +def test_NegativeInfinity(): + assert str(-oo) == "-oo" + +def test_Order(): + assert str(O(x)) == "O(x)" + assert str(O(x**2)) == "O(x**2)" + assert str(O(x*y)) == "O(x*y, x, y)" + assert str(O(x, x)) == "O(x)" + assert str(O(x, (x, 0))) == "O(x)" + assert str(O(x, (x, oo))) == "O(x, (x, oo))" + assert str(O(x, x, y)) == "O(x, x, y)" + assert str(O(x, x, y)) == "O(x, x, y)" + assert str(O(x, (x, oo), (y, oo))) == "O(x, (x, oo), (y, oo))" + + +def test_Permutation_Cycle(): + from sympy.combinatorics import Permutation, Cycle + + # general principle: economically, canonically show all moved elements + # and the size of the permutation. + + for p, s in [ + (Cycle(), + '()'), + (Cycle(2), + '(2)'), + (Cycle(2, 1), + '(1 2)'), + (Cycle(1, 2)(5)(6, 7)(10), + '(1 2)(6 7)(10)'), + (Cycle(3, 4)(1, 2)(3, 4), + '(1 2)(4)'), + ]: + assert sstr(p) == s + + for p, s in [ + (Permutation([]), + 'Permutation([])'), + (Permutation([], size=1), + 'Permutation([0])'), + (Permutation([], size=2), + 'Permutation([0, 1])'), + (Permutation([], size=10), + 'Permutation([], size=10)'), + (Permutation([1, 0, 2]), + 'Permutation([1, 0, 2])'), + (Permutation([1, 0, 2, 3, 4, 5]), + 'Permutation([1, 0], size=6)'), + (Permutation([1, 0, 2, 3, 4, 5], size=10), + 'Permutation([1, 0], size=10)'), + ]: + assert sstr(p, perm_cyclic=False) == s + + for p, s in [ + (Permutation([]), + '()'), + (Permutation([], size=1), + '(0)'), + (Permutation([], size=2), + '(1)'), + (Permutation([], size=10), + '(9)'), + (Permutation([1, 0, 2]), + '(2)(0 1)'), + (Permutation([1, 0, 2, 3, 4, 5]), + '(5)(0 1)'), + (Permutation([1, 0, 2, 3, 4, 5], size=10), + '(9)(0 1)'), + (Permutation([0, 1, 3, 2, 4, 5], size=10), + '(9)(2 3)'), + ]: + assert sstr(p) == s + + + with warns_deprecated_sympy(): + old_print_cyclic = Permutation.print_cyclic + Permutation.print_cyclic = False + assert sstr(Permutation([1, 0, 2])) == 'Permutation([1, 0, 2])' + Permutation.print_cyclic = old_print_cyclic + +def test_Pi(): + assert str(pi) == "pi" + + +def test_Poly(): + assert str(Poly(0, x)) == "Poly(0, x, domain='ZZ')" + assert str(Poly(1, x)) == "Poly(1, x, domain='ZZ')" + assert str(Poly(x, x)) == "Poly(x, x, domain='ZZ')" + + assert str(Poly(2*x + 1, x)) == "Poly(2*x + 1, x, domain='ZZ')" + assert str(Poly(2*x - 1, x)) == "Poly(2*x - 1, x, domain='ZZ')" + + assert str(Poly(-1, x)) == "Poly(-1, x, domain='ZZ')" + assert str(Poly(-x, x)) == "Poly(-x, x, domain='ZZ')" + + assert str(Poly(-2*x + 1, x)) == "Poly(-2*x + 1, x, domain='ZZ')" + assert str(Poly(-2*x - 1, x)) == "Poly(-2*x - 1, x, domain='ZZ')" + + assert str(Poly(x - 1, x)) == "Poly(x - 1, x, domain='ZZ')" + assert str(Poly(2*x + x**5, x)) == "Poly(x**5 + 2*x, x, domain='ZZ')" + + assert str(Poly(3**(2*x), 3**x)) == "Poly((3**x)**2, 3**x, domain='ZZ')" + assert str(Poly((x**2)**x)) == "Poly(((x**2)**x), (x**2)**x, domain='ZZ')" + + assert str(Poly((x + y)**3, (x + y), expand=False) + ) == "Poly((x + y)**3, x + y, domain='ZZ')" + assert str(Poly((x - 1)**2, (x - 1), expand=False) + ) == "Poly((x - 1)**2, x - 1, domain='ZZ')" + + assert str( + Poly(x**2 + 1 + y, x)) == "Poly(x**2 + y + 1, x, domain='ZZ[y]')" + assert str( + Poly(x**2 - 1 + y, x)) == "Poly(x**2 + y - 1, x, domain='ZZ[y]')" + + assert str(Poly(x**2 + I*x, x)) == "Poly(x**2 + I*x, x, domain='ZZ_I')" + assert str(Poly(x**2 - I*x, x)) == "Poly(x**2 - I*x, x, domain='ZZ_I')" + + assert str(Poly(-x*y*z + x*y - 1, x, y, z) + ) == "Poly(-x*y*z + x*y - 1, x, y, z, domain='ZZ')" + assert str(Poly(-w*x**21*y**7*z + (1 + w)*z**3 - 2*x*z + 1, x, y, z)) == \ + "Poly(-w*x**21*y**7*z - 2*x*z + (w + 1)*z**3 + 1, x, y, z, domain='ZZ[w]')" + + assert str(Poly(x**2 + 1, x, modulus=2)) == "Poly(x**2 + 1, x, modulus=2)" + assert str(Poly(2*x**2 + 3*x + 4, x, modulus=17)) == "Poly(2*x**2 + 3*x + 4, x, modulus=17)" + + +def test_PolyRing(): + assert str(ring("x", ZZ, lex)[0]) == "Polynomial ring in x over ZZ with lex order" + assert str(ring("x,y", QQ, grlex)[0]) == "Polynomial ring in x, y over QQ with grlex order" + assert str(ring("x,y,z", ZZ["t"], lex)[0]) == "Polynomial ring in x, y, z over ZZ[t] with lex order" + + +def test_FracField(): + assert str(field("x", ZZ, lex)[0]) == "Rational function field in x over ZZ with lex order" + assert str(field("x,y", QQ, grlex)[0]) == "Rational function field in x, y over QQ with grlex order" + assert str(field("x,y,z", ZZ["t"], lex)[0]) == "Rational function field in x, y, z over ZZ[t] with lex order" + + +def test_PolyElement(): + Ruv, u,v = ring("u,v", ZZ) + Rxyz, x,y,z = ring("x,y,z", Ruv) + Rx_zzi, xz = ring("x", ZZ_I) + + assert str(x - x) == "0" + assert str(x - 1) == "x - 1" + assert str(x + 1) == "x + 1" + assert str(x**2) == "x**2" + + assert str((u**2 + 3*u*v + 1)*x**2*y + u + 1) == "(u**2 + 3*u*v + 1)*x**2*y + u + 1" + assert str((u**2 + 3*u*v + 1)*x**2*y + (u + 1)*x) == "(u**2 + 3*u*v + 1)*x**2*y + (u + 1)*x" + assert str((u**2 + 3*u*v + 1)*x**2*y + (u + 1)*x + 1) == "(u**2 + 3*u*v + 1)*x**2*y + (u + 1)*x + 1" + assert str((-u**2 + 3*u*v - 1)*x**2*y - (u + 1)*x - 1) == "-(u**2 - 3*u*v + 1)*x**2*y - (u + 1)*x - 1" + + assert str(-(v**2 + v + 1)*x + 3*u*v + 1) == "-(v**2 + v + 1)*x + 3*u*v + 1" + assert str(-(v**2 + v + 1)*x - 3*u*v + 1) == "-(v**2 + v + 1)*x - 3*u*v + 1" + + assert str((1+I)*xz + 2) == "(1 + 1*I)*x + (2 + 0*I)" + + +def test_FracElement(): + Fuv, u,v = field("u,v", ZZ) + Fxyzt, x,y,z,t = field("x,y,z,t", Fuv) + Rx_zzi, xz = field("x", QQ_I) + i = QQ_I(0, 1) + + assert str(x - x) == "0" + assert str(x - 1) == "x - 1" + assert str(x + 1) == "x + 1" + + assert str(x/3) == "x/3" + assert str(x/z) == "x/z" + assert str(x*y/z) == "x*y/z" + assert str(x/(z*t)) == "x/(z*t)" + assert str(x*y/(z*t)) == "x*y/(z*t)" + + assert str((x - 1)/y) == "(x - 1)/y" + assert str((x + 1)/y) == "(x + 1)/y" + assert str((-x - 1)/y) == "(-x - 1)/y" + assert str((x + 1)/(y*z)) == "(x + 1)/(y*z)" + assert str(-y/(x + 1)) == "-y/(x + 1)" + assert str(y*z/(x + 1)) == "y*z/(x + 1)" + + assert str(((u + 1)*x*y + 1)/((v - 1)*z - 1)) == "((u + 1)*x*y + 1)/((v - 1)*z - 1)" + assert str(((u + 1)*x*y + 1)/((v - 1)*z - t*u*v - 1)) == "((u + 1)*x*y + 1)/((v - 1)*z - u*v*t - 1)" + + assert str((1+i)/xz) == "(1 + 1*I)/x" + assert str(((1+i)*xz - i)/xz) == "((1 + 1*I)*x + (0 + -1*I))/x" + + +def test_GaussianInteger(): + assert str(ZZ_I(1, 0)) == "1" + assert str(ZZ_I(-1, 0)) == "-1" + assert str(ZZ_I(0, 1)) == "I" + assert str(ZZ_I(0, -1)) == "-I" + assert str(ZZ_I(0, 2)) == "2*I" + assert str(ZZ_I(0, -2)) == "-2*I" + assert str(ZZ_I(1, 1)) == "1 + I" + assert str(ZZ_I(-1, -1)) == "-1 - I" + assert str(ZZ_I(-1, -2)) == "-1 - 2*I" + + +def test_GaussianRational(): + assert str(QQ_I(1, 0)) == "1" + assert str(QQ_I(QQ(2, 3), 0)) == "2/3" + assert str(QQ_I(0, QQ(2, 3))) == "2*I/3" + assert str(QQ_I(QQ(1, 2), QQ(-2, 3))) == "1/2 - 2*I/3" + + +def test_Pow(): + assert str(x**-1) == "1/x" + assert str(x**-2) == "x**(-2)" + assert str(x**2) == "x**2" + assert str((x + y)**-1) == "1/(x + y)" + assert str((x + y)**-2) == "(x + y)**(-2)" + assert str((x + y)**2) == "(x + y)**2" + assert str((x + y)**(1 + x)) == "(x + y)**(x + 1)" + assert str(x**Rational(1, 3)) == "x**(1/3)" + assert str(1/x**Rational(1, 3)) == "x**(-1/3)" + assert str(sqrt(sqrt(x))) == "x**(1/4)" + # not the same as x**-1 + assert str(x**-1.0) == 'x**(-1.0)' + # see issue #2860 + assert str(Pow(S(2), -1.0, evaluate=False)) == '2**(-1.0)' + + +def test_sqrt(): + assert str(sqrt(x)) == "sqrt(x)" + assert str(sqrt(x**2)) == "sqrt(x**2)" + assert str(1/sqrt(x)) == "1/sqrt(x)" + assert str(1/sqrt(x**2)) == "1/sqrt(x**2)" + assert str(y/sqrt(x)) == "y/sqrt(x)" + assert str(x**0.5) == "x**0.5" + assert str(1/x**0.5) == "x**(-0.5)" + + +def test_Rational(): + n1 = Rational(1, 4) + n2 = Rational(1, 3) + n3 = Rational(2, 4) + n4 = Rational(2, -4) + n5 = Rational(0) + n7 = Rational(3) + n8 = Rational(-3) + assert str(n1*n2) == "1/12" + assert str(n1*n2) == "1/12" + assert str(n3) == "1/2" + assert str(n1*n3) == "1/8" + assert str(n1 + n3) == "3/4" + assert str(n1 + n2) == "7/12" + assert str(n1 + n4) == "-1/4" + assert str(n4*n4) == "1/4" + assert str(n4 + n2) == "-1/6" + assert str(n4 + n5) == "-1/2" + assert str(n4*n5) == "0" + assert str(n3 + n4) == "0" + assert str(n1**n7) == "1/64" + assert str(n2**n7) == "1/27" + assert str(n2**n8) == "27" + assert str(n7**n8) == "1/27" + assert str(Rational("-25")) == "-25" + assert str(Rational("1.25")) == "5/4" + assert str(Rational("-2.6e-2")) == "-13/500" + assert str(S("25/7")) == "25/7" + assert str(S("-123/569")) == "-123/569" + assert str(S("0.1[23]", rational=1)) == "61/495" + assert str(S("5.1[666]", rational=1)) == "31/6" + assert str(S("-5.1[666]", rational=1)) == "-31/6" + assert str(S("0.[9]", rational=1)) == "1" + assert str(S("-0.[9]", rational=1)) == "-1" + + assert str(sqrt(Rational(1, 4))) == "1/2" + assert str(sqrt(Rational(1, 36))) == "1/6" + + assert str((123**25) ** Rational(1, 25)) == "123" + assert str((123**25 + 1)**Rational(1, 25)) != "123" + assert str((123**25 - 1)**Rational(1, 25)) != "123" + assert str((123**25 - 1)**Rational(1, 25)) != "122" + + assert str(sqrt(Rational(81, 36))**3) == "27/8" + assert str(1/sqrt(Rational(81, 36))**3) == "8/27" + + assert str(sqrt(-4)) == str(2*I) + assert str(2**Rational(1, 10**10)) == "2**(1/10000000000)" + + assert sstr(Rational(2, 3), sympy_integers=True) == "S(2)/3" + x = Symbol("x") + assert sstr(x**Rational(2, 3), sympy_integers=True) == "x**(S(2)/3)" + assert sstr(Eq(x, Rational(2, 3)), sympy_integers=True) == "Eq(x, S(2)/3)" + assert sstr(Limit(x, x, Rational(7, 2)), sympy_integers=True) == \ + "Limit(x, x, S(7)/2, dir='+')" + + +def test_Float(): + # NOTE dps is the whole number of decimal digits + assert str(Float('1.23', dps=1 + 2)) == '1.23' + assert str(Float('1.23456789', dps=1 + 8)) == '1.23456789' + assert str( + Float('1.234567890123456789', dps=1 + 18)) == '1.234567890123456789' + assert str(pi.evalf(1 + 2)) == '3.14' + assert str(pi.evalf(1 + 14)) == '3.14159265358979' + assert str(pi.evalf(1 + 64)) == ('3.141592653589793238462643383279' + '5028841971693993751058209749445923') + assert str(pi.round(-1)) == '0.0' + assert str((pi**400 - (pi**400).round(1)).n(2)) == '-0.e+88' + assert sstr(Float("100"), full_prec=False, min=-2, max=2) == '1.0e+2' + assert sstr(Float("100"), full_prec=False, min=-2, max=3) == '100.0' + assert sstr(Float("0.1"), full_prec=False, min=-2, max=3) == '0.1' + assert sstr(Float("0.099"), min=-2, max=3) == '9.90000000000000e-2' + + +def test_Relational(): + assert str(Rel(x, y, "<")) == "x < y" + assert str(Rel(x + y, y, "==")) == "Eq(x + y, y)" + assert str(Rel(x, y, "!=")) == "Ne(x, y)" + assert str(Eq(x, 1) | Eq(x, 2)) == "Eq(x, 1) | Eq(x, 2)" + assert str(Ne(x, 1) & Ne(x, 2)) == "Ne(x, 1) & Ne(x, 2)" + + +def test_AppliedBinaryRelation(): + assert str(Q.eq(x, y)) == "Q.eq(x, y)" + assert str(Q.ne(x, y)) == "Q.ne(x, y)" + + +def test_CRootOf(): + assert str(rootof(x**5 + 2*x - 1, 0)) == "CRootOf(x**5 + 2*x - 1, 0)" + + +def test_RootSum(): + f = x**5 + 2*x - 1 + + assert str( + RootSum(f, Lambda(z, z), auto=False)) == "RootSum(x**5 + 2*x - 1)" + assert str(RootSum(f, Lambda( + z, z**2), auto=False)) == "RootSum(x**5 + 2*x - 1, Lambda(z, z**2))" + + +def test_GroebnerBasis(): + assert str(groebner( + [], x, y)) == "GroebnerBasis([], x, y, domain='ZZ', order='lex')" + + F = [x**2 - 3*y - x + 1, y**2 - 2*x + y - 1] + + assert str(groebner(F, order='grlex')) == \ + "GroebnerBasis([x**2 - x - 3*y + 1, y**2 - 2*x + y - 1], x, y, domain='ZZ', order='grlex')" + assert str(groebner(F, order='lex')) == \ + "GroebnerBasis([2*x - y**2 - y + 1, y**4 + 2*y**3 - 3*y**2 - 16*y + 7], x, y, domain='ZZ', order='lex')" + +def test_set(): + assert sstr(set()) == 'set()' + assert sstr(frozenset()) == 'frozenset()' + + assert sstr({1}) == '{1}' + assert sstr(frozenset([1])) == 'frozenset({1})' + assert sstr({1, 2, 3}) == '{1, 2, 3}' + assert sstr(frozenset([1, 2, 3])) == 'frozenset({1, 2, 3})' + + assert sstr( + {1, x, x**2, x**3, x**4}) == '{1, x, x**2, x**3, x**4}' + assert sstr( + frozenset([1, x, x**2, x**3, x**4])) == 'frozenset({1, x, x**2, x**3, x**4})' + + +def test_SparseMatrix(): + M = SparseMatrix([[x**+1, 1], [y, x + y]]) + assert str(M) == "Matrix([[x, 1], [y, x + y]])" + assert sstr(M) == "Matrix([\n[x, 1],\n[y, x + y]])" + + +def test_Sum(): + assert str(summation(cos(3*z), (z, x, y))) == "Sum(cos(3*z), (z, x, y))" + assert str(Sum(x*y**2, (x, -2, 2), (y, -5, 5))) == \ + "Sum(x*y**2, (x, -2, 2), (y, -5, 5))" + + +def test_Symbol(): + assert str(y) == "y" + assert str(x) == "x" + e = x + assert str(e) == "x" + + +def test_tuple(): + assert str((x,)) == sstr((x,)) == "(x,)" + assert str((x + y, 1 + x)) == sstr((x + y, 1 + x)) == "(x + y, x + 1)" + assert str((x + y, ( + 1 + x, x**2))) == sstr((x + y, (1 + x, x**2))) == "(x + y, (x + 1, x**2))" + + +def test_Series_str(): + tf1 = TransferFunction(x*y**2 - z, y**3 - t**3, y) + tf2 = TransferFunction(x - y, x + y, y) + tf3 = TransferFunction(t*x**2 - t**w*x + w, t - y, y) + assert str(Series(tf1, tf2)) == \ + "Series(TransferFunction(x*y**2 - z, -t**3 + y**3, y), TransferFunction(x - y, x + y, y))" + assert str(Series(tf1, tf2, tf3)) == \ + "Series(TransferFunction(x*y**2 - z, -t**3 + y**3, y), TransferFunction(x - y, x + y, y), TransferFunction(t*x**2 - t**w*x + w, t - y, y))" + assert str(Series(-tf2, tf1)) == \ + "Series(TransferFunction(-x + y, x + y, y), TransferFunction(x*y**2 - z, -t**3 + y**3, y))" + + +def test_MIMOSeries_str(): + tf1 = TransferFunction(x*y**2 - z, y**3 - t**3, y) + tf2 = TransferFunction(x - y, x + y, y) + tfm_1 = TransferFunctionMatrix([[tf1, tf2], [tf2, tf1]]) + tfm_2 = TransferFunctionMatrix([[tf2, tf1], [tf1, tf2]]) + assert str(MIMOSeries(tfm_1, tfm_2)) == \ + "MIMOSeries(TransferFunctionMatrix(((TransferFunction(x*y**2 - z, -t**3 + y**3, y), TransferFunction(x - y, x + y, y)), "\ + "(TransferFunction(x - y, x + y, y), TransferFunction(x*y**2 - z, -t**3 + y**3, y)))), "\ + "TransferFunctionMatrix(((TransferFunction(x - y, x + y, y), TransferFunction(x*y**2 - z, -t**3 + y**3, y)), "\ + "(TransferFunction(x*y**2 - z, -t**3 + y**3, y), TransferFunction(x - y, x + y, y)))))" + + +def test_TransferFunction_str(): + tf1 = TransferFunction(x - 1, x + 1, x) + assert str(tf1) == "TransferFunction(x - 1, x + 1, x)" + tf2 = TransferFunction(x + 1, 2 - y, x) + assert str(tf2) == "TransferFunction(x + 1, 2 - y, x)" + tf3 = TransferFunction(y, y**2 + 2*y + 3, y) + assert str(tf3) == "TransferFunction(y, y**2 + 2*y + 3, y)" + + +def test_Parallel_str(): + tf1 = TransferFunction(x*y**2 - z, y**3 - t**3, y) + tf2 = TransferFunction(x - y, x + y, y) + tf3 = TransferFunction(t*x**2 - t**w*x + w, t - y, y) + assert str(Parallel(tf1, tf2)) == \ + "Parallel(TransferFunction(x*y**2 - z, -t**3 + y**3, y), TransferFunction(x - y, x + y, y))" + assert str(Parallel(tf1, tf2, tf3)) == \ + "Parallel(TransferFunction(x*y**2 - z, -t**3 + y**3, y), TransferFunction(x - y, x + y, y), TransferFunction(t*x**2 - t**w*x + w, t - y, y))" + assert str(Parallel(-tf2, tf1)) == \ + "Parallel(TransferFunction(-x + y, x + y, y), TransferFunction(x*y**2 - z, -t**3 + y**3, y))" + + +def test_MIMOParallel_str(): + tf1 = TransferFunction(x*y**2 - z, y**3 - t**3, y) + tf2 = TransferFunction(x - y, x + y, y) + tfm_1 = TransferFunctionMatrix([[tf1, tf2], [tf2, tf1]]) + tfm_2 = TransferFunctionMatrix([[tf2, tf1], [tf1, tf2]]) + assert str(MIMOParallel(tfm_1, tfm_2)) == \ + "MIMOParallel(TransferFunctionMatrix(((TransferFunction(x*y**2 - z, -t**3 + y**3, y), TransferFunction(x - y, x + y, y)), "\ + "(TransferFunction(x - y, x + y, y), TransferFunction(x*y**2 - z, -t**3 + y**3, y)))), "\ + "TransferFunctionMatrix(((TransferFunction(x - y, x + y, y), TransferFunction(x*y**2 - z, -t**3 + y**3, y)), "\ + "(TransferFunction(x*y**2 - z, -t**3 + y**3, y), TransferFunction(x - y, x + y, y)))))" + + +def test_Feedback_str(): + tf1 = TransferFunction(x*y**2 - z, y**3 - t**3, y) + tf2 = TransferFunction(x - y, x + y, y) + tf3 = TransferFunction(t*x**2 - t**w*x + w, t - y, y) + assert str(Feedback(tf1*tf2, tf3)) == \ + "Feedback(Series(TransferFunction(x*y**2 - z, -t**3 + y**3, y), TransferFunction(x - y, x + y, y)), " \ + "TransferFunction(t*x**2 - t**w*x + w, t - y, y), -1)" + assert str(Feedback(tf1, TransferFunction(1, 1, y), 1)) == \ + "Feedback(TransferFunction(x*y**2 - z, -t**3 + y**3, y), TransferFunction(1, 1, y), 1)" + + +def test_MIMOFeedback_str(): + tf1 = TransferFunction(x**2 - y**3, y - z, x) + tf2 = TransferFunction(y - x, z + y, x) + tfm_1 = TransferFunctionMatrix([[tf2, tf1], [tf1, tf2]]) + tfm_2 = TransferFunctionMatrix([[tf1, tf2], [tf2, tf1]]) + assert (str(MIMOFeedback(tfm_1, tfm_2)) \ + == "MIMOFeedback(TransferFunctionMatrix(((TransferFunction(-x + y, y + z, x), TransferFunction(x**2 - y**3, y - z, x))," \ + " (TransferFunction(x**2 - y**3, y - z, x), TransferFunction(-x + y, y + z, x)))), " \ + "TransferFunctionMatrix(((TransferFunction(x**2 - y**3, y - z, x), " \ + "TransferFunction(-x + y, y + z, x)), (TransferFunction(-x + y, y + z, x), TransferFunction(x**2 - y**3, y - z, x)))), -1)") + assert (str(MIMOFeedback(tfm_1, tfm_2, 1)) \ + == "MIMOFeedback(TransferFunctionMatrix(((TransferFunction(-x + y, y + z, x), TransferFunction(x**2 - y**3, y - z, x)), " \ + "(TransferFunction(x**2 - y**3, y - z, x), TransferFunction(-x + y, y + z, x)))), " \ + "TransferFunctionMatrix(((TransferFunction(x**2 - y**3, y - z, x), TransferFunction(-x + y, y + z, x)), "\ + "(TransferFunction(-x + y, y + z, x), TransferFunction(x**2 - y**3, y - z, x)))), 1)") + + +def test_TransferFunctionMatrix_str(): + tf1 = TransferFunction(x*y**2 - z, y**3 - t**3, y) + tf2 = TransferFunction(x - y, x + y, y) + tf3 = TransferFunction(t*x**2 - t**w*x + w, t - y, y) + assert str(TransferFunctionMatrix([[tf1], [tf2]])) == \ + "TransferFunctionMatrix(((TransferFunction(x*y**2 - z, -t**3 + y**3, y),), (TransferFunction(x - y, x + y, y),)))" + assert str(TransferFunctionMatrix([[tf1, tf2], [tf3, tf2]])) == \ + "TransferFunctionMatrix(((TransferFunction(x*y**2 - z, -t**3 + y**3, y), TransferFunction(x - y, x + y, y)), (TransferFunction(t*x**2 - t**w*x + w, t - y, y), TransferFunction(x - y, x + y, y))))" + + +def test_Quaternion_str_printer(): + q = Quaternion(x, y, z, t) + assert str(q) == "x + y*i + z*j + t*k" + q = Quaternion(x,y,z,x*t) + assert str(q) == "x + y*i + z*j + t*x*k" + q = Quaternion(x,y,z,x+t) + assert str(q) == "x + y*i + z*j + (t + x)*k" + + +def test_Quantity_str(): + assert sstr(second, abbrev=True) == "s" + assert sstr(joule, abbrev=True) == "J" + assert str(second) == "second" + assert str(joule) == "joule" + + +def test_wild_str(): + # Check expressions containing Wild not causing infinite recursion + w = Wild('x') + assert str(w + 1) == 'x_ + 1' + assert str(exp(2**w) + 5) == 'exp(2**x_) + 5' + assert str(3*w + 1) == '3*x_ + 1' + assert str(1/w + 1) == '1 + 1/x_' + assert str(w**2 + 1) == 'x_**2 + 1' + assert str(1/(1 - w)) == '1/(1 - x_)' + + +def test_wild_matchpy(): + from sympy.utilities.matchpy_connector import WildDot, WildPlus, WildStar + + matchpy = import_module("matchpy") + + if matchpy is None: + return + + wd = WildDot('w_') + wp = WildPlus('w__') + ws = WildStar('w___') + + assert str(wd) == 'w_' + assert str(wp) == 'w__' + assert str(ws) == 'w___' + + assert str(wp/ws + 2**wd) == '2**w_ + w__/w___' + assert str(sin(wd)*cos(wp)*sqrt(ws)) == 'sqrt(w___)*sin(w_)*cos(w__)' + + +def test_zeta(): + assert str(zeta(3)) == "zeta(3)" + + +def test_issue_3101(): + e = x - y + a = str(e) + b = str(e) + assert a == b + + +def test_issue_3103(): + e = -2*sqrt(x) - y/sqrt(x)/2 + assert str(e) not in ["(-2)*x**1/2(-1/2)*x**(-1/2)*y", + "-2*x**1/2(-1/2)*x**(-1/2)*y", "-2*x**1/2-1/2*x**-1/2*w"] + assert str(e) == "-2*sqrt(x) - y/(2*sqrt(x))" + + +def test_issue_4021(): + e = Integral(x, x) + 1 + assert str(e) == 'Integral(x, x) + 1' + + +def test_sstrrepr(): + assert sstr('abc') == 'abc' + assert sstrrepr('abc') == "'abc'" + + e = ['a', 'b', 'c', x] + assert sstr(e) == "[a, b, c, x]" + assert sstrrepr(e) == "['a', 'b', 'c', x]" + + +def test_infinity(): + assert sstr(oo*I) == "oo*I" + + +def test_full_prec(): + assert sstr(S("0.3"), full_prec=True) == "0.300000000000000" + assert sstr(S("0.3"), full_prec="auto") == "0.300000000000000" + assert sstr(S("0.3"), full_prec=False) == "0.3" + assert sstr(S("0.3")*x, full_prec=True) in [ + "0.300000000000000*x", + "x*0.300000000000000" + ] + assert sstr(S("0.3")*x, full_prec="auto") in [ + "0.3*x", + "x*0.3" + ] + assert sstr(S("0.3")*x, full_prec=False) in [ + "0.3*x", + "x*0.3" + ] + + +def test_noncommutative(): + A, B, C = symbols('A,B,C', commutative=False) + + assert sstr(A*B*C**-1) == "A*B*C**(-1)" + assert sstr(C**-1*A*B) == "C**(-1)*A*B" + assert sstr(A*C**-1*B) == "A*C**(-1)*B" + assert sstr(sqrt(A)) == "sqrt(A)" + assert sstr(1/sqrt(A)) == "A**(-1/2)" + + +def test_empty_printer(): + str_printer = StrPrinter() + assert str_printer.emptyPrinter("foo") == "foo" + assert str_printer.emptyPrinter(x*y) == "x*y" + assert str_printer.emptyPrinter(32) == "32" + +def test_decimal_printer(): + dec_printer = StrPrinter(settings={"dps":3}) + f = Function('f') + assert dec_printer.doprint(f(1.329294)) == "f(1.33)" + + +def test_settings(): + raises(TypeError, lambda: sstr(S(4), method="garbage")) + + +def test_RandomDomain(): + from sympy.stats import Normal, Die, Exponential, pspace, where + X = Normal('x1', 0, 1) + assert str(where(X > 0)) == "Domain: (0 < x1) & (x1 < oo)" + + D = Die('d1', 6) + assert str(where(D > 4)) == "Domain: Eq(d1, 5) | Eq(d1, 6)" + + A = Exponential('a', 1) + B = Exponential('b', 1) + assert str(pspace(Tuple(A, B)).domain) == "Domain: (0 <= a) & (0 <= b) & (a < oo) & (b < oo)" + + +def test_FiniteSet(): + assert str(FiniteSet(*range(1, 51))) == ( + '{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,' + ' 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,' + ' 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50}' + ) + assert str(FiniteSet(*range(1, 6))) == '{1, 2, 3, 4, 5}' + assert str(FiniteSet(*[x*y, x**2])) == '{x**2, x*y}' + assert str(FiniteSet(FiniteSet(FiniteSet(x, y), 5), FiniteSet(x,y), 5) + ) == 'FiniteSet(5, FiniteSet(5, {x, y}), {x, y})' + + +def test_Partition(): + assert str(Partition(FiniteSet(x, y), {z})) == 'Partition({z}, {x, y})' + +def test_UniversalSet(): + assert str(S.UniversalSet) == 'UniversalSet' + + +def test_PrettyPoly(): + F = QQ.frac_field(x, y) + R = QQ[x, y] + assert sstr(F.convert(x/(x + y))) == sstr(x/(x + y)) + assert sstr(R.convert(x + y)) == sstr(x + y) + + +def test_categories(): + from sympy.categories import (Object, NamedMorphism, + IdentityMorphism, Category) + + A = Object("A") + B = Object("B") + + f = NamedMorphism(A, B, "f") + id_A = IdentityMorphism(A) + + K = Category("K") + + assert str(A) == 'Object("A")' + assert str(f) == 'NamedMorphism(Object("A"), Object("B"), "f")' + assert str(id_A) == 'IdentityMorphism(Object("A"))' + + assert str(K) == 'Category("K")' + + +def test_Tr(): + A, B = symbols('A B', commutative=False) + t = Tr(A*B) + assert str(t) == 'Tr(A*B)' + + +def test_issue_6387(): + assert str(factor(-3.0*z + 3)) == '-3.0*(1.0*z - 1.0)' + + +def test_MatMul_MatAdd(): + X, Y = MatrixSymbol("X", 2, 2), MatrixSymbol("Y", 2, 2) + assert str(2*(X + Y)) == "2*X + 2*Y" + + assert str(I*X) == "I*X" + assert str(-I*X) == "-I*X" + assert str((1 + I)*X) == '(1 + I)*X' + assert str(-(1 + I)*X) == '(-1 - I)*X' + assert str(MatAdd(MatAdd(X, Y), MatAdd(X, Y))) == '(X + Y) + (X + Y)' + + +def test_MatrixSlice(): + n = Symbol('n', integer=True) + X = MatrixSymbol('X', n, n) + Y = MatrixSymbol('Y', 10, 10) + Z = MatrixSymbol('Z', 10, 10) + + assert str(MatrixSlice(X, (None, None, None), (None, None, None))) == 'X[:, :]' + assert str(X[x:x + 1, y:y + 1]) == 'X[x:x + 1, y:y + 1]' + assert str(X[x:x + 1:2, y:y + 1:2]) == 'X[x:x + 1:2, y:y + 1:2]' + assert str(X[:x, y:]) == 'X[:x, y:]' + assert str(X[:x, y:]) == 'X[:x, y:]' + assert str(X[x:, :y]) == 'X[x:, :y]' + assert str(X[x:y, z:w]) == 'X[x:y, z:w]' + assert str(X[x:y:t, w:t:x]) == 'X[x:y:t, w:t:x]' + assert str(X[x::y, t::w]) == 'X[x::y, t::w]' + assert str(X[:x:y, :t:w]) == 'X[:x:y, :t:w]' + assert str(X[::x, ::y]) == 'X[::x, ::y]' + assert str(MatrixSlice(X, (0, None, None), (0, None, None))) == 'X[:, :]' + assert str(MatrixSlice(X, (None, n, None), (None, n, None))) == 'X[:, :]' + assert str(MatrixSlice(X, (0, n, None), (0, n, None))) == 'X[:, :]' + assert str(MatrixSlice(X, (0, n, 2), (0, n, 2))) == 'X[::2, ::2]' + assert str(X[1:2:3, 4:5:6]) == 'X[1:2:3, 4:5:6]' + assert str(X[1:3:5, 4:6:8]) == 'X[1:3:5, 4:6:8]' + assert str(X[1:10:2]) == 'X[1:10:2, :]' + assert str(Y[:5, 1:9:2]) == 'Y[:5, 1:9:2]' + assert str(Y[:5, 1:10:2]) == 'Y[:5, 1::2]' + assert str(Y[5, :5:2]) == 'Y[5:6, :5:2]' + assert str(X[0:1, 0:1]) == 'X[:1, :1]' + assert str(X[0:1:2, 0:1:2]) == 'X[:1:2, :1:2]' + assert str((Y + Z)[2:, 2:]) == '(Y + Z)[2:, 2:]' + +def test_true_false(): + assert str(true) == repr(true) == sstr(true) == "True" + assert str(false) == repr(false) == sstr(false) == "False" + +def test_Equivalent(): + assert str(Equivalent(y, x)) == "Equivalent(x, y)" + +def test_Xor(): + assert str(Xor(y, x, evaluate=False)) == "x ^ y" + +def test_Complement(): + assert str(Complement(S.Reals, S.Naturals)) == 'Complement(Reals, Naturals)' + +def test_SymmetricDifference(): + assert str(SymmetricDifference(Interval(2, 3), Interval(3, 4),evaluate=False)) == \ + 'SymmetricDifference(Interval(2, 3), Interval(3, 4))' + + +def test_UnevaluatedExpr(): + a, b = symbols("a b") + expr1 = 2*UnevaluatedExpr(a+b) + assert str(expr1) == "2*(a + b)" + + +def test_MatrixElement_printing(): + # test cases for issue #11821 + A = MatrixSymbol("A", 1, 3) + B = MatrixSymbol("B", 1, 3) + C = MatrixSymbol("C", 1, 3) + + assert(str(A[0, 0]) == "A[0, 0]") + assert(str(3 * A[0, 0]) == "3*A[0, 0]") + + F = C[0, 0].subs(C, A - B) + assert str(F) == "(A - B)[0, 0]" + + +def test_MatrixSymbol_printing(): + A = MatrixSymbol("A", 3, 3) + B = MatrixSymbol("B", 3, 3) + + assert str(A - A*B - B) == "A - A*B - B" + assert str(A*B - (A+B)) == "-A + A*B - B" + assert str(A**(-1)) == "A**(-1)" + assert str(A**3) == "A**3" + + +def test_MatrixExpressions(): + n = Symbol('n', integer=True) + X = MatrixSymbol('X', n, n) + + assert str(X) == "X" + + # Apply function elementwise (`ElementwiseApplyFunc`): + + expr = (X.T*X).applyfunc(sin) + assert str(expr) == 'Lambda(_d, sin(_d)).(X.T*X)' + + lamda = Lambda(x, 1/x) + expr = (n*X).applyfunc(lamda) + assert str(expr) == 'Lambda(x, 1/x).(n*X)' + + +def test_Subs_printing(): + assert str(Subs(x, (x,), (1,))) == 'Subs(x, x, 1)' + assert str(Subs(x + y, (x, y), (1, 2))) == 'Subs(x + y, (x, y), (1, 2))' + + +def test_issue_15716(): + e = Integral(factorial(x), (x, -oo, oo)) + assert e.as_terms() == ([(e, ((1.0, 0.0), (1,), ()))], [e]) + + +def test_str_special_matrices(): + from sympy.matrices import Identity, ZeroMatrix, OneMatrix + assert str(Identity(4)) == 'I' + assert str(ZeroMatrix(2, 2)) == '0' + assert str(OneMatrix(2, 2)) == '1' + + +def test_issue_14567(): + assert factorial(Sum(-1, (x, 0, 0))) + y # doesn't raise an error + + +def test_issue_21823(): + assert str(Partition([1, 2])) == 'Partition({1, 2})' + assert str(Partition({1, 2})) == 'Partition({1, 2})' + + +def test_issue_22689(): + assert str(Mul(Pow(x,-2, evaluate=False), Pow(3,-1,evaluate=False), evaluate=False)) == "1/(x**2*3)" + + +def test_issue_21119_21460(): + ss = lambda x: str(S(x, evaluate=False)) + assert ss('4/2') == '4/2' + assert ss('4/-2') == '4/(-2)' + assert ss('-4/2') == '-4/2' + assert ss('-4/-2') == '-4/(-2)' + assert ss('-2*3/-1') == '-2*3/(-1)' + assert ss('-2*3/-1/2') == '-2*3/(-1*2)' + assert ss('4/2/1') == '4/(2*1)' + assert ss('-2/-1/2') == '-2/(-1*2)' + assert ss('2*3*4**(-2*3)') == '2*3/4**(2*3)' + assert ss('2*3*1*4**(-2*3)') == '2*3*1/4**(2*3)' + + +def test_Str(): + from sympy.core.symbol import Str + assert str(Str('x')) == 'x' + assert sstrrepr(Str('x')) == "Str('x')" + + +def test_diffgeom(): + from sympy.diffgeom import Manifold, Patch, CoordSystem, BaseScalarField + x,y = symbols('x y', real=True) + m = Manifold('M', 2) + assert str(m) == "M" + p = Patch('P', m) + assert str(p) == "P" + rect = CoordSystem('rect', p, [x, y]) + assert str(rect) == "rect" + b = BaseScalarField(rect, 0) + assert str(b) == "x" + +def test_NDimArray(): + assert sstr(NDimArray(1.0), full_prec=True) == '1.00000000000000' + assert sstr(NDimArray(1.0), full_prec=False) == '1.0' + assert sstr(NDimArray([1.0, 2.0]), full_prec=True) == '[1.00000000000000, 2.00000000000000]' + assert sstr(NDimArray([1.0, 2.0]), full_prec=False) == '[1.0, 2.0]' + assert sstr(NDimArray([], (0,))) == 'ImmutableDenseNDimArray([], (0,))' + assert sstr(NDimArray([], (0, 0))) == 'ImmutableDenseNDimArray([], (0, 0))' + assert sstr(NDimArray([], (0, 1))) == 'ImmutableDenseNDimArray([], (0, 1))' + assert sstr(NDimArray([], (1, 0))) == 'ImmutableDenseNDimArray([], (1, 0))' + +def test_Predicate(): + assert sstr(Q.even) == 'Q.even' + +def test_AppliedPredicate(): + assert sstr(Q.even(x)) == 'Q.even(x)' + +def test_printing_str_array_expressions(): + assert sstr(ArraySymbol("A", (2, 3, 4))) == "A" + assert sstr(ArrayElement("A", (2, 1/(1-x), 0))) == "A[2, 1/(1 - x), 0]" + M = MatrixSymbol("M", 3, 3) + N = MatrixSymbol("N", 3, 3) + assert sstr(ArrayElement(M*N, [x, 0])) == "(M*N)[x, 0]" + +def test_printing_stats(): + # issue 24132 + x = RandomSymbol("x") + y = RandomSymbol("y") + z1 = Probability(x > 0)*Identity(2) + z2 = Expectation(x)*Identity(2) + z3 = Variance(x)*Identity(2) + z4 = Covariance(x, y) * Identity(2) + + assert str(z1) == "Probability(x > 0)*I" + assert str(z2) == "Expectation(x)*I" + assert str(z3) == "Variance(x)*I" + assert str(z4) == "Covariance(x, y)*I" + assert z1.is_commutative == False + assert z2.is_commutative == False + assert z3.is_commutative == False + assert z4.is_commutative == False + assert z2._eval_is_commutative() == False + assert z3._eval_is_commutative() == False + assert z4._eval_is_commutative() == False diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_tableform.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_tableform.py new file mode 100644 index 0000000000000000000000000000000000000000..05802dd104a12f2f53d137167ecf31d201ff8dfc --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_tableform.py @@ -0,0 +1,182 @@ +from sympy.core.singleton import S +from sympy.printing.tableform import TableForm +from sympy.printing.latex import latex +from sympy.abc import x +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import sin +from sympy.testing.pytest import raises + +from textwrap import dedent + + +def test_TableForm(): + s = str(TableForm([["a", "b"], ["c", "d"], ["e", 0]], + headings="automatic")) + assert s == ( + ' | 1 2\n' + '-------\n' + '1 | a b\n' + '2 | c d\n' + '3 | e ' + ) + s = str(TableForm([["a", "b"], ["c", "d"], ["e", 0]], + headings="automatic", wipe_zeros=False)) + assert s == dedent('''\ + | 1 2 + ------- + 1 | a b + 2 | c d + 3 | e 0''') + s = str(TableForm([[x**2, "b"], ["c", x**2], ["e", "f"]], + headings=("automatic", None))) + assert s == ( + '1 | x**2 b \n' + '2 | c x**2\n' + '3 | e f ' + ) + s = str(TableForm([["a", "b"], ["c", "d"], ["e", "f"]], + headings=(None, "automatic"))) + assert s == dedent('''\ + 1 2 + --- + a b + c d + e f''') + s = str(TableForm([[5, 7], [4, 2], [10, 3]], + headings=[["Group A", "Group B", "Group C"], ["y1", "y2"]])) + assert s == ( + ' | y1 y2\n' + '---------------\n' + 'Group A | 5 7 \n' + 'Group B | 4 2 \n' + 'Group C | 10 3 ' + ) + raises( + ValueError, + lambda: + TableForm( + [[5, 7], [4, 2], [10, 3]], + headings=[["Group A", "Group B", "Group C"], ["y1", "y2"]], + alignments="middle") + ) + s = str(TableForm([[5, 7], [4, 2], [10, 3]], + headings=[["Group A", "Group B", "Group C"], ["y1", "y2"]], + alignments="right")) + assert s == dedent('''\ + | y1 y2 + --------------- + Group A | 5 7 + Group B | 4 2 + Group C | 10 3''') + + # other alignment permutations + d = [[1, 100], [100, 1]] + s = TableForm(d, headings=(('xxx', 'x'), None), alignments='l') + assert str(s) == ( + 'xxx | 1 100\n' + ' x | 100 1 ' + ) + s = TableForm(d, headings=(('xxx', 'x'), None), alignments='lr') + assert str(s) == dedent('''\ + xxx | 1 100 + x | 100 1''') + s = TableForm(d, headings=(('xxx', 'x'), None), alignments='clr') + assert str(s) == dedent('''\ + xxx | 1 100 + x | 100 1''') + + s = TableForm(d, headings=(('xxx', 'x'), None)) + assert str(s) == ( + 'xxx | 1 100\n' + ' x | 100 1 ' + ) + + raises(ValueError, lambda: TableForm(d, alignments='clr')) + + #pad + s = str(TableForm([[None, "-", 2], [1]], pad='?')) + assert s == dedent('''\ + ? - 2 + 1 ? ?''') + + +def test_TableForm_latex(): + s = latex(TableForm([[0, x**3], ["c", S.One/4], [sqrt(x), sin(x**2)]], + wipe_zeros=True, headings=("automatic", "automatic"))) + assert s == ( + '\\begin{tabular}{r l l}\n' + ' & 1 & 2 \\\\\n' + '\\hline\n' + '1 & & $x^{3}$ \\\\\n' + '2 & $c$ & $\\frac{1}{4}$ \\\\\n' + '3 & $\\sqrt{x}$ & $\\sin{\\left(x^{2} \\right)}$ \\\\\n' + '\\end{tabular}' + ) + s = latex(TableForm([[0, x**3], ["c", S.One/4], [sqrt(x), sin(x**2)]], + wipe_zeros=True, headings=("automatic", "automatic"), alignments='l')) + assert s == ( + '\\begin{tabular}{r l l}\n' + ' & 1 & 2 \\\\\n' + '\\hline\n' + '1 & & $x^{3}$ \\\\\n' + '2 & $c$ & $\\frac{1}{4}$ \\\\\n' + '3 & $\\sqrt{x}$ & $\\sin{\\left(x^{2} \\right)}$ \\\\\n' + '\\end{tabular}' + ) + s = latex(TableForm([[0, x**3], ["c", S.One/4], [sqrt(x), sin(x**2)]], + wipe_zeros=True, headings=("automatic", "automatic"), alignments='l'*3)) + assert s == ( + '\\begin{tabular}{l l l}\n' + ' & 1 & 2 \\\\\n' + '\\hline\n' + '1 & & $x^{3}$ \\\\\n' + '2 & $c$ & $\\frac{1}{4}$ \\\\\n' + '3 & $\\sqrt{x}$ & $\\sin{\\left(x^{2} \\right)}$ \\\\\n' + '\\end{tabular}' + ) + s = latex(TableForm([["a", x**3], ["c", S.One/4], [sqrt(x), sin(x**2)]], + headings=("automatic", "automatic"))) + assert s == ( + '\\begin{tabular}{r l l}\n' + ' & 1 & 2 \\\\\n' + '\\hline\n' + '1 & $a$ & $x^{3}$ \\\\\n' + '2 & $c$ & $\\frac{1}{4}$ \\\\\n' + '3 & $\\sqrt{x}$ & $\\sin{\\left(x^{2} \\right)}$ \\\\\n' + '\\end{tabular}' + ) + s = latex(TableForm([["a", x**3], ["c", S.One/4], [sqrt(x), sin(x**2)]], + formats=['(%s)', None], headings=("automatic", "automatic"))) + assert s == ( + '\\begin{tabular}{r l l}\n' + ' & 1 & 2 \\\\\n' + '\\hline\n' + '1 & (a) & $x^{3}$ \\\\\n' + '2 & (c) & $\\frac{1}{4}$ \\\\\n' + '3 & (sqrt(x)) & $\\sin{\\left(x^{2} \\right)}$ \\\\\n' + '\\end{tabular}' + ) + + def neg_in_paren(x, i, j): + if i % 2: + return ('(%s)' if x < 0 else '%s') % x + else: + pass # use default print + s = latex(TableForm([[-1, 2], [-3, 4]], + formats=[neg_in_paren]*2, headings=("automatic", "automatic"))) + assert s == ( + '\\begin{tabular}{r l l}\n' + ' & 1 & 2 \\\\\n' + '\\hline\n' + '1 & -1 & 2 \\\\\n' + '2 & (-3) & 4 \\\\\n' + '\\end{tabular}' + ) + s = latex(TableForm([["a", x**3], ["c", S.One/4], [sqrt(x), sin(x**2)]])) + assert s == ( + '\\begin{tabular}{l l}\n' + '$a$ & $x^{3}$ \\\\\n' + '$c$ & $\\frac{1}{4}$ \\\\\n' + '$\\sqrt{x}$ & $\\sin{\\left(x^{2} \\right)}$ \\\\\n' + '\\end{tabular}' + ) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_tensorflow.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_tensorflow.py new file mode 100644 index 0000000000000000000000000000000000000000..e9c92cd17b13e1148ebf83f13f66854b983491fe --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_tensorflow.py @@ -0,0 +1,493 @@ +import random +from sympy.core.function import Derivative +from sympy.core.symbol import symbols +from sympy import Piecewise +from sympy.tensor.array.expressions.array_expressions import ArrayTensorProduct, ArrayAdd, \ + PermuteDims, ArrayDiagonal +from sympy.core.relational import Eq, Ne, Ge, Gt, Le, Lt +from sympy.external import import_module +from sympy.functions import \ + Abs, ceiling, exp, floor, sign, sin, asin, sqrt, cos, \ + acos, tan, atan, atan2, cosh, acosh, sinh, asinh, tanh, atanh, \ + re, im, arg, erf, loggamma, log +from sympy.codegen.cfunctions import isnan, isinf +from sympy.matrices import Matrix, MatrixBase, eye, randMatrix +from sympy.matrices.expressions import \ + Determinant, HadamardProduct, Inverse, MatrixSymbol, Trace +from sympy.printing.tensorflow import tensorflow_code +from sympy.tensor.array.expressions.from_matrix_to_array import convert_matrix_to_array +from sympy.utilities.lambdify import lambdify +from sympy.testing.pytest import skip +from sympy.testing.pytest import XFAIL + + +tf = tensorflow = import_module("tensorflow") + +if tensorflow: + # Hide Tensorflow warnings + import os + os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' + + +M = MatrixSymbol("M", 3, 3) +N = MatrixSymbol("N", 3, 3) +P = MatrixSymbol("P", 3, 3) +Q = MatrixSymbol("Q", 3, 3) + +x, y, z, t = symbols("x y z t") + +if tf is not None: + llo = [list(range(i, i+3)) for i in range(0, 9, 3)] + m3x3 = tf.constant(llo) + m3x3sympy = Matrix(llo) + + +def _compare_tensorflow_matrix(variables, expr, use_float=False): + f = lambdify(variables, expr, 'tensorflow') + if not use_float: + random_matrices = [randMatrix(v.rows, v.cols) for v in variables] + else: + random_matrices = [randMatrix(v.rows, v.cols)/100. for v in variables] + + graph = tf.Graph() + r = None + with graph.as_default(): + random_variables = [eval(tensorflow_code(i)) for i in random_matrices] + session = tf.compat.v1.Session(graph=graph) + r = session.run(f(*random_variables)) + + e = expr.subs(dict(zip(variables, random_matrices))) + e = e.doit() + if e.is_Matrix: + if not isinstance(e, MatrixBase): + e = e.as_explicit() + e = e.tolist() + + if not use_float: + assert (r == e).all() + else: + r = [i for row in r for i in row] + e = [i for row in e for i in row] + assert all( + abs(a-b) < 10**-(4-int(log(abs(a), 10))) for a, b in zip(r, e)) + + +# Creating a custom inverse test. +# See https://github.com/sympy/sympy/issues/18469 +def _compare_tensorflow_matrix_inverse(variables, expr, use_float=False): + f = lambdify(variables, expr, 'tensorflow') + if not use_float: + random_matrices = [eye(v.rows, v.cols)*4 for v in variables] + else: + random_matrices = [eye(v.rows, v.cols)*3.14 for v in variables] + + graph = tf.Graph() + r = None + with graph.as_default(): + random_variables = [eval(tensorflow_code(i)) for i in random_matrices] + session = tf.compat.v1.Session(graph=graph) + r = session.run(f(*random_variables)) + + e = expr.subs(dict(zip(variables, random_matrices))) + e = e.doit() + if e.is_Matrix: + if not isinstance(e, MatrixBase): + e = e.as_explicit() + e = e.tolist() + + if not use_float: + assert (r == e).all() + else: + r = [i for row in r for i in row] + e = [i for row in e for i in row] + assert all( + abs(a-b) < 10**-(4-int(log(abs(a), 10))) for a, b in zip(r, e)) + + +def _compare_tensorflow_matrix_scalar(variables, expr): + f = lambdify(variables, expr, 'tensorflow') + random_matrices = [ + randMatrix(v.rows, v.cols).evalf() / 100 for v in variables] + + graph = tf.Graph() + r = None + with graph.as_default(): + random_variables = [eval(tensorflow_code(i)) for i in random_matrices] + session = tf.compat.v1.Session(graph=graph) + r = session.run(f(*random_variables)) + + e = expr.subs(dict(zip(variables, random_matrices))) + e = e.doit() + assert abs(r-e) < 10**-6 + + +def _compare_tensorflow_scalar( + variables, expr, rng=lambda: random.randint(0, 10)): + f = lambdify(variables, expr, 'tensorflow') + rvs = [rng() for v in variables] + + graph = tf.Graph() + r = None + with graph.as_default(): + tf_rvs = [eval(tensorflow_code(i)) for i in rvs] + session = tf.compat.v1.Session(graph=graph) + r = session.run(f(*tf_rvs)) + + e = expr.subs(dict(zip(variables, rvs))).evalf().doit() + assert abs(r-e) < 10**-6 + + +def _compare_tensorflow_relational( + variables, expr, rng=lambda: random.randint(0, 10)): + f = lambdify(variables, expr, 'tensorflow') + rvs = [rng() for v in variables] + + graph = tf.Graph() + r = None + with graph.as_default(): + tf_rvs = [eval(tensorflow_code(i)) for i in rvs] + session = tf.compat.v1.Session(graph=graph) + r = session.run(f(*tf_rvs)) + + e = expr.subs(dict(zip(variables, rvs))).doit() + assert r == e + + +def test_tensorflow_printing(): + assert tensorflow_code(eye(3)) == \ + "tensorflow.constant([[1, 0, 0], [0, 1, 0], [0, 0, 1]])" + + expr = Matrix([[x, sin(y)], [exp(z), -t]]) + assert tensorflow_code(expr) == \ + "tensorflow.Variable(" \ + "[[x, tensorflow.math.sin(y)]," \ + " [tensorflow.math.exp(z), -t]])" + + +# This (random) test is XFAIL because it fails occasionally +# See https://github.com/sympy/sympy/issues/18469 +@XFAIL +def test_tensorflow_math(): + if not tf: + skip("TensorFlow not installed") + + expr = Abs(x) + assert tensorflow_code(expr) == "tensorflow.math.abs(x)" + _compare_tensorflow_scalar((x,), expr) + + expr = sign(x) + assert tensorflow_code(expr) == "tensorflow.math.sign(x)" + _compare_tensorflow_scalar((x,), expr) + + expr = ceiling(x) + assert tensorflow_code(expr) == "tensorflow.math.ceil(x)" + _compare_tensorflow_scalar((x,), expr, rng=lambda: random.random()) + + expr = floor(x) + assert tensorflow_code(expr) == "tensorflow.math.floor(x)" + _compare_tensorflow_scalar((x,), expr, rng=lambda: random.random()) + + expr = exp(x) + assert tensorflow_code(expr) == "tensorflow.math.exp(x)" + _compare_tensorflow_scalar((x,), expr, rng=lambda: random.random()) + + expr = sqrt(x) + assert tensorflow_code(expr) == "tensorflow.math.sqrt(x)" + _compare_tensorflow_scalar((x,), expr, rng=lambda: random.random()) + + expr = x ** 4 + assert tensorflow_code(expr) == "tensorflow.math.pow(x, 4)" + _compare_tensorflow_scalar((x,), expr, rng=lambda: random.random()) + + expr = cos(x) + assert tensorflow_code(expr) == "tensorflow.math.cos(x)" + _compare_tensorflow_scalar((x,), expr, rng=lambda: random.random()) + + expr = acos(x) + assert tensorflow_code(expr) == "tensorflow.math.acos(x)" + _compare_tensorflow_scalar((x,), expr, rng=lambda: random.uniform(0, 0.95)) + + expr = sin(x) + assert tensorflow_code(expr) == "tensorflow.math.sin(x)" + _compare_tensorflow_scalar((x,), expr, rng=lambda: random.random()) + + expr = asin(x) + assert tensorflow_code(expr) == "tensorflow.math.asin(x)" + _compare_tensorflow_scalar((x,), expr, rng=lambda: random.random()) + + expr = tan(x) + assert tensorflow_code(expr) == "tensorflow.math.tan(x)" + _compare_tensorflow_scalar((x,), expr, rng=lambda: random.random()) + + expr = atan(x) + assert tensorflow_code(expr) == "tensorflow.math.atan(x)" + _compare_tensorflow_scalar((x,), expr, rng=lambda: random.random()) + + expr = atan2(y, x) + assert tensorflow_code(expr) == "tensorflow.math.atan2(y, x)" + _compare_tensorflow_scalar((y, x), expr, rng=lambda: random.random()) + + expr = cosh(x) + assert tensorflow_code(expr) == "tensorflow.math.cosh(x)" + _compare_tensorflow_scalar((x,), expr, rng=lambda: random.random()) + + expr = acosh(x) + assert tensorflow_code(expr) == "tensorflow.math.acosh(x)" + _compare_tensorflow_scalar((x,), expr, rng=lambda: random.uniform(1, 2)) + + expr = sinh(x) + assert tensorflow_code(expr) == "tensorflow.math.sinh(x)" + _compare_tensorflow_scalar((x,), expr, rng=lambda: random.uniform(1, 2)) + + expr = asinh(x) + assert tensorflow_code(expr) == "tensorflow.math.asinh(x)" + _compare_tensorflow_scalar((x,), expr, rng=lambda: random.uniform(1, 2)) + + expr = tanh(x) + assert tensorflow_code(expr) == "tensorflow.math.tanh(x)" + _compare_tensorflow_scalar((x,), expr, rng=lambda: random.uniform(1, 2)) + + expr = atanh(x) + assert tensorflow_code(expr) == "tensorflow.math.atanh(x)" + _compare_tensorflow_scalar( + (x,), expr, rng=lambda: random.uniform(-.5, .5)) + + expr = erf(x) + assert tensorflow_code(expr) == "tensorflow.math.erf(x)" + _compare_tensorflow_scalar( + (x,), expr, rng=lambda: random.random()) + + expr = loggamma(x) + assert tensorflow_code(expr) == "tensorflow.math.lgamma(x)" + _compare_tensorflow_scalar( + (x,), expr, rng=lambda: random.random()) + + +def test_tensorflow_complexes(): + assert tensorflow_code(re(x)) == "tensorflow.math.real(x)" + assert tensorflow_code(im(x)) == "tensorflow.math.imag(x)" + assert tensorflow_code(arg(x)) == "tensorflow.math.angle(x)" + + +def test_tensorflow_relational(): + if not tf: + skip("TensorFlow not installed") + + expr = Eq(x, y) + assert tensorflow_code(expr) == "tensorflow.math.equal(x, y)" + _compare_tensorflow_relational((x, y), expr) + + expr = Ne(x, y) + assert tensorflow_code(expr) == "tensorflow.math.not_equal(x, y)" + _compare_tensorflow_relational((x, y), expr) + + expr = Ge(x, y) + assert tensorflow_code(expr) == "tensorflow.math.greater_equal(x, y)" + _compare_tensorflow_relational((x, y), expr) + + expr = Gt(x, y) + assert tensorflow_code(expr) == "tensorflow.math.greater(x, y)" + _compare_tensorflow_relational((x, y), expr) + + expr = Le(x, y) + assert tensorflow_code(expr) == "tensorflow.math.less_equal(x, y)" + _compare_tensorflow_relational((x, y), expr) + + expr = Lt(x, y) + assert tensorflow_code(expr) == "tensorflow.math.less(x, y)" + _compare_tensorflow_relational((x, y), expr) + + +# This (random) test is XFAIL because it fails occasionally +# See https://github.com/sympy/sympy/issues/18469 +@XFAIL +def test_tensorflow_matrices(): + if not tf: + skip("TensorFlow not installed") + + expr = M + assert tensorflow_code(expr) == "M" + _compare_tensorflow_matrix((M,), expr) + + expr = M + N + assert tensorflow_code(expr) == "tensorflow.math.add(M, N)" + _compare_tensorflow_matrix((M, N), expr) + + expr = M * N + assert tensorflow_code(expr) == "tensorflow.linalg.matmul(M, N)" + _compare_tensorflow_matrix((M, N), expr) + + expr = HadamardProduct(M, N) + assert tensorflow_code(expr) == "tensorflow.math.multiply(M, N)" + _compare_tensorflow_matrix((M, N), expr) + + expr = M*N*P*Q + assert tensorflow_code(expr) == \ + "tensorflow.linalg.matmul(" \ + "tensorflow.linalg.matmul(" \ + "tensorflow.linalg.matmul(M, N), P), Q)" + _compare_tensorflow_matrix((M, N, P, Q), expr) + + expr = M**3 + assert tensorflow_code(expr) == \ + "tensorflow.linalg.matmul(tensorflow.linalg.matmul(M, M), M)" + _compare_tensorflow_matrix((M,), expr) + + expr = Trace(M) + assert tensorflow_code(expr) == "tensorflow.linalg.trace(M)" + _compare_tensorflow_matrix((M,), expr) + + expr = Determinant(M) + assert tensorflow_code(expr) == "tensorflow.linalg.det(M)" + _compare_tensorflow_matrix_scalar((M,), expr) + + expr = Inverse(M) + assert tensorflow_code(expr) == "tensorflow.linalg.inv(M)" + _compare_tensorflow_matrix_inverse((M,), expr, use_float=True) + + expr = M.T + assert tensorflow_code(expr, tensorflow_version='1.14') == \ + "tensorflow.linalg.matrix_transpose(M)" + assert tensorflow_code(expr, tensorflow_version='1.13') == \ + "tensorflow.matrix_transpose(M)" + + _compare_tensorflow_matrix((M,), expr) + + +def test_codegen_einsum(): + if not tf: + skip("TensorFlow not installed") + + graph = tf.Graph() + with graph.as_default(): + session = tf.compat.v1.Session(graph=graph) + + M = MatrixSymbol("M", 2, 2) + N = MatrixSymbol("N", 2, 2) + + cg = convert_matrix_to_array(M * N) + f = lambdify((M, N), cg, 'tensorflow') + + ma = tf.constant([[1, 2], [3, 4]]) + mb = tf.constant([[1,-2], [-1, 3]]) + y = session.run(f(ma, mb)) + c = session.run(tf.matmul(ma, mb)) + assert (y == c).all() + + +def test_codegen_extra(): + if not tf: + skip("TensorFlow not installed") + + graph = tf.Graph() + with graph.as_default(): + session = tf.compat.v1.Session() + + M = MatrixSymbol("M", 2, 2) + N = MatrixSymbol("N", 2, 2) + P = MatrixSymbol("P", 2, 2) + Q = MatrixSymbol("Q", 2, 2) + ma = tf.constant([[1, 2], [3, 4]]) + mb = tf.constant([[1,-2], [-1, 3]]) + mc = tf.constant([[2, 0], [1, 2]]) + md = tf.constant([[1,-1], [4, 7]]) + + cg = ArrayTensorProduct(M, N) + assert tensorflow_code(cg) == \ + 'tensorflow.linalg.einsum("ab,cd", M, N)' + f = lambdify((M, N), cg, 'tensorflow') + y = session.run(f(ma, mb)) + c = session.run(tf.einsum("ij,kl", ma, mb)) + assert (y == c).all() + + cg = ArrayAdd(M, N) + assert tensorflow_code(cg) == 'tensorflow.math.add(M, N)' + f = lambdify((M, N), cg, 'tensorflow') + y = session.run(f(ma, mb)) + c = session.run(ma + mb) + assert (y == c).all() + + cg = ArrayAdd(M, N, P) + assert tensorflow_code(cg) == \ + 'tensorflow.math.add(tensorflow.math.add(M, N), P)' + f = lambdify((M, N, P), cg, 'tensorflow') + y = session.run(f(ma, mb, mc)) + c = session.run(ma + mb + mc) + assert (y == c).all() + + cg = ArrayAdd(M, N, P, Q) + assert tensorflow_code(cg) == \ + 'tensorflow.math.add(' \ + 'tensorflow.math.add(tensorflow.math.add(M, N), P), Q)' + f = lambdify((M, N, P, Q), cg, 'tensorflow') + y = session.run(f(ma, mb, mc, md)) + c = session.run(ma + mb + mc + md) + assert (y == c).all() + + cg = PermuteDims(M, [1, 0]) + assert tensorflow_code(cg) == 'tensorflow.transpose(M, [1, 0])' + f = lambdify((M,), cg, 'tensorflow') + y = session.run(f(ma)) + c = session.run(tf.transpose(ma)) + assert (y == c).all() + + cg = PermuteDims(ArrayTensorProduct(M, N), [1, 2, 3, 0]) + assert tensorflow_code(cg) == \ + 'tensorflow.transpose(' \ + 'tensorflow.linalg.einsum("ab,cd", M, N), [1, 2, 3, 0])' + f = lambdify((M, N), cg, 'tensorflow') + y = session.run(f(ma, mb)) + c = session.run(tf.transpose(tf.einsum("ab,cd", ma, mb), [1, 2, 3, 0])) + assert (y == c).all() + + cg = ArrayDiagonal(ArrayTensorProduct(M, N), (1, 2)) + assert tensorflow_code(cg) == \ + 'tensorflow.linalg.einsum("ab,bc->acb", M, N)' + f = lambdify((M, N), cg, 'tensorflow') + y = session.run(f(ma, mb)) + c = session.run(tf.einsum("ab,bc->acb", ma, mb)) + assert (y == c).all() + + +def test_MatrixElement_printing(): + A = MatrixSymbol("A", 1, 3) + B = MatrixSymbol("B", 1, 3) + C = MatrixSymbol("C", 1, 3) + + assert tensorflow_code(A[0, 0]) == "A[0, 0]" + assert tensorflow_code(3 * A[0, 0]) == "3*A[0, 0]" + + F = C[0, 0].subs(C, A - B) + assert tensorflow_code(F) == "(tensorflow.math.add((-1)*B, A))[0, 0]" + + +def test_tensorflow_Derivative(): + expr = Derivative(sin(x), x) + assert tensorflow_code(expr) == \ + "tensorflow.gradients(tensorflow.math.sin(x), x)[0]" + +def test_tensorflow_isnan_isinf(): + if not tf: + skip("TensorFlow not installed") + + # Test for isnan + x = symbols("x") + # Return 0 if x is of nan value, and 1 otherwise + expression = Piecewise((0.0, isnan(x)), (1.0, True)) + printed_code = tensorflow_code(expression) + expected_printed_code = "tensorflow.where(tensorflow.math.is_nan(x), 0.0, 1.0)" + assert tensorflow_code(expression) == expected_printed_code, f"Incorrect printed result {printed_code}, expected {expected_printed_code}" + for _input, _expected in [(float('nan'), 0.0), (float('inf'), 1.0), (float('-inf'), 1.0), (1.0, 1.0)]: + _output = lambdify((x), expression, modules="tensorflow")(x=tf.constant([_input])) + assert (_output == _expected).numpy().all() + + # Test for isinf + x = symbols("x") + # Return 0 if x is of nan value, and 1 otherwise + expression = Piecewise((0.0, isinf(x)), (1.0, True)) + printed_code = tensorflow_code(expression) + expected_printed_code = "tensorflow.where(tensorflow.math.is_inf(x), 0.0, 1.0)" + assert tensorflow_code(expression) == expected_printed_code, f"Incorrect printed result {printed_code}, expected {expected_printed_code}" + for _input, _expected in [(float('inf'), 0.0), (float('-inf'), 0.0), (float('nan'), 1.0), (1.0, 1.0)]: + _output = lambdify((x), expression, modules="tensorflow")(x=tf.constant([_input])) + assert (_output == _expected).numpy().all() diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_theanocode.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_theanocode.py new file mode 100644 index 0000000000000000000000000000000000000000..6ff40f78cb4de16149cb5e780756b7e32b574b71 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_theanocode.py @@ -0,0 +1,639 @@ +""" +Important note on tests in this module - the Theano printing functions use a +global cache by default, which means that tests using it will modify global +state and thus not be independent from each other. Instead of using the "cache" +keyword argument each time, this module uses the theano_code_ and +theano_function_ functions defined below which default to using a new, empty +cache instead. +""" + +import logging + +from sympy.external import import_module +from sympy.testing.pytest import raises, SKIP, warns_deprecated_sympy + +theanologger = logging.getLogger('theano.configdefaults') +theanologger.setLevel(logging.CRITICAL) +theano = import_module('theano') +theanologger.setLevel(logging.WARNING) + + +if theano: + import numpy as np + ts = theano.scalar + tt = theano.tensor + xt, yt, zt = [tt.scalar(name, 'floatX') for name in 'xyz'] + Xt, Yt, Zt = [tt.tensor('floatX', (False, False), name=n) for n in 'XYZ'] +else: + #bin/test will not execute any tests now + disabled = True + +import sympy as sy +from sympy.core.singleton import S +from sympy.abc import x, y, z, t +from sympy.printing.theanocode import (theano_code, dim_handling, + theano_function) + + +# Default set of matrix symbols for testing - make square so we can both +# multiply and perform elementwise operations between them. +X, Y, Z = [sy.MatrixSymbol(n, 4, 4) for n in 'XYZ'] + +# For testing AppliedUndef +f_t = sy.Function('f')(t) + + +def theano_code_(expr, **kwargs): + """ Wrapper for theano_code that uses a new, empty cache by default. """ + kwargs.setdefault('cache', {}) + with warns_deprecated_sympy(): + return theano_code(expr, **kwargs) + +def theano_function_(inputs, outputs, **kwargs): + """ Wrapper for theano_function that uses a new, empty cache by default. """ + kwargs.setdefault('cache', {}) + with warns_deprecated_sympy(): + return theano_function(inputs, outputs, **kwargs) + + +def fgraph_of(*exprs): + """ Transform SymPy expressions into Theano Computation. + + Parameters + ========== + exprs + SymPy expressions + + Returns + ======= + theano.gof.FunctionGraph + """ + outs = list(map(theano_code_, exprs)) + ins = theano.gof.graph.inputs(outs) + ins, outs = theano.gof.graph.clone(ins, outs) + return theano.gof.FunctionGraph(ins, outs) + + +def theano_simplify(fgraph): + """ Simplify a Theano Computation. + + Parameters + ========== + fgraph : theano.gof.FunctionGraph + + Returns + ======= + theano.gof.FunctionGraph + """ + mode = theano.compile.get_default_mode().excluding("fusion") + fgraph = fgraph.clone() + mode.optimizer.optimize(fgraph) + return fgraph + + +def theq(a, b): + """ Test two Theano objects for equality. + + Also accepts numeric types and lists/tuples of supported types. + + Note - debugprint() has a bug where it will accept numeric types but does + not respect the "file" argument and in this case and instead prints the number + to stdout and returns an empty string. This can lead to tests passing where + they should fail because any two numbers will always compare as equal. To + prevent this we treat numbers as a separate case. + """ + numeric_types = (int, float, np.number) + a_is_num = isinstance(a, numeric_types) + b_is_num = isinstance(b, numeric_types) + + # Compare numeric types using regular equality + if a_is_num or b_is_num: + if not (a_is_num and b_is_num): + return False + + return a == b + + # Compare sequences element-wise + a_is_seq = isinstance(a, (tuple, list)) + b_is_seq = isinstance(b, (tuple, list)) + + if a_is_seq or b_is_seq: + if not (a_is_seq and b_is_seq) or type(a) != type(b): + return False + + return list(map(theq, a)) == list(map(theq, b)) + + # Otherwise, assume debugprint() can handle it + astr = theano.printing.debugprint(a, file='str') + bstr = theano.printing.debugprint(b, file='str') + + # Check for bug mentioned above + for argname, argval, argstr in [('a', a, astr), ('b', b, bstr)]: + if argstr == '': + raise TypeError( + 'theano.printing.debugprint(%s) returned empty string ' + '(%s is instance of %r)' + % (argname, argname, type(argval)) + ) + + return astr == bstr + + +def test_example_symbols(): + """ + Check that the example symbols in this module print to their Theano + equivalents, as many of the other tests depend on this. + """ + assert theq(xt, theano_code_(x)) + assert theq(yt, theano_code_(y)) + assert theq(zt, theano_code_(z)) + assert theq(Xt, theano_code_(X)) + assert theq(Yt, theano_code_(Y)) + assert theq(Zt, theano_code_(Z)) + + +def test_Symbol(): + """ Test printing a Symbol to a theano variable. """ + xx = theano_code_(x) + assert isinstance(xx, (tt.TensorVariable, ts.ScalarVariable)) + assert xx.broadcastable == () + assert xx.name == x.name + + xx2 = theano_code_(x, broadcastables={x: (False,)}) + assert xx2.broadcastable == (False,) + assert xx2.name == x.name + +def test_MatrixSymbol(): + """ Test printing a MatrixSymbol to a theano variable. """ + XX = theano_code_(X) + assert isinstance(XX, tt.TensorVariable) + assert XX.broadcastable == (False, False) + +@SKIP # TODO - this is currently not checked but should be implemented +def test_MatrixSymbol_wrong_dims(): + """ Test MatrixSymbol with invalid broadcastable. """ + bcs = [(), (False,), (True,), (True, False), (False, True,), (True, True)] + for bc in bcs: + with raises(ValueError): + theano_code_(X, broadcastables={X: bc}) + +def test_AppliedUndef(): + """ Test printing AppliedUndef instance, which works similarly to Symbol. """ + ftt = theano_code_(f_t) + assert isinstance(ftt, tt.TensorVariable) + assert ftt.broadcastable == () + assert ftt.name == 'f_t' + + +def test_add(): + expr = x + y + comp = theano_code_(expr) + assert comp.owner.op == theano.tensor.add + +def test_trig(): + assert theq(theano_code_(sy.sin(x)), tt.sin(xt)) + assert theq(theano_code_(sy.tan(x)), tt.tan(xt)) + +def test_many(): + """ Test printing a complex expression with multiple symbols. """ + expr = sy.exp(x**2 + sy.cos(y)) * sy.log(2*z) + comp = theano_code_(expr) + expected = tt.exp(xt**2 + tt.cos(yt)) * tt.log(2*zt) + assert theq(comp, expected) + + +def test_dtype(): + """ Test specifying specific data types through the dtype argument. """ + for dtype in ['float32', 'float64', 'int8', 'int16', 'int32', 'int64']: + assert theano_code_(x, dtypes={x: dtype}).type.dtype == dtype + + # "floatX" type + assert theano_code_(x, dtypes={x: 'floatX'}).type.dtype in ('float32', 'float64') + + # Type promotion + assert theano_code_(x + 1, dtypes={x: 'float32'}).type.dtype == 'float32' + assert theano_code_(x + y, dtypes={x: 'float64', y: 'float32'}).type.dtype == 'float64' + + +def test_broadcastables(): + """ Test the "broadcastables" argument when printing symbol-like objects. """ + + # No restrictions on shape + for s in [x, f_t]: + for bc in [(), (False,), (True,), (False, False), (True, False)]: + assert theano_code_(s, broadcastables={s: bc}).broadcastable == bc + + # TODO - matrix broadcasting? + +def test_broadcasting(): + """ Test "broadcastable" attribute after applying element-wise binary op. """ + + expr = x + y + + cases = [ + [(), (), ()], + [(False,), (False,), (False,)], + [(True,), (False,), (False,)], + [(False, True), (False, False), (False, False)], + [(True, False), (False, False), (False, False)], + ] + + for bc1, bc2, bc3 in cases: + comp = theano_code_(expr, broadcastables={x: bc1, y: bc2}) + assert comp.broadcastable == bc3 + + +def test_MatMul(): + expr = X*Y*Z + expr_t = theano_code_(expr) + assert isinstance(expr_t.owner.op, tt.Dot) + assert theq(expr_t, Xt.dot(Yt).dot(Zt)) + +def test_Transpose(): + assert isinstance(theano_code_(X.T).owner.op, tt.DimShuffle) + +def test_MatAdd(): + expr = X+Y+Z + assert isinstance(theano_code_(expr).owner.op, tt.Elemwise) + + +def test_Rationals(): + assert theq(theano_code_(sy.Integer(2) / 3), tt.true_div(2, 3)) + assert theq(theano_code_(S.Half), tt.true_div(1, 2)) + +def test_Integers(): + assert theano_code_(sy.Integer(3)) == 3 + +def test_factorial(): + n = sy.Symbol('n') + assert theano_code_(sy.factorial(n)) + +def test_Derivative(): + simp = lambda expr: theano_simplify(fgraph_of(expr)) + assert theq(simp(theano_code_(sy.Derivative(sy.sin(x), x, evaluate=False))), + simp(theano.grad(tt.sin(xt), xt))) + + +def test_theano_function_simple(): + """ Test theano_function() with single output. """ + f = theano_function_([x, y], [x+y]) + assert f(2, 3) == 5 + +def test_theano_function_multi(): + """ Test theano_function() with multiple outputs. """ + f = theano_function_([x, y], [x+y, x-y]) + o1, o2 = f(2, 3) + assert o1 == 5 + assert o2 == -1 + +def test_theano_function_numpy(): + """ Test theano_function() vs Numpy implementation. """ + f = theano_function_([x, y], [x+y], dim=1, + dtypes={x: 'float64', y: 'float64'}) + assert np.linalg.norm(f([1, 2], [3, 4]) - np.asarray([4, 6])) < 1e-9 + + f = theano_function_([x, y], [x+y], dtypes={x: 'float64', y: 'float64'}, + dim=1) + xx = np.arange(3).astype('float64') + yy = 2*np.arange(3).astype('float64') + assert np.linalg.norm(f(xx, yy) - 3*np.arange(3)) < 1e-9 + + +def test_theano_function_matrix(): + m = sy.Matrix([[x, y], [z, x + y + z]]) + expected = np.array([[1.0, 2.0], [3.0, 1.0 + 2.0 + 3.0]]) + f = theano_function_([x, y, z], [m]) + np.testing.assert_allclose(f(1.0, 2.0, 3.0), expected) + f = theano_function_([x, y, z], [m], scalar=True) + np.testing.assert_allclose(f(1.0, 2.0, 3.0), expected) + f = theano_function_([x, y, z], [m, m]) + assert isinstance(f(1.0, 2.0, 3.0), type([])) + np.testing.assert_allclose(f(1.0, 2.0, 3.0)[0], expected) + np.testing.assert_allclose(f(1.0, 2.0, 3.0)[1], expected) + +def test_dim_handling(): + assert dim_handling([x], dim=2) == {x: (False, False)} + assert dim_handling([x, y], dims={x: 1, y: 2}) == {x: (False, True), + y: (False, False)} + assert dim_handling([x], broadcastables={x: (False,)}) == {x: (False,)} + +def test_theano_function_kwargs(): + """ + Test passing additional kwargs from theano_function() to theano.function(). + """ + import numpy as np + f = theano_function_([x, y, z], [x+y], dim=1, on_unused_input='ignore', + dtypes={x: 'float64', y: 'float64', z: 'float64'}) + assert np.linalg.norm(f([1, 2], [3, 4], [0, 0]) - np.asarray([4, 6])) < 1e-9 + + f = theano_function_([x, y, z], [x+y], + dtypes={x: 'float64', y: 'float64', z: 'float64'}, + dim=1, on_unused_input='ignore') + xx = np.arange(3).astype('float64') + yy = 2*np.arange(3).astype('float64') + zz = 2*np.arange(3).astype('float64') + assert np.linalg.norm(f(xx, yy, zz) - 3*np.arange(3)) < 1e-9 + +def test_theano_function_scalar(): + """ Test the "scalar" argument to theano_function(). """ + + args = [ + ([x, y], [x + y], None, [0]), # Single 0d output + ([X, Y], [X + Y], None, [2]), # Single 2d output + ([x, y], [x + y], {x: 0, y: 1}, [1]), # Single 1d output + ([x, y], [x + y, x - y], None, [0, 0]), # Two 0d outputs + ([x, y, X, Y], [x + y, X + Y], None, [0, 2]), # One 0d output, one 2d + ] + + # Create and test functions with and without the scalar setting + for inputs, outputs, in_dims, out_dims in args: + for scalar in [False, True]: + + f = theano_function_(inputs, outputs, dims=in_dims, scalar=scalar) + + # Check the theano_function attribute is set whether wrapped or not + assert isinstance(f.theano_function, theano.compile.function_module.Function) + + # Feed in inputs of the appropriate size and get outputs + in_values = [ + np.ones([1 if bc else 5 for bc in i.type.broadcastable]) + for i in f.theano_function.input_storage + ] + out_values = f(*in_values) + if not isinstance(out_values, list): + out_values = [out_values] + + # Check output types and shapes + assert len(out_dims) == len(out_values) + for d, value in zip(out_dims, out_values): + + if scalar and d == 0: + # Should have been converted to a scalar value + assert isinstance(value, np.number) + + else: + # Otherwise should be an array + assert isinstance(value, np.ndarray) + assert value.ndim == d + +def test_theano_function_bad_kwarg(): + """ + Passing an unknown keyword argument to theano_function() should raise an + exception. + """ + raises(Exception, lambda : theano_function_([x], [x+1], foobar=3)) + + +def test_slice(): + assert theano_code_(slice(1, 2, 3)) == slice(1, 2, 3) + + def theq_slice(s1, s2): + for attr in ['start', 'stop', 'step']: + a1 = getattr(s1, attr) + a2 = getattr(s2, attr) + if a1 is None or a2 is None: + if not (a1 is None or a2 is None): + return False + elif not theq(a1, a2): + return False + return True + + dtypes = {x: 'int32', y: 'int32'} + assert theq_slice(theano_code_(slice(x, y), dtypes=dtypes), slice(xt, yt)) + assert theq_slice(theano_code_(slice(1, x, 3), dtypes=dtypes), slice(1, xt, 3)) + +def test_MatrixSlice(): + from theano import Constant + + cache = {} + + n = sy.Symbol('n', integer=True) + X = sy.MatrixSymbol('X', n, n) + + Y = X[1:2:3, 4:5:6] + Yt = theano_code_(Y, cache=cache) + + s = ts.Scalar('int64') + assert tuple(Yt.owner.op.idx_list) == (slice(s, s, s), slice(s, s, s)) + assert Yt.owner.inputs[0] == theano_code_(X, cache=cache) + # == doesn't work in theano like it does in SymPy. You have to use + # equals. + assert all(Yt.owner.inputs[i].equals(Constant(s, i)) for i in range(1, 7)) + + k = sy.Symbol('k') + theano_code_(k, dtypes={k: 'int32'}) + start, stop, step = 4, k, 2 + Y = X[start:stop:step] + Yt = theano_code_(Y, dtypes={n: 'int32', k: 'int32'}) + # assert Yt.owner.op.idx_list[0].stop == kt + +def test_BlockMatrix(): + n = sy.Symbol('n', integer=True) + A, B, C, D = [sy.MatrixSymbol(name, n, n) for name in 'ABCD'] + At, Bt, Ct, Dt = map(theano_code_, (A, B, C, D)) + Block = sy.BlockMatrix([[A, B], [C, D]]) + Blockt = theano_code_(Block) + solutions = [tt.join(0, tt.join(1, At, Bt), tt.join(1, Ct, Dt)), + tt.join(1, tt.join(0, At, Ct), tt.join(0, Bt, Dt))] + assert any(theq(Blockt, solution) for solution in solutions) + +@SKIP +def test_BlockMatrix_Inverse_execution(): + k, n = 2, 4 + dtype = 'float32' + A = sy.MatrixSymbol('A', n, k) + B = sy.MatrixSymbol('B', n, n) + inputs = A, B + output = B.I*A + + cutsizes = {A: [(n//2, n//2), (k//2, k//2)], + B: [(n//2, n//2), (n//2, n//2)]} + cutinputs = [sy.blockcut(i, *cutsizes[i]) for i in inputs] + cutoutput = output.subs(dict(zip(inputs, cutinputs))) + + dtypes = dict(zip(inputs, [dtype]*len(inputs))) + f = theano_function_(inputs, [output], dtypes=dtypes, cache={}) + fblocked = theano_function_(inputs, [sy.block_collapse(cutoutput)], + dtypes=dtypes, cache={}) + + ninputs = [np.random.rand(*x.shape).astype(dtype) for x in inputs] + ninputs = [np.arange(n*k).reshape(A.shape).astype(dtype), + np.eye(n).astype(dtype)] + ninputs[1] += np.ones(B.shape)*1e-5 + + assert np.allclose(f(*ninputs), fblocked(*ninputs), rtol=1e-5) + +def test_DenseMatrix(): + t = sy.Symbol('theta') + for MatrixType in [sy.Matrix, sy.ImmutableMatrix]: + X = MatrixType([[sy.cos(t), -sy.sin(t)], [sy.sin(t), sy.cos(t)]]) + tX = theano_code_(X) + assert isinstance(tX, tt.TensorVariable) + assert tX.owner.op == tt.join_ + + +def test_cache_basic(): + """ Test single symbol-like objects are cached when printed by themselves. """ + + # Pairs of objects which should be considered equivalent with respect to caching + pairs = [ + (x, sy.Symbol('x')), + (X, sy.MatrixSymbol('X', *X.shape)), + (f_t, sy.Function('f')(sy.Symbol('t'))), + ] + + for s1, s2 in pairs: + cache = {} + st = theano_code_(s1, cache=cache) + + # Test hit with same instance + assert theano_code_(s1, cache=cache) is st + + # Test miss with same instance but new cache + assert theano_code_(s1, cache={}) is not st + + # Test hit with different but equivalent instance + assert theano_code_(s2, cache=cache) is st + +def test_global_cache(): + """ Test use of the global cache. """ + from sympy.printing.theanocode import global_cache + + backup = dict(global_cache) + try: + # Temporarily empty global cache + global_cache.clear() + + for s in [x, X, f_t]: + with warns_deprecated_sympy(): + st = theano_code(s) + assert theano_code(s) is st + + finally: + # Restore global cache + global_cache.update(backup) + +def test_cache_types_distinct(): + """ + Test that symbol-like objects of different types (Symbol, MatrixSymbol, + AppliedUndef) are distinguished by the cache even if they have the same + name. + """ + symbols = [sy.Symbol('f_t'), sy.MatrixSymbol('f_t', 4, 4), f_t] + + cache = {} # Single shared cache + printed = {} + + for s in symbols: + st = theano_code_(s, cache=cache) + assert st not in printed.values() + printed[s] = st + + # Check all printed objects are distinct + assert len(set(map(id, printed.values()))) == len(symbols) + + # Check retrieving + for s, st in printed.items(): + with warns_deprecated_sympy(): + assert theano_code(s, cache=cache) is st + +def test_symbols_are_created_once(): + """ + Test that a symbol is cached and reused when it appears in an expression + more than once. + """ + expr = sy.Add(x, x, evaluate=False) + comp = theano_code_(expr) + + assert theq(comp, xt + xt) + assert not theq(comp, xt + theano_code_(x)) + +def test_cache_complex(): + """ + Test caching on a complicated expression with multiple symbols appearing + multiple times. + """ + expr = x ** 2 + (y - sy.exp(x)) * sy.sin(z - x * y) + symbol_names = {s.name for s in expr.free_symbols} + expr_t = theano_code_(expr) + + # Iterate through variables in the Theano computational graph that the + # printed expression depends on + seen = set() + for v in theano.gof.graph.ancestors([expr_t]): + # Owner-less, non-constant variables should be our symbols + if v.owner is None and not isinstance(v, theano.gof.graph.Constant): + # Check it corresponds to a symbol and appears only once + assert v.name in symbol_names + assert v.name not in seen + seen.add(v.name) + + # Check all were present + assert seen == symbol_names + + +def test_Piecewise(): + # A piecewise linear + expr = sy.Piecewise((0, x<0), (x, x<2), (1, True)) # ___/III + result = theano_code_(expr) + assert result.owner.op == tt.switch + + expected = tt.switch(xt<0, 0, tt.switch(xt<2, xt, 1)) + assert theq(result, expected) + + expr = sy.Piecewise((x, x < 0)) + result = theano_code_(expr) + expected = tt.switch(xt < 0, xt, np.nan) + assert theq(result, expected) + + expr = sy.Piecewise((0, sy.And(x>0, x<2)), \ + (x, sy.Or(x>2, x<0))) + result = theano_code_(expr) + expected = tt.switch(tt.and_(xt>0,xt<2), 0, \ + tt.switch(tt.or_(xt>2, xt<0), xt, np.nan)) + assert theq(result, expected) + + +def test_Relationals(): + assert theq(theano_code_(sy.Eq(x, y)), tt.eq(xt, yt)) + # assert theq(theano_code_(sy.Ne(x, y)), tt.neq(xt, yt)) # TODO - implement + assert theq(theano_code_(x > y), xt > yt) + assert theq(theano_code_(x < y), xt < yt) + assert theq(theano_code_(x >= y), xt >= yt) + assert theq(theano_code_(x <= y), xt <= yt) + + +def test_complexfunctions(): + with warns_deprecated_sympy(): + xt, yt = theano_code_(x, dtypes={x:'complex128'}), theano_code_(y, dtypes={y: 'complex128'}) + from sympy.functions.elementary.complexes import conjugate + from theano.tensor import as_tensor_variable as atv + from theano.tensor import complex as cplx + with warns_deprecated_sympy(): + assert theq(theano_code_(y*conjugate(x)), yt*(xt.conj())) + assert theq(theano_code_((1+2j)*x), xt*(atv(1.0)+atv(2.0)*cplx(0,1))) + + +def test_constantfunctions(): + with warns_deprecated_sympy(): + tf = theano_function_([],[1+1j]) + assert(tf()==1+1j) + + +def test_Exp1(): + """ + Test that exp(1) prints without error and evaluates close to SymPy's E + """ + # sy.exp(1) should yield same instance of E as sy.E (singleton), but extra + # check added for sanity + e_a = sy.exp(1) + e_b = sy.E + + np.testing.assert_allclose(float(e_a), np.e) + np.testing.assert_allclose(float(e_b), np.e) + + e = theano_code_(e_a) + np.testing.assert_allclose(float(e_a), e.eval()) + + e = theano_code_(e_b) + np.testing.assert_allclose(float(e_b), e.eval()) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_torch.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_torch.py new file mode 100644 index 0000000000000000000000000000000000000000..8ce2c6cec75e03264f93b472a79eb073742e3486 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_torch.py @@ -0,0 +1,531 @@ +import random +import math + +from sympy import symbols, Derivative +from sympy.printing.pytorch import torch_code +from sympy import (eye, MatrixSymbol, Matrix) +from sympy.tensor.array import NDimArray +from sympy.tensor.array.expressions.array_expressions import ( + ArrayTensorProduct, ArrayAdd, + PermuteDims, ArrayDiagonal, _CodegenArrayAbstract) +from sympy.utilities.lambdify import lambdify +from sympy.core.relational import Eq, Ne, Ge, Gt, Le, Lt +from sympy.functions import \ + Abs, ceiling, exp, floor, sign, sin, asin, cos, \ + acos, tan, atan, atan2, cosh, acosh, sinh, asinh, tanh, atanh, \ + re, im, arg, erf, loggamma, sqrt +from sympy.testing.pytest import skip +from sympy.external import import_module +from sympy.matrices.expressions import \ + Determinant, HadamardProduct, Inverse, Trace +from sympy.matrices import randMatrix +from sympy.matrices import Identity, ZeroMatrix, OneMatrix +from sympy import conjugate, I +from sympy import Heaviside, gamma, polygamma + + + +torch = import_module("torch") + +M = MatrixSymbol("M", 3, 3) +N = MatrixSymbol("N", 3, 3) +P = MatrixSymbol("P", 3, 3) +Q = MatrixSymbol("Q", 3, 3) + +x, y, z, t = symbols("x y z t") + +if torch is not None: + llo = [list(range(i, i + 3)) for i in range(0, 9, 3)] + m3x3 = torch.tensor(llo, dtype=torch.float64) + m3x3sympy = Matrix(llo) + + +def _compare_torch_matrix(variables, expr): + f = lambdify(variables, expr, 'torch') + + random_matrices = [randMatrix(i.shape[0], i.shape[1]) for i in variables] + random_variables = [torch.tensor(i.tolist(), dtype=torch.float64) for i in random_matrices] + r = f(*random_variables) + e = expr.subs(dict(zip(variables, random_matrices))).doit() + + if isinstance(e, _CodegenArrayAbstract): + e = e.doit() + + if hasattr(e, 'is_number') and e.is_number: + if isinstance(r, torch.Tensor) and r.dim() == 0: + r = r.item() + e = float(e) + assert abs(r - e) < 1e-6 + return + + if e.is_Matrix or isinstance(e, NDimArray): + e = torch.tensor(e.tolist(), dtype=torch.float64) + assert torch.allclose(r, e, atol=1e-6) + else: + raise TypeError(f"Cannot compare {type(r)} with {type(e)}") + + +def _compare_torch_scalar(variables, expr, rng=lambda: random.uniform(-5, 5)): + f = lambdify(variables, expr, 'torch') + rvs = [rng() for v in variables] + t_rvs = [torch.tensor(i, dtype=torch.float64) for i in rvs] + r = f(*t_rvs) + if isinstance(r, torch.Tensor): + r = r.item() + e = expr.subs(dict(zip(variables, rvs))).doit() + assert abs(r - e) < 1e-6 + + +def _compare_torch_relational(variables, expr, rng=lambda: random.randint(0, 10)): + f = lambdify(variables, expr, 'torch') + rvs = [rng() for v in variables] + t_rvs = [torch.tensor(i, dtype=torch.float64) for i in rvs] + r = f(*t_rvs) + e = bool(expr.subs(dict(zip(variables, rvs))).doit()) + assert r.item() == e + + +def test_torch_math(): + if not torch: + skip("PyTorch not installed") + + expr = Abs(x) + assert torch_code(expr) == "torch.abs(x)" + f = lambdify(x, expr, 'torch') + ma = torch.tensor([[-1, 2, -3, -4]], dtype=torch.float64) + y_abs = f(ma) + c = torch.abs(ma) + assert torch.all(y_abs == c) + + expr = sign(x) + assert torch_code(expr) == "torch.sign(x)" + _compare_torch_scalar((x,), expr, rng=lambda: random.uniform(-10, 10)) + + expr = ceiling(x) + assert torch_code(expr) == "torch.ceil(x)" + _compare_torch_scalar((x,), expr, rng=lambda: random.random()) + + expr = floor(x) + assert torch_code(expr) == "torch.floor(x)" + _compare_torch_scalar((x,), expr, rng=lambda: random.random()) + + expr = exp(x) + assert torch_code(expr) == "torch.exp(x)" + _compare_torch_scalar((x,), expr, rng=lambda: random.uniform(-2, 2)) + + expr = sqrt(x) + assert torch_code(expr) == "torch.sqrt(x)" + _compare_torch_scalar((x,), expr, rng=lambda: random.random()) + + expr = x ** 4 + assert torch_code(expr) == "torch.pow(x, 4)" + _compare_torch_scalar((x,), expr, rng=lambda: random.random()) + + expr = cos(x) + assert torch_code(expr) == "torch.cos(x)" + _compare_torch_scalar((x,), expr, rng=lambda: random.random()) + + expr = acos(x) + assert torch_code(expr) == "torch.acos(x)" + _compare_torch_scalar((x,), expr, rng=lambda: random.uniform(-0.99, 0.99)) + + expr = sin(x) + assert torch_code(expr) == "torch.sin(x)" + _compare_torch_scalar((x,), expr, rng=lambda: random.random()) + + expr = asin(x) + assert torch_code(expr) == "torch.asin(x)" + _compare_torch_scalar((x,), expr, rng=lambda: random.uniform(-0.99, 0.99)) + + expr = tan(x) + assert torch_code(expr) == "torch.tan(x)" + _compare_torch_scalar((x,), expr, rng=lambda: random.uniform(-1.5, 1.5)) + + expr = atan(x) + assert torch_code(expr) == "torch.atan(x)" + _compare_torch_scalar((x,), expr, rng=lambda: random.uniform(-5, 5)) + + expr = atan2(y, x) + assert torch_code(expr) == "torch.atan2(y, x)" + _compare_torch_scalar((y, x), expr, rng=lambda: random.uniform(-5, 5)) + + expr = cosh(x) + assert torch_code(expr) == "torch.cosh(x)" + _compare_torch_scalar((x,), expr, rng=lambda: random.uniform(-2, 2)) + + expr = acosh(x) + assert torch_code(expr) == "torch.acosh(x)" + _compare_torch_scalar((x,), expr, rng=lambda: random.uniform(1.1, 5)) + + expr = sinh(x) + assert torch_code(expr) == "torch.sinh(x)" + _compare_torch_scalar((x,), expr, rng=lambda: random.uniform(-2, 2)) + + expr = asinh(x) + assert torch_code(expr) == "torch.asinh(x)" + _compare_torch_scalar((x,), expr, rng=lambda: random.uniform(-5, 5)) + + expr = tanh(x) + assert torch_code(expr) == "torch.tanh(x)" + _compare_torch_scalar((x,), expr, rng=lambda: random.uniform(-2, 2)) + + expr = atanh(x) + assert torch_code(expr) == "torch.atanh(x)" + _compare_torch_scalar((x,), expr, rng=lambda: random.uniform(-0.9, 0.9)) + + expr = erf(x) + assert torch_code(expr) == "torch.erf(x)" + _compare_torch_scalar((x,), expr, rng=lambda: random.uniform(-2, 2)) + + expr = loggamma(x) + assert torch_code(expr) == "torch.lgamma(x)" + _compare_torch_scalar((x,), expr, rng=lambda: random.uniform(0.5, 5)) + + +def test_torch_complexes(): + assert torch_code(re(x)) == "torch.real(x)" + assert torch_code(im(x)) == "torch.imag(x)" + assert torch_code(arg(x)) == "torch.angle(x)" + + +def test_torch_relational(): + if not torch: + skip("PyTorch not installed") + + expr = Eq(x, y) + assert torch_code(expr) == "torch.eq(x, y)" + _compare_torch_relational((x, y), expr) + + expr = Ne(x, y) + assert torch_code(expr) == "torch.ne(x, y)" + _compare_torch_relational((x, y), expr) + + expr = Ge(x, y) + assert torch_code(expr) == "torch.ge(x, y)" + _compare_torch_relational((x, y), expr) + + expr = Gt(x, y) + assert torch_code(expr) == "torch.gt(x, y)" + _compare_torch_relational((x, y), expr) + + expr = Le(x, y) + assert torch_code(expr) == "torch.le(x, y)" + _compare_torch_relational((x, y), expr) + + expr = Lt(x, y) + assert torch_code(expr) == "torch.lt(x, y)" + _compare_torch_relational((x, y), expr) + + +def test_torch_matrix(): + if torch is None: + skip("PyTorch not installed") + + expr = M + assert torch_code(expr) == "M" + f = lambdify((M,), expr, "torch") + eye_mat = eye(3) + eye_tensor = torch.tensor(eye_mat.tolist(), dtype=torch.float64) + assert torch.allclose(f(eye_tensor), eye_tensor) + + expr = M * N + assert torch_code(expr) == "torch.matmul(M, N)" + _compare_torch_matrix((M, N), expr) + + expr = M ** 3 + assert torch_code(expr) == "torch.mm(torch.mm(M, M), M)" + _compare_torch_matrix((M,), expr) + + expr = M * N * P * Q + assert torch_code(expr) == "torch.matmul(torch.matmul(torch.matmul(M, N), P), Q)" + _compare_torch_matrix((M, N, P, Q), expr) + + expr = Trace(M) + assert torch_code(expr) == "torch.trace(M)" + _compare_torch_matrix((M,), expr) + + expr = Determinant(M) + assert torch_code(expr) == "torch.det(M)" + _compare_torch_matrix((M,), expr) + + expr = HadamardProduct(M, N) + assert torch_code(expr) == "torch.mul(M, N)" + _compare_torch_matrix((M, N), expr) + + expr = Inverse(M) + assert torch_code(expr) == "torch.linalg.inv(M)" + + # For inverse, use a matrix that's guaranteed to be invertible + eye_mat = eye(3) + eye_tensor = torch.tensor(eye_mat.tolist(), dtype=torch.float64) + f = lambdify((M,), expr, "torch") + result = f(eye_tensor) + expected = torch.linalg.inv(eye_tensor) + assert torch.allclose(result, expected) + + +def test_torch_array_operations(): + if not torch: + skip("PyTorch not installed") + + M = MatrixSymbol("M", 2, 2) + N = MatrixSymbol("N", 2, 2) + P = MatrixSymbol("P", 2, 2) + Q = MatrixSymbol("Q", 2, 2) + + ma = torch.tensor([[1., 2.], [3., 4.]], dtype=torch.float64) + mb = torch.tensor([[1., -2.], [-1., 3.]], dtype=torch.float64) + mc = torch.tensor([[2., 0.], [1., 2.]], dtype=torch.float64) + md = torch.tensor([[1., -1.], [4., 7.]], dtype=torch.float64) + + cg = ArrayTensorProduct(M, N) + assert torch_code(cg) == 'torch.einsum("ab,cd", M, N)' + f = lambdify((M, N), cg, 'torch') + y = f(ma, mb) + c = torch.einsum("ij,kl", ma, mb) + assert torch.allclose(y, c) + + cg = ArrayAdd(M, N) + assert torch_code(cg) == 'torch.add(M, N)' + f = lambdify((M, N), cg, 'torch') + y = f(ma, mb) + c = ma + mb + assert torch.allclose(y, c) + + cg = ArrayAdd(M, N, P) + assert torch_code(cg) == 'torch.add(torch.add(M, N), P)' + f = lambdify((M, N, P), cg, 'torch') + y = f(ma, mb, mc) + c = ma + mb + mc + assert torch.allclose(y, c) + + cg = ArrayAdd(M, N, P, Q) + assert torch_code(cg) == 'torch.add(torch.add(torch.add(M, N), P), Q)' + f = lambdify((M, N, P, Q), cg, 'torch') + y = f(ma, mb, mc, md) + c = ma + mb + mc + md + assert torch.allclose(y, c) + + cg = PermuteDims(M, [1, 0]) + assert torch_code(cg) == 'M.permute(1, 0)' + f = lambdify((M,), cg, 'torch') + y = f(ma) + c = ma.T + assert torch.allclose(y, c) + + cg = PermuteDims(ArrayTensorProduct(M, N), [1, 2, 3, 0]) + assert torch_code(cg) == 'torch.einsum("ab,cd", M, N).permute(1, 2, 3, 0)' + f = lambdify((M, N), cg, 'torch') + y = f(ma, mb) + c = torch.einsum("ab,cd", ma, mb).permute(1, 2, 3, 0) + assert torch.allclose(y, c) + + cg = ArrayDiagonal(ArrayTensorProduct(M, N), (1, 2)) + assert torch_code(cg) == 'torch.einsum("ab,bc->acb", M, N)' + f = lambdify((M, N), cg, 'torch') + y = f(ma, mb) + c = torch.einsum("ab,bc->acb", ma, mb) + assert torch.allclose(y, c) + + +def test_torch_derivative(): + """Test derivative handling.""" + expr = Derivative(sin(x), x) + assert torch_code(expr) == 'torch.autograd.grad(torch.sin(x), x)[0]' + + +def test_torch_printing_dtype(): + if not torch: + skip("PyTorch not installed") + + # matrix printing with default dtype + expr = Matrix([[x, sin(y)], [exp(z), -t]]) + assert "dtype=torch.float64" in torch_code(expr) + + # explicit dtype + assert "dtype=torch.float32" in torch_code(expr, dtype="torch.float32") + + # with requires_grad + result = torch_code(expr, requires_grad=True) + assert "requires_grad=True" in result + assert "dtype=torch.float64" in result + + # both + result = torch_code(expr, requires_grad=True, dtype="torch.float32") + assert "requires_grad=True" in result + assert "dtype=torch.float32" in result + + +def test_requires_grad(): + if not torch: + skip("PyTorch not installed") + + expr = sin(x) + cos(y) + f = lambdify([x, y], expr, 'torch') + + # make sure the gradients flow + x_val = torch.tensor(1.0, requires_grad=True) + y_val = torch.tensor(2.0, requires_grad=True) + result = f(x_val, y_val) + assert result.requires_grad + result.backward() + + # x_val.grad should be cos(x_val) which is close to cos(1.0) + assert abs(x_val.grad.item() - float(cos(1.0).evalf())) < 1e-6 + + # y_val.grad should be -sin(y_val) which is close to -sin(2.0) + assert abs(y_val.grad.item() - float(-sin(2.0).evalf())) < 1e-6 + + +def test_torch_multi_variable_derivatives(): + if not torch: + skip("PyTorch not installed") + + x, y, z = symbols("x y z") + + expr = Derivative(sin(x), x) + assert torch_code(expr) == "torch.autograd.grad(torch.sin(x), x)[0]" + + expr = Derivative(sin(x), (x, 2)) + assert torch_code( + expr) == "torch.autograd.grad(torch.autograd.grad(torch.sin(x), x, create_graph=True)[0], x, create_graph=True)[0]" + + expr = Derivative(sin(x * y), x, y) + result = torch_code(expr) + expected = "torch.autograd.grad(torch.autograd.grad(torch.sin(x*y), x, create_graph=True)[0], y, create_graph=True)[0]" + normalized_result = result.replace(" ", "") + normalized_expected = expected.replace(" ", "") + assert normalized_result == normalized_expected + + expr = Derivative(sin(x), x, x) + result = torch_code(expr) + expected = "torch.autograd.grad(torch.autograd.grad(torch.sin(x), x, create_graph=True)[0], x, create_graph=True)[0]" + assert result == expected + + expr = Derivative(sin(x * y * z), x, (y, 2), z) + result = torch_code(expr) + expected = "torch.autograd.grad(torch.autograd.grad(torch.autograd.grad(torch.autograd.grad(torch.sin(x*y*z), x, create_graph=True)[0], y, create_graph=True)[0], y, create_graph=True)[0], z, create_graph=True)[0]" + normalized_result = result.replace(" ", "") + normalized_expected = expected.replace(" ", "") + assert normalized_result == normalized_expected + + +def test_torch_derivative_lambdify(): + if not torch: + skip("PyTorch not installed") + + x = symbols("x") + y = symbols("y") + + expr = Derivative(x ** 2, x) + f = lambdify(x, expr, 'torch') + x_val = torch.tensor(2.0, requires_grad=True) + result = f(x_val) + assert torch.isclose(result, torch.tensor(4.0)) + + expr = Derivative(sin(x), (x, 2)) + f = lambdify(x, expr, 'torch') + # Second derivative of sin(x) at x=0 is 0, not -1 + x_val = torch.tensor(0.0, requires_grad=True) + result = f(x_val) + assert torch.isclose(result, torch.tensor(0.0), atol=1e-5) + + x_val = torch.tensor(math.pi / 2, requires_grad=True) + result = f(x_val) + assert torch.isclose(result, torch.tensor(-1.0), atol=1e-5) + + expr = Derivative(x * y ** 2, x, y) + f = lambdify((x, y), expr, 'torch') + x_val = torch.tensor(2.0, requires_grad=True) + y_val = torch.tensor(3.0, requires_grad=True) + result = f(x_val, y_val) + assert torch.isclose(result, torch.tensor(6.0)) + + +def test_torch_special_matrices(): + if not torch: + skip("PyTorch not installed") + + expr = Identity(3) + assert torch_code(expr) == "torch.eye(3)" + + n = symbols("n") + expr = Identity(n) + assert torch_code(expr) == "torch.eye(n, n)" + + expr = ZeroMatrix(2, 3) + assert torch_code(expr) == "torch.zeros((2, 3))" + + m, n = symbols("m n") + expr = ZeroMatrix(m, n) + assert torch_code(expr) == "torch.zeros((m, n))" + + expr = OneMatrix(2, 3) + assert torch_code(expr) == "torch.ones((2, 3))" + + expr = OneMatrix(m, n) + assert torch_code(expr) == "torch.ones((m, n))" + + +def test_torch_special_matrices_lambdify(): + if not torch: + skip("PyTorch not installed") + + expr = Identity(3) + f = lambdify([], expr, 'torch') + result = f() + expected = torch.eye(3) + assert torch.allclose(result, expected) + + expr = ZeroMatrix(2, 3) + f = lambdify([], expr, 'torch') + result = f() + expected = torch.zeros((2, 3)) + assert torch.allclose(result, expected) + + expr = OneMatrix(2, 3) + f = lambdify([], expr, 'torch') + result = f() + expected = torch.ones((2, 3)) + assert torch.allclose(result, expected) + + +def test_torch_complex_operations(): + if not torch: + skip("PyTorch not installed") + + expr = conjugate(x) + assert torch_code(expr) == "torch.conj(x)" + + # SymPy distributes conjugate over addition and applies specific rules for each term + expr = conjugate(sin(x) + I * cos(y)) + assert torch_code(expr) == "torch.sin(torch.conj(x)) - 1j*torch.cos(torch.conj(y))" + + expr = I + assert torch_code(expr) == "1j" + + expr = 2 * I + x + assert torch_code(expr) == "x + 2*1j" + + expr = exp(I * x) + assert torch_code(expr) == "torch.exp(1j*x)" + + +def test_torch_special_functions(): + if not torch: + skip("PyTorch not installed") + + expr = Heaviside(x) + assert torch_code(expr) == "torch.heaviside(x, 1/2)" + + expr = Heaviside(x, 0) + assert torch_code(expr) == "torch.heaviside(x, 0)" + + expr = gamma(x) + assert torch_code(expr) == "torch.special.gamma(x)" + + expr = polygamma(0, x) # Use polygamma instead of digamma because sympy will default to that anyway + assert torch_code(expr) == "torch.special.digamma(x)" + + expr = gamma(sin(x)) + assert torch_code(expr) == "torch.special.gamma(torch.sin(x))" diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_tree.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_tree.py new file mode 100644 index 0000000000000000000000000000000000000000..cf116d0cac5d38f225815fcd2d4ac90cd0dd96d7 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/printing/tests/test_tree.py @@ -0,0 +1,196 @@ +from sympy.printing.tree import tree +from sympy.testing.pytest import XFAIL + + +# Remove this flag after making _assumptions cache deterministic. +@XFAIL +def test_print_tree_MatAdd(): + from sympy.matrices.expressions import MatrixSymbol + A = MatrixSymbol('A', 3, 3) + B = MatrixSymbol('B', 3, 3) + + test_str = [ + 'MatAdd: A + B\n', + 'algebraic: False\n', + 'commutative: False\n', + 'complex: False\n', + 'composite: False\n', + 'even: False\n', + 'extended_negative: False\n', + 'extended_nonnegative: False\n', + 'extended_nonpositive: False\n', + 'extended_nonzero: False\n', + 'extended_positive: False\n', + 'extended_real: False\n', + 'imaginary: False\n', + 'integer: False\n', + 'irrational: False\n', + 'negative: False\n', + 'noninteger: False\n', + 'nonnegative: False\n', + 'nonpositive: False\n', + 'nonzero: False\n', + 'odd: False\n', + 'positive: False\n', + 'prime: False\n', + 'rational: False\n', + 'real: False\n', + 'transcendental: False\n', + 'zero: False\n', + '+-MatrixSymbol: A\n', + '| algebraic: False\n', + '| commutative: False\n', + '| complex: False\n', + '| composite: False\n', + '| even: False\n', + '| extended_negative: False\n', + '| extended_nonnegative: False\n', + '| extended_nonpositive: False\n', + '| extended_nonzero: False\n', + '| extended_positive: False\n', + '| extended_real: False\n', + '| imaginary: False\n', + '| integer: False\n', + '| irrational: False\n', + '| negative: False\n', + '| noninteger: False\n', + '| nonnegative: False\n', + '| nonpositive: False\n', + '| nonzero: False\n', + '| odd: False\n', + '| positive: False\n', + '| prime: False\n', + '| rational: False\n', + '| real: False\n', + '| transcendental: False\n', + '| zero: False\n', + '| +-Symbol: A\n', + '| | commutative: True\n', + '| +-Integer: 3\n', + '| | algebraic: True\n', + '| | commutative: True\n', + '| | complex: True\n', + '| | extended_negative: False\n', + '| | extended_nonnegative: True\n', + '| | extended_real: True\n', + '| | finite: True\n', + '| | hermitian: True\n', + '| | imaginary: False\n', + '| | infinite: False\n', + '| | integer: True\n', + '| | irrational: False\n', + '| | negative: False\n', + '| | noninteger: False\n', + '| | nonnegative: True\n', + '| | rational: True\n', + '| | real: True\n', + '| | transcendental: False\n', + '| +-Integer: 3\n', + '| algebraic: True\n', + '| commutative: True\n', + '| complex: True\n', + '| extended_negative: False\n', + '| extended_nonnegative: True\n', + '| extended_real: True\n', + '| finite: True\n', + '| hermitian: True\n', + '| imaginary: False\n', + '| infinite: False\n', + '| integer: True\n', + '| irrational: False\n', + '| negative: False\n', + '| noninteger: False\n', + '| nonnegative: True\n', + '| rational: True\n', + '| real: True\n', + '| transcendental: False\n', + '+-MatrixSymbol: B\n', + ' algebraic: False\n', + ' commutative: False\n', + ' complex: False\n', + ' composite: False\n', + ' even: False\n', + ' extended_negative: False\n', + ' extended_nonnegative: False\n', + ' extended_nonpositive: False\n', + ' extended_nonzero: False\n', + ' extended_positive: False\n', + ' extended_real: False\n', + ' imaginary: False\n', + ' integer: False\n', + ' irrational: False\n', + ' negative: False\n', + ' noninteger: False\n', + ' nonnegative: False\n', + ' nonpositive: False\n', + ' nonzero: False\n', + ' odd: False\n', + ' positive: False\n', + ' prime: False\n', + ' rational: False\n', + ' real: False\n', + ' transcendental: False\n', + ' zero: False\n', + ' +-Symbol: B\n', + ' | commutative: True\n', + ' +-Integer: 3\n', + ' | algebraic: True\n', + ' | commutative: True\n', + ' | complex: True\n', + ' | extended_negative: False\n', + ' | extended_nonnegative: True\n', + ' | extended_real: True\n', + ' | finite: True\n', + ' | hermitian: True\n', + ' | imaginary: False\n', + ' | infinite: False\n', + ' | integer: True\n', + ' | irrational: False\n', + ' | negative: False\n', + ' | noninteger: False\n', + ' | nonnegative: True\n', + ' | rational: True\n', + ' | real: True\n', + ' | transcendental: False\n', + ' +-Integer: 3\n', + ' algebraic: True\n', + ' commutative: True\n', + ' complex: True\n', + ' extended_negative: False\n', + ' extended_nonnegative: True\n', + ' extended_real: True\n', + ' finite: True\n', + ' hermitian: True\n', + ' imaginary: False\n', + ' infinite: False\n', + ' integer: True\n', + ' irrational: False\n', + ' negative: False\n', + ' noninteger: False\n', + ' nonnegative: True\n', + ' rational: True\n', + ' real: True\n', + ' transcendental: False\n' + ] + + assert tree(A + B) == "".join(test_str) + + +def test_print_tree_MatAdd_noassumptions(): + from sympy.matrices.expressions import MatrixSymbol + A = MatrixSymbol('A', 3, 3) + B = MatrixSymbol('B', 3, 3) + + test_str = \ +"""MatAdd: A + B ++-MatrixSymbol: A +| +-Str: A +| +-Integer: 3 +| +-Integer: 3 ++-MatrixSymbol: B + +-Str: B + +-Integer: 3 + +-Integer: 3 +""" + + assert tree(A + B, assumptions=False) == test_str diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cfcb144d9986835984a9b3a5352909facfc33fe1 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/acceleration.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/acceleration.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..29062637b7637af7a39b25f1afce6390b08df7ba Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/acceleration.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/approximants.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/approximants.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9a21308323178c03faa07674ef35669de28e649e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/approximants.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/aseries.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/aseries.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..378d82e8dd1dc9f823746584bfb32079d55a4126 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/aseries.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/formal.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/formal.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..55548e9fec5506b9d45a88d11fddd4c2c5f69d31 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/formal.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/fourier.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/fourier.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..94d4cb9c0dd8dc3fb02373341513c449da5e3111 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/fourier.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/gruntz.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/gruntz.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..23c383ea11f8cabb2b525ba273df53e6aa877ce5 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/gruntz.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/kauers.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/kauers.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..87ebeb7f0ab48b6d5b6cefddf78a93423683920c Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/kauers.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/limits.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/limits.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f64eee2f6b1a7ed041348e83543401c894b841dd Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/limits.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/limitseq.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/limitseq.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9c36f76b4ee53514adb2c2b9280743cdac845a15 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/limitseq.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/order.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/order.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5337e4f81a54ffa55083a8191377f5b3d49662b5 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/order.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/residues.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/residues.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..47a0db0c669f724b37e12ba7520074fac81b73a8 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/residues.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/sequences.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/sequences.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f7246e01135cca6832b7353b99c50ed96e093f3a Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/sequences.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/series.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/series.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b116e438f7fd77cce38aef90da3b92ed6723b471 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/series.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/series_class.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/series_class.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..22227c463d895eb9ca51457a06f69f4ebec9c53d Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/__pycache__/series_class.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/benchmarks/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/benchmarks/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/benchmarks/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/benchmarks/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..025e707fbd68ca3afa96237b87ade787b38e2df8 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/benchmarks/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/benchmarks/__pycache__/bench_limit.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/benchmarks/__pycache__/bench_limit.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..da6e48381517612abc56fc5ed3b84c862934a8a7 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/benchmarks/__pycache__/bench_limit.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/benchmarks/__pycache__/bench_order.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/benchmarks/__pycache__/bench_order.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8b45ddf8a04d385fca02951229177446afbf05b4 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/benchmarks/__pycache__/bench_order.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/benchmarks/bench_limit.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/benchmarks/bench_limit.py new file mode 100644 index 0000000000000000000000000000000000000000..eafc28328848dad4b3ea433537971f5785253afe --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/benchmarks/bench_limit.py @@ -0,0 +1,9 @@ +from sympy.core.numbers import oo +from sympy.core.symbol import Symbol +from sympy.series.limits import limit + +x = Symbol('x') + + +def timeit_limit_1x(): + limit(1/x, x, oo) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/benchmarks/bench_order.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/benchmarks/bench_order.py new file mode 100644 index 0000000000000000000000000000000000000000..1c85fa173dfc2a478792de8ab816c23ba9d408ef --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/benchmarks/bench_order.py @@ -0,0 +1,10 @@ +from sympy.core.add import Add +from sympy.core.symbol import Symbol +from sympy.series.order import O + +x = Symbol('x') +l = [x**i for i in range(1000)] +l.append(O(x**1001)) + +def timeit_order_1x(): + Add(*l) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..521648fd84a95f5b6de4259e47effc94df0cf89b Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_approximants.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_approximants.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..747a88ea6d969539b7de37041c21a6e18926d659 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_approximants.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_aseries.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_aseries.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..afc75d0a69e65dbe1fd17dc3f9a1bb5b6cf1648f Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_aseries.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_demidovich.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_demidovich.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2e17a4e10193f99b973932ed0dda61f2eed1d38a Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_demidovich.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_formal.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_formal.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ee7af1b83d5e676f638e33ae8a86b3b39b2274da Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_formal.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_fourier.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_fourier.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4c0abc704e8dd52bf7e1bfb62d3528a9510d61ea Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_fourier.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_gruntz.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_gruntz.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..33e2578a3321a59a2a781afc5e63f31dd60ceea5 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_gruntz.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_kauers.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_kauers.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fc613c5e1fec7c0817b2b766e2689ab8da44d8d2 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_kauers.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_limitseq.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_limitseq.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f818778b1e0e3cccc7ad355e61df5b868467302a Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_limitseq.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_lseries.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_lseries.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c11e061e12b7f51d40674112ccbdbf41eaa8a044 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_lseries.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_nseries.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_nseries.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3d5acec3a7854a1075750d803f63e690d2063d73 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_nseries.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_order.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_order.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..30db5f8e213a5d6ecded9f182b43767e6701e8e6 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_order.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_residues.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_residues.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..79e14edbaccd1ea108ddee80b94d0db0a21c76cf Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_residues.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_sequences.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_sequences.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..33dbc34ea67d3237881a24c445eb4ae1876f6beb Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_sequences.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_series.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_series.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7f28755c4215e9134e5aa3ed14857d049bfdccaf Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/__pycache__/test_series.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_approximants.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_approximants.py new file mode 100644 index 0000000000000000000000000000000000000000..9c03d2ce38add99b0dce8725b6c8d8844b31f76b --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_approximants.py @@ -0,0 +1,23 @@ +from sympy.series import approximants +from sympy.core.symbol import symbols +from sympy.functions.combinatorial.factorials import binomial +from sympy.functions.combinatorial.numbers import (fibonacci, lucas) + + +def test_approximants(): + x, t = symbols("x,t") + g = [lucas(k) for k in range(16)] + assert list(approximants(g)) == ( + [2, -4/(x - 2), (5*x - 2)/(3*x - 1), (x - 2)/(x**2 + x - 1)] ) + g = [lucas(k)+fibonacci(k+2) for k in range(16)] + assert list(approximants(g)) == ( + [3, -3/(x - 1), (3*x - 3)/(2*x - 1), -3/(x**2 + x - 1)] ) + g = [lucas(k)**2 for k in range(16)] + assert list(approximants(g)) == ( + [4, -16/(x - 4), (35*x - 4)/(9*x - 1), (37*x - 28)/(13*x**2 + 11*x - 7), + (50*x**2 + 63*x - 52)/(37*x**2 + 19*x - 13), + (-x**2 - 7*x + 4)/(x**3 - 2*x**2 - 2*x + 1)] ) + p = [sum(binomial(k,i)*x**i for i in range(k+1)) for k in range(16)] + y = approximants(p, t, simplify=True) + assert next(y) == 1 + assert next(y) == -1/(t*(x + 1) - 1) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_aseries.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_aseries.py new file mode 100644 index 0000000000000000000000000000000000000000..cae0ac0a43f2406dd96e45c6a31939ac6b4cdcaa --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_aseries.py @@ -0,0 +1,55 @@ +from sympy.core.function import PoleError +from sympy.core.numbers import oo +from sympy.core.symbol import Symbol +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.series.order import O +from sympy.abc import x + +from sympy.testing.pytest import raises + +def test_simple(): + # Gruntz' theses pp. 91 to 96 + # 6.6 + e = sin(1/x + exp(-x)) - sin(1/x) + assert e.aseries(x) == (1/(24*x**4) - 1/(2*x**2) + 1 + O(x**(-6), (x, oo)))*exp(-x) + + e = exp(x) * (exp(1/x + exp(-x)) - exp(1/x)) + assert e.aseries(x, n=4) == 1/(6*x**3) + 1/(2*x**2) + 1/x + 1 + O(x**(-4), (x, oo)) + + e = exp(exp(x) / (1 - 1/x)) + assert e.aseries(x) == exp(exp(x) / (1 - 1/x)) + + # The implementation of bound in aseries is incorrect currently. This test + # should be commented out when that is fixed. + # assert e.aseries(x, bound=3) == exp(exp(x) / x**2)*exp(exp(x) / x)*exp(-exp(x) + exp(x)/(1 - 1/x) - \ + # exp(x) / x - exp(x) / x**2) * exp(exp(x)) + + e = exp(sin(1/x + exp(-exp(x)))) - exp(sin(1/x)) + assert e.aseries(x, n=4) == (-1/(2*x**3) + 1/x + 1 + O(x**(-4), (x, oo)))*exp(-exp(x)) + + e3 = lambda x:exp(exp(exp(x))) + e = e3(x)/e3(x - 1/e3(x)) + assert e.aseries(x, n=3) == 1 + exp(2*x + 2*exp(x))*exp(-2*exp(exp(x)))/2\ + - exp(2*x + exp(x))*exp(-2*exp(exp(x)))/2 - exp(x + exp(x))*exp(-2*exp(exp(x)))/2\ + + exp(x + exp(x))*exp(-exp(exp(x))) + O(exp(-3*exp(exp(x))), (x, oo)) + + e = exp(exp(x)) * (exp(sin(1/x + 1/exp(exp(x)))) - exp(sin(1/x))) + assert e.aseries(x, n=4) == -1/(2*x**3) + 1/x + 1 + O(x**(-4), (x, oo)) + + n = Symbol('n', integer=True) + e = (sqrt(n)*log(n)**2*exp(sqrt(log(n))*log(log(n))**2*exp(sqrt(log(log(n)))*log(log(log(n)))**3)))/n + assert e.aseries(n) == \ + exp(exp(sqrt(log(log(n)))*log(log(log(n)))**3)*sqrt(log(n))*log(log(n))**2)*log(n)**2/sqrt(n) + + +def test_hierarchical(): + e = sin(1/x + exp(-x)) + assert e.aseries(x, n=3, hir=True) == -exp(-2*x)*sin(1/x)/2 + \ + exp(-x)*cos(1/x) + sin(1/x) + O(exp(-3*x), (x, oo)) + + e = sin(x) * cos(exp(-x)) + assert e.aseries(x, hir=True) == exp(-4*x)*sin(x)/24 - \ + exp(-2*x)*sin(x)/2 + sin(x) + O(exp(-6*x), (x, oo)) + raises(PoleError, lambda: e.aseries(x)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_demidovich.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_demidovich.py new file mode 100644 index 0000000000000000000000000000000000000000..98cafbae6f019dd3d97d306099d5780ed2f37f04 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_demidovich.py @@ -0,0 +1,143 @@ +from sympy.core.numbers import (Rational, oo, pi) +from sympy.core.singleton import S +from sympy.core.symbol import Symbol +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.miscellaneous import (root, sqrt) +from sympy.functions.elementary.trigonometric import (asin, cos, sin, tan) +from sympy.polys.rationaltools import together +from sympy.series.limits import limit + +# Numbers listed with the tests refer to problem numbers in the book +# "Anti-demidovich, problemas resueltos, Ed. URSS" + +x = Symbol("x") + + +def test_leadterm(): + assert (3 + 2*x**(log(3)/log(2) - 1)).leadterm(x) == (3, 0) + + +def root3(x): + return root(x, 3) + + +def root4(x): + return root(x, 4) + + +def test_Limits_simple_0(): + assert limit((2**(x + 1) + 3**(x + 1))/(2**x + 3**x), x, oo) == 3 # 175 + + +def test_Limits_simple_1(): + assert limit((x + 1)*(x + 2)*(x + 3)/x**3, x, oo) == 1 # 172 + assert limit(sqrt(x + 1) - sqrt(x), x, oo) == 0 # 179 + assert limit((2*x - 3)*(3*x + 5)*(4*x - 6)/(3*x**3 + x - 1), x, oo) == 8 # Primjer 1 + assert limit(x/root3(x**3 + 10), x, oo) == 1 # Primjer 2 + assert limit((x + 1)**2/(x**2 + 1), x, oo) == 1 # 181 + + +def test_Limits_simple_2(): + assert limit(1000*x/(x**2 - 1), x, oo) == 0 # 182 + assert limit((x**2 - 5*x + 1)/(3*x + 7), x, oo) is oo # 183 + assert limit((2*x**2 - x + 3)/(x**3 - 8*x + 5), x, oo) == 0 # 184 + assert limit((2*x**2 - 3*x - 4)/sqrt(x**4 + 1), x, oo) == 2 # 186 + assert limit((2*x + 3)/(x + root3(x)), x, oo) == 2 # 187 + assert limit(x**2/(10 + x*sqrt(x)), x, oo) is oo # 188 + assert limit(root3(x**2 + 1)/(x + 1), x, oo) == 0 # 189 + assert limit(sqrt(x)/sqrt(x + sqrt(x + sqrt(x))), x, oo) == 1 # 190 + + +def test_Limits_simple_3a(): + a = Symbol('a') + #issue 3513 + assert together(limit((x**2 - (a + 1)*x + a)/(x**3 - a**3), x, a)) == \ + (a - 1)/(3*a**2) # 196 + + +def test_Limits_simple_3b(): + h = Symbol("h") + assert limit(((x + h)**3 - x**3)/h, h, 0) == 3*x**2 # 197 + assert limit((1/(1 - x) - 3/(1 - x**3)), x, 1) == -1 # 198 + assert limit((sqrt(1 + x) - 1)/(root3(1 + x) - 1), x, 0) == Rational(3)/2 # Primer 4 + assert limit((sqrt(x) - 1)/(x - 1), x, 1) == Rational(1)/2 # 199 + assert limit((sqrt(x) - 8)/(root3(x) - 4), x, 64) == 3 # 200 + assert limit((root3(x) - 1)/(root4(x) - 1), x, 1) == Rational(4)/3 # 201 + assert limit( + (root3(x**2) - 2*root3(x) + 1)/(x - 1)**2, x, 1) == Rational(1)/9 # 202 + + +def test_Limits_simple_4a(): + a = Symbol('a') + assert limit((sqrt(x) - sqrt(a))/(x - a), x, a) == 1/(2*sqrt(a)) # Primer 5 + assert limit((sqrt(x) - 1)/(root3(x) - 1), x, 1) == Rational(3, 2) # 205 + assert limit((sqrt(1 + x) - sqrt(1 - x))/x, x, 0) == 1 # 207 + assert limit(sqrt(x**2 - 5*x + 6) - x, x, oo) == Rational(-5, 2) # 213 + + +def test_limits_simple_4aa(): + assert limit(x*(sqrt(x**2 + 1) - x), x, oo) == Rational(1)/2 # 214 + + +def test_Limits_simple_4b(): + #issue 3511 + assert limit(x - root3(x**3 - 1), x, oo) == 0 # 215 + + +def test_Limits_simple_4c(): + assert limit(log(1 + exp(x))/x, x, -oo) == 0 # 267a + assert limit(log(1 + exp(x))/x, x, oo) == 1 # 267b + + +def test_bounded(): + assert limit(sin(x)/x, x, oo) == 0 # 216b + assert limit(x*sin(1/x), x, 0) == 0 # 227a + + +def test_f1a(): + #issue 3508: + assert limit((sin(2*x)/x)**(1 + x), x, 0) == 2 # Primer 7 + + +def test_f1a2(): + #issue 3509: + assert limit(((x - 1)/(x + 1))**x, x, oo) == exp(-2) # Primer 9 + + +def test_f1b(): + m = Symbol("m") + n = Symbol("n") + h = Symbol("h") + a = Symbol("a") + assert limit(sin(x)/x, x, 2) == sin(2)/2 # 216a + assert limit(sin(3*x)/x, x, 0) == 3 # 217 + assert limit(sin(5*x)/sin(2*x), x, 0) == Rational(5, 2) # 218 + assert limit(sin(pi*x)/sin(3*pi*x), x, 0) == Rational(1, 3) # 219 + assert limit(x*sin(pi/x), x, oo) == pi # 220 + assert limit((1 - cos(x))/x**2, x, 0) == S.Half # 221 + assert limit(x*sin(1/x), x, oo) == 1 # 227b + assert limit((cos(m*x) - cos(n*x))/x**2, x, 0) == -m**2/2 + n**2/2 # 232 + assert limit((tan(x) - sin(x))/x**3, x, 0) == S.Half # 233 + assert limit((x - sin(2*x))/(x + sin(3*x)), x, 0) == -Rational(1, 4) # 237 + assert limit((1 - sqrt(cos(x)))/x**2, x, 0) == Rational(1, 4) # 239 + assert limit((sqrt(1 + sin(x)) - sqrt(1 - sin(x)))/x, x, 0) == 1 # 240 + + assert limit((1 + h/x)**x, x, oo) == exp(h) # Primer 9 + assert limit((sin(x) - sin(a))/(x - a), x, a) == cos(a) # 222, *176 + assert limit((cos(x) - cos(a))/(x - a), x, a) == -sin(a) # 223 + assert limit((sin(x + h) - sin(x))/h, h, 0) == cos(x) # 225 + + +def test_f2a(): + assert limit(((x + 1)/(2*x + 1))**(x**2), x, oo) == 0 # Primer 8 + + +def test_f2(): + assert limit((sqrt( + cos(x)) - root3(cos(x)))/(sin(x)**2), x, 0) == -Rational(1, 12) # *184 + + +def test_f3(): + a = Symbol('a') + #issue 3504 + assert limit(asin(a*x)/x, x, 0) == a diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_formal.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_formal.py new file mode 100644 index 0000000000000000000000000000000000000000..cac60b12534152a5783bb8f0faab2c06da6691fb --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_formal.py @@ -0,0 +1,618 @@ +from sympy.concrete.summations import Sum +from sympy.core.add import Add +from sympy.core.function import (Derivative, Function) +from sympy.core.mul import Mul +from sympy.core.numbers import (I, Rational, oo, pi) +from sympy.core.singleton import S +from sympy.core.symbol import symbols +from sympy.functions.combinatorial.factorials import factorial +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.hyperbolic import (acosh, asech) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (acos, asin, atan, cos, sin) +from sympy.functions.special.bessel import airyai +from sympy.functions.special.error_functions import erf +from sympy.functions.special.gamma_functions import gamma +from sympy.integrals.integrals import integrate +from sympy.series.formal import fps +from sympy.series.order import O +from sympy.series.formal import (rational_algorithm, FormalPowerSeries, + FormalPowerSeriesProduct, FormalPowerSeriesCompose, + FormalPowerSeriesInverse, simpleDE, + rational_independent, exp_re, hyper_re) +from sympy.testing.pytest import raises, XFAIL, slow + +x, y, z = symbols('x y z') +n, m, k = symbols('n m k', integer=True) +f, r = Function('f'), Function('r') + + +def test_rational_algorithm(): + f = 1 / ((x - 1)**2 * (x - 2)) + assert rational_algorithm(f, x, k) == \ + (-2**(-k - 1) + 1 - (factorial(k + 1) / factorial(k)), 0, 0) + + f = (1 + x + x**2 + x**3) / ((x - 1) * (x - 2)) + assert rational_algorithm(f, x, k) == \ + (-15*2**(-k - 1) + 4, x + 4, 0) + + f = z / (y*m - m*x - y*x + x**2) + assert rational_algorithm(f, x, k) == \ + (((-y**(-k - 1)*z) / (y - m)) + ((m**(-k - 1)*z) / (y - m)), 0, 0) + + f = x / (1 - x - x**2) + assert rational_algorithm(f, x, k) is None + assert rational_algorithm(f, x, k, full=True) == \ + (((Rational(-1, 2) + sqrt(5)/2)**(-k - 1) * + (-sqrt(5)/10 + S.Half)) + + ((-sqrt(5)/2 - S.Half)**(-k - 1) * + (sqrt(5)/10 + S.Half)), 0, 0) + + f = 1 / (x**2 + 2*x + 2) + assert rational_algorithm(f, x, k) is None + assert rational_algorithm(f, x, k, full=True) == \ + ((I*(-1 + I)**(-k - 1)) / 2 - (I*(-1 - I)**(-k - 1)) / 2, 0, 0) + + f = log(1 + x) + assert rational_algorithm(f, x, k) == \ + (-(-1)**(-k) / k, 0, 1) + + f = atan(x) + assert rational_algorithm(f, x, k) is None + assert rational_algorithm(f, x, k, full=True) == \ + (((I*I**(-k)) / 2 - (I*(-I)**(-k)) / 2) / k, 0, 1) + + f = x*atan(x) - log(1 + x**2) / 2 + assert rational_algorithm(f, x, k) is None + assert rational_algorithm(f, x, k, full=True) == \ + (((I*I**(-k + 1)) / 2 - (I*(-I)**(-k + 1)) / 2) / + (k*(k - 1)), 0, 2) + + f = log((1 + x) / (1 - x)) / 2 - atan(x) + assert rational_algorithm(f, x, k) is None + assert rational_algorithm(f, x, k, full=True) == \ + ((-(-1)**(-k) / 2 - (I*I**(-k)) / 2 + (I*(-I)**(-k)) / 2 + + S.Half) / k, 0, 1) + + assert rational_algorithm(cos(x), x, k) is None + + +def test_rational_independent(): + ri = rational_independent + assert ri([], x) == [] + assert ri([cos(x), sin(x)], x) == [cos(x), sin(x)] + assert ri([x**2, sin(x), x*sin(x), x**3], x) == \ + [x**3 + x**2, x*sin(x) + sin(x)] + assert ri([S.One, x*log(x), log(x), sin(x)/x, cos(x), sin(x), x], x) == \ + [x + 1, x*log(x) + log(x), sin(x)/x + sin(x), cos(x)] + + +def test_simpleDE(): + # Tests just the first valid DE + for DE in simpleDE(exp(x), x, f): + assert DE == (-f(x) + Derivative(f(x), x), 1) + break + for DE in simpleDE(sin(x), x, f): + assert DE == (f(x) + Derivative(f(x), x, x), 2) + break + for DE in simpleDE(log(1 + x), x, f): + assert DE == ((x + 1)*Derivative(f(x), x, 2) + Derivative(f(x), x), 2) + break + for DE in simpleDE(asin(x), x, f): + assert DE == (x*Derivative(f(x), x) + (x**2 - 1)*Derivative(f(x), x, x), + 2) + break + for DE in simpleDE(exp(x)*sin(x), x, f): + assert DE == (2*f(x) - 2*Derivative(f(x)) + Derivative(f(x), x, x), 2) + break + for DE in simpleDE(((1 + x)/(1 - x))**n, x, f): + assert DE == (2*n*f(x) + (x**2 - 1)*Derivative(f(x), x), 1) + break + for DE in simpleDE(airyai(x), x, f): + assert DE == (-x*f(x) + Derivative(f(x), x, x), 2) + break + + +def test_exp_re(): + d = -f(x) + Derivative(f(x), x) + assert exp_re(d, r, k) == -r(k) + r(k + 1) + + d = f(x) + Derivative(f(x), x, x) + assert exp_re(d, r, k) == r(k) + r(k + 2) + + d = f(x) + Derivative(f(x), x) + Derivative(f(x), x, x) + assert exp_re(d, r, k) == r(k) + r(k + 1) + r(k + 2) + + d = Derivative(f(x), x) + Derivative(f(x), x, x) + assert exp_re(d, r, k) == r(k) + r(k + 1) + + d = Derivative(f(x), x, 3) + Derivative(f(x), x, 4) + Derivative(f(x)) + assert exp_re(d, r, k) == r(k) + r(k + 2) + r(k + 3) + + +def test_hyper_re(): + d = f(x) + Derivative(f(x), x, x) + assert hyper_re(d, r, k) == r(k) + (k+1)*(k+2)*r(k + 2) + + d = -x*f(x) + Derivative(f(x), x, x) + assert hyper_re(d, r, k) == (k + 2)*(k + 3)*r(k + 3) - r(k) + + d = 2*f(x) - 2*Derivative(f(x), x) + Derivative(f(x), x, x) + assert hyper_re(d, r, k) == \ + (-2*k - 2)*r(k + 1) + (k + 1)*(k + 2)*r(k + 2) + 2*r(k) + + d = 2*n*f(x) + (x**2 - 1)*Derivative(f(x), x) + assert hyper_re(d, r, k) == \ + k*r(k) + 2*n*r(k + 1) + (-k - 2)*r(k + 2) + + d = (x**10 + 4)*Derivative(f(x), x) + x*(x**10 - 1)*Derivative(f(x), x, x) + assert hyper_re(d, r, k) == \ + (k*(k - 1) + k)*r(k) + (4*k - (k + 9)*(k + 10) + 40)*r(k + 10) + + d = ((x**2 - 1)*Derivative(f(x), x, 3) + 3*x*Derivative(f(x), x, x) + + Derivative(f(x), x)) + assert hyper_re(d, r, k) == \ + ((k*(k - 2)*(k - 1) + 3*k*(k - 1) + k)*r(k) + + (-k*(k + 1)*(k + 2))*r(k + 2)) + + +def test_fps(): + assert fps(1) == 1 + assert fps(2, x) == 2 + assert fps(2, x, dir='+') == 2 + assert fps(2, x, dir='-') == 2 + assert fps(1/x + 1/x**2) == 1/x + 1/x**2 + assert fps(log(1 + x), hyper=False, rational=False) == log(1 + x) + + f = fps(x**2 + x + 1) + assert isinstance(f, FormalPowerSeries) + assert f.function == x**2 + x + 1 + assert f[0] == 1 + assert f[2] == x**2 + assert f.truncate(4) == x**2 + x + 1 + O(x**4) + assert f.polynomial() == x**2 + x + 1 + + f = fps(log(1 + x)) + assert isinstance(f, FormalPowerSeries) + assert f.function == log(1 + x) + assert f.subs(x, y) == f + assert f[:5] == [0, x, -x**2/2, x**3/3, -x**4/4] + assert f.as_leading_term(x) == x + assert f.polynomial(6) == x - x**2/2 + x**3/3 - x**4/4 + x**5/5 + + k = f.ak.variables[0] + assert f.infinite == Sum((-(-1)**(-k)*x**k)/k, (k, 1, oo)) + + ft, s = f.truncate(n=None), f[:5] + for i, t in enumerate(ft): + if i == 5: + break + assert s[i] == t + + f = sin(x).fps(x) + assert isinstance(f, FormalPowerSeries) + assert f.truncate() == x - x**3/6 + x**5/120 + O(x**6) + + raises(NotImplementedError, lambda: fps(y*x)) + raises(ValueError, lambda: fps(x, dir=0)) + + +@slow +def test_fps__rational(): + assert fps(1/x) == (1/x) + assert fps((x**2 + x + 1) / x**3, dir=-1) == (x**2 + x + 1) / x**3 + + f = 1 / ((x - 1)**2 * (x - 2)) + assert fps(f, x).truncate() == \ + (Rational(-1, 2) - x*Rational(5, 4) - 17*x**2/8 - 49*x**3/16 - 129*x**4/32 - + 321*x**5/64 + O(x**6)) + + f = (1 + x + x**2 + x**3) / ((x - 1) * (x - 2)) + assert fps(f, x).truncate() == \ + (S.Half + x*Rational(5, 4) + 17*x**2/8 + 49*x**3/16 + 113*x**4/32 + + 241*x**5/64 + O(x**6)) + + f = x / (1 - x - x**2) + assert fps(f, x, full=True).truncate() == \ + x + x**2 + 2*x**3 + 3*x**4 + 5*x**5 + O(x**6) + + f = 1 / (x**2 + 2*x + 2) + assert fps(f, x, full=True).truncate() == \ + S.Half - x/2 + x**2/4 - x**4/8 + x**5/8 + O(x**6) + + f = log(1 + x) + assert fps(f, x).truncate() == \ + x - x**2/2 + x**3/3 - x**4/4 + x**5/5 + O(x**6) + assert fps(f, x, dir=1).truncate() == fps(f, x, dir=-1).truncate() + assert fps(f, x, 2).truncate() == \ + (log(3) - Rational(2, 3) - (x - 2)**2/18 + (x - 2)**3/81 - + (x - 2)**4/324 + (x - 2)**5/1215 + x/3 + O((x - 2)**6, (x, 2))) + assert fps(f, x, 2, dir=-1).truncate() == \ + (log(3) - Rational(2, 3) - (-x + 2)**2/18 - (-x + 2)**3/81 - + (-x + 2)**4/324 - (-x + 2)**5/1215 + x/3 + O((x - 2)**6, (x, 2))) + + f = atan(x) + assert fps(f, x, full=True).truncate() == x - x**3/3 + x**5/5 + O(x**6) + assert fps(f, x, full=True, dir=1).truncate() == \ + fps(f, x, full=True, dir=-1).truncate() + assert fps(f, x, 2, full=True).truncate() == \ + (atan(2) - Rational(2, 5) - 2*(x - 2)**2/25 + 11*(x - 2)**3/375 - + 6*(x - 2)**4/625 + 41*(x - 2)**5/15625 + x/5 + O((x - 2)**6, (x, 2))) + assert fps(f, x, 2, full=True, dir=-1).truncate() == \ + (atan(2) - Rational(2, 5) - 2*(-x + 2)**2/25 - 11*(-x + 2)**3/375 - + 6*(-x + 2)**4/625 - 41*(-x + 2)**5/15625 + x/5 + O((x - 2)**6, (x, 2))) + + f = x*atan(x) - log(1 + x**2) / 2 + assert fps(f, x, full=True).truncate() == x**2/2 - x**4/12 + O(x**6) + + f = log((1 + x) / (1 - x)) / 2 - atan(x) + assert fps(f, x, full=True).truncate(n=10) == 2*x**3/3 + 2*x**7/7 + O(x**10) + + +@slow +def test_fps__hyper(): + f = sin(x) + assert fps(f, x).truncate() == x - x**3/6 + x**5/120 + O(x**6) + + f = cos(x) + assert fps(f, x).truncate() == 1 - x**2/2 + x**4/24 + O(x**6) + + f = exp(x) + assert fps(f, x).truncate() == \ + 1 + x + x**2/2 + x**3/6 + x**4/24 + x**5/120 + O(x**6) + + f = atan(x) + assert fps(f, x).truncate() == x - x**3/3 + x**5/5 + O(x**6) + + f = exp(acos(x)) + assert fps(f, x).truncate() == \ + (exp(pi/2) - x*exp(pi/2) + x**2*exp(pi/2)/2 - x**3*exp(pi/2)/3 + + 5*x**4*exp(pi/2)/24 - x**5*exp(pi/2)/6 + O(x**6)) + + f = exp(acosh(x)) + assert fps(f, x).truncate() == I + x - I*x**2/2 - I*x**4/8 + O(x**6) + + f = atan(1/x) + assert fps(f, x).truncate() == pi/2 - x + x**3/3 - x**5/5 + O(x**6) + + f = x*atan(x) - log(1 + x**2) / 2 + assert fps(f, x, rational=False).truncate() == x**2/2 - x**4/12 + O(x**6) + + f = log(1 + x) + assert fps(f, x, rational=False).truncate() == \ + x - x**2/2 + x**3/3 - x**4/4 + x**5/5 + O(x**6) + + f = airyai(x**2) + assert fps(f, x).truncate() == \ + (3**Rational(5, 6)*gamma(Rational(1, 3))/(6*pi) - + 3**Rational(2, 3)*x**2/(3*gamma(Rational(1, 3))) + O(x**6)) + + f = exp(x)*sin(x) + assert fps(f, x).truncate() == x + x**2 + x**3/3 - x**5/30 + O(x**6) + + f = exp(x)*sin(x)/x + assert fps(f, x).truncate() == 1 + x + x**2/3 - x**4/30 - x**5/90 + O(x**6) + + f = sin(x) * cos(x) + assert fps(f, x).truncate() == x - 2*x**3/3 + 2*x**5/15 + O(x**6) + + +def test_fps_shift(): + f = x**-5*sin(x) + assert fps(f, x).truncate() == \ + 1/x**4 - 1/(6*x**2) + Rational(1, 120) - x**2/5040 + x**4/362880 + O(x**6) + + f = x**2*atan(x) + assert fps(f, x, rational=False).truncate() == \ + x**3 - x**5/3 + O(x**6) + + f = cos(sqrt(x))*x + assert fps(f, x).truncate() == \ + x - x**2/2 + x**3/24 - x**4/720 + x**5/40320 + O(x**6) + + f = x**2*cos(sqrt(x)) + assert fps(f, x).truncate() == \ + x**2 - x**3/2 + x**4/24 - x**5/720 + O(x**6) + + +def test_fps__Add_expr(): + f = x*atan(x) - log(1 + x**2) / 2 + assert fps(f, x).truncate() == x**2/2 - x**4/12 + O(x**6) + + f = sin(x) + cos(x) - exp(x) + log(1 + x) + assert fps(f, x).truncate() == x - 3*x**2/2 - x**4/4 + x**5/5 + O(x**6) + + f = 1/x + sin(x) + assert fps(f, x).truncate() == 1/x + x - x**3/6 + x**5/120 + O(x**6) + + f = sin(x) - cos(x) + 1/(x - 1) + assert fps(f, x).truncate() == \ + -2 - x**2/2 - 7*x**3/6 - 25*x**4/24 - 119*x**5/120 + O(x**6) + + +def test_fps__asymptotic(): + f = exp(x) + assert fps(f, x, oo) == f + assert fps(f, x, -oo).truncate() == O(1/x**6, (x, oo)) + + f = erf(x) + assert fps(f, x, oo).truncate() == 1 + O(1/x**6, (x, oo)) + assert fps(f, x, -oo).truncate() == -1 + O(1/x**6, (x, oo)) + + f = atan(x) + assert fps(f, x, oo, full=True).truncate() == \ + -1/(5*x**5) + 1/(3*x**3) - 1/x + pi/2 + O(1/x**6, (x, oo)) + assert fps(f, x, -oo, full=True).truncate() == \ + -1/(5*x**5) + 1/(3*x**3) - 1/x - pi/2 + O(1/x**6, (x, oo)) + + f = log(1 + x) + assert fps(f, x, oo) != \ + (-1/(5*x**5) - 1/(4*x**4) + 1/(3*x**3) - 1/(2*x**2) + 1/x - log(1/x) + + O(1/x**6, (x, oo))) + assert fps(f, x, -oo) != \ + (-1/(5*x**5) - 1/(4*x**4) + 1/(3*x**3) - 1/(2*x**2) + 1/x + I*pi - + log(-1/x) + O(1/x**6, (x, oo))) + + +def test_fps__fractional(): + f = sin(sqrt(x)) / x + assert fps(f, x).truncate() == \ + (1/sqrt(x) - sqrt(x)/6 + x**Rational(3, 2)/120 - + x**Rational(5, 2)/5040 + x**Rational(7, 2)/362880 - + x**Rational(9, 2)/39916800 + x**Rational(11, 2)/6227020800 + O(x**6)) + + f = sin(sqrt(x)) * x + assert fps(f, x).truncate() == \ + (x**Rational(3, 2) - x**Rational(5, 2)/6 + x**Rational(7, 2)/120 - + x**Rational(9, 2)/5040 + x**Rational(11, 2)/362880 + O(x**6)) + + f = atan(sqrt(x)) / x**2 + assert fps(f, x).truncate() == \ + (x**Rational(-3, 2) - x**Rational(-1, 2)/3 + x**S.Half/5 - + x**Rational(3, 2)/7 + x**Rational(5, 2)/9 - x**Rational(7, 2)/11 + + x**Rational(9, 2)/13 - x**Rational(11, 2)/15 + O(x**6)) + + f = exp(sqrt(x)) + assert fps(f, x).truncate().expand() == \ + (1 + x/2 + x**2/24 + x**3/720 + x**4/40320 + x**5/3628800 + sqrt(x) + + x**Rational(3, 2)/6 + x**Rational(5, 2)/120 + x**Rational(7, 2)/5040 + + x**Rational(9, 2)/362880 + x**Rational(11, 2)/39916800 + O(x**6)) + + f = exp(sqrt(x))*x + assert fps(f, x).truncate().expand() == \ + (x + x**2/2 + x**3/24 + x**4/720 + x**5/40320 + x**Rational(3, 2) + + x**Rational(5, 2)/6 + x**Rational(7, 2)/120 + x**Rational(9, 2)/5040 + + x**Rational(11, 2)/362880 + O(x**6)) + + +def test_fps__logarithmic_singularity(): + f = log(1 + 1/x) + assert fps(f, x) != \ + -log(x) + x - x**2/2 + x**3/3 - x**4/4 + x**5/5 + O(x**6) + assert fps(f, x, rational=False) != \ + -log(x) + x - x**2/2 + x**3/3 - x**4/4 + x**5/5 + O(x**6) + + +@XFAIL +def test_fps__logarithmic_singularity_fail(): + f = asech(x) # Algorithms for computing limits probably needs improvements + assert fps(f, x) == log(2) - log(x) - x**2/4 - 3*x**4/64 + O(x**6) + + +def test_fps_symbolic(): + f = x**n*sin(x**2) + assert fps(f, x).truncate(8) == x**(n + 2) - x**(n + 6)/6 + O(x**(n + 8), x) + + f = x**n*log(1 + x) + fp = fps(f, x) + k = fp.ak.variables[0] + assert fp.infinite == \ + Sum((-(-1)**(-k)*x**(k + n))/k, (k, 1, oo)) + + f = (x - 2)**n*log(1 + x) + assert fps(f, x, 2).truncate() == \ + ((x - 2)**n*log(3) + (x - 2)**(n + 1)/3 - (x - 2)**(n + 2)/18 + (x - 2)**(n + 3)/81 - + (x - 2)**(n + 4)/324 + (x - 2)**(n + 5)/1215 + O((x - 2)**(n + 6), (x, 2))) + + f = x**(n - 2)*cos(x) + assert fps(f, x).truncate() == \ + (x**(n - 2) - x**n/2 + x**(n + 2)/24 + O(x**(n + 4), x)) + + f = x**(n - 2)*sin(x) + x**n*exp(x) + assert fps(f, x).truncate() == \ + (x**(n - 1) + x**(n + 1) + x**(n + 2)/2 + x**n + + x**(n + 4)/24 + x**(n + 5)/60 + O(x**(n + 6), x)) + + f = x**n*atan(x) + assert fps(f, x, oo).truncate() == \ + (-x**(n - 5)/5 + x**(n - 3)/3 + x**n*(pi/2 - 1/x) + + O((1/x)**(-n)/x**6, (x, oo))) + + f = x**(n/2)*cos(x) + assert fps(f, x).truncate() == \ + x**(n/2) - x**(n/2 + 2)/2 + x**(n/2 + 4)/24 + O(x**(n/2 + 6), x) + + f = x**(n + m)*sin(x) + assert fps(f, x).truncate() == \ + x**(m + n + 1) - x**(m + n + 3)/6 + x**(m + n + 5)/120 + O(x**(m + n + 6), x) + + +def test_fps__slow(): + f = x*exp(x)*sin(2*x) # TODO: rsolve needs improvement + assert fps(f, x).truncate() == 2*x**2 + 2*x**3 - x**4/3 - x**5 + O(x**6) + + +def test_fps__operations(): + f1, f2 = fps(sin(x)), fps(cos(x)) + + fsum = f1 + f2 + assert fsum.function == sin(x) + cos(x) + assert fsum.truncate() == \ + 1 + x - x**2/2 - x**3/6 + x**4/24 + x**5/120 + O(x**6) + + fsum = f1 + 1 + assert fsum.function == sin(x) + 1 + assert fsum.truncate() == 1 + x - x**3/6 + x**5/120 + O(x**6) + + fsum = 1 + f2 + assert fsum.function == cos(x) + 1 + assert fsum.truncate() == 2 - x**2/2 + x**4/24 + O(x**6) + + assert (f1 + x) == Add(f1, x) + + assert -f2.truncate() == -1 + x**2/2 - x**4/24 + O(x**6) + assert (f1 - f1) is S.Zero + + fsub = f1 - f2 + assert fsub.function == sin(x) - cos(x) + assert fsub.truncate() == \ + -1 + x + x**2/2 - x**3/6 - x**4/24 + x**5/120 + O(x**6) + + fsub = f1 - 1 + assert fsub.function == sin(x) - 1 + assert fsub.truncate() == -1 + x - x**3/6 + x**5/120 + O(x**6) + + fsub = 1 - f2 + assert fsub.function == -cos(x) + 1 + assert fsub.truncate() == x**2/2 - x**4/24 + O(x**6) + + raises(ValueError, lambda: f1 + fps(exp(x), dir=-1)) + raises(ValueError, lambda: f1 + fps(exp(x), x0=1)) + + fm = f1 * 3 + + assert fm.function == 3*sin(x) + assert fm.truncate() == 3*x - x**3/2 + x**5/40 + O(x**6) + + fm = 3 * f2 + + assert fm.function == 3*cos(x) + assert fm.truncate() == 3 - 3*x**2/2 + x**4/8 + O(x**6) + + assert (f1 * f2) == Mul(f1, f2) + assert (f1 * x) == Mul(f1, x) + + fd = f1.diff() + assert fd.function == cos(x) + assert fd.truncate() == 1 - x**2/2 + x**4/24 + O(x**6) + + fd = f2.diff() + assert fd.function == -sin(x) + assert fd.truncate() == -x + x**3/6 - x**5/120 + O(x**6) + + fd = f2.diff().diff() + assert fd.function == -cos(x) + assert fd.truncate() == -1 + x**2/2 - x**4/24 + O(x**6) + + f3 = fps(exp(sqrt(x))) + fd = f3.diff() + assert fd.truncate().expand() == \ + (1/(2*sqrt(x)) + S.Half + x/12 + x**2/240 + x**3/10080 + x**4/725760 + + x**5/79833600 + sqrt(x)/4 + x**Rational(3, 2)/48 + x**Rational(5, 2)/1440 + + x**Rational(7, 2)/80640 + x**Rational(9, 2)/7257600 + x**Rational(11, 2)/958003200 + + O(x**6)) + + assert f1.integrate((x, 0, 1)) == -cos(1) + 1 + assert integrate(f1, (x, 0, 1)) == -cos(1) + 1 + + fi = integrate(f1, x) + assert fi.function == -cos(x) + assert fi.truncate() == -1 + x**2/2 - x**4/24 + O(x**6) + + fi = f2.integrate(x) + assert fi.function == sin(x) + assert fi.truncate() == x - x**3/6 + x**5/120 + O(x**6) + +def test_fps__product(): + f1, f2, f3 = fps(sin(x)), fps(exp(x)), fps(cos(x)) + + raises(ValueError, lambda: f1.product(exp(x), x)) + raises(ValueError, lambda: f1.product(fps(exp(x), dir=-1), x, 4)) + raises(ValueError, lambda: f1.product(fps(exp(x), x0=1), x, 4)) + raises(ValueError, lambda: f1.product(fps(exp(y)), x, 4)) + + fprod = f1.product(f2, x) + assert isinstance(fprod, FormalPowerSeriesProduct) + assert isinstance(fprod.ffps, FormalPowerSeries) + assert isinstance(fprod.gfps, FormalPowerSeries) + assert fprod.f == sin(x) + assert fprod.g == exp(x) + assert fprod.function == sin(x) * exp(x) + assert fprod._eval_terms(4) == x + x**2 + x**3/3 + assert fprod.truncate(4) == x + x**2 + x**3/3 + O(x**4) + assert fprod.polynomial(4) == x + x**2 + x**3/3 + + raises(NotImplementedError, lambda: fprod._eval_term(5)) + raises(NotImplementedError, lambda: fprod.infinite) + raises(NotImplementedError, lambda: fprod._eval_derivative(x)) + raises(NotImplementedError, lambda: fprod.integrate(x)) + + assert f1.product(f3, x)._eval_terms(4) == x - 2*x**3/3 + assert f1.product(f3, x).truncate(4) == x - 2*x**3/3 + O(x**4) + + +def test_fps__compose(): + f1, f2, f3 = fps(exp(x)), fps(sin(x)), fps(cos(x)) + + raises(ValueError, lambda: f1.compose(sin(x), x)) + raises(ValueError, lambda: f1.compose(fps(sin(x), dir=-1), x, 4)) + raises(ValueError, lambda: f1.compose(fps(sin(x), x0=1), x, 4)) + raises(ValueError, lambda: f1.compose(fps(sin(y)), x, 4)) + + raises(ValueError, lambda: f1.compose(f3, x)) + raises(ValueError, lambda: f2.compose(f3, x)) + + fcomp = f1.compose(f2, x) + assert isinstance(fcomp, FormalPowerSeriesCompose) + assert isinstance(fcomp.ffps, FormalPowerSeries) + assert isinstance(fcomp.gfps, FormalPowerSeries) + assert fcomp.f == exp(x) + assert fcomp.g == sin(x) + assert fcomp.function == exp(sin(x)) + assert fcomp._eval_terms(6) == 1 + x + x**2/2 - x**4/8 - x**5/15 + assert fcomp.truncate() == 1 + x + x**2/2 - x**4/8 - x**5/15 + O(x**6) + assert fcomp.truncate(5) == 1 + x + x**2/2 - x**4/8 + O(x**5) + + raises(NotImplementedError, lambda: fcomp._eval_term(5)) + raises(NotImplementedError, lambda: fcomp.infinite) + raises(NotImplementedError, lambda: fcomp._eval_derivative(x)) + raises(NotImplementedError, lambda: fcomp.integrate(x)) + + assert f1.compose(f2, x).truncate(4) == 1 + x + x**2/2 + O(x**4) + assert f1.compose(f2, x).truncate(8) == \ + 1 + x + x**2/2 - x**4/8 - x**5/15 - x**6/240 + x**7/90 + O(x**8) + assert f1.compose(f2, x).truncate(6) == \ + 1 + x + x**2/2 - x**4/8 - x**5/15 + O(x**6) + + assert f2.compose(f2, x).truncate(4) == x - x**3/3 + O(x**4) + assert f2.compose(f2, x).truncate(8) == x - x**3/3 + x**5/10 - 8*x**7/315 + O(x**8) + assert f2.compose(f2, x).truncate(6) == x - x**3/3 + x**5/10 + O(x**6) + + +def test_fps__inverse(): + f1, f2, f3 = fps(sin(x)), fps(exp(x)), fps(cos(x)) + + raises(ValueError, lambda: f1.inverse(x)) + + finv = f2.inverse(x) + assert isinstance(finv, FormalPowerSeriesInverse) + assert isinstance(finv.ffps, FormalPowerSeries) + raises(ValueError, lambda: finv.gfps) + + assert finv.f == exp(x) + assert finv.function == exp(-x) + assert finv._eval_terms(5) == 1 - x + x**2/2 - x**3/6 + x**4/24 + assert finv.truncate() == 1 - x + x**2/2 - x**3/6 + x**4/24 - x**5/120 + O(x**6) + assert finv.truncate(5) == 1 - x + x**2/2 - x**3/6 + x**4/24 + O(x**5) + + raises(NotImplementedError, lambda: finv._eval_term(5)) + raises(ValueError, lambda: finv.g) + raises(NotImplementedError, lambda: finv.infinite) + raises(NotImplementedError, lambda: finv._eval_derivative(x)) + raises(NotImplementedError, lambda: finv.integrate(x)) + + assert f2.inverse(x).truncate(8) == \ + 1 - x + x**2/2 - x**3/6 + x**4/24 - x**5/120 + x**6/720 - x**7/5040 + O(x**8) + + assert f3.inverse(x).truncate() == 1 + x**2/2 + 5*x**4/24 + O(x**6) + assert f3.inverse(x).truncate(8) == 1 + x**2/2 + 5*x**4/24 + 61*x**6/720 + O(x**8) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_fourier.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_fourier.py new file mode 100644 index 0000000000000000000000000000000000000000..994f182088b09b038e0e1b3885fec1c27f69f2b0 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_fourier.py @@ -0,0 +1,165 @@ +from sympy.core.add import Add +from sympy.core.numbers import (Rational, oo, pi) +from sympy.core.singleton import S +from sympy.core.symbol import symbols +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.piecewise import Piecewise +from sympy.functions.elementary.trigonometric import (cos, sin, sinc, tan) +from sympy.series.fourier import fourier_series +from sympy.series.fourier import FourierSeries +from sympy.testing.pytest import raises +from functools import lru_cache + +x, y, z = symbols('x y z') + +# Don't declare these during import because they are slow +@lru_cache() +def _get_examples(): + fo = fourier_series(x, (x, -pi, pi)) + fe = fourier_series(x**2, (-pi, pi)) + fp = fourier_series(Piecewise((0, x < 0), (pi, True)), (x, -pi, pi)) + return fo, fe, fp + + +def test_FourierSeries(): + fo, fe, fp = _get_examples() + + assert fourier_series(1, (-pi, pi)) == 1 + assert (Piecewise((0, x < 0), (pi, True)). + fourier_series((x, -pi, pi)).truncate()) == fp.truncate() + assert isinstance(fo, FourierSeries) + assert fo.function == x + assert fo.x == x + assert fo.period == (-pi, pi) + + assert fo.term(3) == 2*sin(3*x) / 3 + assert fe.term(3) == -4*cos(3*x) / 9 + assert fp.term(3) == 2*sin(3*x) / 3 + + assert fo.as_leading_term(x) == 2*sin(x) + assert fe.as_leading_term(x) == pi**2 / 3 + assert fp.as_leading_term(x) == pi / 2 + + assert fo.truncate() == 2*sin(x) - sin(2*x) + (2*sin(3*x) / 3) + assert fe.truncate() == -4*cos(x) + cos(2*x) + pi**2 / 3 + assert fp.truncate() == 2*sin(x) + (2*sin(3*x) / 3) + pi / 2 + + fot = fo.truncate(n=None) + s = [0, 2*sin(x), -sin(2*x)] + for i, t in enumerate(fot): + if i == 3: + break + assert s[i] == t + + def _check_iter(f, i): + for ind, t in enumerate(f): + assert t == f[ind] # noqa: PLR1736 + if ind == i: + break + + _check_iter(fo, 3) + _check_iter(fe, 3) + _check_iter(fp, 3) + + assert fo.subs(x, x**2) == fo + + raises(ValueError, lambda: fourier_series(x, (0, 1, 2))) + raises(ValueError, lambda: fourier_series(x, (x, 0, oo))) + raises(ValueError, lambda: fourier_series(x*y, (0, oo))) + + +def test_FourierSeries_2(): + p = Piecewise((0, x < 0), (x, True)) + f = fourier_series(p, (x, -2, 2)) + + assert f.term(3) == (2*sin(3*pi*x / 2) / (3*pi) - + 4*cos(3*pi*x / 2) / (9*pi**2)) + assert f.truncate() == (2*sin(pi*x / 2) / pi - sin(pi*x) / pi - + 4*cos(pi*x / 2) / pi**2 + S.Half) + + +def test_square_wave(): + """Test if fourier_series approximates discontinuous function correctly.""" + square_wave = Piecewise((1, x < pi), (-1, True)) + s = fourier_series(square_wave, (x, 0, 2*pi)) + + assert s.truncate(3) == 4 / pi * sin(x) + 4 / (3 * pi) * sin(3 * x) + \ + 4 / (5 * pi) * sin(5 * x) + assert s.sigma_approximation(4) == 4 / pi * sin(x) * sinc(pi / 4) + \ + 4 / (3 * pi) * sin(3 * x) * sinc(3 * pi / 4) + + +def test_sawtooth_wave(): + s = fourier_series(x, (x, 0, pi)) + assert s.truncate(4) == \ + pi/2 - sin(2*x) - sin(4*x)/2 - sin(6*x)/3 + s = fourier_series(x, (x, 0, 1)) + assert s.truncate(4) == \ + S.Half - sin(2*pi*x)/pi - sin(4*pi*x)/(2*pi) - sin(6*pi*x)/(3*pi) + + +def test_FourierSeries__operations(): + fo, fe, fp = _get_examples() + + fes = fe.scale(-1).shift(pi**2) + assert fes.truncate() == 4*cos(x) - cos(2*x) + 2*pi**2 / 3 + + assert fp.shift(-pi/2).truncate() == (2*sin(x) + (2*sin(3*x) / 3) + + (2*sin(5*x) / 5)) + + fos = fo.scale(3) + assert fos.truncate() == 6*sin(x) - 3*sin(2*x) + 2*sin(3*x) + + fx = fe.scalex(2).shiftx(1) + assert fx.truncate() == -4*cos(2*x + 2) + cos(4*x + 4) + pi**2 / 3 + + fl = fe.scalex(3).shift(-pi).scalex(2).shiftx(1).scale(4) + assert fl.truncate() == (-16*cos(6*x + 6) + 4*cos(12*x + 12) - + 4*pi + 4*pi**2 / 3) + + raises(ValueError, lambda: fo.shift(x)) + raises(ValueError, lambda: fo.shiftx(sin(x))) + raises(ValueError, lambda: fo.scale(x*y)) + raises(ValueError, lambda: fo.scalex(x**2)) + + +def test_FourierSeries__neg(): + fo, fe, fp = _get_examples() + + assert (-fo).truncate() == -2*sin(x) + sin(2*x) - (2*sin(3*x) / 3) + assert (-fe).truncate() == +4*cos(x) - cos(2*x) - pi**2 / 3 + + +def test_FourierSeries__add__sub(): + fo, fe, fp = _get_examples() + + assert fo + fo == fo.scale(2) + assert fo - fo == 0 + assert -fe - fe == fe.scale(-2) + + assert (fo + fe).truncate() == 2*sin(x) - sin(2*x) - 4*cos(x) + cos(2*x) \ + + pi**2 / 3 + assert (fo - fe).truncate() == 2*sin(x) - sin(2*x) + 4*cos(x) - cos(2*x) \ + - pi**2 / 3 + + assert isinstance(fo + 1, Add) + + raises(ValueError, lambda: fo + fourier_series(x, (x, 0, 2))) + + +def test_FourierSeries_finite(): + + assert fourier_series(sin(x)).truncate(1) == sin(x) + # assert type(fourier_series(sin(x)*log(x))).truncate() == FourierSeries + # assert type(fourier_series(sin(x**2+6))).truncate() == FourierSeries + assert fourier_series(sin(x)*log(y)*exp(z),(x,pi,-pi)).truncate() == sin(x)*log(y)*exp(z) + assert fourier_series(sin(x)**6).truncate(oo) == -15*cos(2*x)/32 + 3*cos(4*x)/16 - cos(6*x)/32 \ + + Rational(5, 16) + assert fourier_series(sin(x) ** 6).truncate() == -15 * cos(2 * x) / 32 + 3 * cos(4 * x) / 16 \ + + Rational(5, 16) + assert fourier_series(sin(4*x+3) + cos(3*x+4)).truncate(oo) == -sin(4)*sin(3*x) + sin(4*x)*cos(3) \ + + cos(4)*cos(3*x) + sin(3)*cos(4*x) + assert fourier_series(sin(x)+cos(x)*tan(x)).truncate(oo) == 2*sin(x) + assert fourier_series(cos(pi*x), (x, -1, 1)).truncate(oo) == cos(pi*x) + assert fourier_series(cos(3*pi*x + 4) - sin(4*pi*x)*log(pi*y), (x, -1, 1)).truncate(oo) == -log(pi*y)*sin(4*pi*x)\ + - sin(4)*sin(3*pi*x) + cos(4)*cos(3*pi*x) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_gruntz.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_gruntz.py new file mode 100644 index 0000000000000000000000000000000000000000..4cae15297048bc52a69a3d9ca57a7614cfcdc61c --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_gruntz.py @@ -0,0 +1,490 @@ +from sympy.core import EulerGamma +from sympy.core.function import Function +from sympy.core.numbers import (E, I, Integer, Rational, oo, pi) +from sympy.core.singleton import S +from sympy.core.symbol import Symbol +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (acot, atan, cos, sin) +from sympy.functions.special.error_functions import (Ei, erf) +from sympy.functions.special.gamma_functions import (digamma, gamma, loggamma) +from sympy.functions.special.zeta_functions import zeta +from sympy.polys.polytools import cancel +from sympy.functions.elementary.hyperbolic import cosh, coth, sinh, tanh +from sympy.series.gruntz import compare, mrv, rewrite, mrv_leadterm, gruntz, \ + sign +from sympy.testing.pytest import XFAIL, raises, skip, slow + +""" +This test suite is testing the limit algorithm using the bottom up approach. +See the documentation in limits2.py. The algorithm itself is highly recursive +by nature, so "compare" is logically the lowest part of the algorithm, yet in +some sense it's the most complex part, because it needs to calculate a limit +to return the result. + +Nevertheless, the rest of the algorithm depends on compare working correctly. +""" + +x = Symbol('x', real=True) +m = Symbol('m', real=True) + + +runslow = False + + +def _sskip(): + if not runslow: + skip("slow") + + +@slow +def test_gruntz_evaluation(): + # Gruntz' thesis pp. 122 to 123 + # 8.1 + assert gruntz(exp(x)*(exp(1/x - exp(-x)) - exp(1/x)), x, oo) == -1 + # 8.2 + assert gruntz(exp(x)*(exp(1/x + exp(-x) + exp(-x**2)) + - exp(1/x - exp(-exp(x)))), x, oo) == 1 + # 8.3 + assert gruntz(exp(exp(x - exp(-x))/(1 - 1/x)) - exp(exp(x)), x, oo) is oo + # 8.5 + assert gruntz(exp(exp(exp(x + exp(-x)))) / exp(exp(exp(x))), x, oo) is oo + # 8.6 + assert gruntz(exp(exp(exp(x))) / exp(exp(exp(x - exp(-exp(x))))), + x, oo) is oo + # 8.7 + assert gruntz(exp(exp(exp(x))) / exp(exp(exp(x - exp(-exp(exp(x)))))), + x, oo) == 1 + # 8.8 + assert gruntz(exp(exp(x)) / exp(exp(x - exp(-exp(exp(x))))), x, oo) == 1 + # 8.9 + assert gruntz(log(x)**2 * exp(sqrt(log(x))*(log(log(x)))**2 + * exp(sqrt(log(log(x))) * (log(log(log(x))))**3)) / sqrt(x), + x, oo) == 0 + # 8.10 + assert gruntz((x*log(x)*(log(x*exp(x) - x**2))**2) + / (log(log(x**2 + 2*exp(exp(3*x**3*log(x)))))), x, oo) == Rational(1, 3) + # 8.11 + assert gruntz((exp(x*exp(-x)/(exp(-x) + exp(-2*x**2/(x + 1)))) - exp(x))/x, + x, oo) == -exp(2) + # 8.12 + assert gruntz((3**x + 5**x)**(1/x), x, oo) == 5 + # 8.13 + assert gruntz(x/log(x**(log(x**(log(2)/log(x))))), x, oo) is oo + # 8.14 + assert gruntz(exp(exp(2*log(x**5 + x)*log(log(x)))) + / exp(exp(10*log(x)*log(log(x)))), x, oo) is oo + # 8.15 + assert gruntz(exp(exp(Rational(5, 2)*x**Rational(-5, 7) + Rational(21, 8)*x**Rational(6, 11) + + 2*x**(-8) + Rational(54, 17)*x**Rational(49, 45)))**8 + / log(log(-log(Rational(4, 3)*x**Rational(-5, 14))))**Rational(7, 6), x, oo) is oo + # 8.16 + assert gruntz((exp(4*x*exp(-x)/(1/exp(x) + 1/exp(2*x**2/(x + 1)))) - exp(x)) + / exp(x)**4, x, oo) == 1 + # 8.17 + assert gruntz(exp(x*exp(-x)/(exp(-x) + exp(-2*x**2/(x + 1))))/exp(x), x, oo) \ + == 1 + # 8.19 + assert gruntz(log(x)*(log(log(x) + log(log(x))) - log(log(x))) + / (log(log(x) + log(log(log(x))))), x, oo) == 1 + # 8.20 + assert gruntz(exp((log(log(x + exp(log(x)*log(log(x)))))) + / (log(log(log(exp(x) + x + log(x)))))), x, oo) == E + # Another + assert gruntz(exp(exp(exp(x + exp(-x)))) / exp(exp(x)), x, oo) is oo + + +def test_gruntz_evaluation_slow(): + _sskip() + # 8.4 + assert gruntz(exp(exp(exp(x)/(1 - 1/x))) + - exp(exp(exp(x)/(1 - 1/x - log(x)**(-log(x))))), x, oo) is -oo + # 8.18 + assert gruntz((exp(exp(-x/(1 + exp(-x))))*exp(-x/(1 + exp(-x/(1 + exp(-x))))) + *exp(exp(-x + exp(-x/(1 + exp(-x)))))) + / (exp(-x/(1 + exp(-x))))**2 - exp(x) + x, x, oo) == 2 + + +@slow +def test_gruntz_eval_special(): + # Gruntz, p. 126 + assert gruntz(exp(x)*(sin(1/x + exp(-x)) - sin(1/x + exp(-x**2))), x, oo) == 1 + assert gruntz((erf(x - exp(-exp(x))) - erf(x)) * exp(exp(x)) * exp(x**2), + x, oo) == -2/sqrt(pi) + assert gruntz(exp(exp(x)) * (exp(sin(1/x + exp(-exp(x)))) - exp(sin(1/x))), + x, oo) == 1 + assert gruntz(exp(x)*(gamma(x + exp(-x)) - gamma(x)), x, oo) is oo + assert gruntz(exp(exp(digamma(digamma(x))))/x, x, oo) == exp(Rational(-1, 2)) + assert gruntz(exp(exp(digamma(log(x))))/x, x, oo) == exp(Rational(-1, 2)) + assert gruntz(digamma(digamma(digamma(x))), x, oo) is oo + assert gruntz(loggamma(loggamma(x)), x, oo) is oo + assert gruntz(((gamma(x + 1/gamma(x)) - gamma(x))/log(x) - cos(1/x)) + * x*log(x), x, oo) == Rational(-1, 2) + assert gruntz(x * (gamma(x - 1/gamma(x)) - gamma(x) + log(x)), x, oo) \ + == S.Half + assert gruntz((gamma(x + 1/gamma(x)) - gamma(x)) / log(x), x, oo) == 1 + + +def test_gruntz_eval_special_slow(): + _sskip() + assert gruntz(gamma(x + 1)/sqrt(2*pi) + - exp(-x)*(x**(x + S.Half) + x**(x - S.Half)/12), x, oo) is oo + assert gruntz(exp(exp(exp(digamma(digamma(digamma(x))))))/x, x, oo) == 0 + + +@XFAIL +def test_grunts_eval_special_slow_sometimes_fail(): + _sskip() + # XXX This sometimes fails!!! + assert gruntz(exp(gamma(x - exp(-x))*exp(1/x)) - exp(gamma(x)), x, oo) is oo + + +def test_gruntz_Ei(): + assert gruntz((Ei(x - exp(-exp(x))) - Ei(x)) *exp(-x)*exp(exp(x))*x, x, oo) == -1 + + +@XFAIL +def test_gruntz_eval_special_fail(): + # TODO zeta function series + assert gruntz( + exp((log(2) + 1)*x) * (zeta(x + exp(-x)) - zeta(x)), x, oo) == -log(2) + + # TODO 8.35 - 8.37 (bessel, max-min) + + +def test_gruntz_hyperbolic(): + assert gruntz(cosh(x), x, oo) is oo + assert gruntz(cosh(x), x, -oo) is oo + assert gruntz(sinh(x), x, oo) is oo + assert gruntz(sinh(x), x, -oo) is -oo + assert gruntz(2*cosh(x)*exp(x), x, oo) is oo + assert gruntz(2*cosh(x)*exp(x), x, -oo) == 1 + assert gruntz(2*sinh(x)*exp(x), x, oo) is oo + assert gruntz(2*sinh(x)*exp(x), x, -oo) == -1 + assert gruntz(tanh(x), x, oo) == 1 + assert gruntz(tanh(x), x, -oo) == -1 + assert gruntz(coth(x), x, oo) == 1 + assert gruntz(coth(x), x, -oo) == -1 + + +def test_compare1(): + assert compare(2, x, x) == "<" + assert compare(x, exp(x), x) == "<" + assert compare(exp(x), exp(x**2), x) == "<" + assert compare(exp(x**2), exp(exp(x)), x) == "<" + assert compare(1, exp(exp(x)), x) == "<" + + assert compare(x, 2, x) == ">" + assert compare(exp(x), x, x) == ">" + assert compare(exp(x**2), exp(x), x) == ">" + assert compare(exp(exp(x)), exp(x**2), x) == ">" + assert compare(exp(exp(x)), 1, x) == ">" + + assert compare(2, 3, x) == "=" + assert compare(3, -5, x) == "=" + assert compare(2, -5, x) == "=" + + assert compare(x, x**2, x) == "=" + assert compare(x**2, x**3, x) == "=" + assert compare(x**3, 1/x, x) == "=" + assert compare(1/x, x**m, x) == "=" + assert compare(x**m, -x, x) == "=" + + assert compare(exp(x), exp(-x), x) == "=" + assert compare(exp(-x), exp(2*x), x) == "=" + assert compare(exp(2*x), exp(x)**2, x) == "=" + assert compare(exp(x)**2, exp(x + exp(-x)), x) == "=" + assert compare(exp(x), exp(x + exp(-x)), x) == "=" + + assert compare(exp(x**2), 1/exp(x**2), x) == "=" + + +def test_compare2(): + assert compare(exp(x), x**5, x) == ">" + assert compare(exp(x**2), exp(x)**2, x) == ">" + assert compare(exp(x), exp(x + exp(-x)), x) == "=" + assert compare(exp(x + exp(-x)), exp(x), x) == "=" + assert compare(exp(x + exp(-x)), exp(-x), x) == "=" + assert compare(exp(-x), x, x) == ">" + assert compare(x, exp(-x), x) == "<" + assert compare(exp(x + 1/x), x, x) == ">" + assert compare(exp(-exp(x)), exp(x), x) == ">" + assert compare(exp(exp(-exp(x)) + x), exp(-exp(x)), x) == "<" + + +def test_compare3(): + assert compare(exp(exp(x)), exp(x + exp(-exp(x))), x) == ">" + + +def test_sign1(): + assert sign(Rational(0), x) == 0 + assert sign(Rational(3), x) == 1 + assert sign(Rational(-5), x) == -1 + assert sign(log(x), x) == 1 + assert sign(exp(-x), x) == 1 + assert sign(exp(x), x) == 1 + assert sign(-exp(x), x) == -1 + assert sign(3 - 1/x, x) == 1 + assert sign(-3 - 1/x, x) == -1 + assert sign(sin(1/x), x) == 1 + assert sign((x**Integer(2)), x) == 1 + assert sign(x**2, x) == 1 + assert sign(x**5, x) == 1 + + +def test_sign2(): + assert sign(x, x) == 1 + assert sign(-x, x) == -1 + y = Symbol("y", positive=True) + assert sign(y, x) == 1 + assert sign(-y, x) == -1 + assert sign(y*x, x) == 1 + assert sign(-y*x, x) == -1 + + +def mmrv(a, b): + return set(mrv(a, b)[0].keys()) + + +def test_mrv1(): + assert mmrv(x, x) == {x} + assert mmrv(x + 1/x, x) == {x} + assert mmrv(x**2, x) == {x} + assert mmrv(log(x), x) == {x} + assert mmrv(exp(x), x) == {exp(x)} + assert mmrv(exp(-x), x) == {exp(-x)} + assert mmrv(exp(x**2), x) == {exp(x**2)} + assert mmrv(-exp(1/x), x) == {x} + assert mmrv(exp(x + 1/x), x) == {exp(x + 1/x)} + + +def test_mrv2a(): + assert mmrv(exp(x + exp(-exp(x))), x) == {exp(-exp(x))} + assert mmrv(exp(x + exp(-x)), x) == {exp(x + exp(-x)), exp(-x)} + assert mmrv(exp(1/x + exp(-x)), x) == {exp(-x)} + +#sometimes infinite recursion due to log(exp(x**2)) not simplifying + + +def test_mrv2b(): + assert mmrv(exp(x + exp(-x**2)), x) == {exp(-x**2)} + +#sometimes infinite recursion due to log(exp(x**2)) not simplifying + + +def test_mrv2c(): + assert mmrv( + exp(-x + 1/x**2) - exp(x + 1/x), x) == {exp(x + 1/x), exp(1/x**2 - x)} + +#sometimes infinite recursion due to log(exp(x**2)) not simplifying + + +def test_mrv3(): + assert mmrv(exp(x**2) + x*exp(x) + log(x)**x/x, x) == {exp(x**2)} + assert mmrv( + exp(x)*(exp(1/x + exp(-x)) - exp(1/x)), x) == {exp(x), exp(-x)} + assert mmrv(log( + x**2 + 2*exp(exp(3*x**3*log(x)))), x) == {exp(exp(3*x**3*log(x)))} + assert mmrv(log(x - log(x))/log(x), x) == {x} + assert mmrv( + (exp(1/x - exp(-x)) - exp(1/x))*exp(x), x) == {exp(x), exp(-x)} + assert mmrv( + 1/exp(-x + exp(-x)) - exp(x), x) == {exp(x), exp(-x), exp(x - exp(-x))} + assert mmrv(log(log(x*exp(x*exp(x)) + 1)), x) == {exp(x*exp(x))} + assert mmrv(exp(exp(log(log(x) + 1/x))), x) == {x} + + +def test_mrv4(): + ln = log + assert mmrv((ln(ln(x) + ln(ln(x))) - ln(ln(x)))/ln(ln(x) + ln(ln(ln(x))))*ln(x), + x) == {x} + assert mmrv(log(log(x*exp(x*exp(x)) + 1)) - exp(exp(log(log(x) + 1/x))), x) == \ + {exp(x*exp(x))} + + +def mrewrite(a, b, c): + return rewrite(a[1], a[0], b, c) + + +def test_rewrite1(): + e = exp(x) + assert mrewrite(mrv(e, x), x, m) == (1/m, -x) + e = exp(x**2) + assert mrewrite(mrv(e, x), x, m) == (1/m, -x**2) + e = exp(x + 1/x) + assert mrewrite(mrv(e, x), x, m) == (1/m, -x - 1/x) + e = 1/exp(-x + exp(-x)) - exp(x) + assert mrewrite(mrv(e, x), x, m) == ((-m*exp(m) + m)*exp(-m)/m**2, -x) + + +def test_rewrite2(): + e = exp(x)*log(log(exp(x))) + assert mmrv(e, x) == {exp(x)} + assert mrewrite(mrv(e, x), x, m) == (1/m*log(x), -x) + +#sometimes infinite recursion due to log(exp(x**2)) not simplifying + + +def test_rewrite3(): + e = exp(-x + 1/x**2) - exp(x + 1/x) + #both of these are correct and should be equivalent: + assert mrewrite(mrv(e, x), x, m) in [(-1/m + m*exp( + (x**2 + x)/x**3), -x - 1/x), ((m**2 - exp((x**2 + x)/x**3))/m, x**(-2) - x)] + + +def test_mrv_leadterm1(): + assert mrv_leadterm(-exp(1/x), x) == (-1, 0) + assert mrv_leadterm(1/exp(-x + exp(-x)) - exp(x), x) == (-1, 0) + assert mrv_leadterm( + (exp(1/x - exp(-x)) - exp(1/x))*exp(x), x) == (-exp(1/x), 0) + + +def test_mrv_leadterm2(): + #Gruntz: p51, 3.25 + assert mrv_leadterm((log(exp(x) + x) - x)/log(exp(x) + log(x))*exp(x), x) == \ + (1, 0) + + +def test_mrv_leadterm3(): + #Gruntz: p56, 3.27 + assert mmrv(exp(-x + exp(-x)*exp(-x*log(x))), x) == {exp(-x - x*log(x))} + assert mrv_leadterm(exp(-x + exp(-x)*exp(-x*log(x))), x) == (exp(-x), 0) + + +def test_limit1(): + assert gruntz(x, x, oo) is oo + assert gruntz(x, x, -oo) is -oo + assert gruntz(-x, x, oo) is -oo + assert gruntz(x**2, x, -oo) is oo + assert gruntz(-x**2, x, oo) is -oo + assert gruntz(x*log(x), x, 0, dir="+") == 0 + assert gruntz(1/x, x, oo) == 0 + assert gruntz(exp(x), x, oo) is oo + assert gruntz(-exp(x), x, oo) is -oo + assert gruntz(exp(x)/x, x, oo) is oo + assert gruntz(1/x - exp(-x), x, oo) == 0 + assert gruntz(x + 1/x, x, oo) is oo + + +def test_limit2(): + assert gruntz(x**x, x, 0, dir="+") == 1 + assert gruntz((exp(x) - 1)/x, x, 0) == 1 + assert gruntz(1 + 1/x, x, oo) == 1 + assert gruntz(-exp(1/x), x, oo) == -1 + assert gruntz(x + exp(-x), x, oo) is oo + assert gruntz(x + exp(-x**2), x, oo) is oo + assert gruntz(x + exp(-exp(x)), x, oo) is oo + assert gruntz(13 + 1/x - exp(-x), x, oo) == 13 + + +def test_limit3(): + a = Symbol('a') + assert gruntz(x - log(1 + exp(x)), x, oo) == 0 + assert gruntz(x - log(a + exp(x)), x, oo) == 0 + assert gruntz(exp(x)/(1 + exp(x)), x, oo) == 1 + assert gruntz(exp(x)/(a + exp(x)), x, oo) == 1 + + +def test_limit4(): + #issue 3463 + assert gruntz((3**x + 5**x)**(1/x), x, oo) == 5 + #issue 3463 + assert gruntz((3**(1/x) + 5**(1/x))**x, x, 0) == 5 + + +@XFAIL +def test_MrvTestCase_page47_ex3_21(): + h = exp(-x/(1 + exp(-x))) + expr = exp(h)*exp(-x/(1 + h))*exp(exp(-x + h))/h**2 - exp(x) + x + assert mmrv(expr, x) == {1/h, exp(-x), exp(x), exp(x - h), exp(x/(1 + h))} + + +def test_gruntz_I(): + y = Symbol("y") + assert gruntz(I*x, x, oo) == I*oo + assert gruntz(y*I*x, x, oo) == y*I*oo + assert gruntz(y*3*I*x, x, oo) == y*I*oo + assert gruntz(y*3*sin(I)*x, x, oo) == y*I*oo + + +def test_issue_4814(): + assert gruntz((x + 1)**(1/log(x + 1)), x, oo) == E + + +def test_intractable(): + assert gruntz(1/gamma(x), x, oo) == 0 + assert gruntz(1/loggamma(x), x, oo) == 0 + assert gruntz(gamma(x)/loggamma(x), x, oo) is oo + assert gruntz(exp(gamma(x))/gamma(x), x, oo) is oo + assert gruntz(gamma(x), x, 3) == 2 + assert gruntz(gamma(Rational(1, 7) + 1/x), x, oo) == gamma(Rational(1, 7)) + assert gruntz(log(x**x)/log(gamma(x)), x, oo) == 1 + assert gruntz(log(gamma(gamma(x)))/exp(x), x, oo) is oo + + +def test_aseries_trig(): + assert cancel(gruntz(1/log(atan(x)), x, oo) + - 1/(log(pi) + log(S.Half))) == 0 + assert gruntz(1/acot(x), x, -oo) is -oo + + +def test_exp_log_series(): + assert gruntz(x/log(log(x*exp(x))), x, oo) is oo + + +def test_issue_3644(): + assert gruntz(((x**7 + x + 1)/(2**x + x**2))**(-1/x), x, oo) == 2 + + +def test_issue_6843(): + n = Symbol('n', integer=True, positive=True) + r = (n + 1)*x**(n + 1)/(x**(n + 1) - 1) - x/(x - 1) + assert gruntz(r, x, 1).simplify() == n/2 + + +def test_issue_4190(): + assert gruntz(x - gamma(1/x), x, oo) == S.EulerGamma + + +@XFAIL +def test_issue_5172(): + n = Symbol('n') + r = Symbol('r', positive=True) + c = Symbol('c') + p = Symbol('p', positive=True) + m = Symbol('m', negative=True) + expr = ((2*n*(n - r + 1)/(n + r*(n - r + 1)))**c + \ + (r - 1)*(n*(n - r + 2)/(n + r*(n - r + 1)))**c - n)/(n**c - n) + expr = expr.subs(c, c + 1) + assert gruntz(expr.subs(c, m), n, oo) == 1 + # fail: + assert gruntz(expr.subs(c, p), n, oo).simplify() == \ + (2**(p + 1) + r - 1)/(r + 1)**(p + 1) + + +def test_issue_4109(): + assert gruntz(1/gamma(x), x, 0) == 0 + assert gruntz(x*gamma(x), x, 0) == 1 + + +def test_issue_6682(): + assert gruntz(exp(2*Ei(-x))/x**2, x, 0) == exp(2*EulerGamma) + + +def test_issue_7096(): + from sympy.functions import sign + assert gruntz(x**-pi, x, 0, dir='-') == oo*sign((-1)**(-pi)) + + +def test_issue_7391_8166(): + f = Function('f') + # limit should depend on the continuity of the expression at the point passed + raises(ValueError, lambda: gruntz(f(x), x, 4)) + raises(ValueError, lambda: gruntz(x*f(x)**2/(x**2 + f(x)**4), x, 0)) + + +def test_issue_24210_25885(): + eq = exp(x)/(1+1/x)**x**2 + ans = sqrt(E) + assert gruntz(eq, x, oo) == ans + assert gruntz(1/eq, x, oo) == 1/ans diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_kauers.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_kauers.py new file mode 100644 index 0000000000000000000000000000000000000000..bfb9044b33416bc38879649b258150ba2906250c --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_kauers.py @@ -0,0 +1,23 @@ +from sympy.series.kauers import finite_diff +from sympy.series.kauers import finite_diff_kauers +from sympy.abc import x, y, z, m, n, w +from sympy.core.numbers import pi +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.concrete.summations import Sum + + +def test_finite_diff(): + assert finite_diff(x**2 + 2*x + 1, x) == 2*x + 3 + assert finite_diff(y**3 + 2*y**2 + 3*y + 5, y) == 3*y**2 + 7*y + 6 + assert finite_diff(z**2 - 2*z + 3, z) == 2*z - 1 + assert finite_diff(w**2 + 3*w - 2, w) == 2*w + 4 + assert finite_diff(sin(x), x, pi/6) == -sin(x) + sin(x + pi/6) + assert finite_diff(cos(y), y, pi/3) == -cos(y) + cos(y + pi/3) + assert finite_diff(x**2 - 2*x + 3, x, 2) == 4*x + assert finite_diff(n**2 - 2*n + 3, n, 3) == 6*n + 3 + +def test_finite_diff_kauers(): + assert finite_diff_kauers(Sum(x**2, (x, 1, n))) == (n + 1)**2 + assert finite_diff_kauers(Sum(y, (y, 1, m))) == (m + 1) + assert finite_diff_kauers(Sum((x*y), (x, 1, m), (y, 1, n))) == (m + 1)*(n + 1) + assert finite_diff_kauers(Sum((x*y**2), (x, 1, m), (y, 1, n))) == (n + 1)**2*(m + 1) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_limits.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_limits.py new file mode 100644 index 0000000000000000000000000000000000000000..aa3ab7683f057424f1c3215a06381d27687710dc --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_limits.py @@ -0,0 +1,1440 @@ +from itertools import product + +from sympy.concrete.summations import Sum +from sympy.core.function import (Function, diff) +from sympy.core import EulerGamma, GoldenRatio +from sympy.core.mod import Mod +from sympy.core.numbers import (E, I, Rational, oo, pi, zoo) +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.combinatorial.numbers import fibonacci +from sympy.functions.combinatorial.factorials import (binomial, factorial, subfactorial) +from sympy.functions.elementary.complexes import (Abs, re, sign) +from sympy.functions.elementary.exponential import (LambertW, exp, log) +from sympy.functions.elementary.hyperbolic import (atanh, asinh, acosh, acoth, acsch, asech, tanh, sinh) +from sympy.functions.elementary.integers import (ceiling, floor, frac) +from sympy.functions.elementary.miscellaneous import (cbrt, real_root, sqrt) +from sympy.functions.elementary.piecewise import Piecewise +from sympy.functions.elementary.trigonometric import (acos, acot, acsc, asec, asin, + atan, cos, cot, csc, sec, sin, tan) +from sympy.functions.special.bessel import (besseli, bessely, besselj, besselk) +from sympy.functions.special.error_functions import (Ei, erf, erfc, erfi, fresnelc, fresnels) +from sympy.functions.special.gamma_functions import (digamma, gamma, uppergamma) +from sympy.functions.special.hyper import meijerg +from sympy.integrals.integrals import (Integral, integrate) +from sympy.series.limits import (Limit, limit) +from sympy.simplify.simplify import (logcombine, simplify) +from sympy.simplify.hyperexpand import hyperexpand + +from sympy.calculus.accumulationbounds import AccumBounds +from sympy.core.mul import Mul +from sympy.series.limits import heuristics +from sympy.series.order import Order +from sympy.testing.pytest import XFAIL, raises + +from sympy import elliptic_e, elliptic_k + +from sympy.abc import x, y, z, k +n = Symbol('n', integer=True, positive=True) + + +def test_basic1(): + assert limit(x, x, oo) is oo + assert limit(x, x, -oo) is -oo + assert limit(-x, x, oo) is -oo + assert limit(x**2, x, -oo) is oo + assert limit(-x**2, x, oo) is -oo + assert limit(x*log(x), x, 0, dir="+") == 0 + assert limit(1/x, x, oo) == 0 + assert limit(exp(x), x, oo) is oo + assert limit(-exp(x), x, oo) is -oo + assert limit(exp(x)/x, x, oo) is oo + assert limit(1/x - exp(-x), x, oo) == 0 + assert limit(x + 1/x, x, oo) is oo + assert limit(x - x**2, x, oo) is -oo + assert limit((1 + x)**(1 + sqrt(2)), x, 0) == 1 + assert limit((1 + x)**oo, x, 0) == Limit((x + 1)**oo, x, 0) + assert limit((1 + x)**oo, x, 0, dir='-') == Limit((x + 1)**oo, x, 0, dir='-') + assert limit((1 + x + y)**oo, x, 0, dir='-') == Limit((1 + x + y)**oo, x, 0, dir='-') + assert limit(y/x/log(x), x, 0) == -oo*sign(y) + assert limit(cos(x + y)/x, x, 0) == sign(cos(y))*oo + assert limit(gamma(1/x + 3), x, oo) == 2 + assert limit(S.NaN, x, -oo) is S.NaN + assert limit(Order(2)*x, x, S.NaN) is S.NaN + assert limit(1/(x - 1), x, 1, dir="+") is oo + assert limit(1/(x - 1), x, 1, dir="-") is -oo + assert limit(1/(5 - x)**3, x, 5, dir="+") is -oo + assert limit(1/(5 - x)**3, x, 5, dir="-") is oo + assert limit(1/sin(x), x, pi, dir="+") is -oo + assert limit(1/sin(x), x, pi, dir="-") is oo + assert limit(1/cos(x), x, pi/2, dir="+") is -oo + assert limit(1/cos(x), x, pi/2, dir="-") is oo + assert limit(1/tan(x**3), x, (2*pi)**Rational(1, 3), dir="+") is oo + assert limit(1/tan(x**3), x, (2*pi)**Rational(1, 3), dir="-") is -oo + assert limit(1/cot(x)**3, x, (pi*Rational(3, 2)), dir="+") is -oo + assert limit(1/cot(x)**3, x, (pi*Rational(3, 2)), dir="-") is oo + assert limit(tan(x), x, oo) == AccumBounds(S.NegativeInfinity, S.Infinity) + assert limit(cot(x), x, oo) == AccumBounds(S.NegativeInfinity, S.Infinity) + assert limit(sec(x), x, oo) == AccumBounds(S.NegativeInfinity, S.Infinity) + assert limit(csc(x), x, oo) == AccumBounds(S.NegativeInfinity, S.Infinity) + + # test bi-directional limits + assert limit(sin(x)/x, x, 0, dir="+-") == 1 + assert limit(x**2, x, 0, dir="+-") == 0 + assert limit(1/x**2, x, 0, dir="+-") is oo + + # test failing bi-directional limits + assert limit(1/x, x, 0, dir="+-") is zoo + # approaching 0 + # from dir="+" + assert limit(1 + 1/x, x, 0) is oo + # from dir='-' + # Add + assert limit(1 + 1/x, x, 0, dir='-') is -oo + # Pow + assert limit(x**(-2), x, 0, dir='-') is oo + assert limit(x**(-3), x, 0, dir='-') is -oo + assert limit(1/sqrt(x), x, 0, dir='-') == (-oo)*I + assert limit(x**2, x, 0, dir='-') == 0 + assert limit(sqrt(x), x, 0, dir='-') == 0 + assert limit(x**-pi, x, 0, dir='-') == -oo*(-1)**(1 - pi) + assert limit((1 + cos(x))**oo, x, 0) == Limit((cos(x) + 1)**oo, x, 0) + + # test pull request 22491 + assert limit(1/asin(x), x, 0, dir = '+') == oo + assert limit(1/asin(x), x, 0, dir = '-') == -oo + assert limit(1/sinh(x), x, 0, dir = '+') == oo + assert limit(1/sinh(x), x, 0, dir = '-') == -oo + assert limit(log(1/x) + 1/sin(x), x, 0, dir = '+') == oo + assert limit(log(1/x) + 1/x, x, 0, dir = '+') == oo + + +def test_basic2(): + assert limit(x**x, x, 0, dir="+") == 1 + assert limit((exp(x) - 1)/x, x, 0) == 1 + assert limit(1 + 1/x, x, oo) == 1 + assert limit(-exp(1/x), x, oo) == -1 + assert limit(x + exp(-x), x, oo) is oo + assert limit(x + exp(-x**2), x, oo) is oo + assert limit(x + exp(-exp(x)), x, oo) is oo + assert limit(13 + 1/x - exp(-x), x, oo) == 13 + + +def test_basic3(): + assert limit(1/x, x, 0, dir="+") is oo + assert limit(1/x, x, 0, dir="-") is -oo + + +def test_basic4(): + assert limit(2*x + y*x, x, 0) == 0 + assert limit(2*x + y*x, x, 1) == 2 + y + assert limit(2*x**8 + y*x**(-3), x, -2) == 512 - y/8 + assert limit(sqrt(x + 1) - sqrt(x), x, oo) == 0 + assert integrate(1/(x**3 + 1), (x, 0, oo)) == 2*pi*sqrt(3)/9 + + +def test_log(): + # https://github.com/sympy/sympy/issues/21598 + a, b, c = symbols('a b c', positive=True) + A = log(a/b) - (log(a) - log(b)) + assert A.limit(a, oo) == 0 + assert (A * c).limit(a, oo) == 0 + + tau, x = symbols('tau x', positive=True) + # The value of manualintegrate in the issue + expr = tau**2*((tau - 1)*(tau + 1)*log(x + 1)/(tau**2 + 1)**2 + 1/((tau**2\ + + 1)*(x + 1)) - (-2*tau*atan(x/tau) + (tau**2/2 - 1/2)*log(tau**2\ + + x**2))/(tau**2 + 1)**2) + assert limit(expr, x, oo) == pi*tau**3/(tau**2 + 1)**2 + + +def test_piecewise(): + # https://github.com/sympy/sympy/issues/18363 + assert limit((real_root(x - 6, 3) + 2)/(x + 2), x, -2, '+') == Rational(1, 12) + + +def test_piecewise2(): + func1 = 2*sqrt(x)*Piecewise(((4*x - 2)/Abs(sqrt(4 - 4*(2*x - 1)**2)), 4*x - 2\ + >= 0), ((2 - 4*x)/Abs(sqrt(4 - 4*(2*x - 1)**2)), True)) + func2 = Piecewise((x**2/2, x <= 0.5), (x/2 - 0.125, True)) + func3 = Piecewise(((x - 9) / 5, x < -1), ((x - 9) / 5, x > 4), (sqrt(Abs(x - 3)), True)) + assert limit(func1, x, 0) == 1 + assert limit(func2, x, 0) == 0 + assert limit(func3, x, -1) == 2 + + +def test_basic5(): + class my(Function): + @classmethod + def eval(cls, arg): + if arg is S.Infinity: + return S.NaN + assert limit(my(x), x, oo) == Limit(my(x), x, oo) + + +def test_issue_3885(): + assert limit(x*y + x*z, z, 2) == x*y + 2*x + + +def test_Limit(): + assert Limit(sin(x)/x, x, 0) != 1 + assert Limit(sin(x)/x, x, 0).doit() == 1 + assert Limit(x, x, 0, dir='+-').args == (x, x, 0, Symbol('+-')) + + +def test_floor(): + assert limit(floor(x), x, -2, "+") == -2 + assert limit(floor(x), x, -2, "-") == -3 + assert limit(floor(x), x, -1, "+") == -1 + assert limit(floor(x), x, -1, "-") == -2 + assert limit(floor(x), x, 0, "+") == 0 + assert limit(floor(x), x, 0, "-") == -1 + assert limit(floor(x), x, 1, "+") == 1 + assert limit(floor(x), x, 1, "-") == 0 + assert limit(floor(x), x, 2, "+") == 2 + assert limit(floor(x), x, 2, "-") == 1 + assert limit(floor(x), x, 248, "+") == 248 + assert limit(floor(x), x, 248, "-") == 247 + + # https://github.com/sympy/sympy/issues/14478 + assert limit(x*floor(3/x)/2, x, 0, '+') == Rational(3, 2) + assert limit(floor(x + 1/2) - floor(x), x, oo) == AccumBounds(-S.Half, S(3)/2) + + # test issue 9158 + assert limit(floor(atan(x)), x, oo) == 1 + assert limit(floor(atan(x)), x, -oo) == -2 + assert limit(ceiling(atan(x)), x, oo) == 2 + assert limit(ceiling(atan(x)), x, -oo) == -1 + + +def test_floor_requires_robust_assumptions(): + assert limit(floor(sin(x)), x, 0, "+") == 0 + assert limit(floor(sin(x)), x, 0, "-") == -1 + assert limit(floor(cos(x)), x, 0, "+") == 0 + assert limit(floor(cos(x)), x, 0, "-") == 0 + assert limit(floor(5 + sin(x)), x, 0, "+") == 5 + assert limit(floor(5 + sin(x)), x, 0, "-") == 4 + assert limit(floor(5 + cos(x)), x, 0, "+") == 5 + assert limit(floor(5 + cos(x)), x, 0, "-") == 5 + + +def test_ceiling(): + assert limit(ceiling(x), x, -2, "+") == -1 + assert limit(ceiling(x), x, -2, "-") == -2 + assert limit(ceiling(x), x, -1, "+") == 0 + assert limit(ceiling(x), x, -1, "-") == -1 + assert limit(ceiling(x), x, 0, "+") == 1 + assert limit(ceiling(x), x, 0, "-") == 0 + assert limit(ceiling(x), x, 1, "+") == 2 + assert limit(ceiling(x), x, 1, "-") == 1 + assert limit(ceiling(x), x, 2, "+") == 3 + assert limit(ceiling(x), x, 2, "-") == 2 + assert limit(ceiling(x), x, 248, "+") == 249 + assert limit(ceiling(x), x, 248, "-") == 248 + + # https://github.com/sympy/sympy/issues/14478 + assert limit(x*ceiling(3/x)/2, x, 0, '+') == Rational(3, 2) + assert limit(ceiling(x + 1/2) - ceiling(x), x, oo) == AccumBounds(-S.Half, S(3)/2) + + +def test_ceiling_requires_robust_assumptions(): + assert limit(ceiling(sin(x)), x, 0, "+") == 1 + assert limit(ceiling(sin(x)), x, 0, "-") == 0 + assert limit(ceiling(cos(x)), x, 0, "+") == 1 + assert limit(ceiling(cos(x)), x, 0, "-") == 1 + assert limit(ceiling(5 + sin(x)), x, 0, "+") == 6 + assert limit(ceiling(5 + sin(x)), x, 0, "-") == 5 + assert limit(ceiling(5 + cos(x)), x, 0, "+") == 6 + assert limit(ceiling(5 + cos(x)), x, 0, "-") == 6 + + +def test_frac(): + assert limit(frac(x), x, oo) == AccumBounds(0, 1) + assert limit(frac(x)**(1/x), x, oo) == AccumBounds(0, 1) + assert limit(frac(x)**(1/x), x, -oo) == AccumBounds(1, oo) + assert limit(frac(x)**x, x, oo) == AccumBounds(0, oo) # wolfram gives (0, 1) + assert limit(frac(sin(x)), x, 0, "+") == 0 + assert limit(frac(sin(x)), x, 0, "-") == 1 + assert limit(frac(cos(x)), x, 0, "+-") == 1 + assert limit(frac(x**2), x, 0, "+-") == 0 + raises(ValueError, lambda: limit(frac(x), x, 0, '+-')) + assert limit(frac(-2*x + 1), x, 0, "+") == 1 + assert limit(frac(-2*x + 1), x, 0, "-") == 0 + assert limit(frac(x + S.Half), x, 0, "+-") == S(1)/2 + assert limit(frac(1/x), x, 0) == AccumBounds(0, 1) + + +def test_issue_14355(): + assert limit(floor(sin(x)/x), x, 0, '+') == 0 + assert limit(floor(sin(x)/x), x, 0, '-') == 0 + # test comment https://github.com/sympy/sympy/issues/14355#issuecomment-372121314 + assert limit(floor(-tan(x)/x), x, 0, '+') == -2 + assert limit(floor(-tan(x)/x), x, 0, '-') == -2 + + +def test_atan(): + x = Symbol("x", real=True) + assert limit(atan(x)*sin(1/x), x, 0) == 0 + assert limit(atan(x) + sqrt(x + 1) - sqrt(x), x, oo) == pi/2 + + +def test_set_signs(): + assert limit(abs(x), x, 0) == 0 + assert limit(abs(sin(x)), x, 0) == 0 + assert limit(abs(cos(x)), x, 0) == 1 + assert limit(abs(sin(x + 1)), x, 0) == sin(1) + + # https://github.com/sympy/sympy/issues/9449 + assert limit((Abs(x + y) - Abs(x - y))/(2*x), x, 0) == sign(y) + + # https://github.com/sympy/sympy/issues/12398 + assert limit(Abs(log(x)/x**3), x, oo) == 0 + assert limit(x*(Abs(log(x)/x**3)/Abs(log(x + 1)/(x + 1)**3) - 1), x, oo) == 3 + + # https://github.com/sympy/sympy/issues/18501 + assert limit(Abs(log(x - 1)**3 - 1), x, 1, '+') == oo + + # https://github.com/sympy/sympy/issues/18997 + assert limit(Abs(log(x)), x, 0) == oo + assert limit(Abs(log(Abs(x))), x, 0) == oo + + # https://github.com/sympy/sympy/issues/19026 + z = Symbol('z', positive=True) + assert limit(Abs(log(z) + 1)/log(z), z, oo) == 1 + + # https://github.com/sympy/sympy/issues/20704 + assert limit(z*(Abs(1/z + y) - Abs(y - 1/z))/2, z, 0) == 0 + + # https://github.com/sympy/sympy/issues/21606 + assert limit(cos(z)/sign(z), z, pi, '-') == -1 + + +def test_heuristic(): + x = Symbol("x", real=True) + assert heuristics(sin(1/x) + atan(x), x, 0, '+') == AccumBounds(-1, 1) + assert limit(log(2 + sqrt(atan(x))*sqrt(sin(1/x))), x, 0) == log(2) + + +def test_issue_3871(): + z = Symbol("z", positive=True) + f = -1/z*exp(-z*x) + assert limit(f, x, oo) == 0 + assert f.limit(x, oo) == 0 + + +def test_exponential(): + n = Symbol('n') + x = Symbol('x', real=True) + assert limit((1 + x/n)**n, n, oo) == exp(x) + assert limit((1 + x/(2*n))**n, n, oo) == exp(x/2) + assert limit((1 + x/(2*n + 1))**n, n, oo) == exp(x/2) + assert limit(((x - 1)/(x + 1))**x, x, oo) == exp(-2) + assert limit(1 + (1 + 1/x)**x, x, oo) == 1 + S.Exp1 + assert limit((2 + 6*x)**x/(6*x)**x, x, oo) == exp(S('1/3')) + + +def test_exponential2(): + n = Symbol('n') + assert limit((1 + x/(n + sin(n)))**n, n, oo) == exp(x) + + +def test_doit(): + f = Integral(2 * x, x) + l = Limit(f, x, oo) + assert l.doit() is oo + + +def test_series_AccumBounds(): + assert limit(sin(k) - sin(k + 1), k, oo) == AccumBounds(-2, 2) + assert limit(cos(k) - cos(k + 1) + 1, k, oo) == AccumBounds(-1, 3) + + # not the exact bound + assert limit(sin(k) - sin(k)*cos(k), k, oo) == AccumBounds(-2, 2) + + # test for issue #9934 + lo = (-3 + cos(1))/2 + hi = (1 + cos(1))/2 + t1 = Mul(AccumBounds(lo, hi), 1/(-1 + cos(1)), evaluate=False) + assert limit(simplify(Sum(cos(n).rewrite(exp), (n, 0, k)).doit().rewrite(sin)), k, oo) == t1 + + t2 = Mul(AccumBounds(-1 + sin(1)/2, sin(1)/2 + 1), 1/(1 - cos(1))) + assert limit(simplify(Sum(sin(n).rewrite(exp), (n, 0, k)).doit().rewrite(sin)), k, oo) == t2 + + assert limit(((sin(x) + 1)/2)**x, x, oo) == AccumBounds(0, oo) # wolfram says 0 + + # https://github.com/sympy/sympy/issues/12312 + e = 2**(-x)*(sin(x) + 1)**x + assert limit(e, x, oo) == AccumBounds(0, oo) + + +def test_bessel_functions_at_infinity(): + # Pull Request 23844 implements limits for all bessel and modified bessel + # functions approaching infinity along any direction i.e. abs(z0) tends to oo + + assert limit(besselj(1, x), x, oo) == 0 + assert limit(besselj(1, x), x, -oo) == 0 + assert limit(besselj(1, x), x, I*oo) == oo*I + assert limit(besselj(1, x), x, -I*oo) == -oo*I + assert limit(bessely(1, x), x, oo) == 0 + assert limit(bessely(1, x), x, -oo) == 0 + assert limit(bessely(1, x), x, I*oo) == -oo + assert limit(bessely(1, x), x, -I*oo) == -oo + assert limit(besseli(1, x), x, oo) == oo + assert limit(besseli(1, x), x, -oo) == -oo + assert limit(besseli(1, x), x, I*oo) == 0 + assert limit(besseli(1, x), x, -I*oo) == 0 + assert limit(besselk(1, x), x, oo) == 0 + assert limit(besselk(1, x), x, -oo) == -oo*I + assert limit(besselk(1, x), x, I*oo) == 0 + assert limit(besselk(1, x), x, -I*oo) == 0 + + # test issue 14874 + assert limit(besselk(0, x), x, oo) == 0 + + +@XFAIL +def test_doit2(): + f = Integral(2 * x, x) + l = Limit(f, x, oo) + # limit() breaks on the contained Integral. + assert l.doit(deep=False) == l + + +def test_issue_2929(): + assert limit((x * exp(x))/(exp(x) - 1), x, -oo) == 0 + + +def test_issue_3792(): + assert limit((1 - cos(x))/x**2, x, S.Half) == 4 - 4*cos(S.Half) + assert limit(sin(sin(x + 1) + 1), x, 0) == sin(1 + sin(1)) + assert limit(abs(sin(x + 1) + 1), x, 0) == 1 + sin(1) + + +def test_issue_4090(): + assert limit(1/(x + 3), x, 2) == Rational(1, 5) + assert limit(1/(x + pi), x, 2) == S.One/(2 + pi) + assert limit(log(x)/(x**2 + 3), x, 2) == log(2)/7 + assert limit(log(x)/(x**2 + pi), x, 2) == log(2)/(4 + pi) + + +def test_issue_4547(): + assert limit(cot(x), x, 0, dir='+') is oo + assert limit(cot(x), x, pi/2, dir='+') == 0 + + +def test_issue_5164(): + assert limit(x**0.5, x, oo) == oo**0.5 is oo + assert limit(x**0.5, x, 16) == 4 # Should this be a float? + assert limit(x**0.5, x, 0) == 0 + assert limit(x**(-0.5), x, oo) == 0 + assert limit(x**(-0.5), x, 4) == S.Half # Should this be a float? + + +def test_issue_5383(): + func = (1.0 * 1 + 1.0 * x)**(1.0 * 1 / x) + assert limit(func, x, 0) == E + + +def test_issue_14793(): + expr = ((x + S(1)/2) * log(x) - x + log(2*pi)/2 - \ + log(factorial(x)) + S(1)/(12*x))*x**3 + assert limit(expr, x, oo) == S(1)/360 + + +def test_issue_5183(): + # using list(...) so py.test can recalculate values + tests = list(product([x, -x], + [-1, 1], + [2, 3, S.Half, Rational(2, 3)], + ['-', '+'])) + results = (oo, oo, -oo, oo, -oo*I, oo, -oo*(-1)**Rational(1, 3), oo, + 0, 0, 0, 0, 0, 0, 0, 0, + oo, oo, oo, -oo, oo, -oo*I, oo, -oo*(-1)**Rational(1, 3), + 0, 0, 0, 0, 0, 0, 0, 0) + assert len(tests) == len(results) + for i, (args, res) in enumerate(zip(tests, results)): + y, s, e, d = args + eq = y**(s*e) + try: + assert limit(eq, x, 0, dir=d) == res + except AssertionError: + if 0: # change to 1 if you want to see the failing tests + print() + print(i, res, eq, d, limit(eq, x, 0, dir=d)) + else: + assert None + + +def test_issue_5184(): + assert limit(sin(x)/x, x, oo) == 0 + assert limit(atan(x), x, oo) == pi/2 + assert limit(gamma(x), x, oo) is oo + assert limit(cos(x)/x, x, oo) == 0 + assert limit(gamma(x), x, S.Half) == sqrt(pi) + + r = Symbol('r', real=True) + assert limit(r*sin(1/r), r, 0) == 0 + + +def test_issue_5229(): + assert limit((1 + y)**(1/y) - S.Exp1, y, 0) == 0 + + +def test_issue_4546(): + # using list(...) so py.test can recalculate values + tests = list(product([cot, tan], + [-pi/2, 0, pi/2, pi, pi*Rational(3, 2)], + ['-', '+'])) + results = (0, 0, -oo, oo, 0, 0, -oo, oo, 0, 0, + oo, -oo, 0, 0, oo, -oo, 0, 0, oo, -oo) + assert len(tests) == len(results) + for i, (args, res) in enumerate(zip(tests, results)): + f, l, d = args + eq = f(x) + try: + assert limit(eq, x, l, dir=d) == res + except AssertionError: + if 0: # change to 1 if you want to see the failing tests + print() + print(i, res, eq, l, d, limit(eq, x, l, dir=d)) + else: + assert None + + +def test_issue_3934(): + assert limit((1 + x**log(3))**(1/x), x, 0) == 1 + assert limit((5**(1/x) + 3**(1/x))**x, x, 0) == 5 + + +def test_issue_5955(): + assert limit((x**16)/(1 + x**16), x, oo) == 1 + assert limit((x**100)/(1 + x**100), x, oo) == 1 + assert limit((x**1885)/(1 + x**1885), x, oo) == 1 + assert limit((x**1000/((x + 1)**1000 + exp(-x))), x, oo) == 1 + + +def test_newissue(): + assert limit(exp(1/sin(x))/exp(cot(x)), x, 0) == 1 + + +def test_extended_real_line(): + assert limit(x - oo, x, oo) == Limit(x - oo, x, oo) + assert limit(1/(x + sin(x)) - oo, x, 0) == Limit(1/(x + sin(x)) - oo, x, 0) + assert limit(oo/x, x, oo) == Limit(oo/x, x, oo) + assert limit(x - oo + 1/x, x, oo) == Limit(x - oo + 1/x, x, oo) + + +@XFAIL +def test_order_oo(): + x = Symbol('x', positive=True) + assert Order(x)*oo != Order(1, x) + assert limit(oo/(x**2 - 4), x, oo) is oo + + +def test_issue_5436(): + raises(NotImplementedError, lambda: limit(exp(x*y), x, oo)) + raises(NotImplementedError, lambda: limit(exp(-x*y), x, oo)) + + +def test_Limit_dir(): + raises(TypeError, lambda: Limit(x, x, 0, dir=0)) + raises(ValueError, lambda: Limit(x, x, 0, dir='0')) + + +def test_polynomial(): + assert limit((x + 1)**1000/((x + 1)**1000 + 1), x, oo) == 1 + assert limit((x + 1)**1000/((x + 1)**1000 + 1), x, -oo) == 1 + assert limit(x ** Rational(77, 3) / (1 + x ** Rational(77, 3)), x, oo) == 1 + assert limit(x ** 101.1 / (1 + x ** 101.1), x, oo) == 1 + + +def test_rational(): + assert limit(1/y - (1/(y + x) + x/(y + x)/y)/z, x, oo) == (z - 1)/(y*z) + assert limit(1/y - (1/(y + x) + x/(y + x)/y)/z, x, -oo) == (z - 1)/(y*z) + + +def test_issue_5740(): + assert limit(log(x)*z - log(2*x)*y, x, 0) == oo*sign(y - z) + + +def test_issue_6366(): + n = Symbol('n', integer=True, positive=True) + r = (n + 1)*x**(n + 1)/(x**(n + 1) - 1) - x/(x - 1) + assert limit(r, x, 1).cancel() == n/2 + + +def test_factorial(): + f = factorial(x) + assert limit(f, x, oo) is oo + assert limit(x/f, x, oo) == 0 + # see Stirling's approximation: + # https://en.wikipedia.org/wiki/Stirling's_approximation + assert limit(f/(sqrt(2*pi*x)*(x/E)**x), x, oo) == 1 + assert limit(f, x, -oo) == gamma(-oo) + + +def test_issue_6560(): + e = (5*x**3/4 - x*Rational(3, 4) + (y*(3*x**2/2 - S.Half) + + 35*x**4/8 - 15*x**2/4 + Rational(3, 8))/(2*(y + 1))) + assert limit(e, y, oo) == 5*x**3/4 + 3*x**2/4 - 3*x/4 - Rational(1, 4) + +@XFAIL +def test_issue_5172(): + n = Symbol('n') + r = Symbol('r', positive=True) + c = Symbol('c') + p = Symbol('p', positive=True) + m = Symbol('m', negative=True) + expr = ((2*n*(n - r + 1)/(n + r*(n - r + 1)))**c + + (r - 1)*(n*(n - r + 2)/(n + r*(n - r + 1)))**c - n)/(n**c - n) + expr = expr.subs(c, c + 1) + raises(NotImplementedError, lambda: limit(expr, n, oo)) + assert limit(expr.subs(c, m), n, oo) == 1 + assert limit(expr.subs(c, p), n, oo).simplify() == \ + (2**(p + 1) + r - 1)/(r + 1)**(p + 1) + + +def test_issue_7088(): + a = Symbol('a') + assert limit(sqrt(x/(x + a)), x, oo) == 1 + + +def test_branch_cuts(): + assert limit(asin(I*x + 2), x, 0) == pi - asin(2) + assert limit(asin(I*x + 2), x, 0, '-') == asin(2) + assert limit(asin(I*x - 2), x, 0) == -asin(2) + assert limit(asin(I*x - 2), x, 0, '-') == -pi + asin(2) + assert limit(acos(I*x + 2), x, 0) == -acos(2) + assert limit(acos(I*x + 2), x, 0, '-') == acos(2) + assert limit(acos(I*x - 2), x, 0) == acos(-2) + assert limit(acos(I*x - 2), x, 0, '-') == 2*pi - acos(-2) + assert limit(atan(x + 2*I), x, 0) == I*atanh(2) + assert limit(atan(x + 2*I), x, 0, '-') == -pi + I*atanh(2) + assert limit(atan(x - 2*I), x, 0) == pi - I*atanh(2) + assert limit(atan(x - 2*I), x, 0, '-') == -I*atanh(2) + assert limit(atan(1/x), x, 0) == pi/2 + assert limit(atan(1/x), x, 0, '-') == -pi/2 + assert limit(atan(x), x, oo) == pi/2 + assert limit(atan(x), x, -oo) == -pi/2 + assert limit(acot(x + S(1)/2*I), x, 0) == pi - I*acoth(S(1)/2) + assert limit(acot(x + S(1)/2*I), x, 0, '-') == -I*acoth(S(1)/2) + assert limit(acot(x - S(1)/2*I), x, 0) == I*acoth(S(1)/2) + assert limit(acot(x - S(1)/2*I), x, 0, '-') == -pi + I*acoth(S(1)/2) + assert limit(acot(x), x, 0) == pi/2 + assert limit(acot(x), x, 0, '-') == -pi/2 + assert limit(asec(I*x + S(1)/2), x, 0) == asec(S(1)/2) + assert limit(asec(I*x + S(1)/2), x, 0, '-') == -asec(S(1)/2) + assert limit(asec(I*x - S(1)/2), x, 0) == 2*pi - asec(-S(1)/2) + assert limit(asec(I*x - S(1)/2), x, 0, '-') == asec(-S(1)/2) + assert limit(acsc(I*x + S(1)/2), x, 0) == acsc(S(1)/2) + assert limit(acsc(I*x + S(1)/2), x, 0, '-') == pi - acsc(S(1)/2) + assert limit(acsc(I*x - S(1)/2), x, 0) == -pi + acsc(S(1)/2) + assert limit(acsc(I*x - S(1)/2), x, 0, '-') == -acsc(S(1)/2) + + assert limit(log(I*x - 1), x, 0) == I*pi + assert limit(log(I*x - 1), x, 0, '-') == -I*pi + assert limit(log(-I*x - 1), x, 0) == -I*pi + assert limit(log(-I*x - 1), x, 0, '-') == I*pi + + assert limit(sqrt(I*x - 1), x, 0) == I + assert limit(sqrt(I*x - 1), x, 0, '-') == -I + assert limit(sqrt(-I*x - 1), x, 0) == -I + assert limit(sqrt(-I*x - 1), x, 0, '-') == I + + assert limit(cbrt(I*x - 1), x, 0) == (-1)**(S(1)/3) + assert limit(cbrt(I*x - 1), x, 0, '-') == -(-1)**(S(2)/3) + assert limit(cbrt(-I*x - 1), x, 0) == -(-1)**(S(2)/3) + assert limit(cbrt(-I*x - 1), x, 0, '-') == (-1)**(S(1)/3) + + +def test_issue_6364(): + a = Symbol('a') + e = z/(1 - sqrt(1 + z)*sin(a)**2 - sqrt(1 - z)*cos(a)**2) + assert limit(e, z, 0) == 1/(cos(a)**2 - S.Half) + + +def test_issue_6682(): + assert limit(exp(2*Ei(-x))/x**2, x, 0) == exp(2*EulerGamma) + + +def test_issue_4099(): + a = Symbol('a') + assert limit(a/x, x, 0) == oo*sign(a) + assert limit(-a/x, x, 0) == -oo*sign(a) + assert limit(-a*x, x, oo) == -oo*sign(a) + assert limit(a*x, x, oo) == oo*sign(a) + + +def test_issue_4503(): + dx = Symbol('dx') + assert limit((sqrt(1 + exp(x + dx)) - sqrt(1 + exp(x)))/dx, dx, 0) == \ + exp(x)/(2*sqrt(exp(x) + 1)) + + +def test_issue_6052(): + G = meijerg((), (), (1,), (0,), -x) + g = hyperexpand(G) + assert limit(g, x, 0, '+-') == 0 + assert limit(g, x, oo) == -oo + + +def test_issue_7224(): + expr = sqrt(x)*besseli(1,sqrt(8*x)) + assert limit(x*diff(expr, x, x)/expr, x, 0) == 2 + assert limit(x*diff(expr, x, x)/expr, x, 1).evalf() == 2.0 + + +def test_issue_7391_8166(): + f = Function('f') + # limit should depend on the continuity of the expression at the point passed + assert limit(f(x), x, 4) == Limit(f(x), x, 4, dir='+') + assert limit(x*f(x)**2/(x**2 + f(x)**4), x, 0) == Limit(x*f(x)**2/(x**2 + f(x)**4), x, 0, dir='+') + + +def test_issue_8208(): + assert limit(n**(Rational(1, 1e9) - 1), n, oo) == 0 + + +def test_issue_8229(): + assert limit((x**Rational(1, 4) - 2)/(sqrt(x) - 4)**Rational(2, 3), x, 16) == 0 + + +def test_issue_8433(): + d, t = symbols('d t', positive=True) + assert limit(erf(1 - t/d), t, oo) == -1 + + +def test_issue_8481(): + k = Symbol('k', integer=True, nonnegative=True) + lamda = Symbol('lamda', positive=True) + assert limit(lamda**k * exp(-lamda) / factorial(k), k, oo) == 0 + + +def test_issue_8462(): + assert limit(binomial(n, n/2), n, oo) == oo + assert limit(binomial(n, n/2) * 3 ** (-n), n, oo) == 0 + + +def test_issue_8634(): + n = Symbol('n', integer=True, positive=True) + x = Symbol('x') + assert limit(x**n, x, -oo) == oo*sign((-1)**n) + + +def test_issue_8635_18176(): + x = Symbol('x', real=True) + k = Symbol('k', positive=True) + assert limit(x**n - x**(n - 0), x, oo) == 0 + assert limit(x**n - x**(n - 5), x, oo) == oo + assert limit(x**n - x**(n - 2.5), x, oo) == oo + assert limit(x**n - x**(n - k - 1), x, oo) == oo + x = Symbol('x', positive=True) + assert limit(x**n - x**(n - 1), x, oo) == oo + assert limit(x**n - x**(n + 2), x, oo) == -oo + + +def test_issue_8730(): + assert limit(subfactorial(x), x, oo) is oo + + +def test_issue_9252(): + n = Symbol('n', integer=True) + c = Symbol('c', positive=True) + assert limit((log(n))**(n/log(n)) / (1 + c)**n, n, oo) == 0 + # limit should depend on the value of c + raises(NotImplementedError, lambda: limit((log(n))**(n/log(n)) / c**n, n, oo)) + + +def test_issue_9558(): + assert limit(sin(x)**15, x, 0, '-') == 0 + + +def test_issue_10801(): + # make sure limits work with binomial + assert limit(16**k / (k * binomial(2*k, k)**2), k, oo) == pi + + +def test_issue_10976(): + s, x = symbols('s x', real=True) + assert limit(erf(s*x)/erf(s), s, 0) == x + + +def test_issue_9041(): + assert limit(factorial(n) / ((n/exp(1))**n * sqrt(2*pi*n)), n, oo) == 1 + + +def test_issue_9205(): + x, y, a = symbols('x, y, a') + assert Limit(x, x, a).free_symbols == {a} + assert Limit(x, x, a, '-').free_symbols == {a} + assert Limit(x + y, x + y, a).free_symbols == {a} + assert Limit(-x**2 + y, x**2, a).free_symbols == {y, a} + + +def test_issue_9471(): + assert limit(((27**(log(n,3)))/n**3),n,oo) == 1 + assert limit(((27**(log(n,3)+1))/n**3),n,oo) == 27 + + +def test_issue_10382(): + assert limit(fibonacci(n + 1)/fibonacci(n), n, oo) == GoldenRatio + + +def test_issue_11496(): + assert limit(erfc(log(1/x)), x, oo) == 2 + + +def test_issue_11879(): + assert simplify(limit(((x+y)**n-x**n)/y, y, 0)) == n*x**(n-1) + + +def test_limit_with_Float(): + k = symbols("k") + assert limit(1.0 ** k, k, oo) == 1 + assert limit(0.3*1.0**k, k, oo) == Rational(3, 10) + + +def test_issue_10610(): + assert limit(3**x*3**(-x - 1)*(x + 1)**2/x**2, x, oo) == Rational(1, 3) + + +def test_issue_10868(): + assert limit(log(x) + asech(x), x, 0, '+') == log(2) + assert limit(log(x) + asech(x), x, 0, '-') == log(2) + 2*I*pi + raises(ValueError, lambda: limit(log(x) + asech(x), x, 0, '+-')) + assert limit(log(x) + asech(x), x, oo) == oo + assert limit(log(x) + acsch(x), x, 0, '+') == log(2) + assert limit(log(x) + acsch(x), x, 0, '-') == -oo + raises(ValueError, lambda: limit(log(x) + acsch(x), x, 0, '+-')) + assert limit(log(x) + acsch(x), x, oo) == oo + + +def test_issue_6599(): + assert limit((n + cos(n))/n, n, oo) == 1 + + +def test_issue_12555(): + assert limit((3**x + 2* x**10) / (x**10 + exp(x)), x, -oo) == 2 + assert limit((3**x + 2* x**10) / (x**10 + exp(x)), x, oo) is oo + + +def test_issue_12769(): + r, z, x = symbols('r z x', real=True) + a, b, s0, K, F0, s, T = symbols('a b s0 K F0 s T', positive=True, real=True) + fx = (F0**b*K**b*r*s0 - sqrt((F0**2*K**(2*b)*a**2*(b - 1) + \ + F0**(2*b)*K**2*a**2*(b - 1) + F0**(2*b)*K**(2*b)*s0**2*(b - 1)*(b**2 - 2*b + 1) - \ + 2*F0**(2*b)*K**(b + 1)*a*r*s0*(b**2 - 2*b + 1) + \ + 2*F0**(b + 1)*K**(2*b)*a*r*s0*(b**2 - 2*b + 1) - \ + 2*F0**(b + 1)*K**(b + 1)*a**2*(b - 1))/((b - 1)*(b**2 - 2*b + 1))))*(b*r - b - r + 1) + + assert fx.subs(K, F0).factor(deep=True) == limit(fx, K, F0).factor(deep=True) + + +def test_issue_13332(): + assert limit(sqrt(30)*5**(-5*x - 1)*(46656*x)**x*(5*x + 2)**(5*x + 5*S.Half) * + (6*x + 2)**(-6*x - 5*S.Half), x, oo) == Rational(25, 36) + + +def test_issue_12564(): + assert limit(x**2 + x*sin(x) + cos(x), x, -oo) is oo + assert limit(x**2 + x*sin(x) + cos(x), x, oo) is oo + assert limit(((x + cos(x))**2).expand(), x, oo) is oo + assert limit(((x + sin(x))**2).expand(), x, oo) is oo + assert limit(((x + cos(x))**2).expand(), x, -oo) is oo + assert limit(((x + sin(x))**2).expand(), x, -oo) is oo + + +def test_issue_14456(): + raises(NotImplementedError, lambda: Limit(exp(x), x, zoo).doit()) + raises(NotImplementedError, lambda: Limit(x**2/(x+1), x, zoo).doit()) + + +def test_issue_14411(): + assert limit(3*sec(4*pi*x - x/3), x, 3*pi/(24*pi - 2)) is -oo + + +def test_issue_13382(): + assert limit(x*(((x + 1)**2 + 1)/(x**2 + 1) - 1), x, oo) == 2 + + +def test_issue_13403(): + assert limit(x*(-1 + (x + log(x + 1) + 1)/(x + log(x))), x, oo) == 1 + + +def test_issue_13416(): + assert limit((-x**3*log(x)**3 + (x - 1)*(x + 1)**2*log(x + 1)**3)/(x**2*log(x)**3), x, oo) == 1 + + +def test_issue_13462(): + assert limit(n**2*(2*n*(-(1 - 1/(2*n))**x + 1) - x - (-x**2/4 + x/4)/n), n, oo) == x**3/24 - x**2/8 + x/12 + + +def test_issue_13750(): + a = Symbol('a') + assert limit(erf(a - x), x, oo) == -1 + assert limit(erf(sqrt(x) - x), x, oo) == -1 + + +def test_issue_14276(): + assert isinstance(limit(sin(x)**log(x), x, oo), Limit) + assert isinstance(limit(sin(x)**cos(x), x, oo), Limit) + assert isinstance(limit(sin(log(cos(x))), x, oo), Limit) + assert limit((1 + 1/(x**2 + cos(x)))**(x**2 + x), x, oo) == E + + +def test_issue_14514(): + assert limit((1/(log(x)**log(x)))**(1/x), x, oo) == 1 + + +def test_issues_14525(): + assert limit(sin(x)**2 - cos(x) + tan(x)*csc(x), x, oo) == AccumBounds(S.NegativeInfinity, S.Infinity) + assert limit(sin(x)**2 - cos(x) + sin(x)*cot(x), x, oo) == AccumBounds(S.NegativeInfinity, S.Infinity) + assert limit(cot(x) - tan(x)**2, x, oo) == AccumBounds(S.NegativeInfinity, S.Infinity) + assert limit(cos(x) - tan(x)**2, x, oo) == AccumBounds(S.NegativeInfinity, S.One) + assert limit(sin(x) - tan(x)**2, x, oo) == AccumBounds(S.NegativeInfinity, S.One) + assert limit(cos(x)**2 - tan(x)**2, x, oo) == AccumBounds(S.NegativeInfinity, S.One) + assert limit(tan(x)**2 + sin(x)**2 - cos(x), x, oo) == AccumBounds(-S.One, S.Infinity) + + +def test_issue_14574(): + assert limit(sqrt(x)*cos(x - x**2) / (x + 1), x, oo) == 0 + + +def test_issue_10102(): + assert limit(fresnels(x), x, oo) == S.Half + assert limit(3 + fresnels(x), x, oo) == 3 + S.Half + assert limit(5*fresnels(x), x, oo) == Rational(5, 2) + assert limit(fresnelc(x), x, oo) == S.Half + assert limit(fresnels(x), x, -oo) == Rational(-1, 2) + assert limit(4*fresnelc(x), x, -oo) == -2 + + +def test_issue_14377(): + raises(NotImplementedError, lambda: limit(exp(I*x)*sin(pi*x), x, oo)) + + +def test_issue_15146(): + e = (x/2) * (-2*x**3 - 2*(x**3 - 1) * x**2 * digamma(x**3 + 1) + \ + 2*(x**3 - 1) * x**2 * digamma(x**3 + x + 1) + x + 3) + assert limit(e, x, oo) == S(1)/3 + + +def test_issue_15202(): + e = (2**x*(2 + 2**(-x)*(-2*2**x + x + 2))/(x + 1))**(x + 1) + assert limit(e, x, oo) == exp(1) + + e = (log(x, 2)**7 + 10*x*factorial(x) + 5**x) / (factorial(x + 1) + 3*factorial(x) + 10**x) + assert limit(e, x, oo) == 10 + + +def test_issue_15282(): + assert limit((x**2000 - (x + 1)**2000) / x**1999, x, oo) == -2000 + + +def test_issue_15984(): + assert limit((-x + log(exp(x) + 1))/x, x, oo, dir='-') == 0 + + +def test_issue_13571(): + assert limit(uppergamma(x, 1) / gamma(x), x, oo) == 1 + + +def test_issue_13575(): + assert limit(acos(erfi(x)), x, 1) == acos(erfi(S.One)) + + +def test_issue_17325(): + assert Limit(sin(x)/x, x, 0, dir="+-").doit() == 1 + assert Limit(x**2, x, 0, dir="+-").doit() == 0 + assert Limit(1/x**2, x, 0, dir="+-").doit() is oo + assert Limit(1/x, x, 0, dir="+-").doit() is zoo + + +def test_issue_10978(): + assert LambertW(x).limit(x, 0) == 0 + + +def test_issue_14313_comment(): + assert limit(floor(n/2), n, oo) is oo + + +def test_issue_15323(): + d = ((1 - 1/x)**x).diff(x) + assert limit(d, x, 1, dir='+') == 1 + + +def test_issue_12571(): + assert limit(-LambertW(-log(x))/log(x), x, 1) == 1 + + +def test_issue_14590(): + assert limit((x**3*((x + 1)/x)**x)/((x + 1)*(x + 2)*(x + 3)), x, oo) == exp(1) + + +def test_issue_14393(): + a, b = symbols('a b') + assert limit((x**b - y**b)/(x**a - y**a), x, y) == b*y**(-a + b)/a + + +def test_issue_14556(): + assert limit(factorial(n + 1)**(1/(n + 1)) - factorial(n)**(1/n), n, oo) == exp(-1) + + +def test_issue_14811(): + assert limit(((1 + ((S(2)/3)**(x + 1)))**(2**x))/(2**((S(4)/3)**(x - 1))), x, oo) == oo + + +def test_issue_16222(): + assert limit(exp(x), x, 1000000000) == exp(1000000000) + + +def test_issue_16714(): + assert limit(((x**(x + 1) + (x + 1)**x) / x**(x + 1))**x, x, oo) == exp(exp(1)) + + +def test_issue_16722(): + z = symbols('z', positive=True) + assert limit(binomial(n + z, n)*n**-z, n, oo) == 1/gamma(z + 1) + z = symbols('z', positive=True, integer=True) + assert limit(binomial(n + z, n)*n**-z, n, oo) == 1/gamma(z + 1) + + +def test_issue_17431(): + assert limit(((n + 1) + 1) / (((n + 1) + 2) * factorial(n + 1)) * + (n + 2) * factorial(n) / (n + 1), n, oo) == 0 + assert limit((n + 2)**2*factorial(n)/((n + 1)*(n + 3)*factorial(n + 1)) + , n, oo) == 0 + assert limit((n + 1) * factorial(n) / (n * factorial(n + 1)), n, oo) == 0 + + +def test_issue_17671(): + assert limit(Ei(-log(x)) - log(log(x))/x, x, 1) == EulerGamma + + +def test_issue_17751(): + a, b, c, x = symbols('a b c x', positive=True) + assert limit((a + 1)*x - sqrt((a + 1)**2*x**2 + b*x + c), x, oo) == -b/(2*a + 2) + + +def test_issue_17792(): + assert limit(factorial(n)/sqrt(n)*(exp(1)/n)**n, n, oo) == sqrt(2)*sqrt(pi) + + +def test_issue_18118(): + assert limit(sign(sin(x)), x, 0, "-") == -1 + assert limit(sign(sin(x)), x, 0, "+") == 1 + + +def test_issue_18306(): + assert limit(sin(sqrt(x))/sqrt(sin(x)), x, 0, '+') == 1 + + +def test_issue_18378(): + assert limit(log(exp(3*x) + x)/log(exp(x) + x**100), x, oo) == 3 + + +def test_issue_18399(): + assert limit((1 - S(1)/2*x)**(3*x), x, oo) is zoo + assert limit((-x)**x, x, oo) is zoo + + +def test_issue_18442(): + assert limit(tan(x)**(2**(sqrt(pi))), x, oo, dir='-') == Limit(tan(x)**(2**(sqrt(pi))), x, oo, dir='-') + + +def test_issue_18452(): + assert limit(abs(log(x))**x, x, 0) == 1 + assert limit(abs(log(x))**x, x, 0, "-") == 1 + + +def test_issue_18473(): + assert limit(sin(x)**(1/x), x, oo) == Limit(sin(x)**(1/x), x, oo, dir='-') + assert limit(cos(x)**(1/x), x, oo) == Limit(cos(x)**(1/x), x, oo, dir='-') + assert limit(tan(x)**(1/x), x, oo) == Limit(tan(x)**(1/x), x, oo, dir='-') + assert limit((cos(x) + 2)**(1/x), x, oo) == 1 + assert limit((sin(x) + 10)**(1/x), x, oo) == 1 + assert limit((cos(x) - 2)**(1/x), x, oo) == Limit((cos(x) - 2)**(1/x), x, oo, dir='-') + assert limit((cos(x) + 1)**(1/x), x, oo) == AccumBounds(0, 1) + assert limit((tan(x)**2)**(2/x) , x, oo) == AccumBounds(0, oo) + assert limit((sin(x)**2)**(1/x), x, oo) == AccumBounds(0, 1) + # Tests for issue #23751 + assert limit((cos(x) + 1)**(1/x), x, -oo) == AccumBounds(1, oo) + assert limit((sin(x)**2)**(1/x), x, -oo) == AccumBounds(1, oo) + assert limit((tan(x)**2)**(2/x) , x, -oo) == AccumBounds(0, oo) + + +def test_issue_18482(): + assert limit((2*exp(3*x)/(exp(2*x) + 1))**(1/x), x, oo) == exp(1) + + +def test_issue_18508(): + assert limit(sin(x)/sqrt(1-cos(x)), x, 0) == sqrt(2) + assert limit(sin(x)/sqrt(1-cos(x)), x, 0, dir='+') == sqrt(2) + assert limit(sin(x)/sqrt(1-cos(x)), x, 0, dir='-') == -sqrt(2) + + +def test_issue_18521(): + raises(NotImplementedError, lambda: limit(exp((2 - n) * x), x, oo)) + + +def test_issue_18969(): + a, b = symbols('a b', positive=True) + assert limit(LambertW(a), a, b) == LambertW(b) + assert limit(exp(LambertW(a)), a, b) == exp(LambertW(b)) + + +def test_issue_18992(): + assert limit(n/(factorial(n)**(1/n)), n, oo) == exp(1) + + +def test_issue_19067(): + x = Symbol('x') + assert limit(gamma(x)/(gamma(x - 1)*gamma(x + 2)), x, 0) == -1 + + +def test_issue_19586(): + assert limit(x**(2**x*3**(-x)), x, oo) == 1 + + +def test_issue_13715(): + n = Symbol('n') + p = Symbol('p', zero=True) + assert limit(n + p, n, 0) == 0 + + +def test_issue_15055(): + assert limit(n**3*((-n - 1)*sin(1/n) + (n + 2)*sin(1/(n + 1)))/(-n + 1), n, oo) == 1 + + +def test_issue_16708(): + m, vi = symbols('m vi', positive=True) + B, ti, d = symbols('B ti d') + assert limit((B*ti*vi - sqrt(m)*sqrt(-2*B*d*vi + m*(vi)**2) + m*vi)/(B*vi), B, 0) == (d + ti*vi)/vi + + +def test_issue_19154(): + assert limit(besseli(1, 3 *x)/(x *besseli(1, x)**3), x , oo) == 2*sqrt(3)*pi/3 + assert limit(besseli(1, 3 *x)/(x *besseli(1, x)**3), x , -oo) == -2*sqrt(3)*pi/3 + + +def test_issue_19453(): + beta = Symbol("beta", positive=True) + h = Symbol("h", positive=True) + m = Symbol("m", positive=True) + w = Symbol("omega", positive=True) + g = Symbol("g", positive=True) + + e = exp(1) + q = 3*h**2*beta*g*e**(0.5*h*beta*w) + p = m**2*w**2 + s = e**(h*beta*w) - 1 + Z = -q/(4*p*s) - q/(2*p*s**2) - q*(e**(h*beta*w) + 1)/(2*p*s**3)\ + + e**(0.5*h*beta*w)/s + E = -diff(log(Z), beta) + + assert limit(E - 0.5*h*w, beta, oo) == 0 + assert limit(E.simplify() - 0.5*h*w, beta, oo) == 0 + + +def test_issue_19739(): + assert limit((-S(1)/4)**x, x, oo) == 0 + + +def test_issue_19766(): + assert limit(2**(-x)*sqrt(4**(x + 1) + 1), x, oo) == 2 + + +def test_issue_19770(): + m = Symbol('m') + # the result is not 0 for non-real m + assert limit(cos(m*x)/x, x, oo) == Limit(cos(m*x)/x, x, oo, dir='-') + m = Symbol('m', real=True) + # can be improved to give the correct result 0 + assert limit(cos(m*x)/x, x, oo) == Limit(cos(m*x)/x, x, oo, dir='-') + m = Symbol('m', nonzero=True) + assert limit(cos(m*x), x, oo) == AccumBounds(-1, 1) + assert limit(cos(m*x)/x, x, oo) == 0 + + +def test_issue_7535(): + assert limit(tan(x)/sin(tan(x)), x, pi/2) == Limit(tan(x)/sin(tan(x)), x, pi/2, dir='+') + assert limit(tan(x)/sin(tan(x)), x, pi/2, dir='-') == Limit(tan(x)/sin(tan(x)), x, pi/2, dir='-') + assert limit(tan(x)/sin(tan(x)), x, pi/2, dir='+-') == Limit(tan(x)/sin(tan(x)), x, pi/2, dir='+-') + assert limit(sin(tan(x)),x,pi/2) == AccumBounds(-1, 1) + assert -oo*(1/sin(-oo)) == AccumBounds(-oo, oo) + assert oo*(1/sin(oo)) == AccumBounds(-oo, oo) + assert oo*(1/sin(-oo)) == AccumBounds(-oo, oo) + assert -oo*(1/sin(oo)) == AccumBounds(-oo, oo) + + +def test_issue_20365(): + assert limit(((x + 1)**(1/x) - E)/x, x, 0) == -E/2 + + +def test_issue_21031(): + assert limit(((1 + x)**(1/x) - (1 + 2*x)**(1/(2*x)))/asin(x), x, 0) == E/2 + + +def test_issue_21038(): + assert limit(sin(pi*x)/(3*x - 12), x, 4) == pi/3 + + +def test_issue_20578(): + expr = abs(x) * sin(1/x) + assert limit(expr,x,0,'+') == 0 + assert limit(expr,x,0,'-') == 0 + assert limit(expr,x,0,'+-') == 0 + + +def test_issue_21227(): + f = log(x) + + assert f.nseries(x, logx=y) == y + assert f.nseries(x, logx=-x) == -x + + f = log(-log(x)) + + assert f.nseries(x, logx=y) == log(-y) + assert f.nseries(x, logx=-x) == log(x) + + f = log(log(x)) + + assert f.nseries(x, logx=y) == log(y) + assert f.nseries(x, logx=-x) == log(-x) + assert f.nseries(x, logx=x) == log(x) + + f = log(log(log(1/x))) + + assert f.nseries(x, logx=y) == log(log(-y)) + assert f.nseries(x, logx=-y) == log(log(y)) + assert f.nseries(x, logx=x) == log(log(-x)) + assert f.nseries(x, logx=-x) == log(log(x)) + + +def test_issue_21415(): + exp = (x-1)*cos(1/(x-1)) + assert exp.limit(x,1) == 0 + assert exp.expand().limit(x,1) == 0 + + +def test_issue_21530(): + assert limit(sinh(n + 1)/sinh(n), n, oo) == E + + +def test_issue_21550(): + r = (sqrt(5) - 1)/2 + assert limit((x - r)/(x**2 + x - 1), x, r) == sqrt(5)/5 + + +def test_issue_21661(): + out = limit((x**(x + 1) * (log(x) + 1) + 1) / x, x, 11) + assert out == S(3138428376722)/11 + 285311670611*log(11) + + +def test_issue_21701(): + assert limit((besselj(z, x)/x**z).subs(z, 7), x, 0) == S(1)/645120 + + +def test_issue_21721(): + a = Symbol('a', real=True) + I = integrate(1/(pi*(1 + (x - a)**2)), x) + assert I.limit(x, oo) == S.Half + + +def test_issue_21756(): + term = (1 - exp(-2*I*pi*z))/(1 - exp(-2*I*pi*z/5)) + assert term.limit(z, 0) == 5 + assert re(term).limit(z, 0) == 5 + + +def test_issue_21785(): + a = Symbol('a') + assert sqrt((-a**2 + x**2)/(1 - x**2)).limit(a, 1, '-') == I + + +def test_issue_22181(): + assert limit((-1)**x * 2**(-x), x, oo) == 0 + + +def test_issue_22220(): + e1 = sqrt(30)*atan(sqrt(30)*tan(x/2)/6)/30 + e2 = sqrt(30)*I*(-log(sqrt(2)*tan(x/2) - 2*sqrt(15)*I/5) + + +log(sqrt(2)*tan(x/2) + 2*sqrt(15)*I/5))/60 + + assert limit(e1, x, -pi) == -sqrt(30)*pi/60 + assert limit(e2, x, -pi) == -sqrt(30)*pi/30 + + assert limit(e1, x, -pi, '-') == sqrt(30)*pi/60 + assert limit(e2, x, -pi, '-') == 0 + + # test https://github.com/sympy/sympy/issues/22220#issuecomment-972727694 + expr = log(x - I) - log(-x - I) + expr2 = logcombine(expr, force=True) + assert limit(expr, x, oo) == limit(expr2, x, oo) == I*pi + + # test https://github.com/sympy/sympy/issues/22220#issuecomment-1077618340 + expr = expr = (-log(tan(x/2) - I) +log(tan(x/2) + I)) + assert limit(expr, x, pi, '+') == 2*I*pi + assert limit(expr, x, pi, '-') == 0 + + +def test_issue_22334(): + k, n = symbols('k, n', positive=True) + assert limit((n+1)**k/((n+1)**(k+1) - (n)**(k+1)), n, oo) == 1/(k + 1) + assert limit((n+1)**k/((n+1)**(k+1) - (n)**(k+1)).expand(), n, oo) == 1/(k + 1) + assert limit((n+1)**k/(n*(-n**k + (n + 1)**k) + (n + 1)**k), n, oo) == 1/(k + 1) + + +def test_issue_22836_limit(): + assert limit(2**(1/x)/factorial(1/(x)), x, 0) == S.Zero + + +def test_sympyissue_22986(): + assert limit(acosh(1 + 1/x)*sqrt(x), x, oo) == sqrt(2) + + +def test_issue_23231(): + f = (2**x - 2**(-x))/(2**x + 2**(-x)) + assert limit(f, x, -oo) == -1 + + +def test_issue_23596(): + assert integrate(((1 + x)/x**2)*exp(-1/x), (x, 0, oo)) == oo + + +def test_issue_23752(): + expr1 = sqrt(-I*x**2 + x - 3) + expr2 = sqrt(-I*x**2 + I*x - 3) + assert limit(expr1, x, 0, '+') == -sqrt(3)*I + assert limit(expr1, x, 0, '-') == -sqrt(3)*I + assert limit(expr2, x, 0, '+') == sqrt(3)*I + assert limit(expr2, x, 0, '-') == -sqrt(3)*I + + +def test_issue_24276(): + fx = log(tan(pi/2*tanh(x))).diff(x) + assert fx.limit(x, oo) == 2 + assert fx.simplify().limit(x, oo) == 2 + assert fx.rewrite(sin).limit(x, oo) == 2 + assert fx.rewrite(sin).simplify().limit(x, oo) == 2 + +def test_issue_25230(): + a = Symbol('a', real = True) + b = Symbol('b', positive = True) + c = Symbol('c', negative = True) + n = Symbol('n', integer = True) + raises(NotImplementedError, lambda: limit(Mod(x, a), x, a)) + assert limit(Mod(x, b), x, n*b, '+') == 0 + assert limit(Mod(x, b), x, n*b, '-') == b + assert limit(Mod(x, c), x, n*c, '+') == c + assert limit(Mod(x, c), x, n*c, '-') == 0 + + +def test_issue_25582(): + + assert limit(asin(exp(x)), x, oo, '-') == -oo*I + assert limit(acos(exp(x)), x, oo, '-') == oo*I + assert limit(atan(exp(x)), x, oo, '-') == pi/2 + assert limit(acot(exp(x)), x, oo, '-') == 0 + assert limit(asec(exp(x)), x, oo, '-') == pi/2 + assert limit(acsc(exp(x)), x, oo, '-') == 0 + + +def test_issue_25847(): + #atan + assert limit(atan(sin(x)/x), x, 0, '+-') == pi/4 + assert limit(atan(exp(1/x)), x, 0, '+') == pi/2 + assert limit(atan(exp(1/x)), x, 0, '-') == 0 + + #asin + assert limit(asin(sin(x)/x), x, 0, '+-') == pi/2 + assert limit(asin(exp(1/x)), x, 0, '+') == -oo*I + assert limit(asin(exp(1/x)), x, 0, '-') == 0 + + #acos + assert limit(acos(sin(x)/x), x, 0, '+-') == 0 + assert limit(acos(exp(1/x)), x, 0, '+') == oo*I + assert limit(acos(exp(1/x)), x, 0, '-') == pi/2 + + #acot + assert limit(acot(sin(x)/x), x, 0, '+-') == pi/4 + assert limit(acot(exp(1/x)), x, 0, '+') == 0 + assert limit(acot(exp(1/x)), x, 0, '-') == pi/2 + + #asec + assert limit(asec(sin(x)/x), x, 0, '+-') == 0 + assert limit(asec(exp(1/x)), x, 0, '+') == pi/2 + assert limit(asec(exp(1/x)), x, 0, '-') == oo*I + + #acsc + assert limit(acsc(sin(x)/x), x, 0, '+-') == pi/2 + assert limit(acsc(exp(1/x)), x, 0, '+') == 0 + assert limit(acsc(exp(1/x)), x, 0, '-') == -oo*I + + #atanh + assert limit(atanh(sin(x)/x), x, 0, '+-') == oo + assert limit(atanh(exp(1/x)), x, 0, '+') == -I*pi/2 + assert limit(atanh(exp(1/x)), x, 0, '-') == 0 + + #asinh + assert limit(asinh(sin(x)/x), x, 0, '+-') == log(1 + sqrt(2)) + assert limit(asinh(exp(1/x)), x, 0, '+') == oo + assert limit(asinh(exp(1/x)), x, 0, '-') == 0 + + #acosh + assert limit(acosh(sin(x)/x), x, 0, '+-') == 0 + assert limit(acosh(exp(1/x)), x, 0, '+') == oo + assert limit(acosh(exp(1/x)), x, 0, '-') == I*pi/2 + + #acoth + assert limit(acoth(sin(x)/x), x, 0, '+-') == oo + assert limit(acoth(exp(1/x)), x, 0, '+') == 0 + assert limit(acoth(exp(1/x)), x, 0, '-') == -I*pi/2 + + #asech + assert limit(asech(sin(x)/x), x, 0, '+-') == 0 + assert limit(asech(exp(1/x)), x, 0, '+') == I*pi/2 + assert limit(asech(exp(1/x)), x, 0, '-') == oo + + #acsch + assert limit(acsch(sin(x)/x), x, 0, '+-') == log(1 + sqrt(2)) + assert limit(acsch(exp(1/x)), x, 0, '+') == 0 + assert limit(acsch(exp(1/x)), x, 0, '-') == oo + + +def test_issue_26040(): + assert limit(besseli(0, x + 1)/besseli(0, x), x, oo) == S.Exp1 + + +def test_issue_26250(): + e = elliptic_e(4*x/(x**2 + 2*x + 1)) + k = elliptic_k(4*x/(x**2 + 2*x + 1)) + e1 = ((1-3*x**2)*e**2/2 - (x**2-2*x+1)*e*k/2) + e2 = pi**2*(x**8 - 2*x**7 - x**6 + 4*x**5 - x**4 - 2*x**3 + x**2) + assert limit(e1/e2, x, 0) == -S(1)/8 + + +def test_issue_26513(): + assert limit(abs((-x/(x+1))**x), x ,oo) == exp(-1) + assert limit((x/(x + 1))**x, x, oo) == exp(-1) + raises (NotImplementedError, lambda: limit((-x/(x+1))**x, x, oo)) + + +def test_issue_26916(): + assert limit(Ei(x)*exp(-x), x, +oo) == 0 + assert limit(Ei(x)*exp(-x), x, -oo) == 0 + + +def test_issue_22982_15323(): + assert limit((log(E + 1/x) - 1)**(1 - sqrt(E + 1/x)), x, oo) == oo + assert limit((1 - 1/x)**x*(log(1 - 1/x) + 1/(x*(1 - 1/x))), x, 1, dir='+') == 1 + assert limit((log(E + 1/x) )**(1 - sqrt(E + 1/x)), x, oo) == 1 + assert limit((log(E + 1/x) - 1)**(- sqrt(E + 1/x)), x, oo) == oo + + +def test_issue_26991(): + assert limit(x/((x - 6)*sinh(tanh(0.03*x)) + tanh(x) - 0.5), x, oo) == 1/sinh(1) + +def test_issue_27278(): + expr = (1/(x*log((x + 3)/x)))**x*((x + 1)*log((x + 4)/(x + 1)))**(x + 1)/3 + assert limit(expr, x, oo) == 1 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_limitseq.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_limitseq.py new file mode 100644 index 0000000000000000000000000000000000000000..362bb0397feb0ec63929920855c81279eca0bd6a --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_limitseq.py @@ -0,0 +1,177 @@ +from sympy.concrete.summations import Sum +from sympy.core.add import Add +from sympy.core.numbers import (I, Rational, oo, pi) +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.combinatorial.factorials import (binomial, factorial, subfactorial) +from sympy.functions.combinatorial.numbers import (fibonacci, harmonic) +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.functions.special.gamma_functions import gamma +from sympy.series.limitseq import limit_seq +from sympy.series.limitseq import difference_delta as dd +from sympy.testing.pytest import raises, XFAIL +from sympy.calculus.accumulationbounds import AccumulationBounds + +n, m, k = symbols('n m k', integer=True) + + +def test_difference_delta(): + e = n*(n + 1) + e2 = e * k + + assert dd(e) == 2*n + 2 + assert dd(e2, n, 2) == k*(4*n + 6) + + raises(ValueError, lambda: dd(e2)) + raises(ValueError, lambda: dd(e2, n, oo)) + + +def test_difference_delta__Sum(): + e = Sum(1/k, (k, 1, n)) + assert dd(e, n) == 1/(n + 1) + assert dd(e, n, 5) == Add(*[1/(i + n + 1) for i in range(5)]) + + e = Sum(1/k, (k, 1, 3*n)) + assert dd(e, n) == Add(*[1/(i + 3*n + 1) for i in range(3)]) + + e = n * Sum(1/k, (k, 1, n)) + assert dd(e, n) == 1 + Sum(1/k, (k, 1, n)) + + e = Sum(1/k, (k, 1, n), (m, 1, n)) + assert dd(e, n) == harmonic(n) + + +def test_difference_delta__Add(): + e = n + n*(n + 1) + assert dd(e, n) == 2*n + 3 + assert dd(e, n, 2) == 4*n + 8 + + e = n + Sum(1/k, (k, 1, n)) + assert dd(e, n) == 1 + 1/(n + 1) + assert dd(e, n, 5) == 5 + Add(*[1/(i + n + 1) for i in range(5)]) + + +def test_difference_delta__Pow(): + e = 4**n + assert dd(e, n) == 3*4**n + assert dd(e, n, 2) == 15*4**n + + e = 4**(2*n) + assert dd(e, n) == 15*4**(2*n) + assert dd(e, n, 2) == 255*4**(2*n) + + e = n**4 + assert dd(e, n) == (n + 1)**4 - n**4 + + e = n**n + assert dd(e, n) == (n + 1)**(n + 1) - n**n + + +def test_limit_seq(): + e = binomial(2*n, n) / Sum(binomial(2*k, k), (k, 1, n)) + assert limit_seq(e) == S(3) / 4 + assert limit_seq(e, m) == e + + e = (5*n**3 + 3*n**2 + 4) / (3*n**3 + 4*n - 5) + assert limit_seq(e, n) == S(5) / 3 + + e = (harmonic(n) * Sum(harmonic(k), (k, 1, n))) / (n * harmonic(2*n)**2) + assert limit_seq(e, n) == 1 + + e = Sum(k**2 * Sum(2**m/m, (m, 1, k)), (k, 1, n)) / (2**n*n) + assert limit_seq(e, n) == 4 + + e = (Sum(binomial(3*k, k) * binomial(5*k, k), (k, 1, n)) / + (binomial(3*n, n) * binomial(5*n, n))) + assert limit_seq(e, n) == S(84375) / 83351 + + e = Sum(harmonic(k)**2/k, (k, 1, 2*n)) / harmonic(n)**3 + assert limit_seq(e, n) == S.One / 3 + + raises(ValueError, lambda: limit_seq(e * m)) + + +def test_alternating_sign(): + assert limit_seq((-1)**n/n**2, n) == 0 + assert limit_seq((-2)**(n+1)/(n + 3**n), n) == 0 + assert limit_seq((2*n + (-1)**n)/(n + 1), n) == 2 + assert limit_seq(sin(pi*n), n) == 0 + assert limit_seq(cos(2*pi*n), n) == 1 + assert limit_seq((S.NegativeOne/5)**n, n) == 0 + assert limit_seq((Rational(-1, 5))**n, n) == 0 + assert limit_seq((I/3)**n, n) == 0 + assert limit_seq(sqrt(n)*(I/2)**n, n) == 0 + assert limit_seq(n**7*(I/3)**n, n) == 0 + assert limit_seq(n/(n + 1) + (I/2)**n, n) == 1 + + +def test_accum_bounds(): + assert limit_seq((-1)**n, n) == AccumulationBounds(-1, 1) + assert limit_seq(cos(pi*n), n) == AccumulationBounds(-1, 1) + assert limit_seq(sin(pi*n/2)**2, n) == AccumulationBounds(0, 1) + assert limit_seq(2*(-3)**n/(n + 3**n), n) == AccumulationBounds(-2, 2) + assert limit_seq(3*n/(n + 1) + 2*(-1)**n, n) == AccumulationBounds(1, 5) + + +def test_limitseq_sum(): + from sympy.abc import x, y, z + assert limit_seq(Sum(1/x, (x, 1, y)) - log(y), y) == S.EulerGamma + assert limit_seq(Sum(1/x, (x, 1, y)) - 1/y, y) is S.Infinity + assert (limit_seq(binomial(2*x, x) / Sum(binomial(2*y, y), (y, 1, x)), x) == + S(3) / 4) + assert (limit_seq(Sum(y**2 * Sum(2**z/z, (z, 1, y)), (y, 1, x)) / + (2**x*x), x) == 4) + + +def test_issue_9308(): + assert limit_seq(subfactorial(n)/factorial(n), n) == exp(-1) + + +def test_issue_10382(): + n = Symbol('n', integer=True) + assert limit_seq(fibonacci(n+1)/fibonacci(n), n).together() == S.GoldenRatio + + +def test_issue_11672(): + assert limit_seq(Rational(-1, 2)**n, n) == 0 + + +def test_issue_14196(): + k, n = symbols('k, n', positive=True) + m = Symbol('m') + assert limit_seq(Sum(m**k, (m, 1, n)).doit()/(n**(k + 1)), n) == 1/(k + 1) + + +def test_issue_16735(): + assert limit_seq(5**n/factorial(n), n) == 0 + + +def test_issue_19868(): + assert limit_seq(1/gamma(n + S.One/2), n) == 0 + + +@XFAIL +def test_limit_seq_fail(): + # improve Summation algorithm or add ad-hoc criteria + e = (harmonic(n)**3 * Sum(1/harmonic(k), (k, 1, n)) / + (n * Sum(harmonic(k)/k, (k, 1, n)))) + assert limit_seq(e, n) == 2 + + # No unique dominant term + e = (Sum(2**k * binomial(2*k, k) / k**2, (k, 1, n)) / + (Sum(2**k/k*2, (k, 1, n)) * Sum(binomial(2*k, k), (k, 1, n)))) + assert limit_seq(e, n) == S(3) / 7 + + # Simplifications of summations needs to be improved. + e = n**3*Sum(2**k/k**2, (k, 1, n))**2 / (2**n * Sum(2**k/k, (k, 1, n))) + assert limit_seq(e, n) == 2 + + e = (harmonic(n) * Sum(2**k/k, (k, 1, n)) / + (n * Sum(2**k*harmonic(k)/k**2, (k, 1, n)))) + assert limit_seq(e, n) == 1 + + e = (Sum(2**k*factorial(k) / k**2, (k, 1, 2*n)) / + (Sum(4**k/k**2, (k, 1, n)) * Sum(factorial(k), (k, 1, 2*n)))) + assert limit_seq(e, n) == S(3) / 16 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_lseries.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_lseries.py new file mode 100644 index 0000000000000000000000000000000000000000..42d327bf60c76eebdc4570d631efef4bc84b58e3 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_lseries.py @@ -0,0 +1,65 @@ +from sympy.core.numbers import E +from sympy.core.singleton import S +from sympy.functions.elementary.exponential import exp +from sympy.functions.elementary.hyperbolic import tanh +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.series.order import Order +from sympy.abc import x, y + + +def test_sin(): + e = sin(x).lseries(x) + assert next(e) == x + assert next(e) == -x**3/6 + assert next(e) == x**5/120 + + +def test_cos(): + e = cos(x).lseries(x) + assert next(e) == 1 + assert next(e) == -x**2/2 + assert next(e) == x**4/24 + + +def test_exp(): + e = exp(x).lseries(x) + assert next(e) == 1 + assert next(e) == x + assert next(e) == x**2/2 + assert next(e) == x**3/6 + + +def test_exp2(): + e = exp(cos(x)).lseries(x) + assert next(e) == E + assert next(e) == -E*x**2/2 + assert next(e) == E*x**4/6 + assert next(e) == -31*E*x**6/720 + + +def test_simple(): + assert list(x.lseries()) == [x] + assert list(S.One.lseries(x)) == [1] + assert not next((x/(x + y)).lseries(y)).has(Order) + + +def test_issue_5183(): + s = (x + 1/x).lseries() + assert list(s) == [1/x, x] + assert next((x + x**2).lseries()) == x + assert next(((1 + x)**7).lseries(x)) == 1 + assert next((sin(x + y)).series(x, n=3).lseries(y)) == x + # it would be nice if all terms were grouped, but in the + # following case that would mean that all the terms would have + # to be known since, for example, every term has a constant in it. + s = ((1 + x)**7).series(x, 1, n=None) + assert [next(s) for i in range(2)] == [128, -448 + 448*x] + + +def test_issue_6999(): + s = tanh(x).lseries(x, 1) + assert next(s) == tanh(1) + assert next(s) == x - (x - 1)*tanh(1)**2 - 1 + assert next(s) == -(x - 1)**2*tanh(1) + (x - 1)**2*tanh(1)**3 + assert next(s) == -(x - 1)**3*tanh(1)**4 - (x - 1)**3/3 + \ + 4*(x - 1)**3*tanh(1)**2/3 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_nseries.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_nseries.py new file mode 100644 index 0000000000000000000000000000000000000000..a2f20add82d3e858e2ce145fc9fcd4a6548a48cc --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_nseries.py @@ -0,0 +1,557 @@ +from sympy.calculus.util import AccumBounds +from sympy.core.function import (Derivative, PoleError) +from sympy.core.numbers import (E, I, Integer, Rational, pi) +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.elementary.complexes import sign +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.hyperbolic import (acosh, acoth, asinh, atanh, cosh, coth, sinh, tanh) +from sympy.functions.elementary.integers import (ceiling, floor, frac) +from sympy.functions.elementary.miscellaneous import (cbrt, sqrt) +from sympy.functions.elementary.trigonometric import (asin, cos, cot, sin, tan) +from sympy.series.limits import limit +from sympy.series.order import O +from sympy.abc import x, y, z + +from sympy.testing.pytest import raises, XFAIL + + +def test_simple_1(): + assert x.nseries(x, n=5) == x + assert y.nseries(x, n=5) == y + assert (1/(x*y)).nseries(y, n=5) == 1/(x*y) + assert Rational(3, 4).nseries(x, n=5) == Rational(3, 4) + assert x.nseries() == x + + +def test_mul_0(): + assert (x*log(x)).nseries(x, n=5) == x*log(x) + + +def test_mul_1(): + assert (x*log(2 + x)).nseries(x, n=5) == x*log(2) + x**2/2 - x**3/8 + \ + x**4/24 + O(x**5) + assert (x*log(1 + x)).nseries( + x, n=5) == x**2 - x**3/2 + x**4/3 + O(x**5) + + +def test_pow_0(): + assert (x**2).nseries(x, n=5) == x**2 + assert (1/x).nseries(x, n=5) == 1/x + assert (1/x**2).nseries(x, n=5) == 1/x**2 + assert (x**Rational(2, 3)).nseries(x, n=5) == (x**Rational(2, 3)) + assert (sqrt(x)**3).nseries(x, n=5) == (sqrt(x)**3) + + +def test_pow_1(): + assert ((1 + x)**2).nseries(x, n=5) == x**2 + 2*x + 1 + + # https://github.com/sympy/sympy/issues/21075 + assert ((sqrt(x) + 1)**2).nseries(x) == 2*sqrt(x) + x + 1 + assert ((sqrt(x) + cbrt(x))**2).nseries(x) == 2*x**Rational(5, 6)\ + + x**Rational(2, 3) + x + + +def test_geometric_1(): + assert (1/(1 - x)).nseries(x, n=5) == 1 + x + x**2 + x**3 + x**4 + O(x**5) + assert (x/(1 - x)).nseries(x, n=6) == x + x**2 + x**3 + x**4 + x**5 + O(x**6) + assert (x**3/(1 - x)).nseries(x, n=8) == x**3 + x**4 + x**5 + x**6 + \ + x**7 + O(x**8) + + +def test_sqrt_1(): + assert sqrt(1 + x).nseries(x, n=5) == 1 + x/2 - x**2/8 + x**3/16 - 5*x**4/128 + O(x**5) + + +def test_exp_1(): + assert exp(x).nseries(x, n=5) == 1 + x + x**2/2 + x**3/6 + x**4/24 + O(x**5) + assert exp(x).nseries(x, n=12) == 1 + x + x**2/2 + x**3/6 + x**4/24 + x**5/120 + \ + x**6/720 + x**7/5040 + x**8/40320 + x**9/362880 + x**10/3628800 + \ + x**11/39916800 + O(x**12) + assert exp(1/x).nseries(x, n=5) == exp(1/x) + assert exp(1/(1 + x)).nseries(x, n=4) == \ + (E*(1 - x - 13*x**3/6 + 3*x**2/2)).expand() + O(x**4) + assert exp(2 + x).nseries(x, n=5) == \ + (exp(2)*(1 + x + x**2/2 + x**3/6 + x**4/24)).expand() + O(x**5) + + +def test_exp_sqrt_1(): + assert exp(1 + sqrt(x)).nseries(x, n=3) == \ + (exp(1)*(1 + sqrt(x) + x/2 + sqrt(x)*x/6)).expand() + O(sqrt(x)**3) + + +def test_power_x_x1(): + assert (exp(x*log(x))).nseries(x, n=4) == \ + 1 + x*log(x) + x**2*log(x)**2/2 + x**3*log(x)**3/6 + O(x**4*log(x)**4) + + +def test_power_x_x2(): + assert (x**x).nseries(x, n=4) == \ + 1 + x*log(x) + x**2*log(x)**2/2 + x**3*log(x)**3/6 + O(x**4*log(x)**4) + + +def test_log_singular1(): + assert log(1 + 1/x).nseries(x, n=5) == x - log(x) - x**2/2 + x**3/3 - \ + x**4/4 + O(x**5) + + +def test_log_power1(): + e = 1 / (1/x + x ** (log(3)/log(2))) + assert e.nseries(x, n=5) == -x**(log(3)/log(2) + 2) + x + O(x**5) + + +def test_log_series(): + l = Symbol('l') + e = 1/(1 - log(x)) + assert e.nseries(x, n=5, logx=l) == 1/(1 - l) + + +def test_log2(): + e = log(-1/x) + assert e.nseries(x, n=5) == -log(x) + log(-1) + + +def test_log3(): + l = Symbol('l') + e = 1/log(-1/x) + assert e.nseries(x, n=4, logx=l) == 1/(-l + log(-1)) + + +def test_series1(): + e = sin(x) + assert e.nseries(x, 0, 0) != 0 + assert e.nseries(x, 0, 0) == O(1, x) + assert e.nseries(x, 0, 1) == O(x, x) + assert e.nseries(x, 0, 2) == x + O(x**2, x) + assert e.nseries(x, 0, 3) == x + O(x**3, x) + assert e.nseries(x, 0, 4) == x - x**3/6 + O(x**4, x) + + e = (exp(x) - 1)/x + assert e.nseries(x, 0, 3) == 1 + x/2 + x**2/6 + O(x**3) + + assert x.nseries(x, 0, 2) == x + + +@XFAIL +def test_series1_failing(): + assert x.nseries(x, 0, 0) == O(1, x) + assert x.nseries(x, 0, 1) == O(x, x) + + +def test_seriesbug1(): + assert (1/x).nseries(x, 0, 3) == 1/x + assert (x + 1/x).nseries(x, 0, 3) == x + 1/x + + +def test_series2x(): + assert ((x + 1)**(-2)).nseries(x, 0, 4) == 1 - 2*x + 3*x**2 - 4*x**3 + O(x**4, x) + assert ((x + 1)**(-1)).nseries(x, 0, 4) == 1 - x + x**2 - x**3 + O(x**4, x) + assert ((x + 1)**0).nseries(x, 0, 3) == 1 + assert ((x + 1)**1).nseries(x, 0, 3) == 1 + x + assert ((x + 1)**2).nseries(x, 0, 3) == x**2 + 2*x + 1 + assert ((x + 1)**3).nseries(x, 0, 3) == 1 + 3*x + 3*x**2 + O(x**3) + + assert (1/(1 + x)).nseries(x, 0, 4) == 1 - x + x**2 - x**3 + O(x**4, x) + assert (x + 3/(1 + 2*x)).nseries(x, 0, 4) == 3 - 5*x + 12*x**2 - 24*x**3 + O(x**4, x) + + assert ((1/x + 1)**3).nseries(x, 0, 3) == 1 + 3/x + 3/x**2 + x**(-3) + assert (1/(1 + 1/x)).nseries(x, 0, 4) == x - x**2 + x**3 - O(x**4, x) + assert (1/(1 + 1/x**2)).nseries(x, 0, 6) == x**2 - x**4 + O(x**6, x) + + +def test_bug2(): # 1/log(0)*log(0) problem + w = Symbol("w") + e = (w**(-1) + w**( + -log(3)*log(2)**(-1)))**(-1)*(3*w**(-log(3)*log(2)**(-1)) + 2*w**(-1)) + e = e.expand() + assert e.nseries(w, 0, 4).subs(w, 0) == 3 + + +def test_exp(): + e = (1 + x)**(1/x) + assert e.nseries(x, n=3) == exp(1) - x*exp(1)/2 + 11*exp(1)*x**2/24 + O(x**3) + + +def test_exp2(): + w = Symbol("w") + e = w**(1 - log(x)/(log(2) + log(x))) + logw = Symbol("logw") + assert e.nseries( + w, 0, 1, logx=logw) == exp(logw*log(2)/(log(x) + log(2))) + + +def test_bug3(): + e = (2/x + 3/x**2)/(1/x + 1/x**2) + assert e.nseries(x, n=3) == 3 - x + x**2 + O(x**3) + + +def test_generalexponent(): + p = 2 + e = (2/x + 3/x**p)/(1/x + 1/x**p) + assert e.nseries(x, 0, 3) == 3 - x + x**2 + O(x**3) + p = S.Half + e = (2/x + 3/x**p)/(1/x + 1/x**p) + assert e.nseries(x, 0, 2) == 2 - x + sqrt(x) + x**(S(3)/2) + O(x**2) + + e = 1 + sqrt(x) + assert e.nseries(x, 0, 4) == 1 + sqrt(x) + +# more complicated example + + +def test_genexp_x(): + e = 1/(1 + sqrt(x)) + assert e.nseries(x, 0, 2) == \ + 1 + x - sqrt(x) - sqrt(x)**3 + O(x**2, x) + +# more complicated example + + +def test_genexp_x2(): + p = Rational(3, 2) + e = (2/x + 3/x**p)/(1/x + 1/x**p) + assert e.nseries(x, 0, 3) == 3 + x + x**2 - sqrt(x) - x**(S(3)/2) - x**(S(5)/2) + O(x**3) + + +def test_seriesbug2(): + w = Symbol("w") + #simple case (1): + e = ((2*w)/w)**(1 + w) + assert e.nseries(w, 0, 1) == 2 + O(w, w) + assert e.nseries(w, 0, 1).subs(w, 0) == 2 + + +def test_seriesbug2b(): + w = Symbol("w") + #test sin + e = sin(2*w)/w + assert e.nseries(w, 0, 3) == 2 - 4*w**2/3 + O(w**3) + + +def test_seriesbug2d(): + w = Symbol("w", real=True) + e = log(sin(2*w)/w) + assert e.series(w, n=5) == log(2) - 2*w**2/3 - 4*w**4/45 + O(w**5) + + +def test_seriesbug2c(): + w = Symbol("w", real=True) + #more complicated case, but sin(x)~x, so the result is the same as in (1) + e = (sin(2*w)/w)**(1 + w) + assert e.series(w, 0, 1) == 2 + O(w) + assert e.series(w, 0, 3) == 2 + 2*w*log(2) + \ + w**2*(Rational(-4, 3) + log(2)**2) + O(w**3) + assert e.series(w, 0, 2).subs(w, 0) == 2 + + +def test_expbug4(): + x = Symbol("x", real=True) + assert (log( + sin(2*x)/x)*(1 + x)).series(x, 0, 2) == log(2) + x*log(2) + O(x**2, x) + assert exp( + log(sin(2*x)/x)*(1 + x)).series(x, 0, 2) == 2 + 2*x*log(2) + O(x**2) + + assert exp(log(2) + O(x)).nseries(x, 0, 2) == 2 + O(x) + assert ((2 + O(x))**(1 + x)).nseries(x, 0, 2) == 2 + O(x) + + +def test_logbug4(): + assert log(2 + O(x)).nseries(x, 0, 2) == log(2) + O(x, x) + + +def test_expbug5(): + assert exp(log(1 + x)/x).nseries(x, n=3) == exp(1) + -exp(1)*x/2 + 11*exp(1)*x**2/24 + O(x**3) + + assert exp(O(x)).nseries(x, 0, 2) == 1 + O(x) + + +def test_sinsinbug(): + assert sin(sin(x)).nseries(x, 0, 8) == x - x**3/3 + x**5/10 - 8*x**7/315 + O(x**8) + + +def test_issue_3258(): + a = x/(exp(x) - 1) + assert a.nseries(x, 0, 5) == 1 - x/2 - x**4/720 + x**2/12 + O(x**5) + + +def test_issue_3204(): + x = Symbol("x", nonnegative=True) + f = sin(x**3)**Rational(1, 3) + assert f.nseries(x, 0, 17) == x - x**7/18 - x**13/3240 + O(x**17) + + +def test_issue_3224(): + f = sqrt(1 - sqrt(y)) + assert f.nseries(y, 0, 2) == 1 - sqrt(y)/2 - y/8 - sqrt(y)**3/16 + O(y**2) + + +def test_issue_3463(): + w, i = symbols('w,i') + r = log(5)/log(3) + p = w**(-1 + r) + e = 1/x*(-log(w**(1 + r)) + log(w + w**r)) + e_ser = -r*log(w)/x + p/x - p**2/(2*x) + O(w) + assert e.nseries(w, n=1) == e_ser + + +def test_sin(): + assert sin(8*x).nseries(x, n=4) == 8*x - 256*x**3/3 + O(x**4) + assert sin(x + y).nseries(x, n=1) == sin(y) + O(x) + assert sin(x + y).nseries(x, n=2) == sin(y) + cos(y)*x + O(x**2) + assert sin(x + y).nseries(x, n=5) == sin(y) + cos(y)*x - sin(y)*x**2/2 - \ + cos(y)*x**3/6 + sin(y)*x**4/24 + O(x**5) + + +def test_issue_3515(): + e = sin(8*x)/x + assert e.nseries(x, n=6) == 8 - 256*x**2/3 + 4096*x**4/15 + O(x**6) + + +def test_issue_3505(): + e = sin(x)**(-4)*(sqrt(cos(x))*sin(x)**2 - + cos(x)**Rational(1, 3)*sin(x)**2) + assert e.nseries(x, n=9) == Rational(-1, 12) - 7*x**2/288 - \ + 43*x**4/10368 - 1123*x**6/2488320 + 377*x**8/29859840 + O(x**9) + + +def test_issue_3501(): + a = Symbol("a") + e = x**(-2)*(x*sin(a + x) - x*sin(a)) + assert e.nseries(x, n=6) == cos(a) - sin(a)*x/2 - cos(a)*x**2/6 + \ + x**3*sin(a)/24 + x**4*cos(a)/120 - x**5*sin(a)/720 + O(x**6) + e = x**(-2)*(x*cos(a + x) - x*cos(a)) + assert e.nseries(x, n=6) == -sin(a) - cos(a)*x/2 + sin(a)*x**2/6 + \ + cos(a)*x**3/24 - x**4*sin(a)/120 - x**5*cos(a)/720 + O(x**6) + + +def test_issue_3502(): + e = sin(5*x)/sin(2*x) + assert e.nseries(x, n=2) == Rational(5, 2) + O(x**2) + assert e.nseries(x, n=6) == \ + Rational(5, 2) - 35*x**2/4 + 329*x**4/48 + O(x**6) + + +def test_issue_3503(): + e = sin(2 + x)/(2 + x) + assert e.nseries(x, n=2) == sin(2)/2 + x*cos(2)/2 - x*sin(2)/4 + O(x**2) + + +def test_issue_3506(): + e = (x + sin(3*x))**(-2)*(x*(x + sin(3*x)) - (x + sin(3*x))*sin(2*x)) + assert e.nseries(x, n=7) == \ + Rational(-1, 4) + 5*x**2/96 + 91*x**4/768 + 11117*x**6/129024 + O(x**7) + + +def test_issue_3508(): + x = Symbol("x", real=True) + assert log(sin(x)).series(x, n=5) == log(x) - x**2/6 - x**4/180 + O(x**5) + e = -log(x) + x*(-log(x) + log(sin(2*x))) + log(sin(2*x)) + assert e.series(x, n=5) == \ + log(2) + log(2)*x - 2*x**2/3 - 2*x**3/3 - 4*x**4/45 + O(x**5) + + +def test_issue_3507(): + e = x**(-4)*(x**2 - x**2*sqrt(cos(x))) + assert e.nseries(x, n=9) == \ + Rational(1, 4) + x**2/96 + 19*x**4/5760 + 559*x**6/645120 + 29161*x**8/116121600 + O(x**9) + + +def test_issue_3639(): + assert sin(cos(x)).nseries(x, n=5) == \ + sin(1) - x**2*cos(1)/2 - x**4*sin(1)/8 + x**4*cos(1)/24 + O(x**5) + + +def test_hyperbolic(): + assert sinh(x).nseries(x, n=6) == x + x**3/6 + x**5/120 + O(x**6) + assert cosh(x).nseries(x, n=5) == 1 + x**2/2 + x**4/24 + O(x**5) + assert tanh(x).nseries(x, n=6) == x - x**3/3 + 2*x**5/15 + O(x**6) + assert coth(x).nseries(x, n=6) == \ + 1/x - x**3/45 + x/3 + 2*x**5/945 + O(x**6) + assert asinh(x).nseries(x, n=6) == x - x**3/6 + 3*x**5/40 + O(x**6) + assert acosh(x).nseries(x, n=6) == \ + pi*I/2 - I*x - 3*I*x**5/40 - I*x**3/6 + O(x**6) + assert atanh(x).nseries(x, n=6) == x + x**3/3 + x**5/5 + O(x**6) + assert acoth(x).nseries(x, n=6) == -I*pi/2 + x + x**3/3 + x**5/5 + O(x**6) + + +def test_series2(): + w = Symbol("w", real=True) + x = Symbol("x", real=True) + e = w**(-2)*(w*exp(1/x - w) - w*exp(1/x)) + assert e.nseries(w, n=4) == -exp(1/x) + w*exp(1/x)/2 - w**2*exp(1/x)/6 + w**3*exp(1/x)/24 + O(w**4) + + +def test_series3(): + w = Symbol("w", real=True) + e = w**(-6)*(w**3*tan(w) - w**3*sin(w)) + assert e.nseries(w, n=8) == Integer(1)/2 + w**2/8 + 13*w**4/240 + 529*w**6/24192 + O(w**8) + + +def test_bug4(): + w = Symbol("w") + e = x/(w**4 + x**2*w**4 + 2*x*w**4)*w**4 + assert e.nseries(w, n=2).removeO().expand() in [x/(1 + 2*x + x**2), + 1/(1 + x/2 + 1/x/2)/2, 1/x/(1 + 2/x + x**(-2))] + + +def test_bug5(): + w = Symbol("w") + l = Symbol('l') + e = (-log(w) + log(1 + w*log(x)))**(-2)*w**(-2)*((-log(w) + + log(1 + x*w))*(-log(w) + log(1 + w*log(x)))*w - x*(-log(w) + + log(1 + w*log(x)))*w) + assert e.nseries(w, n=0, logx=l) == x/w/l + 1/w + O(1, w) + assert e.nseries(w, n=1, logx=l) == x/w/l + 1/w - x/l + 1/l*log(x) \ + + x*log(x)/l**2 + O(w) + + +def test_issue_4115(): + assert (sin(x)/(1 - cos(x))).nseries(x, n=1) == 2/x + O(x) + assert (sin(x)**2/(1 - cos(x))).nseries(x, n=1) == 2 + O(x) + + +def test_pole(): + raises(PoleError, lambda: sin(1/x).series(x, 0, 5)) + raises(PoleError, lambda: sin(1 + 1/x).series(x, 0, 5)) + raises(PoleError, lambda: (x*sin(1/x)).series(x, 0, 5)) + + +def test_expsinbug(): + assert exp(sin(x)).series(x, 0, 0) == O(1, x) + assert exp(sin(x)).series(x, 0, 1) == 1 + O(x) + assert exp(sin(x)).series(x, 0, 2) == 1 + x + O(x**2) + assert exp(sin(x)).series(x, 0, 3) == 1 + x + x**2/2 + O(x**3) + assert exp(sin(x)).series(x, 0, 4) == 1 + x + x**2/2 + O(x**4) + assert exp(sin(x)).series(x, 0, 5) == 1 + x + x**2/2 - x**4/8 + O(x**5) + + +def test_floor(): + x = Symbol('x') + assert floor(x).series(x) == 0 + assert floor(-x).series(x) == -1 + assert floor(sin(x)).series(x) == 0 + assert floor(sin(-x)).series(x) == -1 + assert floor(x**3).series(x) == 0 + assert floor(-x**3).series(x) == -1 + assert floor(cos(x)).series(x) == 0 + assert floor(cos(-x)).series(x) == 0 + assert floor(5 + sin(x)).series(x) == 5 + assert floor(5 + sin(-x)).series(x) == 4 + + assert floor(x).series(x, 2) == 2 + assert floor(-x).series(x, 2) == -3 + + x = Symbol('x', negative=True) + assert floor(x + 1.5).series(x) == 1 + + +def test_frac(): + assert frac(x).series(x, cdir=1) == x + assert frac(x).series(x, cdir=-1) == 1 + x + assert frac(2*x + 1).series(x, cdir=1) == 2*x + assert frac(2*x + 1).series(x, cdir=-1) == 1 + 2*x + assert frac(x**2).series(x, cdir=1) == x**2 + assert frac(x**2).series(x, cdir=-1) == x**2 + assert frac(sin(x) + 5).series(x, cdir=1) == x - x**3/6 + x**5/120 + O(x**6) + assert frac(sin(x) + 5).series(x, cdir=-1) == 1 + x - x**3/6 + x**5/120 + O(x**6) + assert frac(sin(x) + S.Half).series(x) == S.Half + x - x**3/6 + x**5/120 + O(x**6) + assert frac(x**8).series(x, cdir=1) == O(x**6) + assert frac(1/x).series(x) == AccumBounds(0, 1) + O(x**6) + + +def test_ceiling(): + assert ceiling(x).series(x) == 1 + assert ceiling(-x).series(x) == 0 + assert ceiling(sin(x)).series(x) == 1 + assert ceiling(sin(-x)).series(x) == 0 + assert ceiling(1 - cos(x)).series(x) == 1 + assert ceiling(1 - cos(-x)).series(x) == 1 + assert ceiling(x).series(x, 2) == 3 + assert ceiling(-x).series(x, 2) == -2 + + +def test_abs(): + a = Symbol('a') + assert abs(x).nseries(x, n=4) == x + assert abs(-x).nseries(x, n=4) == x + assert abs(x + 1).nseries(x, n=4) == x + 1 + assert abs(sin(x)).nseries(x, n=4) == x - Rational(1, 6)*x**3 + O(x**4) + assert abs(sin(-x)).nseries(x, n=4) == x - Rational(1, 6)*x**3 + O(x**4) + assert abs(x - a).nseries(x, 1) == -a*sign(1 - a) + (x - 1)*sign(1 - a) + sign(1 - a) + + +def test_dir(): + assert abs(x).series(x, 0, dir="+") == x + assert abs(x).series(x, 0, dir="-") == -x + assert floor(x + 2).series(x, 0, dir='+') == 2 + assert floor(x + 2).series(x, 0, dir='-') == 1 + assert floor(x + 2.2).series(x, 0, dir='-') == 2 + assert ceiling(x + 2.2).series(x, 0, dir='-') == 3 + assert sin(x + y).series(x, 0, dir='-') == sin(x + y).series(x, 0, dir='+') + + +def test_cdir(): + assert abs(x).series(x, 0, cdir=1) == x + assert abs(x).series(x, 0, cdir=-1) == -x + assert floor(x + 2).series(x, 0, cdir=1) == 2 + assert floor(x + 2).series(x, 0, cdir=-1) == 1 + assert floor(x + 2.2).series(x, 0, cdir=1) == 2 + assert ceiling(x + 2.2).series(x, 0, cdir=-1) == 3 + assert sin(x + y).series(x, 0, cdir=-1) == sin(x + y).series(x, 0, cdir=1) + + +def test_issue_3504(): + a = Symbol("a") + e = asin(a*x)/x + assert e.series(x, 4, n=2).removeO() == \ + (x - 4)*(a/(4*sqrt(-16*a**2 + 1)) - asin(4*a)/16) + asin(4*a)/4 + + +def test_issue_4441(): + a, b = symbols('a,b') + f = 1/(1 + a*x) + assert f.series(x, 0, 5) == 1 - a*x + a**2*x**2 - a**3*x**3 + \ + a**4*x**4 + O(x**5) + f = 1/(1 + (a + b)*x) + assert f.series(x, 0, 3) == 1 + x*(-a - b)\ + + x**2*(a + b)**2 + O(x**3) + + +def test_issue_4329(): + assert tan(x).series(x, pi/2, n=3).removeO() == \ + -pi/6 + x/3 - 1/(x - pi/2) + assert cot(x).series(x, pi, n=3).removeO() == \ + -x/3 + pi/3 + 1/(x - pi) + assert limit(tan(x)**tan(2*x), x, pi/4) == exp(-1) + + +def test_issue_5183(): + assert abs(x + x**2).series(n=1) == O(x) + assert abs(x + x**2).series(n=2) == x + O(x**2) + assert ((1 + x)**2).series(x, n=6) == x**2 + 2*x + 1 + assert (1 + 1/x).series() == 1 + 1/x + assert Derivative(exp(x).series(), x).doit() == \ + 1 + x + x**2/2 + x**3/6 + x**4/24 + O(x**5) + + +def test_issue_5654(): + a = Symbol('a') + assert (1/(x**2+a**2)**2).nseries(x, x0=I*a, n=0) == \ + -I/(4*a**3*(-I*a + x)) - 1/(4*a**2*(-I*a + x)**2) + O(1, (x, I*a)) + assert (1/(x**2+a**2)**2).nseries(x, x0=I*a, n=1) == 3/(16*a**4) \ + -I/(4*a**3*(-I*a + x)) - 1/(4*a**2*(-I*a + x)**2) + O(-I*a + x, (x, I*a)) + + +def test_issue_5925(): + sx = sqrt(x + z).series(z, 0, 1) + sxy = sqrt(x + y + z).series(z, 0, 1) + s1, s2 = sx.subs(x, x + y), sxy + assert (s1 - s2).expand().removeO().simplify() == 0 + + sx = sqrt(x + z).series(z, 0, 1) + sxy = sqrt(x + y + z).series(z, 0, 1) + assert sxy.subs({x:1, y:2}) == sx.subs(x, 3) + + +def test_exp_2(): + assert exp(x**3).nseries(x, 0, 14) == 1 + x**3 + x**6/2 + x**9/6 + x**12/24 + O(x**14) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_order.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_order.py new file mode 100644 index 0000000000000000000000000000000000000000..50fcb861ee2a76c730baae6d26cc1e7a00347176 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_order.py @@ -0,0 +1,503 @@ +from sympy.core.add import Add +from sympy.core.function import (Function, expand) +from sympy.core.numbers import (I, Rational, nan, oo, pi) +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.combinatorial.factorials import factorial +from sympy.functions.elementary.complexes import (conjugate, transpose) +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.integrals.integrals import Integral +from sympy.series.order import O, Order +from sympy.core.expr import unchanged +from sympy.testing.pytest import raises +from sympy.abc import w, x, y, z +from sympy.testing.pytest import XFAIL + + +def test_caching_bug(): + #needs to be a first test, so that all caches are clean + #cache it + O(w) + #and test that this won't raise an exception + O(w**(-1/x/log(3)*log(5)), w) + + +def test_free_symbols(): + assert Order(1).free_symbols == set() + assert Order(x).free_symbols == {x} + assert Order(1, x).free_symbols == {x} + assert Order(x*y).free_symbols == {x, y} + assert Order(x, x, y).free_symbols == {x, y} + + +def test_simple_1(): + o = Rational(0) + assert Order(2*x) == Order(x) + assert Order(x)*3 == Order(x) + assert -28*Order(x) == Order(x) + assert Order(Order(x)) == Order(x) + assert Order(Order(x), y) == Order(Order(x), x, y) + assert Order(-23) == Order(1) + assert Order(exp(x)) == Order(1, x) + assert Order(exp(1/x)).expr == exp(1/x) + assert Order(x*exp(1/x)).expr == x*exp(1/x) + assert Order(x**(o/3)).expr == x**(o/3) + assert Order(x**(o*Rational(5, 3))).expr == x**(o*Rational(5, 3)) + assert Order(x**2 + x + y, x) == O(1, x) + assert Order(x**2 + x + y, y) == O(1, y) + raises(ValueError, lambda: Order(exp(x), x, x)) + raises(TypeError, lambda: Order(x, 2 - x)) + + +def test_simple_2(): + assert Order(2*x)*x == Order(x**2) + assert Order(2*x)/x == Order(1, x) + assert Order(2*x)*x*exp(1/x) == Order(x**2*exp(1/x)) + assert (Order(2*x)*x*exp(1/x)/log(x)**3).expr == x**2*exp(1/x)*log(x)**-3 + + +def test_simple_3(): + assert Order(x) + x == Order(x) + assert Order(x) + 2 == 2 + Order(x) + assert Order(x) + x**2 == Order(x) + assert Order(x) + 1/x == 1/x + Order(x) + assert Order(1/x) + 1/x**2 == 1/x**2 + Order(1/x) + assert Order(x) + exp(1/x) == Order(x) + exp(1/x) + + +def test_simple_4(): + assert Order(x)**2 == Order(x**2) + + +def test_simple_5(): + assert Order(x) + Order(x**2) == Order(x) + assert Order(x) + Order(x**-2) == Order(x**-2) + assert Order(x) + Order(1/x) == Order(1/x) + + +def test_simple_6(): + assert Order(x) - Order(x) == Order(x) + assert Order(x) + Order(1) == Order(1) + assert Order(x) + Order(x**2) == Order(x) + assert Order(1/x) + Order(1) == Order(1/x) + assert Order(x) + Order(exp(1/x)) == Order(exp(1/x)) + assert Order(x**3) + Order(exp(2/x)) == Order(exp(2/x)) + assert Order(x**-3) + Order(exp(2/x)) == Order(exp(2/x)) + + +def test_simple_7(): + assert 1 + O(1) == O(1) + assert 2 + O(1) == O(1) + assert x + O(1) == O(1) + assert 1/x + O(1) == 1/x + O(1) + + +def test_simple_8(): + assert O(sqrt(-x)) == O(sqrt(x)) + assert O(x**2*sqrt(x)) == O(x**Rational(5, 2)) + assert O(x**3*sqrt(-(-x)**3)) == O(x**Rational(9, 2)) + assert O(x**Rational(3, 2)*sqrt((-x)**3)) == O(x**3) + assert O(x*(-2*x)**(I/2)) == O(x*(-x)**(I/2)) + + +def test_as_expr_variables(): + assert Order(x).as_expr_variables(None) == (x, ((x, 0),)) + assert Order(x).as_expr_variables(((x, 0),)) == (x, ((x, 0),)) + assert Order(y).as_expr_variables(((x, 0),)) == (y, ((x, 0), (y, 0))) + assert Order(y).as_expr_variables(((x, 0), (y, 0))) == (y, ((x, 0), (y, 0))) + + +def test_contains_0(): + assert Order(1, x).contains(Order(1, x)) + assert Order(1, x).contains(Order(1)) + assert Order(1).contains(Order(1, x)) is False + + +def test_contains_1(): + assert Order(x).contains(Order(x)) + assert Order(x).contains(Order(x**2)) + assert not Order(x**2).contains(Order(x)) + assert not Order(x).contains(Order(1/x)) + assert not Order(1/x).contains(Order(exp(1/x))) + assert not Order(x).contains(Order(exp(1/x))) + assert Order(1/x).contains(Order(x)) + assert Order(exp(1/x)).contains(Order(x)) + assert Order(exp(1/x)).contains(Order(1/x)) + assert Order(exp(1/x)).contains(Order(exp(1/x))) + assert Order(exp(2/x)).contains(Order(exp(1/x))) + assert not Order(exp(1/x)).contains(Order(exp(2/x))) + + +def test_contains_2(): + assert Order(x).contains(Order(y)) is None + assert Order(x).contains(Order(y*x)) + assert Order(y*x).contains(Order(x)) + assert Order(y).contains(Order(x*y)) + assert Order(x).contains(Order(y**2*x)) + + +def test_contains_3(): + assert Order(x*y**2).contains(Order(x**2*y)) is None + assert Order(x**2*y).contains(Order(x*y**2)) is None + + +def test_contains_4(): + assert Order(sin(1/x**2)).contains(Order(cos(1/x**2))) is True + assert Order(cos(1/x**2)).contains(Order(sin(1/x**2))) is True + + +def test_contains(): + assert Order(1, x) not in Order(1) + assert Order(1) in Order(1, x) + raises(TypeError, lambda: Order(x*y**2) in Order(x**2*y)) + + +def test_add_1(): + assert Order(x + x) == Order(x) + assert Order(3*x - 2*x**2) == Order(x) + assert Order(1 + x) == Order(1, x) + assert Order(1 + 1/x) == Order(1/x) + # TODO : A better output for Order(log(x) + 1/log(x)) + # could be Order(log(x)). Currently Order for expressions + # where all arguments would involve a log term would fall + # in this category and outputs for these should be improved. + assert Order(log(x) + 1/log(x)) == Order((log(x)**2 + 1)/log(x)) + assert Order(exp(1/x) + x) == Order(exp(1/x)) + assert Order(exp(1/x) + 1/x**20) == Order(exp(1/x)) + + +def test_ln_args(): + assert O(log(x)) + O(log(2*x)) == O(log(x)) + assert O(log(x)) + O(log(x**3)) == O(log(x)) + assert O(log(x*y)) + O(log(x) + log(y)) == O(log(x) + log(y), x, y) + + +def test_multivar_0(): + assert Order(x*y).expr == x*y + assert Order(x*y**2).expr == x*y**2 + assert Order(x*y, x).expr == x + assert Order(x*y**2, y).expr == y**2 + assert Order(x*y*z).expr == x*y*z + assert Order(x/y).expr == x/y + assert Order(x*exp(1/y)).expr == x*exp(1/y) + assert Order(exp(x)*exp(1/y)).expr == exp(x)*exp(1/y) + + +def test_multivar_0a(): + assert Order(exp(1/x)*exp(1/y)).expr == exp(1/x)*exp(1/y) + + +def test_multivar_1(): + assert Order(x + y).expr == x + y + assert Order(x + 2*y).expr == x + y + assert (Order(x + y) + x).expr == (x + y) + assert (Order(x + y) + x**2) == Order(x + y) + assert (Order(x + y) + 1/x) == 1/x + Order(x + y) + assert Order(x**2 + y*x).expr == x**2 + y*x + + +def test_multivar_2(): + assert Order(x**2*y + y**2*x, x, y).expr == x**2*y + y**2*x + + +def test_multivar_mul_1(): + assert Order(x + y)*x == Order(x**2 + y*x, x, y) + + +def test_multivar_3(): + assert (Order(x) + Order(y)).args in [ + (Order(x), Order(y)), + (Order(y), Order(x))] + assert Order(x) + Order(y) + Order(x + y) == Order(x + y) + assert (Order(x**2*y) + Order(y**2*x)).args in [ + (Order(x*y**2), Order(y*x**2)), + (Order(y*x**2), Order(x*y**2))] + assert (Order(x**2*y) + Order(y*x)) == Order(x*y) + + +def test_issue_3468(): + y = Symbol('y', negative=True) + z = Symbol('z', complex=True) + + # check that Order does not modify assumptions about symbols + Order(x) + Order(y) + Order(z) + + assert x.is_positive is None + assert y.is_positive is False + assert z.is_positive is None + + +def test_leading_order(): + assert (x + 1 + 1/x**5).extract_leading_order(x) == ((1/x**5, O(1/x**5)),) + assert (1 + 1/x).extract_leading_order(x) == ((1/x, O(1/x)),) + assert (1 + x).extract_leading_order(x) == ((1, O(1, x)),) + assert (1 + x**2).extract_leading_order(x) == ((1, O(1, x)),) + assert (2 + x**2).extract_leading_order(x) == ((2, O(1, x)),) + assert (x + x**2).extract_leading_order(x) == ((x, O(x)),) + + +def test_leading_order2(): + assert set((2 + pi + x**2).extract_leading_order(x)) == {(pi, O(1, x)), + (S(2), O(1, x))} + assert set((2*x + pi*x + x**2).extract_leading_order(x)) == {(2*x, O(x)), + (x*pi, O(x))} + + +def test_order_leadterm(): + assert O(x**2)._eval_as_leading_term(x, None, 1) == O(x**2) + + +def test_order_symbols(): + e = x*y*sin(x)*Integral(x, (x, 1, 2)) + assert O(e) == O(x**2*y, x, y) + assert O(e, x) == O(x**2) + + +def test_nan(): + assert O(nan) is nan + assert not O(x).contains(nan) + + +def test_O1(): + assert O(1, x) * x == O(x) + assert O(1, y) * x == O(1, y) + + +def test_getn(): + # other lines are tested incidentally by the suite + assert O(x).getn() == 1 + assert O(x/log(x)).getn() == 1 + assert O(x**2/log(x)**2).getn() == 2 + assert O(x*log(x)).getn() == 1 + raises(NotImplementedError, lambda: (O(x) + O(y)).getn()) + + +def test_diff(): + assert O(x**2).diff(x) == O(x) + + +def test_getO(): + assert (x).getO() is None + assert (x).removeO() == x + assert (O(x)).getO() == O(x) + assert (O(x)).removeO() == 0 + assert (z + O(x) + O(y)).getO() == O(x) + O(y) + assert (z + O(x) + O(y)).removeO() == z + raises(NotImplementedError, lambda: (O(x) + O(y)).getn()) + + +def test_leading_term(): + from sympy.functions.special.gamma_functions import digamma + assert O(1/digamma(1/x)) == O(1/log(x)) + + +def test_eval(): + assert Order(x).subs(Order(x), 1) == 1 + assert Order(x).subs(x, y) == Order(y) + assert Order(x).subs(y, x) == Order(x) + assert Order(x).subs(x, x + y) == Order(x + y, (x, -y)) + assert (O(1)**x).is_Pow + + +def test_issue_4279(): + a, b = symbols('a b') + assert O(a, a, b) + O(1, a, b) == O(1, a, b) + assert O(b, a, b) + O(1, a, b) == O(1, a, b) + assert O(a + b, a, b) + O(1, a, b) == O(1, a, b) + assert O(1, a, b) + O(a, a, b) == O(1, a, b) + assert O(1, a, b) + O(b, a, b) == O(1, a, b) + assert O(1, a, b) + O(a + b, a, b) == O(1, a, b) + + +def test_issue_4855(): + assert 1/O(1) != O(1) + assert 1/O(x) != O(1/x) + assert 1/O(x, (x, oo)) != O(1/x, (x, oo)) + + f = Function('f') + assert 1/O(f(x)) != O(1/x) + + +def test_order_conjugate_transpose(): + x = Symbol('x', real=True) + y = Symbol('y', imaginary=True) + assert conjugate(Order(x)) == Order(conjugate(x)) + assert conjugate(Order(y)) == Order(conjugate(y)) + assert conjugate(Order(x**2)) == Order(conjugate(x)**2) + assert conjugate(Order(y**2)) == Order(conjugate(y)**2) + assert transpose(Order(x)) == Order(transpose(x)) + assert transpose(Order(y)) == Order(transpose(y)) + assert transpose(Order(x**2)) == Order(transpose(x)**2) + assert transpose(Order(y**2)) == Order(transpose(y)**2) + + +def test_order_noncommutative(): + A = Symbol('A', commutative=False) + assert Order(A + A*x, x) == Order(1, x) + assert (A + A*x)*Order(x) == Order(x) + assert (A*x)*Order(x) == Order(x**2, x) + assert expand((1 + Order(x))*A*A*x) == A*A*x + Order(x**2, x) + assert expand((A*A + Order(x))*x) == A*A*x + Order(x**2, x) + assert expand((A + Order(x))*A*x) == A*A*x + Order(x**2, x) + + +def test_issue_6753(): + assert (1 + x**2)**10000*O(x) == O(x) + + +def test_order_at_infinity(): + assert Order(1 + x, (x, oo)) == Order(x, (x, oo)) + assert Order(3*x, (x, oo)) == Order(x, (x, oo)) + assert Order(x, (x, oo))*3 == Order(x, (x, oo)) + assert -28*Order(x, (x, oo)) == Order(x, (x, oo)) + assert Order(Order(x, (x, oo)), (x, oo)) == Order(x, (x, oo)) + assert Order(Order(x, (x, oo)), (y, oo)) == Order(x, (x, oo), (y, oo)) + assert Order(3, (x, oo)) == Order(1, (x, oo)) + assert Order(x**2 + x + y, (x, oo)) == O(x**2, (x, oo)) + assert Order(x**2 + x + y, (y, oo)) == O(y, (y, oo)) + + assert Order(2*x, (x, oo))*x == Order(x**2, (x, oo)) + assert Order(2*x, (x, oo))/x == Order(1, (x, oo)) + assert Order(2*x, (x, oo))*x*exp(1/x) == Order(x**2*exp(1/x), (x, oo)) + assert Order(2*x, (x, oo))*x*exp(1/x)/log(x)**3 == Order(x**2*exp(1/x)*log(x)**-3, (x, oo)) + + assert Order(x, (x, oo)) + 1/x == 1/x + Order(x, (x, oo)) == Order(x, (x, oo)) + assert Order(x, (x, oo)) + 1 == 1 + Order(x, (x, oo)) == Order(x, (x, oo)) + assert Order(x, (x, oo)) + x == x + Order(x, (x, oo)) == Order(x, (x, oo)) + assert Order(x, (x, oo)) + x**2 == x**2 + Order(x, (x, oo)) + assert Order(1/x, (x, oo)) + 1/x**2 == 1/x**2 + Order(1/x, (x, oo)) == Order(1/x, (x, oo)) + assert Order(x, (x, oo)) + exp(1/x) == exp(1/x) + Order(x, (x, oo)) + + assert Order(x, (x, oo))**2 == Order(x**2, (x, oo)) + + assert Order(x, (x, oo)) + Order(x**2, (x, oo)) == Order(x**2, (x, oo)) + assert Order(x, (x, oo)) + Order(x**-2, (x, oo)) == Order(x, (x, oo)) + assert Order(x, (x, oo)) + Order(1/x, (x, oo)) == Order(x, (x, oo)) + + assert Order(x, (x, oo)) - Order(x, (x, oo)) == Order(x, (x, oo)) + assert Order(x, (x, oo)) + Order(1, (x, oo)) == Order(x, (x, oo)) + assert Order(x, (x, oo)) + Order(x**2, (x, oo)) == Order(x**2, (x, oo)) + assert Order(1/x, (x, oo)) + Order(1, (x, oo)) == Order(1, (x, oo)) + assert Order(x, (x, oo)) + Order(exp(1/x), (x, oo)) == Order(x, (x, oo)) + assert Order(x**3, (x, oo)) + Order(exp(2/x), (x, oo)) == Order(x**3, (x, oo)) + assert Order(x**-3, (x, oo)) + Order(exp(2/x), (x, oo)) == Order(exp(2/x), (x, oo)) + + # issue 7207 + assert Order(exp(x), (x, oo)).expr == Order(2*exp(x), (x, oo)).expr == exp(x) + assert Order(y**x, (x, oo)).expr == Order(2*y**x, (x, oo)).expr == exp(x*log(y)) + + # issue 19545 + assert Order(1/x - 3/(3*x + 2), (x, oo)).expr == x**(-2) + +def test_mixing_order_at_zero_and_infinity(): + assert (Order(x, (x, 0)) + Order(x, (x, oo))).is_Add + assert Order(x, (x, 0)) + Order(x, (x, oo)) == Order(x, (x, oo)) + Order(x, (x, 0)) + assert Order(Order(x, (x, oo))) == Order(x, (x, oo)) + + # not supported (yet) + raises(NotImplementedError, lambda: Order(x, (x, 0))*Order(x, (x, oo))) + raises(NotImplementedError, lambda: Order(x, (x, oo))*Order(x, (x, 0))) + raises(NotImplementedError, lambda: Order(Order(x, (x, oo)), y)) + raises(NotImplementedError, lambda: Order(Order(x), (x, oo))) + + +def test_order_at_some_point(): + assert Order(x, (x, 1)) == Order(1, (x, 1)) + assert Order(2*x - 2, (x, 1)) == Order(x - 1, (x, 1)) + assert Order(-x + 1, (x, 1)) == Order(x - 1, (x, 1)) + assert Order(x - 1, (x, 1))**2 == Order((x - 1)**2, (x, 1)) + assert Order(x - 2, (x, 2)) - O(x - 2, (x, 2)) == Order(x - 2, (x, 2)) + + +def test_order_subs_limits(): + # issue 3333 + assert (1 + Order(x)).subs(x, 1/x) == 1 + Order(1/x, (x, oo)) + assert (1 + Order(x)).limit(x, 0) == 1 + # issue 5769 + assert ((x + Order(x**2))/x).limit(x, 0) == 1 + + assert Order(x**2).subs(x, y - 1) == Order((y - 1)**2, (y, 1)) + assert Order(10*x**2, (x, 2)).subs(x, y - 1) == Order(1, (y, 3)) + + #issue 19120 + assert O(x).subs(x, O(x)) == O(x) + assert O(x**2).subs(x, x + O(x)) == O(x**2) + assert O(x, (x, oo)).subs(x, O(x, (x, oo))) == O(x, (x, oo)) + assert O(x**2, (x, oo)).subs(x, x + O(x, (x, oo))) == O(x**2, (x, oo)) + assert (x + O(x**2)).subs(x, x + O(x**2)) == x + O(x**2) + assert (x**2 + O(x**2) + 1/x**2).subs(x, x + O(x**2)) == (x + O(x**2))**(-2) + O(x**2) + assert (x**2 + O(x**2) + 1).subs(x, x + O(x**2)) == 1 + O(x**2) + assert O(x, (x, oo)).subs(x, x + O(x**2, (x, oo))) == O(x**2, (x, oo)) + assert sin(x).series(n=8).subs(x,sin(x).series(n=8)).expand() == x - x**3/3 + x**5/10 - 8*x**7/315 + O(x**8) + assert cos(x).series(n=8).subs(x,sin(x).series(n=8)).expand() == 1 - x**2/2 + 5*x**4/24 - 37*x**6/720 + O(x**8) + assert O(x).subs(x, O(1/x, (x, oo))) == O(1/x, (x, oo)) + +@XFAIL +def test_order_failing_due_to_solveset(): + assert O(x**3).subs(x, exp(-x**2)) == O(exp(-3*x**2), (x, -oo)) + raises(NotImplementedError, lambda: O(x).subs(x, O(1/x))) # mixing of order at different points + + +def test_issue_9351(): + assert exp(x).series(x, 10, 1) == exp(10) + Order(x - 10, (x, 10)) + + +def test_issue_9192(): + assert O(1)*O(1) == O(1) + assert O(1)**O(1) == O(1) + + +def test_issue_9910(): + assert O(x*log(x) + sin(x), (x, oo)) == O(x*log(x), (x, oo)) + + +def test_performance_of_adding_order(): + l = [x**i for i in range(1000)] + l.append(O(x**1001)) + assert Add(*l).subs(x,1) == O(1) + +def test_issue_14622(): + assert (x**(-4) + x**(-3) + x**(-1) + O(x**(-6), (x, oo))).as_numer_denom() == ( + x**4 + x**5 + x**7 + O(x**2, (x, oo)), x**8) + assert (x**3 + O(x**2, (x, oo))).is_Add + assert O(x**2, (x, oo)).contains(x**3) is False + assert O(x, (x, oo)).contains(O(x, (x, 0))) is None + assert O(x, (x, 0)).contains(O(x, (x, oo))) is None + raises(NotImplementedError, lambda: O(x**3).contains(x**w)) + + +def test_issue_15539(): + assert O(1/x**2 + 1/x**4, (x, -oo)) == O(1/x**2, (x, -oo)) + assert O(1/x**4 + exp(x), (x, -oo)) == O(1/x**4, (x, -oo)) + assert O(1/x**4 + exp(-x), (x, -oo)) == O(exp(-x), (x, -oo)) + assert O(1/x, (x, oo)).subs(x, -x) == O(-1/x, (x, -oo)) + +def test_issue_18606(): + assert unchanged(Order, 0) + + +def test_issue_22165(): + assert O(log(x)).contains(2) + + +def test_issue_23231(): + # This test checks Order for expressions having + # arguments containing variables in exponents/powers. + assert O(x**x + 2**x, (x, oo)) == O(exp(x*log(x)), (x, oo)) + assert O(x**x + x**2, (x, oo)) == O(exp(x*log(x)), (x, oo)) + assert O(x**x + 1/x**2, (x, oo)) == O(exp(x*log(x)), (x, oo)) + assert O(2**x + 3**x , (x, oo)) == O(exp(x*log(3)), (x, oo)) + + +def test_issue_9917(): + assert O(x*sin(x) + 1, (x, oo)) == O(x, (x, oo)) + + +def test_issue_22836(): + assert O(2**x + factorial(x), (x, oo)) == O(factorial(x), (x, oo)) + assert O(2**x + factorial(x) + x**x, (x, oo)) == O(exp(x*log(x)), (x, oo)) + assert O(x + factorial(x), (x, oo)) == O(factorial(x), (x, oo)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_residues.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_residues.py new file mode 100644 index 0000000000000000000000000000000000000000..9f7d075a56500d008e3c8b46c1fda5db890fd76a --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_residues.py @@ -0,0 +1,101 @@ +from sympy.core.function import Function +from sympy.core.numbers import (I, Rational, pi) +from sympy.core.singleton import S +from sympy.core.symbol import Symbol +from sympy.functions.combinatorial.factorials import factorial +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.hyperbolic import tanh +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (cot, sin, tan) +from sympy.series.residues import residue +from sympy.testing.pytest import XFAIL, raises +from sympy.abc import x, z, a, s, k + + +def test_basic1(): + assert residue(1/x, x, 0) == 1 + assert residue(-2/x, x, 0) == -2 + assert residue(81/x, x, 0) == 81 + assert residue(1/x**2, x, 0) == 0 + assert residue(0, x, 0) == 0 + assert residue(5, x, 0) == 0 + assert residue(x, x, 0) == 0 + assert residue(x**2, x, 0) == 0 + + +def test_basic2(): + assert residue(1/x, x, 1) == 0 + assert residue(-2/x, x, 1) == 0 + assert residue(81/x, x, -1) == 0 + assert residue(1/x**2, x, 1) == 0 + assert residue(0, x, 1) == 0 + assert residue(5, x, 1) == 0 + assert residue(x, x, 1) == 0 + assert residue(x**2, x, 5) == 0 + + +def test_f(): + f = Function("f") + assert residue(f(x)/x**5, x, 0) == f(x).diff(x, 4).subs(x, 0)/24 + + +def test_functions(): + assert residue(1/sin(x), x, 0) == 1 + assert residue(2/sin(x), x, 0) == 2 + assert residue(1/sin(x)**2, x, 0) == 0 + assert residue(1/sin(x)**5, x, 0) == Rational(3, 8) + + +def test_expressions(): + assert residue(1/(x + 1), x, 0) == 0 + assert residue(1/(x + 1), x, -1) == 1 + assert residue(1/(x**2 + 1), x, -1) == 0 + assert residue(1/(x**2 + 1), x, I) == -I/2 + assert residue(1/(x**2 + 1), x, -I) == I/2 + assert residue(1/(x**4 + 1), x, 0) == 0 + assert residue(1/(x**4 + 1), x, exp(I*pi/4)).equals(-(Rational(1, 4) + I/4)/sqrt(2)) + assert residue(1/(x**2 + a**2)**2, x, a*I) == -I/4/a**3 + + +@XFAIL +def test_expressions_failing(): + n = Symbol('n', integer=True, positive=True) + assert residue(exp(z)/(z - pi*I/4*a)**n, z, I*pi*a) == \ + exp(I*pi*a/4)/factorial(n - 1) + + +def test_NotImplemented(): + raises(NotImplementedError, lambda: residue(exp(1/z), z, 0)) + + +def test_bug(): + assert residue(2**(z)*(s + z)*(1 - s - z)/z**2, z, 0) == \ + 1 + s*log(2) - s**2*log(2) - 2*s + + +def test_issue_5654(): + assert residue(1/(x**2 + a**2)**2, x, a*I) == -I/(4*a**3) + assert residue(1/s*1/(z - exp(s)), s, 0) == 1/(z - 1) + assert residue((1 + k)/s*1/(z - exp(s)), s, 0) == k/(z - 1) + 1/(z - 1) + + +def test_issue_6499(): + assert residue(1/(exp(z) - 1), z, 0) == 1 + + +def test_issue_14037(): + assert residue(sin(x**50)/x**51, x, 0) == 1 + + +def test_issue_21176(): + f = x**2*cot(pi*x)/(x**4 + 1) + assert residue(f, x, -sqrt(2)/2 - sqrt(2)*I/2).cancel().together(deep=True)\ + == sqrt(2)*(1 - I)/(8*tan(sqrt(2)*pi*(1 + I)/2)) + + +def test_issue_21177(): + r = -sqrt(3)*tanh(sqrt(3)*pi/2)/3 + a = residue(cot(pi*x)/((x - 1)*(x - 2) + 1), x, S(3)/2 - sqrt(3)*I/2) + b = residue(cot(pi*x)/(x**2 - 3*x + 3), x, S(3)/2 - sqrt(3)*I/2) + assert a == r + assert (b - a).cancel() == 0 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_sequences.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_sequences.py new file mode 100644 index 0000000000000000000000000000000000000000..61e276ad67982f0a9877de3548d70238976d28a5 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_sequences.py @@ -0,0 +1,312 @@ +from sympy.core.containers import Tuple +from sympy.core.function import Function +from sympy.core.numbers import oo, Rational +from sympy.core.singleton import S +from sympy.core.symbol import symbols, Symbol +from sympy.functions.combinatorial.numbers import tribonacci, fibonacci +from sympy.functions.elementary.exponential import exp +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import cos, sin +from sympy.series import EmptySequence +from sympy.series.sequences import (SeqMul, SeqAdd, SeqPer, SeqFormula, + sequence) +from sympy.sets.sets import Interval +from sympy.tensor.indexed import Indexed, Idx +from sympy.series.sequences import SeqExpr, SeqExprOp, RecursiveSeq +from sympy.testing.pytest import raises, slow + +x, y, z = symbols('x y z') +n, m = symbols('n m') + + +def test_EmptySequence(): + assert S.EmptySequence is EmptySequence + + assert S.EmptySequence.interval is S.EmptySet + assert S.EmptySequence.length is S.Zero + + assert list(S.EmptySequence) == [] + + +def test_SeqExpr(): + #SeqExpr is a baseclass and does not take care of + #ensuring all arguments are Basics hence the use of + #Tuple(...) here. + s = SeqExpr(Tuple(1, n, y), Tuple(x, 0, 10)) + + assert isinstance(s, SeqExpr) + assert s.gen == (1, n, y) + assert s.interval == Interval(0, 10) + assert s.start == 0 + assert s.stop == 10 + assert s.length == 11 + assert s.variables == (x,) + + assert SeqExpr(Tuple(1, 2, 3), Tuple(x, 0, oo)).length is oo + + +def test_SeqPer(): + s = SeqPer((1, n, 3), (x, 0, 5)) + + assert isinstance(s, SeqPer) + assert s.periodical == Tuple(1, n, 3) + assert s.period == 3 + assert s.coeff(3) == 1 + assert s.free_symbols == {n} + + assert list(s) == [1, n, 3, 1, n, 3] + assert s[:] == [1, n, 3, 1, n, 3] + assert SeqPer((1, n, 3), (x, -oo, 0))[0:6] == [1, n, 3, 1, n, 3] + + raises(ValueError, lambda: SeqPer((1, 2, 3), (0, 1, 2))) + raises(ValueError, lambda: SeqPer((1, 2, 3), (x, -oo, oo))) + raises(ValueError, lambda: SeqPer(n**2, (0, oo))) + + assert SeqPer((n, n**2, n**3), (m, 0, oo))[:6] == \ + [n, n**2, n**3, n, n**2, n**3] + assert SeqPer((n, n**2, n**3), (n, 0, oo))[:6] == [0, 1, 8, 3, 16, 125] + assert SeqPer((n, m), (n, 0, oo))[:6] == [0, m, 2, m, 4, m] + + +def test_SeqFormula(): + s = SeqFormula(n**2, (n, 0, 5)) + + assert isinstance(s, SeqFormula) + assert s.formula == n**2 + assert s.coeff(3) == 9 + + assert list(s) == [i**2 for i in range(6)] + assert s[:] == [i**2 for i in range(6)] + assert SeqFormula(n**2, (n, -oo, 0))[0:6] == [i**2 for i in range(6)] + + assert SeqFormula(n**2, (0, oo)) == SeqFormula(n**2, (n, 0, oo)) + + assert SeqFormula(n**2, (0, m)).subs(m, x) == SeqFormula(n**2, (0, x)) + assert SeqFormula(m*n**2, (n, 0, oo)).subs(m, x) == \ + SeqFormula(x*n**2, (n, 0, oo)) + + raises(ValueError, lambda: SeqFormula(n**2, (0, 1, 2))) + raises(ValueError, lambda: SeqFormula(n**2, (n, -oo, oo))) + raises(ValueError, lambda: SeqFormula(m*n**2, (0, oo))) + + seq = SeqFormula(x*(y**2 + z), (z, 1, 100)) + assert seq.expand() == SeqFormula(x*y**2 + x*z, (z, 1, 100)) + seq = SeqFormula(sin(x*(y**2 + z)),(z, 1, 100)) + assert seq.expand(trig=True) == SeqFormula(sin(x*y**2)*cos(x*z) + sin(x*z)*cos(x*y**2), (z, 1, 100)) + assert seq.expand() == SeqFormula(sin(x*y**2 + x*z), (z, 1, 100)) + assert seq.expand(trig=False) == SeqFormula(sin(x*y**2 + x*z), (z, 1, 100)) + seq = SeqFormula(exp(x*(y**2 + z)), (z, 1, 100)) + assert seq.expand() == SeqFormula(exp(x*y**2)*exp(x*z), (z, 1, 100)) + assert seq.expand(power_exp=False) == SeqFormula(exp(x*y**2 + x*z), (z, 1, 100)) + assert seq.expand(mul=False, power_exp=False) == SeqFormula(exp(x*(y**2 + z)), (z, 1, 100)) + +def test_sequence(): + form = SeqFormula(n**2, (n, 0, 5)) + per = SeqPer((1, 2, 3), (n, 0, 5)) + inter = SeqFormula(n**2) + + assert sequence(n**2, (n, 0, 5)) == form + assert sequence((1, 2, 3), (n, 0, 5)) == per + assert sequence(n**2) == inter + + +def test_SeqExprOp(): + form = SeqFormula(n**2, (n, 0, 10)) + per = SeqPer((1, 2, 3), (m, 5, 10)) + + s = SeqExprOp(form, per) + assert s.gen == (n**2, (1, 2, 3)) + assert s.interval == Interval(5, 10) + assert s.start == 5 + assert s.stop == 10 + assert s.length == 6 + assert s.variables == (n, m) + + +def test_SeqAdd(): + per = SeqPer((1, 2, 3), (n, 0, oo)) + form = SeqFormula(n**2) + + per_bou = SeqPer((1, 2), (n, 1, 5)) + form_bou = SeqFormula(n**2, (6, 10)) + form_bou2 = SeqFormula(n**2, (1, 5)) + + assert SeqAdd() == S.EmptySequence + assert SeqAdd(S.EmptySequence) == S.EmptySequence + assert SeqAdd(per) == per + assert SeqAdd(per, S.EmptySequence) == per + assert SeqAdd(per_bou, form_bou) == S.EmptySequence + + s = SeqAdd(per_bou, form_bou2, evaluate=False) + assert s.args == (form_bou2, per_bou) + assert s[:] == [2, 6, 10, 18, 26] + assert list(s) == [2, 6, 10, 18, 26] + + assert isinstance(SeqAdd(per, per_bou, evaluate=False), SeqAdd) + + s1 = SeqAdd(per, per_bou) + assert isinstance(s1, SeqPer) + assert s1 == SeqPer((2, 4, 4, 3, 3, 5), (n, 1, 5)) + s2 = SeqAdd(form, form_bou) + assert isinstance(s2, SeqFormula) + assert s2 == SeqFormula(2*n**2, (6, 10)) + + assert SeqAdd(form, form_bou, per) == \ + SeqAdd(per, SeqFormula(2*n**2, (6, 10))) + assert SeqAdd(form, SeqAdd(form_bou, per)) == \ + SeqAdd(per, SeqFormula(2*n**2, (6, 10))) + assert SeqAdd(per, SeqAdd(form, form_bou), evaluate=False) == \ + SeqAdd(per, SeqFormula(2*n**2, (6, 10))) + + assert SeqAdd(SeqPer((1, 2), (n, 0, oo)), SeqPer((1, 2), (m, 0, oo))) == \ + SeqPer((2, 4), (n, 0, oo)) + + +def test_SeqMul(): + per = SeqPer((1, 2, 3), (n, 0, oo)) + form = SeqFormula(n**2) + + per_bou = SeqPer((1, 2), (n, 1, 5)) + form_bou = SeqFormula(n**2, (n, 6, 10)) + form_bou2 = SeqFormula(n**2, (1, 5)) + + assert SeqMul() == S.EmptySequence + assert SeqMul(S.EmptySequence) == S.EmptySequence + assert SeqMul(per) == per + assert SeqMul(per, S.EmptySequence) == S.EmptySequence + assert SeqMul(per_bou, form_bou) == S.EmptySequence + + s = SeqMul(per_bou, form_bou2, evaluate=False) + assert s.args == (form_bou2, per_bou) + assert s[:] == [1, 8, 9, 32, 25] + assert list(s) == [1, 8, 9, 32, 25] + + assert isinstance(SeqMul(per, per_bou, evaluate=False), SeqMul) + + s1 = SeqMul(per, per_bou) + assert isinstance(s1, SeqPer) + assert s1 == SeqPer((1, 4, 3, 2, 2, 6), (n, 1, 5)) + s2 = SeqMul(form, form_bou) + assert isinstance(s2, SeqFormula) + assert s2 == SeqFormula(n**4, (6, 10)) + + assert SeqMul(form, form_bou, per) == \ + SeqMul(per, SeqFormula(n**4, (6, 10))) + assert SeqMul(form, SeqMul(form_bou, per)) == \ + SeqMul(per, SeqFormula(n**4, (6, 10))) + assert SeqMul(per, SeqMul(form, form_bou2, + evaluate=False), evaluate=False) == \ + SeqMul(form, per, form_bou2, evaluate=False) + + assert SeqMul(SeqPer((1, 2), (n, 0, oo)), SeqPer((1, 2), (n, 0, oo))) == \ + SeqPer((1, 4), (n, 0, oo)) + + +def test_add(): + per = SeqPer((1, 2), (n, 0, oo)) + form = SeqFormula(n**2) + + assert per + (SeqPer((2, 3))) == SeqPer((3, 5), (n, 0, oo)) + assert form + SeqFormula(n**3) == SeqFormula(n**2 + n**3) + + assert per + form == SeqAdd(per, form) + + raises(TypeError, lambda: per + n) + raises(TypeError, lambda: n + per) + + +def test_sub(): + per = SeqPer((1, 2), (n, 0, oo)) + form = SeqFormula(n**2) + + assert per - (SeqPer((2, 3))) == SeqPer((-1, -1), (n, 0, oo)) + assert form - (SeqFormula(n**3)) == SeqFormula(n**2 - n**3) + + assert per - form == SeqAdd(per, -form) + + raises(TypeError, lambda: per - n) + raises(TypeError, lambda: n - per) + + +def test_mul__coeff_mul(): + assert SeqPer((1, 2), (n, 0, oo)).coeff_mul(2) == SeqPer((2, 4), (n, 0, oo)) + assert SeqFormula(n**2).coeff_mul(2) == SeqFormula(2*n**2) + assert S.EmptySequence.coeff_mul(100) == S.EmptySequence + + assert SeqPer((1, 2), (n, 0, oo)) * (SeqPer((2, 3))) == \ + SeqPer((2, 6), (n, 0, oo)) + assert SeqFormula(n**2) * SeqFormula(n**3) == SeqFormula(n**5) + + assert S.EmptySequence * SeqFormula(n**2) == S.EmptySequence + assert SeqFormula(n**2) * S.EmptySequence == S.EmptySequence + + raises(TypeError, lambda: sequence(n**2) * n) + raises(TypeError, lambda: n * sequence(n**2)) + + +def test_neg(): + assert -SeqPer((1, -2), (n, 0, oo)) == SeqPer((-1, 2), (n, 0, oo)) + assert -SeqFormula(n**2) == SeqFormula(-n**2) + + +def test_operations(): + per = SeqPer((1, 2), (n, 0, oo)) + per2 = SeqPer((2, 4), (n, 0, oo)) + form = SeqFormula(n**2) + form2 = SeqFormula(n**3) + + assert per + form + form2 == SeqAdd(per, form, form2) + assert per + form - form2 == SeqAdd(per, form, -form2) + assert per + form - S.EmptySequence == SeqAdd(per, form) + assert per + per2 + form == SeqAdd(SeqPer((3, 6), (n, 0, oo)), form) + assert S.EmptySequence - per == -per + assert form + form == SeqFormula(2*n**2) + + assert per * form * form2 == SeqMul(per, form, form2) + assert form * form == SeqFormula(n**4) + assert form * -form == SeqFormula(-n**4) + + assert form * (per + form2) == SeqMul(form, SeqAdd(per, form2)) + assert form * (per + per) == SeqMul(form, per2) + + assert form.coeff_mul(m) == SeqFormula(m*n**2, (n, 0, oo)) + assert per.coeff_mul(m) == SeqPer((m, 2*m), (n, 0, oo)) + + +def test_Idx_limits(): + i = symbols('i', cls=Idx) + r = Indexed('r', i) + + assert SeqFormula(r, (i, 0, 5))[:] == [r.subs(i, j) for j in range(6)] + assert SeqPer((1, 2), (i, 0, 5))[:] == [1, 2, 1, 2, 1, 2] + + +@slow +def test_find_linear_recurrence(): + assert sequence((0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55), \ + (n, 0, 10)).find_linear_recurrence(11) == [1, 1] + assert sequence((1, 2, 4, 7, 28, 128, 582, 2745, 13021, 61699, 292521, \ + 1387138), (n, 0, 11)).find_linear_recurrence(12) == [5, -2, 6, -11] + assert sequence(x*n**3+y*n, (n, 0, oo)).find_linear_recurrence(10) \ + == [4, -6, 4, -1] + assert sequence(x**n, (n,0,20)).find_linear_recurrence(21) == [x] + assert sequence((1,2,3)).find_linear_recurrence(10, 5) == [0, 0, 1] + assert sequence(((1 + sqrt(5))/2)**n + \ + (-(1 + sqrt(5))/2)**(-n)).find_linear_recurrence(10) == [1, 1] + assert sequence(x*((1 + sqrt(5))/2)**n + y*(-(1 + sqrt(5))/2)**(-n), \ + (n,0,oo)).find_linear_recurrence(10) == [1, 1] + assert sequence((1,2,3,4,6),(n, 0, 4)).find_linear_recurrence(5) == [] + assert sequence((2,3,4,5,6,79),(n, 0, 5)).find_linear_recurrence(6,gfvar=x) \ + == ([], None) + assert sequence((2,3,4,5,8,30),(n, 0, 5)).find_linear_recurrence(6,gfvar=x) \ + == ([Rational(19, 2), -20, Rational(27, 2)], (-31*x**2 + 32*x - 4)/(27*x**3 - 40*x**2 + 19*x -2)) + assert sequence(fibonacci(n)).find_linear_recurrence(30,gfvar=x) \ + == ([1, 1], -x/(x**2 + x - 1)) + assert sequence(tribonacci(n)).find_linear_recurrence(30,gfvar=x) \ + == ([1, 1, 1], -x/(x**3 + x**2 + x - 1)) + +def test_RecursiveSeq(): + y = Function('y') + n = Symbol('n') + fib = RecursiveSeq(y(n - 1) + y(n - 2), y(n), n, [0, 1]) + assert fib.coeff(3) == 2 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_series.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_series.py new file mode 100644 index 0000000000000000000000000000000000000000..e3f3c122b98c14a58c6d5c6636cbb53e1e66a75d --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/series/tests/test_series.py @@ -0,0 +1,421 @@ +from sympy.core.evalf import N +from sympy.core.function import (Derivative, Function, PoleError, Subs) +from sympy.core.numbers import (E, Float, Rational, oo, pi, I) +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.elementary.exponential import (LambertW, exp, log) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (atan, cos, sin) +from sympy.functions.special.gamma_functions import gamma +from sympy.integrals.integrals import Integral, integrate +from sympy.series.order import O +from sympy.series.series import series +from sympy.abc import x, y, n, k +from sympy.testing.pytest import raises +from sympy.core import EulerGamma + + +def test_sin(): + e1 = sin(x).series(x, 0) + e2 = series(sin(x), x, 0) + assert e1 == e2 + + +def test_cos(): + e1 = cos(x).series(x, 0) + e2 = series(cos(x), x, 0) + assert e1 == e2 + + +def test_exp(): + e1 = exp(x).series(x, 0) + e2 = series(exp(x), x, 0) + assert e1 == e2 + + +def test_exp2(): + e1 = exp(cos(x)).series(x, 0) + e2 = series(exp(cos(x)), x, 0) + assert e1 == e2 + + +def test_issue_5223(): + assert series(1, x) == 1 + assert next(S.Zero.lseries(x)) == 0 + assert cos(x).series() == cos(x).series(x) + raises(ValueError, lambda: cos(x + y).series()) + raises(ValueError, lambda: x.series(dir="")) + + assert (cos(x).series(x, 1) - + cos(x + 1).series(x).subs(x, x - 1)).removeO() == 0 + e = cos(x).series(x, 1, n=None) + assert [next(e) for i in range(2)] == [cos(1), -((x - 1)*sin(1))] + e = cos(x).series(x, 1, n=None, dir='-') + assert [next(e) for i in range(2)] == [cos(1), (1 - x)*sin(1)] + # the following test is exact so no need for x -> x - 1 replacement + assert abs(x).series(x, 1, dir='-') == x + assert exp(x).series(x, 1, dir='-', n=3).removeO() == \ + E - E*(-x + 1) + E*(-x + 1)**2/2 + + D = Derivative + assert D(x**2 + x**3*y**2, x, 2, y, 1).series(x).doit() == 12*x*y + assert next(D(cos(x), x).lseries()) == D(1, x) + assert D( + exp(x), x).series(n=3) == D(1, x) + D(x, x) + D(x**2/2, x) + D(x**3/6, x) + O(x**3) + + assert Integral(x, (x, 1, 3), (y, 1, x)).series(x) == -4 + 4*x + + assert (1 + x + O(x**2)).getn() == 2 + assert (1 + x).getn() is None + + raises(PoleError, lambda: ((1/sin(x))**oo).series()) + logx = Symbol('logx') + assert ((sin(x))**y).nseries(x, n=1, logx=logx) == \ + exp(y*logx) + O(x*exp(y*logx), x) + + assert sin(1/x).series(x, oo, n=5) == 1/x - 1/(6*x**3) + O(x**(-5), (x, oo)) + assert abs(x).series(x, oo, n=5, dir='+') == x + assert abs(x).series(x, -oo, n=5, dir='-') == -x + assert abs(-x).series(x, oo, n=5, dir='+') == x + assert abs(-x).series(x, -oo, n=5, dir='-') == -x + + assert exp(x*log(x)).series(n=3) == \ + 1 + x*log(x) + x**2*log(x)**2/2 + O(x**3*log(x)**3) + # XXX is this right? If not, fix "ngot > n" handling in expr. + p = Symbol('p', positive=True) + assert exp(sqrt(p)**3*log(p)).series(n=3) == \ + 1 + p**S('3/2')*log(p) + O(p**3*log(p)**3) + + assert exp(sin(x)*log(x)).series(n=2) == 1 + x*log(x) + O(x**2*log(x)**2) + + +def test_issue_6350(): + expr = integrate(exp(k*(y**3 - 3*y)), (y, 0, oo), conds='none') + assert expr.series(k, 0, 3) == -(-1)**(S(2)/3)*sqrt(3)*gamma(S(1)/3)**2*gamma(S(2)/3)/(6*pi*k**(S(1)/3)) - \ + sqrt(3)*k*gamma(-S(2)/3)*gamma(-S(1)/3)/(6*pi) - \ + (-1)**(S(1)/3)*sqrt(3)*k**(S(1)/3)*gamma(-S(1)/3)*gamma(S(1)/3)*gamma(S(2)/3)/(6*pi) - \ + (-1)**(S(2)/3)*sqrt(3)*k**(S(5)/3)*gamma(S(1)/3)**2*gamma(S(2)/3)/(4*pi) - \ + (-1)**(S(1)/3)*sqrt(3)*k**(S(7)/3)*gamma(-S(1)/3)*gamma(S(1)/3)*gamma(S(2)/3)/(8*pi) + O(k**3) + + +def test_issue_11313(): + assert Integral(cos(x), x).series(x) == sin(x).series(x) + assert Derivative(sin(x), x).series(x, n=3).doit() == cos(x).series(x, n=3) + + assert Derivative(x**3, x).as_leading_term(x) == 3*x**2 + assert Derivative(x**3, y).as_leading_term(x) == 0 + assert Derivative(sin(x), x).as_leading_term(x) == 1 + assert Derivative(cos(x), x).as_leading_term(x) == -x + + # This result is equivalent to zero, zero is not return because + # `Expr.series` doesn't currently detect an `x` in its `free_symbol`s. + assert Derivative(1, x).as_leading_term(x) == Derivative(1, x) + + assert Derivative(exp(x), x).series(x).doit() == exp(x).series(x) + assert 1 + Integral(exp(x), x).series(x) == exp(x).series(x) + + assert Derivative(log(x), x).series(x).doit() == (1/x).series(x) + assert Integral(log(x), x).series(x) == Integral(log(x), x).doit().series(x).removeO() + + +def test_series_of_Subs(): + from sympy.abc import z + + subs1 = Subs(sin(x), x, y) + subs2 = Subs(sin(x) * cos(z), x, y) + subs3 = Subs(sin(x * z), (x, z), (y, x)) + + assert subs1.series(x) == subs1 + subs1_series = (Subs(x, x, y) + Subs(-x**3/6, x, y) + + Subs(x**5/120, x, y) + O(y**6)) + assert subs1.series() == subs1_series + assert subs1.series(y) == subs1_series + assert subs1.series(z) == subs1 + assert subs2.series(z) == (Subs(z**4*sin(x)/24, x, y) + + Subs(-z**2*sin(x)/2, x, y) + Subs(sin(x), x, y) + O(z**6)) + assert subs3.series(x).doit() == subs3.doit().series(x) + assert subs3.series(z).doit() == sin(x*y) + + raises(ValueError, lambda: Subs(x + 2*y, y, z).series()) + assert Subs(x + y, y, z).series(x).doit() == x + z + + +def test_issue_3978(): + f = Function('f') + assert f(x).series(x, 0, 3, dir='-') == \ + f(0) + x*Subs(Derivative(f(x), x), x, 0) + \ + x**2*Subs(Derivative(f(x), x, x), x, 0)/2 + O(x**3) + assert f(x).series(x, 0, 3) == \ + f(0) + x*Subs(Derivative(f(x), x), x, 0) + \ + x**2*Subs(Derivative(f(x), x, x), x, 0)/2 + O(x**3) + assert f(x**2).series(x, 0, 3) == \ + f(0) + x**2*Subs(Derivative(f(x), x), x, 0) + O(x**3) + assert f(x**2+1).series(x, 0, 3) == \ + f(1) + x**2*Subs(Derivative(f(x), x), x, 1) + O(x**3) + + class TestF(Function): + pass + + assert TestF(x).series(x, 0, 3) == TestF(0) + \ + x*Subs(Derivative(TestF(x), x), x, 0) + \ + x**2*Subs(Derivative(TestF(x), x, x), x, 0)/2 + O(x**3) + +from sympy.series.acceleration import richardson, shanks +from sympy.concrete.summations import Sum +from sympy.core.numbers import Integer + + +def test_acceleration(): + e = (1 + 1/n)**n + assert round(richardson(e, n, 10, 20).evalf(), 10) == round(E.evalf(), 10) + + A = Sum(Integer(-1)**(k + 1) / k, (k, 1, n)) + assert round(shanks(A, n, 25).evalf(), 4) == round(log(2).evalf(), 4) + assert round(shanks(A, n, 25, 5).evalf(), 10) == round(log(2).evalf(), 10) + + +def test_issue_5852(): + assert series(1/cos(x/log(x)), x, 0) == 1 + x**2/(2*log(x)**2) + \ + 5*x**4/(24*log(x)**4) + O(x**6) + + +def test_issue_4583(): + assert cos(1 + x + x**2).series(x, 0, 5) == cos(1) - x*sin(1) + \ + x**2*(-sin(1) - cos(1)/2) + x**3*(-cos(1) + sin(1)/6) + \ + x**4*(-11*cos(1)/24 + sin(1)/2) + O(x**5) + + +def test_issue_6318(): + eq = (1/x)**Rational(2, 3) + assert (eq + 1).as_leading_term(x) == eq + + +def test_x_is_base_detection(): + eq = (x**2)**Rational(2, 3) + assert eq.series() == x**Rational(4, 3) + + +def test_issue_7203(): + assert series(cos(x), x, pi, 3) == \ + -1 + (x - pi)**2/2 + O((x - pi)**3, (x, pi)) + + +def test_exp_product_positive_factors(): + a, b = symbols('a, b', positive=True) + x = a * b + assert series(exp(x), x, n=8) == 1 + a*b + a**2*b**2/2 + \ + a**3*b**3/6 + a**4*b**4/24 + a**5*b**5/120 + a**6*b**6/720 + \ + a**7*b**7/5040 + O(a**8*b**8, a, b) + + +def test_issue_8805(): + assert series(1, n=8) == 1 + + +def test_issue_9173(): + p0,p1,p2,p3,b0,b1,b2=symbols('p0 p1 p2 p3 b0 b1 b2') + Q=(p0+(p1+(p2+p3/y)/y)/y)/(1+((p3/(b0*y)+(b0*p2-b1*p3)/b0**2)/y+\ + (b0**2*p1-b0*b1*p2-p3*(b0*b2-b1**2))/b0**3)/y) + + series = Q.series(y,n=3) + + assert series == y*(b0*p2/p3+b0*(-p2/p3+b1/b0))+y**2*(b0*p1/p3+b0*p2*\ + (-p2/p3+b1/b0)/p3+b0*(-p1/p3+(p2/p3-b1/b0)**2+b1*p2/(b0*p3)+\ + b2/b0-b1**2/b0**2))+b0+O(y**3) + assert series.simplify() == b2*y**2 + b1*y + b0 + O(y**3) + + +def test_issue_9549(): + y = (x**2 + x + 1) / (x**3 + x**2) + assert series(y, x, oo) == x**(-5) - 1/x**4 + x**(-3) + 1/x + O(x**(-6), (x, oo)) + + +def test_issue_10761(): + assert series(1/(x**-2 + x**-3), x, 0) == x**3 - x**4 + x**5 + O(x**6) + + +def test_issue_12578(): + y = (1 - 1/(x/2 - 1/(2*x))**4)**(S(1)/8) + assert y.series(x, 0, n=17) == 1 - 2*x**4 - 8*x**6 - 34*x**8 - 152*x**10 - 714*x**12 - \ + 3472*x**14 - 17318*x**16 + O(x**17) + + +def test_issue_12791(): + beta = symbols('beta', positive=True) + theta, varphi = symbols('theta varphi', real=True) + + expr = (-beta**2*varphi*sin(theta) + beta**2*cos(theta) + \ + beta*varphi*sin(theta) - beta*cos(theta) - beta + 1)/(beta*cos(theta) - 1)**2 + + sol = (0.5/(0.5*cos(theta) - 1.0)**2 - 0.25*cos(theta)/(0.5*cos(theta) - 1.0)**2 + + (beta - 0.5)*(-0.25*varphi*sin(2*theta) - 1.5*cos(theta) + + 0.25*cos(2*theta) + 1.25)/((0.5*cos(theta) - 1.0)**2*(0.5*cos(theta) - 1.0)) + + 0.25*varphi*sin(theta)/(0.5*cos(theta) - 1.0)**2 + + O((beta - S.Half)**2, (beta, S.Half))) + + assert expr.series(beta, 0.5, 2).trigsimp() == sol + + +def test_issue_14384(): + x, a = symbols('x a') + assert series(x**a, x) == x**a + assert series(x**(-2*a), x) == x**(-2*a) + assert series(exp(a*log(x)), x) == exp(a*log(x)) + raises(PoleError, lambda: series(x**I, x)) + raises(PoleError, lambda: series(x**(I + 1), x)) + raises(PoleError, lambda: series(exp(I*log(x)), x)) + + +def test_issue_14885(): + assert series(x**Rational(-3, 2)*exp(x), x, 0) == (x**Rational(-3, 2) + 1/sqrt(x) + + sqrt(x)/2 + x**Rational(3, 2)/6 + x**Rational(5, 2)/24 + x**Rational(7, 2)/120 + + x**Rational(9, 2)/720 + x**Rational(11, 2)/5040 + O(x**6)) + + +def test_issue_15539(): + assert series(atan(x), x, -oo) == (-1/(5*x**5) + 1/(3*x**3) - 1/x - pi/2 + + O(x**(-6), (x, -oo))) + assert series(atan(x), x, oo) == (-1/(5*x**5) + 1/(3*x**3) - 1/x + pi/2 + + O(x**(-6), (x, oo))) + + +def test_issue_7259(): + assert series(LambertW(x), x) == x - x**2 + 3*x**3/2 - 8*x**4/3 + 125*x**5/24 + O(x**6) + assert series(LambertW(x**2), x, n=8) == x**2 - x**4 + 3*x**6/2 + O(x**8) + assert series(LambertW(sin(x)), x, n=4) == x - x**2 + 4*x**3/3 + O(x**4) + +def test_issue_11884(): + assert cos(x).series(x, 1, n=1) == cos(1) + O(x - 1, (x, 1)) + + +def test_issue_18008(): + y = x*(1 + x*(1 - x))/((1 + x*(1 - x)) - (1 - x)*(1 - x)) + assert y.series(x, oo, n=4) == -9/(32*x**3) - 3/(16*x**2) - 1/(8*x) + S(1)/4 + x/2 + \ + O(x**(-4), (x, oo)) + + +def test_issue_18842(): + f = log(x/(1 - x)) + assert f.series(x, 0.491, n=1).removeO().nsimplify() == \ + -S(180019443780011)/5000000000000000 + + +def test_issue_19534(): + dt = symbols('dt', real=True) + expr = 16*dt*(0.125*dt*(2.0*dt + 1.0) + 0.875*dt + 1.0)/45 + \ + 49*dt*(-0.049335189898860408029*dt*(2.0*dt + 1.0) + \ + 0.29601113939316244817*dt*(0.125*dt*(2.0*dt + 1.0) + 0.875*dt + 1.0) - \ + 0.12564355335492979587*dt*(0.074074074074074074074*dt*(2.0*dt + 1.0) + \ + 0.2962962962962962963*dt*(0.125*dt*(2.0*dt + 1.0) + 0.875*dt + 1.0) + \ + 0.96296296296296296296*dt + 1.0) + 0.051640768506639183825*dt + \ + dt*(1/2 - sqrt(21)/14) + 1.0)/180 + 49*dt*(-0.23637909581542530626*dt*(2.0*dt + 1.0) - \ + 0.74817562366625959291*dt*(0.125*dt*(2.0*dt + 1.0) + 0.875*dt + 1.0) + \ + 0.88085458023927036857*dt*(0.074074074074074074074*dt*(2.0*dt + 1.0) + \ + 0.2962962962962962963*dt*(0.125*dt*(2.0*dt + 1.0) + 0.875*dt + 1.0) + \ + 0.96296296296296296296*dt + 1.0) + \ + 2.1165151389911680013*dt*(-0.049335189898860408029*dt*(2.0*dt + 1.0) + \ + 0.29601113939316244817*dt*(0.125*dt*(2.0*dt + 1.0) + 0.875*dt + 1.0) - \ + 0.12564355335492979587*dt*(0.074074074074074074074*dt*(2.0*dt + 1.0) + \ + 0.2962962962962962963*dt*(0.125*dt*(2.0*dt + 1.0) + 0.875*dt + 1.0) + \ + 0.96296296296296296296*dt + 1.0) + 0.22431393315265061193*dt + 1.0) - \ + 1.1854881643947648988*dt + dt*(sqrt(21)/14 + 1/2) + 1.0)/180 + \ + dt*(0.66666666666666666667*dt*(2.0*dt + 1.0) + \ + 6.0173399699313066769*dt*(0.125*dt*(2.0*dt + 1.0) + 0.875*dt + 1.0) - \ + 4.1117044797036320069*dt*(0.074074074074074074074*dt*(2.0*dt + 1.0) + \ + 0.2962962962962962963*dt*(0.125*dt*(2.0*dt + 1.0) + 0.875*dt + 1.0) + \ + 0.96296296296296296296*dt + 1.0) - \ + 7.0189140975801991157*dt*(-0.049335189898860408029*dt*(2.0*dt + 1.0) + \ + 0.29601113939316244817*dt*(0.125*dt*(2.0*dt + 1.0) + 0.875*dt + 1.0) - \ + 0.12564355335492979587*dt*(0.074074074074074074074*dt*(2.0*dt + 1.0) + \ + 0.2962962962962962963*dt*(0.125*dt*(2.0*dt + 1.0) + 0.875*dt + 1.0) + \ + 0.96296296296296296296*dt + 1.0) + 0.22431393315265061193*dt + 1.0) + \ + 0.94010945196161777522*dt*(-0.23637909581542530626*dt*(2.0*dt + 1.0) - \ + 0.74817562366625959291*dt*(0.125*dt*(2.0*dt + 1.0) + 0.875*dt + 1.0) + \ + 0.88085458023927036857*dt*(0.074074074074074074074*dt*(2.0*dt + 1.0) + \ + 0.2962962962962962963*dt*(0.125*dt*(2.0*dt + 1.0) + 0.875*dt + 1.0) + \ + 0.96296296296296296296*dt + 1.0) + \ + 2.1165151389911680013*dt*(-0.049335189898860408029*dt*(2.0*dt + 1.0) + \ + 0.29601113939316244817*dt*(0.125*dt*(2.0*dt + 1.0) + 0.875*dt + 1.0) - \ + 0.12564355335492979587*dt*(0.074074074074074074074*dt*(2.0*dt + 1.0) + \ + 0.2962962962962962963*dt*(0.125*dt*(2.0*dt + 1.0) + 0.875*dt + 1.0) + \ + 0.96296296296296296296*dt + 1.0) + 0.22431393315265061193*dt + 1.0) - \ + 0.35816132904077632692*dt + 1.0) + 5.5065024887242400038*dt + 1.0)/20 + dt/20 + 1 + + assert N(expr.series(dt, 0, 8), 20) == ( + - Float('0.00092592592592592596126289', precision=70) * dt**7 + + Float('0.0027777777777777783174695', precision=70) * dt**6 + + Float('0.016666666666666656027029', precision=70) * dt**5 + + Float('0.083333333333333300951828', precision=70) * dt**4 + + Float('0.33333333333333337034077', precision=70) * dt**3 + + Float('1.0', precision=70) * dt**2 + + Float('1.0', precision=70) * dt + + Float('1.0', precision=70) + ) + + +def test_issue_11407(): + a, b, c, x = symbols('a b c x') + assert series(sqrt(a + b + c*x), x, 0, 1) == sqrt(a + b) + O(x) + assert series(sqrt(a + b + c + c*x), x, 0, 1) == sqrt(a + b + c) + O(x) + + +def test_issue_14037(): + assert (sin(x**50)/x**51).series(x, n=0) == 1/x + O(1, x) + + +def test_issue_20551(): + expr = (exp(x)/x).series(x, n=None) + terms = [ next(expr) for i in range(3) ] + assert terms == [1/x, 1, x/2] + + +def test_issue_20697(): + p_0, p_1, p_2, p_3, b_0, b_1, b_2 = symbols('p_0 p_1 p_2 p_3 b_0 b_1 b_2') + Q = (p_0 + (p_1 + (p_2 + p_3/y)/y)/y)/(1 + ((p_3/(b_0*y) + (b_0*p_2\ + - b_1*p_3)/b_0**2)/y + (b_0**2*p_1 - b_0*b_1*p_2 - p_3*(b_0*b_2\ + - b_1**2))/b_0**3)/y) + assert Q.series(y, n=3).ratsimp() == b_2*y**2 + b_1*y + b_0 + O(y**3) + + +def test_issue_21245(): + fi = (1 + sqrt(5))/2 + assert (1/(1 - x - x**2)).series(x, 1/fi, 1).factor() == \ + (-37*sqrt(5) - 83 + 13*sqrt(5)*x + 29*x + O((x - 2/(1 + sqrt(5)))**2, (x\ + , 2/(1 + sqrt(5)))))/((2*sqrt(5) + 5)**2*(x + sqrt(5)*x - 2)) + + + +def test_issue_21938(): + expr = sin(1/x + exp(-x)) - sin(1/x) + assert expr.series(x, oo) == (1/(24*x**4) - 1/(2*x**2) + 1 + O(x**(-6), (x, oo)))*exp(-x) + + +def test_issue_23432(): + expr = 1/sqrt(1 - x**2) + result = expr.series(x, 0.5) + assert result.is_Add and len(result.args) == 7 + + +def test_issue_23727(): + res = series(sqrt(1 - x**2), x, 0.1) + assert res.is_Add == True + + +def test_issue_24266(): + #type1: exp(f(x)) + assert (exp(-I*pi*(2*x+1))).series(x, 0, 3) == -1 + 2*I*pi*x + 2*pi**2*x**2 + O(x**3) + assert (exp(-I*pi*(2*x+1))*gamma(1+x)).series(x, 0, 3) == -1 + x*(EulerGamma + 2*I*pi) + \ + x**2*(-EulerGamma**2/2 + 23*pi**2/12 - 2*EulerGamma*I*pi) + O(x**3) + + #type2: c**f(x) + assert ((2*I)**(-I*pi*(2*x+1))).series(x, 0, 2) == exp(pi**2/2 - I*pi*log(2)) + \ + x*(pi**2*exp(pi**2/2 - I*pi*log(2)) - 2*I*pi*exp(pi**2/2 - I*pi*log(2))*log(2)) + O(x**2) + assert ((2)**(-I*pi*(2*x+1))).series(x, 0, 2) == exp(-I*pi*log(2)) - 2*I*pi*x*exp(-I*pi*log(2))*log(2) + O(x**2) + + #type3: f(y)**g(x) + assert ((y)**(I*pi*(2*x+1))).series(x, 0, 2) == exp(I*pi*log(y)) + 2*I*pi*x*exp(I*pi*log(y))*log(y) + O(x**2) + assert ((I*y)**(I*pi*(2*x+1))).series(x, 0, 2) == exp(I*pi*log(I*y)) + 2*I*pi*x*exp(I*pi*log(I*y))*log(I*y) + O(x**2) + + +def test_issue_26856(): + raises(ValueError, lambda: (2**x).series(x, oo, -1)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bf5894854cfcd9feca06d1673feef0eed942f298 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/_cse_diff.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/_cse_diff.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..edb5597042b41dfd0c1ae8f0f80d84c306c66c0c Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/_cse_diff.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/cse_main.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/cse_main.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e48cbdbd621d017e4081fe8e6f6ea75bd9f98d15 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/cse_main.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/cse_opts.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/cse_opts.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f4d5ede7295186d31fb04481a3b899943ff5cd59 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/cse_opts.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/gammasimp.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/gammasimp.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..679c2f31e19353ba166d3828145a3c73c95373f0 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/gammasimp.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/hyperexpand_doc.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/hyperexpand_doc.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4ad311adf912a317b145afeaa645618b8adbf911 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/hyperexpand_doc.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/powsimp.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/powsimp.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b4cd27957f396711f8231e7d86e61ad8fcae4745 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/powsimp.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/radsimp.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/radsimp.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a2d17f10c38d5286e8e1dfc2e1db22b08451e8e7 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/radsimp.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/ratsimp.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/ratsimp.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..35a19528d08e38ee9451e9fca0cf9920e344f9fd Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/ratsimp.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/simplify.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/simplify.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..98d019d29e13779b99e6b94e814d89dbbeb65663 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/simplify.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/sqrtdenest.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/sqrtdenest.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d0a73fe9babc29936e27cf98972f449c7aeade57 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/sqrtdenest.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/traversaltools.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/traversaltools.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b0f219e2512a356eaba4f0fcd37df20e36984e4f Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/traversaltools.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/trigsimp.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/trigsimp.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0c0837fbe1a73942d4bc669de4d5d4c2e7c5fc4a Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/__pycache__/trigsimp.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_combsimp.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_combsimp.py new file mode 100644 index 0000000000000000000000000000000000000000..e56758a005fbb013c2b6ea4121b16c3434a54b03 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_combsimp.py @@ -0,0 +1,75 @@ +from sympy.core.numbers import Rational +from sympy.core.symbol import symbols +from sympy.functions.combinatorial.factorials import (FallingFactorial, RisingFactorial, binomial, factorial) +from sympy.functions.special.gamma_functions import gamma +from sympy.simplify.combsimp import combsimp +from sympy.abc import x + + +def test_combsimp(): + k, m, n = symbols('k m n', integer = True) + + assert combsimp(factorial(n)) == factorial(n) + assert combsimp(binomial(n, k)) == binomial(n, k) + + assert combsimp(factorial(n)/factorial(n - 3)) == n*(-1 + n)*(-2 + n) + assert combsimp(binomial(n + 1, k + 1)/binomial(n, k)) == (1 + n)/(1 + k) + + assert combsimp(binomial(3*n + 4, n + 1)/binomial(3*n + 1, n)) == \ + Rational(3, 2)*((3*n + 2)*(3*n + 4)/((n + 1)*(2*n + 3))) + + assert combsimp(factorial(n)**2/factorial(n - 3)) == \ + factorial(n)*n*(-1 + n)*(-2 + n) + assert combsimp(factorial(n)*binomial(n + 1, k + 1)/binomial(n, k)) == \ + factorial(n + 1)/(1 + k) + + assert combsimp(gamma(n + 3)) == factorial(n + 2) + + assert combsimp(factorial(x)) == gamma(x + 1) + + # issue 9699 + assert combsimp((n + 1)*factorial(n)) == factorial(n + 1) + assert combsimp(factorial(n)/n) == factorial(n-1) + + # issue 6658 + assert combsimp(binomial(n, n - k)) == binomial(n, k) + + # issue 6341, 7135 + assert combsimp(factorial(n)/(factorial(k)*factorial(n - k))) == \ + binomial(n, k) + assert combsimp(factorial(k)*factorial(n - k)/factorial(n)) == \ + 1/binomial(n, k) + assert combsimp(factorial(2*n)/factorial(n)**2) == binomial(2*n, n) + assert combsimp(factorial(2*n)*factorial(k)*factorial(n - k)/ + factorial(n)**3) == binomial(2*n, n)/binomial(n, k) + + assert combsimp(factorial(n*(1 + n) - n**2 - n)) == 1 + + assert combsimp(6*FallingFactorial(-4, n)/factorial(n)) == \ + (-1)**n*(n + 1)*(n + 2)*(n + 3) + assert combsimp(6*FallingFactorial(-4, n - 1)/factorial(n - 1)) == \ + (-1)**(n - 1)*n*(n + 1)*(n + 2) + assert combsimp(6*FallingFactorial(-4, n - 3)/factorial(n - 3)) == \ + (-1)**(n - 3)*n*(n - 1)*(n - 2) + assert combsimp(6*FallingFactorial(-4, -n - 1)/factorial(-n - 1)) == \ + -(-1)**(-n - 1)*n*(n - 1)*(n - 2) + + assert combsimp(6*RisingFactorial(4, n)/factorial(n)) == \ + (n + 1)*(n + 2)*(n + 3) + assert combsimp(6*RisingFactorial(4, n - 1)/factorial(n - 1)) == \ + n*(n + 1)*(n + 2) + assert combsimp(6*RisingFactorial(4, n - 3)/factorial(n - 3)) == \ + n*(n - 1)*(n - 2) + assert combsimp(6*RisingFactorial(4, -n - 1)/factorial(-n - 1)) == \ + -n*(n - 1)*(n - 2) + + +def test_issue_6878(): + n = symbols('n', integer=True) + assert combsimp(RisingFactorial(-10, n)) == 3628800*(-1)**n/factorial(10 - n) + + +def test_issue_14528(): + p = symbols("p", integer=True, positive=True) + assert combsimp(binomial(1,p)) == 1/(factorial(p)*factorial(1-p)) + assert combsimp(factorial(2-p)) == factorial(2-p) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_cse.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_cse.py new file mode 100644 index 0000000000000000000000000000000000000000..c2a34dfb0e227547bd41bed2491284fd7150d0b6 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_cse.py @@ -0,0 +1,761 @@ +from functools import reduce +import itertools +from operator import add + +from sympy.codegen.matrix_nodes import MatrixSolve +from sympy.core.add import Add +from sympy.core.containers import Tuple +from sympy.core.expr import UnevaluatedExpr +from sympy.core.function import Function +from sympy.core.mul import Mul +from sympy.core.power import Pow +from sympy.core.relational import Eq +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.core.sympify import sympify +from sympy.functions.elementary.exponential import exp +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.piecewise import Piecewise +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.matrices.dense import Matrix +from sympy.matrices.expressions import Inverse, MatAdd, MatMul, Transpose +from sympy.polys.rootoftools import CRootOf +from sympy.series.order import O +from sympy.simplify.cse_main import cse +from sympy.simplify.simplify import signsimp +from sympy.tensor.indexed import (Idx, IndexedBase) + +from sympy.core.function import count_ops +from sympy.simplify.cse_opts import sub_pre, sub_post +from sympy.functions.special.hyper import meijerg +from sympy.simplify import cse_main, cse_opts +from sympy.utilities.iterables import subsets +from sympy.testing.pytest import XFAIL, raises +from sympy.matrices import (MutableDenseMatrix, MutableSparseMatrix, + ImmutableDenseMatrix, ImmutableSparseMatrix) +from sympy.matrices.expressions import MatrixSymbol + + +w, x, y, z = symbols('w,x,y,z') +x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12 = symbols('x:13') + + +def test_numbered_symbols(): + ns = cse_main.numbered_symbols(prefix='y') + assert list(itertools.islice( + ns, 0, 10)) == [Symbol('y%s' % i) for i in range(0, 10)] + ns = cse_main.numbered_symbols(prefix='y') + assert list(itertools.islice( + ns, 10, 20)) == [Symbol('y%s' % i) for i in range(10, 20)] + ns = cse_main.numbered_symbols() + assert list(itertools.islice( + ns, 0, 10)) == [Symbol('x%s' % i) for i in range(0, 10)] + +# Dummy "optimization" functions for testing. + + +def opt1(expr): + return expr + y + + +def opt2(expr): + return expr*z + + +def test_preprocess_for_cse(): + assert cse_main.preprocess_for_cse(x, [(opt1, None)]) == x + y + assert cse_main.preprocess_for_cse(x, [(None, opt1)]) == x + assert cse_main.preprocess_for_cse(x, [(None, None)]) == x + assert cse_main.preprocess_for_cse(x, [(opt1, opt2)]) == x + y + assert cse_main.preprocess_for_cse( + x, [(opt1, None), (opt2, None)]) == (x + y)*z + + +def test_postprocess_for_cse(): + assert cse_main.postprocess_for_cse(x, [(opt1, None)]) == x + assert cse_main.postprocess_for_cse(x, [(None, opt1)]) == x + y + assert cse_main.postprocess_for_cse(x, [(None, None)]) == x + assert cse_main.postprocess_for_cse(x, [(opt1, opt2)]) == x*z + # Note the reverse order of application. + assert cse_main.postprocess_for_cse( + x, [(None, opt1), (None, opt2)]) == x*z + y + + +def test_cse_single(): + # Simple substitution. + e = Add(Pow(x + y, 2), sqrt(x + y)) + substs, reduced = cse([e]) + assert substs == [(x0, x + y)] + assert reduced == [sqrt(x0) + x0**2] + + subst42, (red42,) = cse([42]) # issue_15082 + assert len(subst42) == 0 and red42 == 42 + subst_half, (red_half,) = cse([0.5]) + assert len(subst_half) == 0 and red_half == 0.5 + + +def test_cse_single2(): + # Simple substitution, test for being able to pass the expression directly + e = Add(Pow(x + y, 2), sqrt(x + y)) + substs, reduced = cse(e) + assert substs == [(x0, x + y)] + assert reduced == [sqrt(x0) + x0**2] + substs, reduced = cse(Matrix([[1]])) + assert isinstance(reduced[0], Matrix) + + subst42, (red42,) = cse(42) # issue 15082 + assert len(subst42) == 0 and red42 == 42 + subst_half, (red_half,) = cse(0.5) # issue 15082 + assert len(subst_half) == 0 and red_half == 0.5 + + +def test_cse_not_possible(): + # No substitution possible. + e = Add(x, y) + substs, reduced = cse([e]) + assert substs == [] + assert reduced == [x + y] + # issue 6329 + eq = (meijerg((1, 2), (y, 4), (5,), [], x) + + meijerg((1, 3), (y, 4), (5,), [], x)) + assert cse(eq) == ([], [eq]) + + +def test_nested_substitution(): + # Substitution within a substitution. + e = Add(Pow(w*x + y, 2), sqrt(w*x + y)) + substs, reduced = cse([e]) + assert substs == [(x0, w*x + y)] + assert reduced == [sqrt(x0) + x0**2] + + +def test_subtraction_opt(): + # Make sure subtraction is optimized. + e = (x - y)*(z - y) + exp((x - y)*(z - y)) + substs, reduced = cse( + [e], optimizations=[(cse_opts.sub_pre, cse_opts.sub_post)]) + assert substs == [(x0, (x - y)*(y - z))] + assert reduced == [-x0 + exp(-x0)] + e = -(x - y)*(z - y) + exp(-(x - y)*(z - y)) + substs, reduced = cse( + [e], optimizations=[(cse_opts.sub_pre, cse_opts.sub_post)]) + assert substs == [(x0, (x - y)*(y - z))] + assert reduced == [x0 + exp(x0)] + # issue 4077 + n = -1 + 1/x + e = n/x/(-n)**2 - 1/n/x + assert cse(e, optimizations=[(cse_opts.sub_pre, cse_opts.sub_post)]) == \ + ([], [0]) + assert cse(((w + x + y + z)*(w - y - z))/(w + x)**3) == \ + ([(x0, w + x), (x1, y + z)], [(w - x1)*(x0 + x1)/x0**3]) + + +def test_multiple_expressions(): + e1 = (x + y)*z + e2 = (x + y)*w + substs, reduced = cse([e1, e2]) + assert substs == [(x0, x + y)] + assert reduced == [x0*z, x0*w] + l = [w*x*y + z, w*y] + substs, reduced = cse(l) + rsubsts, _ = cse(reversed(l)) + assert substs == rsubsts + assert reduced == [z + x*x0, x0] + l = [w*x*y, w*x*y + z, w*y] + substs, reduced = cse(l) + rsubsts, _ = cse(reversed(l)) + assert substs == rsubsts + assert reduced == [x1, x1 + z, x0] + l = [(x - z)*(y - z), x - z, y - z] + substs, reduced = cse(l) + rsubsts, _ = cse(reversed(l)) + assert substs == [(x0, -z), (x1, x + x0), (x2, x0 + y)] + assert rsubsts == [(x0, -z), (x1, x0 + y), (x2, x + x0)] + assert reduced == [x1*x2, x1, x2] + l = [w*y + w + x + y + z, w*x*y] + assert cse(l) == ([(x0, w*y)], [w + x + x0 + y + z, x*x0]) + assert cse([x + y, x + y + z]) == ([(x0, x + y)], [x0, z + x0]) + assert cse([x + y, x + z]) == ([], [x + y, x + z]) + assert cse([x*y, z + x*y, x*y*z + 3]) == \ + ([(x0, x*y)], [x0, z + x0, 3 + x0*z]) + + +@XFAIL # CSE of non-commutative Mul terms is disabled +def test_non_commutative_cse(): + A, B, C = symbols('A B C', commutative=False) + l = [A*B*C, A*C] + assert cse(l) == ([], l) + l = [A*B*C, A*B] + assert cse(l) == ([(x0, A*B)], [x0*C, x0]) + + +# Test if CSE of non-commutative Mul terms is disabled +def test_bypass_non_commutatives(): + A, B, C = symbols('A B C', commutative=False) + l = [A*B*C, A*C] + assert cse(l) == ([], l) + l = [A*B*C, A*B] + assert cse(l) == ([], l) + l = [B*C, A*B*C] + assert cse(l) == ([], l) + + +@XFAIL # CSE fails when replacing non-commutative sub-expressions +def test_non_commutative_order(): + A, B, C = symbols('A B C', commutative=False) + x0 = symbols('x0', commutative=False) + l = [B+C, A*(B+C)] + assert cse(l) == ([(x0, B+C)], [x0, A*x0]) + + +@XFAIL # Worked in gh-11232, but was reverted due to performance considerations +def test_issue_10228(): + assert cse([x*y**2 + x*y]) == ([(x0, x*y)], [x0*y + x0]) + assert cse([x + y, 2*x + y]) == ([(x0, x + y)], [x0, x + x0]) + assert cse((w + 2*x + y + z, w + x + 1)) == ( + [(x0, w + x)], [x0 + x + y + z, x0 + 1]) + assert cse(((w + x + y + z)*(w - x))/(w + x)) == ( + [(x0, w + x)], [(x0 + y + z)*(w - x)/x0]) + a, b, c, d, f, g, j, m = symbols('a, b, c, d, f, g, j, m') + exprs = (d*g**2*j*m, 4*a*f*g*m, a*b*c*f**2) + assert cse(exprs) == ( + [(x0, g*m), (x1, a*f)], [d*g*j*x0, 4*x0*x1, b*c*f*x1] +) + +@XFAIL +def test_powers(): + assert cse(x*y**2 + x*y) == ([(x0, x*y)], [x0*y + x0]) + + +def test_issue_4498(): + assert cse(w/(x - y) + z/(y - x), optimizations='basic') == \ + ([], [(w - z)/(x - y)]) + + +def test_issue_4020(): + assert cse(x**5 + x**4 + x**3 + x**2, optimizations='basic') \ + == ([(x0, x**2)], [x0*(x**3 + x + x0 + 1)]) + + +def test_issue_4203(): + assert cse(sin(x**x)/x**x) == ([(x0, x**x)], [sin(x0)/x0]) + + +def test_issue_6263(): + e = Eq(x*(-x + 1) + x*(x - 1), 0) + assert cse(e, optimizations='basic') == ([], [True]) + + +def test_issue_25043(): + c = symbols("c") + x = symbols("x0", real=True) + cse_expr = cse(c*x**2 + c*(x**4 - x**2))[-1][-1] + free = cse_expr.free_symbols + assert len(free) == len({i.name for i in free}) + + +def test_dont_cse_tuples(): + from sympy.core.function import Subs + f = Function("f") + g = Function("g") + + name_val, (expr,) = cse( + Subs(f(x, y), (x, y), (0, 1)) + + Subs(g(x, y), (x, y), (0, 1))) + + assert name_val == [] + assert expr == (Subs(f(x, y), (x, y), (0, 1)) + + Subs(g(x, y), (x, y), (0, 1))) + + name_val, (expr,) = cse( + Subs(f(x, y), (x, y), (0, x + y)) + + Subs(g(x, y), (x, y), (0, x + y))) + + assert name_val == [(x0, x + y)] + assert expr == Subs(f(x, y), (x, y), (0, x0)) + \ + Subs(g(x, y), (x, y), (0, x0)) + + +def test_pow_invpow(): + assert cse(1/x**2 + x**2) == \ + ([(x0, x**2)], [x0 + 1/x0]) + assert cse(x**2 + (1 + 1/x**2)/x**2) == \ + ([(x0, x**2), (x1, 1/x0)], [x0 + x1*(x1 + 1)]) + assert cse(1/x**2 + (1 + 1/x**2)*x**2) == \ + ([(x0, x**2), (x1, 1/x0)], [x0*(x1 + 1) + x1]) + assert cse(cos(1/x**2) + sin(1/x**2)) == \ + ([(x0, x**(-2))], [sin(x0) + cos(x0)]) + assert cse(cos(x**2) + sin(x**2)) == \ + ([(x0, x**2)], [sin(x0) + cos(x0)]) + assert cse(y/(2 + x**2) + z/x**2/y) == \ + ([(x0, x**2)], [y/(x0 + 2) + z/(x0*y)]) + assert cse(exp(x**2) + x**2*cos(1/x**2)) == \ + ([(x0, x**2)], [x0*cos(1/x0) + exp(x0)]) + assert cse((1 + 1/x**2)/x**2) == \ + ([(x0, x**(-2))], [x0*(x0 + 1)]) + assert cse(x**(2*y) + x**(-2*y)) == \ + ([(x0, x**(2*y))], [x0 + 1/x0]) + + +def test_postprocess(): + eq = (x + 1 + exp((x + 1)/(y + 1)) + cos(y + 1)) + assert cse([eq, Eq(x, z + 1), z - 2, (z + 1)*(x + 1)], + postprocess=cse_main.cse_separate) == \ + [[(x0, y + 1), (x2, z + 1), (x, x2), (x1, x + 1)], + [x1 + exp(x1/x0) + cos(x0), z - 2, x1*x2]] + + +def test_issue_4499(): + # previously, this gave 16 constants + from sympy.abc import a, b + B = Function('B') + G = Function('G') + t = Tuple(* + (a, a + S.Half, 2*a, b, 2*a - b + 1, (sqrt(z)/2)**(-2*a + 1)*B(2*a - + b, sqrt(z))*B(b - 1, sqrt(z))*G(b)*G(2*a - b + 1), + sqrt(z)*(sqrt(z)/2)**(-2*a + 1)*B(b, sqrt(z))*B(2*a - b, + sqrt(z))*G(b)*G(2*a - b + 1), sqrt(z)*(sqrt(z)/2)**(-2*a + 1)*B(b - 1, + sqrt(z))*B(2*a - b + 1, sqrt(z))*G(b)*G(2*a - b + 1), + (sqrt(z)/2)**(-2*a + 1)*B(b, sqrt(z))*B(2*a - b + 1, + sqrt(z))*G(b)*G(2*a - b + 1), 1, 0, S.Half, z/2, -b + 1, -2*a + b, + -2*a)) + c = cse(t) + ans = ( + [(x0, 2*a), (x1, -b + x0), (x2, x1 + 1), (x3, b - 1), (x4, sqrt(z)), + (x5, B(x3, x4)), (x6, (x4/2)**(1 - x0)*G(b)*G(x2)), (x7, x6*B(x1, x4)), + (x8, B(b, x4)), (x9, x6*B(x2, x4))], + [(a, a + S.Half, x0, b, x2, x5*x7, x4*x7*x8, x4*x5*x9, x8*x9, + 1, 0, S.Half, z/2, -x3, -x1, -x0)]) + assert ans == c + + +def test_issue_6169(): + r = CRootOf(x**6 - 4*x**5 - 2, 1) + assert cse(r) == ([], [r]) + # and a check that the right thing is done with the new + # mechanism + assert sub_post(sub_pre((-x - y)*z - x - y)) == -z*(x + y) - x - y + + +def test_cse_Indexed(): + len_y = 5 + y = IndexedBase('y', shape=(len_y,)) + x = IndexedBase('x', shape=(len_y,)) + i = Idx('i', len_y-1) + + expr1 = (y[i+1]-y[i])/(x[i+1]-x[i]) + expr2 = 1/(x[i+1]-x[i]) + replacements, reduced_exprs = cse([expr1, expr2]) + assert len(replacements) > 0 + + +def test_cse_MatrixSymbol(): + # MatrixSymbols have non-Basic args, so make sure that works + A = MatrixSymbol("A", 3, 3) + assert cse(A) == ([], [A]) + + n = symbols('n', integer=True) + B = MatrixSymbol("B", n, n) + assert cse(B) == ([], [B]) + + assert cse(A[0] * A[0]) == ([], [A[0]*A[0]]) + + assert cse(A[0,0]*A[0,1] + A[0,0]*A[0,1]*A[0,2]) == ([(x0, A[0, 0]*A[0, 1])], [x0*A[0, 2] + x0]) + +def test_cse_MatrixExpr(): + A = MatrixSymbol('A', 3, 3) + y = MatrixSymbol('y', 3, 1) + + expr1 = (A.T*A).I * A * y + expr2 = (A.T*A) * A * y + replacements, reduced_exprs = cse([expr1, expr2]) + assert len(replacements) > 0 + + replacements, reduced_exprs = cse([expr1 + expr2, expr1]) + assert replacements + + replacements, reduced_exprs = cse([A**2, A + A**2]) + assert replacements + + +def test_Piecewise(): + f = Piecewise((-z + x*y, Eq(y, 0)), (-z - x*y, True)) + ans = cse(f) + actual_ans = ([(x0, x*y)], + [Piecewise((x0 - z, Eq(y, 0)), (-z - x0, True))]) + assert ans == actual_ans + + +def test_ignore_order_terms(): + eq = exp(x).series(x,0,3) + sin(y+x**3) - 1 + assert cse(eq) == ([], [sin(x**3 + y) + x + x**2/2 + O(x**3)]) + + +def test_name_conflict(): + z1 = x0 + y + z2 = x2 + x3 + l = [cos(z1) + z1, cos(z2) + z2, x0 + x2] + substs, reduced = cse(l) + assert [e.subs(reversed(substs)) for e in reduced] == l + + +def test_name_conflict_cust_symbols(): + z1 = x0 + y + z2 = x2 + x3 + l = [cos(z1) + z1, cos(z2) + z2, x0 + x2] + substs, reduced = cse(l, symbols("x:10")) + assert [e.subs(reversed(substs)) for e in reduced] == l + + +def test_symbols_exhausted_error(): + l = cos(x+y)+x+y+cos(w+y)+sin(w+y) + sym = [x, y, z] + with raises(ValueError): + cse(l, symbols=sym) + + +def test_issue_7840(): + # daveknippers' example + C393 = sympify( \ + 'Piecewise((C391 - 1.65, C390 < 0.5), (Piecewise((C391 - 1.65, \ + C391 > 2.35), (C392, True)), True))' + ) + C391 = sympify( \ + 'Piecewise((2.05*C390**(-1.03), C390 < 0.5), (2.5*C390**(-0.625), True))' + ) + C393 = C393.subs('C391',C391) + # simple substitution + sub = {} + sub['C390'] = 0.703451854 + sub['C392'] = 1.01417794 + ss_answer = C393.subs(sub) + # cse + substitutions,new_eqn = cse(C393) + for pair in substitutions: + sub[pair[0].name] = pair[1].subs(sub) + cse_answer = new_eqn[0].subs(sub) + # both methods should be the same + assert ss_answer == cse_answer + + # GitRay's example + expr = sympify( + "Piecewise((Symbol('ON'), Equality(Symbol('mode'), Symbol('ON'))), \ + (Piecewise((Piecewise((Symbol('OFF'), StrictLessThan(Symbol('x'), \ + Symbol('threshold'))), (Symbol('ON'), true)), Equality(Symbol('mode'), \ + Symbol('AUTO'))), (Symbol('OFF'), true)), true))" + ) + substitutions, new_eqn = cse(expr) + # this Piecewise should be exactly the same + assert new_eqn[0] == expr + # there should not be any replacements + assert len(substitutions) < 1 + + +def test_issue_8891(): + for cls in (MutableDenseMatrix, MutableSparseMatrix, + ImmutableDenseMatrix, ImmutableSparseMatrix): + m = cls(2, 2, [x + y, 0, 0, 0]) + res = cse([x + y, m]) + ans = ([(x0, x + y)], [x0, cls([[x0, 0], [0, 0]])]) + assert res == ans + assert isinstance(res[1][-1], cls) + + +def test_issue_11230(): + # a specific test that always failed + a, b, f, k, l, i = symbols('a b f k l i') + p = [a*b*f*k*l, a*i*k**2*l, f*i*k**2*l] + R, C = cse(p) + assert not any(i.is_Mul for a in C for i in a.args) + + # random tests for the issue + from sympy.core.random import choice + from sympy.core.function import expand_mul + s = symbols('a:m') + # 35 Mul tests, none of which should ever fail + ex = [Mul(*[choice(s) for i in range(5)]) for i in range(7)] + for p in subsets(ex, 3): + p = list(p) + R, C = cse(p) + assert not any(i.is_Mul for a in C for i in a.args) + for ri in reversed(R): + for i in range(len(C)): + C[i] = C[i].subs(*ri) + assert p == C + # 35 Add tests, none of which should ever fail + ex = [Add(*[choice(s[:7]) for i in range(5)]) for i in range(7)] + for p in subsets(ex, 3): + p = list(p) + R, C = cse(p) + assert not any(i.is_Add for a in C for i in a.args) + for ri in reversed(R): + for i in range(len(C)): + C[i] = C[i].subs(*ri) + # use expand_mul to handle cases like this: + # p = [a + 2*b + 2*e, 2*b + c + 2*e, b + 2*c + 2*g] + # x0 = 2*(b + e) is identified giving a rebuilt p that + # is now `[a + 2*(b + e), c + 2*(b + e), b + 2*c + 2*g]` + assert p == [expand_mul(i) for i in C] + + +@XFAIL +def test_issue_11577(): + def check(eq): + r, c = cse(eq) + assert eq.count_ops() >= \ + len(r) + sum(i[1].count_ops() for i in r) + \ + count_ops(c) + + eq = x**5*y**2 + x**5*y + x**5 + assert cse(eq) == ( + [(x0, x**4), (x1, x*y)], [x**5 + x0*x1*y + x0*x1]) + # ([(x0, x**5*y)], [x0*y + x0 + x**5]) or + # ([(x0, x**5)], [x0*y**2 + x0*y + x0]) + check(eq) + + eq = x**2/(y + 1)**2 + x/(y + 1) + assert cse(eq) == ( + [(x0, y + 1)], [x**2/x0**2 + x/x0]) + # ([(x0, x/(y + 1))], [x0**2 + x0]) + check(eq) + + +def test_hollow_rejection(): + eq = [x + 3, x + 4] + assert cse(eq) == ([], eq) + + +def test_cse_ignore(): + exprs = [exp(y)*(3*y + 3*sqrt(x+1)), exp(y)*(5*y + 5*sqrt(x+1))] + subst1, red1 = cse(exprs) + assert any(y in sub.free_symbols for _, sub in subst1), "cse failed to identify any term with y" + + subst2, red2 = cse(exprs, ignore=(y,)) # y is not allowed in substitutions + assert not any(y in sub.free_symbols for _, sub in subst2), "Sub-expressions containing y must be ignored" + assert any(sub - sqrt(x + 1) == 0 for _, sub in subst2), "cse failed to identify sqrt(x + 1) as sub-expression" + + +def test_cse_ignore_issue_15002(): + l = [ + w*exp(x)*exp(-z), + exp(y)*exp(x)*exp(-z) + ] + substs, reduced = cse(l, ignore=(x,)) + rl = [e.subs(reversed(substs)) for e in reduced] + assert rl == l + + +def test_cse_unevaluated(): + xp1 = UnevaluatedExpr(x + 1) + # This used to cause RecursionError + [(x0, ue)], [red] = cse([(-1 - xp1) / (1 - xp1)]) + if ue == xp1: + assert red == (-1 - x0) / (1 - x0) + elif ue == -xp1: + assert red == (-1 + x0) / (1 + x0) + else: + msg = f'Expected common subexpression {xp1} or {-xp1}, instead got {ue}' + assert False, msg + + +def test_cse__performance(): + nexprs, nterms = 3, 20 + x = symbols('x:%d' % nterms) + exprs = [ + reduce(add, [x[j]*(-1)**(i+j) for j in range(nterms)]) + for i in range(nexprs) + ] + assert (exprs[0] + exprs[1]).simplify() == 0 + subst, red = cse(exprs) + assert len(subst) > 0, "exprs[0] == -exprs[2], i.e. a CSE" + for i, e in enumerate(red): + assert (e.subs(reversed(subst)) - exprs[i]).simplify() == 0 + + +def test_issue_12070(): + exprs = [x + y, 2 + x + y, x + y + z, 3 + x + y + z] + subst, red = cse(exprs) + assert 6 >= (len(subst) + sum(v.count_ops() for k, v in subst) + + count_ops(red)) + + +def test_issue_13000(): + eq = x/(-4*x**2 + y**2) + cse_eq = cse(eq)[1][0] + assert cse_eq == eq + + +def test_issue_18203(): + eq = CRootOf(x**5 + 11*x - 2, 0) + CRootOf(x**5 + 11*x - 2, 1) + assert cse(eq) == ([], [eq]) + + +def test_unevaluated_mul(): + eq = Mul(x + y, x + y, evaluate=False) + assert cse(eq) == ([(x0, x + y)], [x0**2]) + + +def test_cse_release_variables(): + from sympy.simplify.cse_main import cse_release_variables + _0, _1, _2, _3, _4 = symbols('_:5') + eqs = [(x + y - 1)**2, x, + x + y, (x + y)/(2*x + 1) + (x + y - 1)**2, + (2*x + 1)**(x + y)] + r, e = cse(eqs, postprocess=cse_release_variables) + # this can change in keeping with the intention of the function + assert r, e == ([ + (x0, x + y), (x1, (x0 - 1)**2), (x2, 2*x + 1), + (_3, x0/x2 + x1), (_4, x2**x0), (x2, None), (_0, x1), + (x1, None), (_2, x0), (x0, None), (_1, x)], (_0, _1, _2, _3, _4)) + r.reverse() + r = [(s, v) for s, v in r if v is not None] + assert eqs == [i.subs(r) for i in e] + + +def test_cse_list(): + _cse = lambda x: cse(x, list=False) + assert _cse(x) == ([], x) + assert _cse('x') == ([], 'x') + it = [x] + for c in (list, tuple, set): + assert _cse(c(it)) == ([], c(it)) + #Tuple works different from tuple: + assert _cse(Tuple(*it)) == ([], Tuple(*it)) + d = {x: 1} + assert _cse(d) == ([], d) + +def test_issue_18991(): + A = MatrixSymbol('A', 2, 2) + assert signsimp(-A * A - A) == -A * A - A + + +def test_unevaluated_Mul(): + m = [Mul(1, 2, evaluate=False)] + assert cse(m) == ([], m) + + +def test_cse_matrix_expression_inverse(): + A = ImmutableDenseMatrix(symbols('A:4')).reshape(2, 2) + x = Inverse(A) + cse_expr = cse(x) + assert cse_expr == ([], [Inverse(A)]) + + +def test_cse_matrix_expression_matmul_inverse(): + A = ImmutableDenseMatrix(symbols('A:4')).reshape(2, 2) + b = ImmutableDenseMatrix(symbols('b:2')) + x = MatMul(Inverse(A), b) + cse_expr = cse(x) + assert cse_expr == ([], [x]) + + +def test_cse_matrix_negate_matrix(): + A = ImmutableDenseMatrix(symbols('A:4')).reshape(2, 2) + x = MatMul(S.NegativeOne, A) + cse_expr = cse(x) + assert cse_expr == ([], [x]) + + +def test_cse_matrix_negate_matmul_not_extracted(): + A = ImmutableDenseMatrix(symbols('A:4')).reshape(2, 2) + B = ImmutableDenseMatrix(symbols('B:4')).reshape(2, 2) + x = MatMul(S.NegativeOne, A, B) + cse_expr = cse(x) + assert cse_expr == ([], [x]) + + +@XFAIL # No simplification rule for nested associative operations +def test_cse_matrix_nested_matmul_collapsed(): + A = ImmutableDenseMatrix(symbols('A:4')).reshape(2, 2) + B = ImmutableDenseMatrix(symbols('B:4')).reshape(2, 2) + x = MatMul(S.NegativeOne, MatMul(A, B)) + cse_expr = cse(x) + assert cse_expr == ([], [MatMul(S.NegativeOne, A, B)]) + + +def test_cse_matrix_optimize_out_single_argument_mul(): + A = ImmutableDenseMatrix(symbols('A:4')).reshape(2, 2) + x = MatMul(MatMul(MatMul(A))) + cse_expr = cse(x) + assert cse_expr == ([], [A]) + + +@XFAIL # Multiple simplification passed not supported in CSE +def test_cse_matrix_optimize_out_single_argument_mul_combined(): + A = ImmutableDenseMatrix(symbols('A:4')).reshape(2, 2) + x = MatAdd(MatMul(MatMul(MatMul(A))), MatMul(MatMul(A)), MatMul(A), A) + cse_expr = cse(x) + assert cse_expr == ([], [MatMul(4, A)]) + + +def test_cse_matrix_optimize_out_single_argument_add(): + A = ImmutableDenseMatrix(symbols('A:4')).reshape(2, 2) + x = MatAdd(MatAdd(MatAdd(MatAdd(A)))) + cse_expr = cse(x) + assert cse_expr == ([], [A]) + + +@XFAIL # Multiple simplification passed not supported in CSE +def test_cse_matrix_optimize_out_single_argument_add_combined(): + A = ImmutableDenseMatrix(symbols('A:4')).reshape(2, 2) + x = MatMul(MatAdd(MatAdd(MatAdd(A))), MatAdd(MatAdd(A)), MatAdd(A), A) + cse_expr = cse(x) + assert cse_expr == ([], [MatMul(4, A)]) + + +def test_cse_matrix_expression_matrix_solve(): + A = ImmutableDenseMatrix(symbols('A:4')).reshape(2, 2) + b = ImmutableDenseMatrix(symbols('b:2')) + x = MatrixSolve(A, b) + cse_expr = cse(x) + assert cse_expr == ([], [x]) + + +def test_cse_matrix_matrix_expression(): + X = ImmutableDenseMatrix(symbols('X:4')).reshape(2, 2) + y = ImmutableDenseMatrix(symbols('y:2')) + b = MatMul(Inverse(MatMul(Transpose(X), X)), Transpose(X), y) + cse_expr = cse(b) + x0 = MatrixSymbol('x0', 2, 2) + reduced_expr_expected = MatMul(Inverse(MatMul(x0, X)), x0, y) + assert cse_expr == ([(x0, Transpose(X))], [reduced_expr_expected]) + + +def test_cse_matrix_kalman_filter(): + """Kalman Filter example from Matthew Rocklin's SciPy 2013 talk. + + Talk titled: "Matrix Expressions and BLAS/LAPACK; SciPy 2013 Presentation" + + Video: https://pyvideo.org/scipy-2013/matrix-expressions-and-blaslapack-scipy-2013-pr.html + + Notes + ===== + + Equations are: + + new_mu = mu + Sigma*H.T * (R + H*Sigma*H.T).I * (H*mu - data) + = MatAdd(mu, MatMul(Sigma, Transpose(H), Inverse(MatAdd(R, MatMul(H, Sigma, Transpose(H)))), MatAdd(MatMul(H, mu), MatMul(S.NegativeOne, data)))) + new_Sigma = Sigma - Sigma*H.T * (R + H*Sigma*H.T).I * H * Sigma + = MatAdd(Sigma, MatMul(S.NegativeOne, Sigma, Transpose(H)), Inverse(MatAdd(R, MatMul(H*Sigma*Transpose(H)))), H, Sigma)) + + """ + N = 2 + mu = ImmutableDenseMatrix(symbols(f'mu:{N}')) + Sigma = ImmutableDenseMatrix(symbols(f'Sigma:{N * N}')).reshape(N, N) + H = ImmutableDenseMatrix(symbols(f'H:{N * N}')).reshape(N, N) + R = ImmutableDenseMatrix(symbols(f'R:{N * N}')).reshape(N, N) + data = ImmutableDenseMatrix(symbols(f'data:{N}')) + new_mu = MatAdd(mu, MatMul(Sigma, Transpose(H), Inverse(MatAdd(R, MatMul(H, Sigma, Transpose(H)))), MatAdd(MatMul(H, mu), MatMul(S.NegativeOne, data)))) + new_Sigma = MatAdd(Sigma, MatMul(S.NegativeOne, Sigma, Transpose(H), Inverse(MatAdd(R, MatMul(H, Sigma, Transpose(H)))), H, Sigma)) + cse_expr = cse([new_mu, new_Sigma]) + x0 = MatrixSymbol('x0', N, N) + x1 = MatrixSymbol('x1', N, N) + replacements_expected = [ + (x0, Transpose(H)), + (x1, Inverse(MatAdd(R, MatMul(H, Sigma, x0)))), + ] + reduced_exprs_expected = [ + MatAdd(mu, MatMul(Sigma, x0, x1, MatAdd(MatMul(H, mu), MatMul(S.NegativeOne, data)))), + MatAdd(Sigma, MatMul(S.NegativeOne, Sigma, x0, x1, H, Sigma)), + ] + assert cse_expr == (replacements_expected, reduced_exprs_expected) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_cse_diff.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_cse_diff.py new file mode 100644 index 0000000000000000000000000000000000000000..92b2d3d6bbaafb838a5e75f32a214511a1d39567 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_cse_diff.py @@ -0,0 +1,206 @@ +"""Tests for the ``sympy.simplify._cse_diff.py`` module.""" + +import pytest + +from sympy.core.symbol import (Symbol, symbols) +from sympy.core.numbers import Integer +from sympy.core.function import Function +from sympy.core import Derivative +from sympy.functions.elementary.exponential import exp +from sympy.matrices.immutable import ImmutableDenseMatrix +from sympy.physics.mechanics import dynamicsymbols +from sympy.simplify._cse_diff import (_forward_jacobian, + _remove_cse_from_derivative, + _forward_jacobian_cse, + _forward_jacobian_norm_in_cse_out) +from sympy.simplify.simplify import simplify +from sympy.matrices import Matrix, eye + +from sympy.testing.pytest import raises +from sympy.functions.elementary.trigonometric import (cos, sin, tan) +from sympy.simplify.trigsimp import trigsimp + +from sympy import cse + + +w = Symbol('w') +x = Symbol('x') +y = Symbol('y') +z = Symbol('z') + +q1, q2, q3 = dynamicsymbols('q1 q2 q3') + +# Define the custom functions +k = Function('k')(x, y) +f = Function('f')(k, z) + +zero = Integer(0) +one = Integer(1) +two = Integer(2) +neg_one = Integer(-1) + + +@pytest.mark.parametrize( + 'expr, wrt', + [ + ([zero], [x]), + ([one], [x]), + ([two], [x]), + ([neg_one], [x]), + ([x], [x]), + ([y], [x]), + ([x + y], [x]), + ([x*y], [x]), + ([x**2], [x]), + ([x**y], [x]), + ([exp(x)], [x]), + ([sin(x)], [x]), + ([tan(x)], [x]), + ([zero, one, x, y, x*y, x + y], [x, y]), + ([((x/y) + sin(x/y) - exp(y))*((x/y) - exp(y))], [x, y]), + ([w*tan(y*z)/(x - tan(y*z)), w*x*tan(y*z)/(x - tan(y*z))], [w, x, y, z]), + ([q1**2 + q2, q2**2 + q3, q3**2 + q1], [q1, q2, q3]), + ([f + Derivative(f, x) + k + 2*x], [x]) + ] +) + + +def test_forward_jacobian(expr, wrt): + expr = ImmutableDenseMatrix([expr]).T + wrt = ImmutableDenseMatrix([wrt]).T + jacobian = _forward_jacobian(expr, wrt) + zeros = ImmutableDenseMatrix.zeros(*jacobian.shape) + assert simplify(jacobian - expr.jacobian(wrt)) == zeros + + +def test_process_cse(): + x, y, z = symbols('x y z') + f = Function('f') + k = Function('k') + expr = Matrix([f(k(x,y), z) + Derivative(f(k(x,y), z), x) + k(x,y) + 2*x]) + repl, reduced = cse(expr) + p_repl, p_reduced = _remove_cse_from_derivative(repl, reduced) + + x0 = symbols('x0') + x1 = symbols('x1') + + expected_output = ( + [(x0, k(x, y)), (x1, f(x0, z))], + [Matrix([2 * x + x0 + x1 + Derivative(f(k(x, y), z), x)])] + ) + + assert p_repl == expected_output[0], f"Expected {expected_output[0]}, but got {p_repl}" + assert p_reduced == expected_output[1], f"Expected {expected_output[1]}, but got {p_reduced}" + + +def test_io_matrix_type(): + x, y, z = symbols('x y z') + expr = ImmutableDenseMatrix([ + x * y + y * z + x * y * z, + x ** 2 + y ** 2 + z ** 2, + x * y + x * z + y * z + ]) + wrt = ImmutableDenseMatrix([x, y, z]) + + replacements, reduced_expr = cse(expr) + + # Test _forward_jacobian_core + replacements_core, jacobian_core, precomputed_fs_core = _forward_jacobian_cse(replacements, reduced_expr, wrt) + assert isinstance(jacobian_core[0], type(reduced_expr[0])), "Jacobian should be a Matrix of the same type as the input" + + # Test _forward_jacobian_norm_in_dag_out + replacements_norm, jacobian_norm, precomputed_fs_norm = _forward_jacobian_norm_in_cse_out( + expr, wrt) + assert isinstance(jacobian_norm[0], type(reduced_expr[0])), "Jacobian should be a Matrix of the same type as the input" + + # Test _forward_jacobian + jacobian = _forward_jacobian(expr, wrt) + assert isinstance(jacobian, type(expr)), "Jacobian should be a Matrix of the same type as the input" + + +def test_forward_jacobian_input_output(): + x, y, z = symbols('x y z') + expr = Matrix([ + x * y + y * z + x * y * z, + x ** 2 + y ** 2 + z ** 2, + x * y + x * z + y * z + ]) + wrt = Matrix([x, y, z]) + + replacements, reduced_expr = cse(expr) + + # Test _forward_jacobian_core + replacements_core, jacobian_core, precomputed_fs_core = _forward_jacobian_cse(replacements, reduced_expr, wrt) + assert isinstance(replacements_core, type(replacements)), "Replacements should be a list" + assert isinstance(jacobian_core, type(reduced_expr)), "Jacobian should be a list" + assert isinstance(precomputed_fs_core, list), "Precomputed free symbols should be a list" + assert len(replacements_core) == len(replacements), "Length of replacements does not match" + assert len(jacobian_core) == 1, "Jacobian should have one element" + assert len(precomputed_fs_core) == len(replacements), "Length of precomputed free symbols does not match" + + # Test _forward_jacobian_norm_in_dag_out + replacements_norm, jacobian_norm, precomputed_fs_norm = _forward_jacobian_norm_in_cse_out(expr, wrt) + assert isinstance(replacements_norm, type(replacements)), "Replacements should be a list" + assert isinstance(jacobian_norm, type(reduced_expr)), "Jacobian should be a list" + assert isinstance(precomputed_fs_norm, list), "Precomputed free symbols should be a list" + assert len(replacements_norm) == len(replacements), "Length of replacements does not match" + assert len(jacobian_norm) == 1, "Jacobian should have one element" + assert len(precomputed_fs_norm) == len(replacements), "Length of precomputed free symbols does not match" + + +def test_jacobian_hessian(): + L = Matrix(1, 2, [x**2*y, 2*y**2 + x*y]) + syms = [x, y] + assert _forward_jacobian(L, syms) == Matrix([[2*x*y, x**2], [y, 4*y + x]]) + + L = Matrix(1, 2, [x, x**2*y**3]) + assert _forward_jacobian(L, syms) == Matrix([[1, 0], [2*x*y**3, x**2*3*y**2]]) + + +def test_jacobian_metrics(): + rho, phi = symbols("rho,phi") + X = Matrix([rho * cos(phi), rho * sin(phi)]) + Y = Matrix([rho, phi]) + J = _forward_jacobian(X, Y) + assert J == X.jacobian(Y.T) + assert J == (X.T).jacobian(Y) + assert J == (X.T).jacobian(Y.T) + g = J.T * eye(J.shape[0]) * J + g = g.applyfunc(trigsimp) + assert g == Matrix([[1, 0], [0, rho ** 2]]) + + +def test_jacobian2(): + rho, phi = symbols("rho,phi") + X = Matrix([rho * cos(phi), rho * sin(phi), rho ** 2]) + Y = Matrix([rho, phi]) + J = Matrix([ + [cos(phi), -rho * sin(phi)], + [sin(phi), rho * cos(phi)], + [2 * rho, 0], + ]) + assert _forward_jacobian(X, Y) == J + + +def test_issue_4564(): + X = Matrix([exp(x + y + z), exp(x + y + z), exp(x + y + z)]) + Y = Matrix([x, y, z]) + for i in range(1, 3): + for j in range(1, 3): + X_slice = X[:i, :] + Y_slice = Y[:j, :] + J = _forward_jacobian(X_slice, Y_slice) + assert J.rows == i + assert J.cols == j + for k in range(j): + assert J[:, k] == X_slice + + +def test_nonvectorJacobian(): + X = Matrix([[exp(x + y + z), exp(x + y + z)], + [exp(x + y + z), exp(x + y + z)]]) + raises(TypeError, lambda: _forward_jacobian(X, Matrix([x, y, z]))) + X = X[0, :] + Y = Matrix([[x, y], [x, z]]) + raises(TypeError, lambda: _forward_jacobian(X, Y)) + raises(TypeError, lambda: _forward_jacobian(X, Matrix([[x, y], [x, z]]))) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_epathtools.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_epathtools.py new file mode 100644 index 0000000000000000000000000000000000000000..a8bb47b2f2ff624077ab9905677b181c587ab5a7 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_epathtools.py @@ -0,0 +1,90 @@ +"""Tests for tools for manipulation of expressions using paths. """ + +from sympy.simplify.epathtools import epath, EPath +from sympy.testing.pytest import raises + +from sympy.core.numbers import E +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.abc import x, y, z, t + + +def test_epath_select(): + expr = [((x, 1, t), 2), ((3, y, 4), z)] + + assert epath("/*", expr) == [((x, 1, t), 2), ((3, y, 4), z)] + assert epath("/*/*", expr) == [(x, 1, t), 2, (3, y, 4), z] + assert epath("/*/*/*", expr) == [x, 1, t, 3, y, 4] + assert epath("/*/*/*/*", expr) == [] + + assert epath("/[:]", expr) == [((x, 1, t), 2), ((3, y, 4), z)] + assert epath("/[:]/[:]", expr) == [(x, 1, t), 2, (3, y, 4), z] + assert epath("/[:]/[:]/[:]", expr) == [x, 1, t, 3, y, 4] + assert epath("/[:]/[:]/[:]/[:]", expr) == [] + + assert epath("/*/[:]", expr) == [(x, 1, t), 2, (3, y, 4), z] + + assert epath("/*/[0]", expr) == [(x, 1, t), (3, y, 4)] + assert epath("/*/[1]", expr) == [2, z] + assert epath("/*/[2]", expr) == [] + + assert epath("/*/int", expr) == [2] + assert epath("/*/Symbol", expr) == [z] + assert epath("/*/tuple", expr) == [(x, 1, t), (3, y, 4)] + assert epath("/*/__iter__?", expr) == [(x, 1, t), (3, y, 4)] + + assert epath("/*/int|tuple", expr) == [(x, 1, t), 2, (3, y, 4)] + assert epath("/*/Symbol|tuple", expr) == [(x, 1, t), (3, y, 4), z] + assert epath("/*/int|Symbol|tuple", expr) == [(x, 1, t), 2, (3, y, 4), z] + + assert epath("/*/int|__iter__?", expr) == [(x, 1, t), 2, (3, y, 4)] + assert epath("/*/Symbol|__iter__?", expr) == [(x, 1, t), (3, y, 4), z] + assert epath( + "/*/int|Symbol|__iter__?", expr) == [(x, 1, t), 2, (3, y, 4), z] + + assert epath("/*/[0]/int", expr) == [1, 3, 4] + assert epath("/*/[0]/Symbol", expr) == [x, t, y] + + assert epath("/*/[0]/int[1:]", expr) == [1, 4] + assert epath("/*/[0]/Symbol[1:]", expr) == [t, y] + + assert epath("/Symbol", x + y + z + 1) == [x, y, z] + assert epath("/*/*/Symbol", t + sin(x + 1) + cos(x + y + E)) == [x, x, y] + + +def test_epath_apply(): + expr = [((x, 1, t), 2), ((3, y, 4), z)] + func = lambda expr: expr**2 + + assert epath("/*", expr, list) == [[(x, 1, t), 2], [(3, y, 4), z]] + + assert epath("/*/[0]", expr, list) == [([x, 1, t], 2), ([3, y, 4], z)] + assert epath("/*/[1]", expr, func) == [((x, 1, t), 4), ((3, y, 4), z**2)] + assert epath("/*/[2]", expr, list) == expr + + assert epath("/*/[0]/int", expr, func) == [((x, 1, t), 2), ((9, y, 16), z)] + assert epath("/*/[0]/Symbol", expr, func) == [((x**2, 1, t**2), 2), + ((3, y**2, 4), z)] + assert epath( + "/*/[0]/int[1:]", expr, func) == [((x, 1, t), 2), ((3, y, 16), z)] + assert epath("/*/[0]/Symbol[1:]", expr, func) == [((x, 1, t**2), + 2), ((3, y**2, 4), z)] + + assert epath("/Symbol", x + y + z + 1, func) == x**2 + y**2 + z**2 + 1 + assert epath("/*/*/Symbol", t + sin(x + 1) + cos(x + y + E), func) == \ + t + sin(x**2 + 1) + cos(x**2 + y**2 + E) + + +def test_EPath(): + assert EPath("/*/[0]")._path == "/*/[0]" + assert EPath(EPath("/*/[0]"))._path == "/*/[0]" + assert isinstance(epath("/*/[0]"), EPath) is True + + assert repr(EPath("/*/[0]")) == "EPath('/*/[0]')" + + raises(ValueError, lambda: EPath("")) + raises(ValueError, lambda: EPath("/")) + raises(ValueError, lambda: EPath("/|x")) + raises(ValueError, lambda: EPath("/[")) + raises(ValueError, lambda: EPath("/[0]%")) + + raises(NotImplementedError, lambda: EPath("Symbol")) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_fu.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_fu.py new file mode 100644 index 0000000000000000000000000000000000000000..2de2126b7333195fceeffe72dc9cb642e7eba9a9 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_fu.py @@ -0,0 +1,492 @@ +from sympy.core.add import Add +from sympy.core.mul import Mul +from sympy.core.numbers import (I, Rational, pi) +from sympy.core.parameters import evaluate +from sympy.core.singleton import S +from sympy.core.symbol import (Dummy, Symbol, symbols) +from sympy.functions.elementary.hyperbolic import (cosh, coth, csch, sech, sinh, tanh) +from sympy.functions.elementary.miscellaneous import (root, sqrt) +from sympy.functions.elementary.trigonometric import (cos, cot, csc, sec, sin, tan) +from sympy.simplify.powsimp import powsimp +from sympy.simplify.fu import ( + L, TR1, TR10, TR10i, TR11, _TR11, TR12, TR12i, TR13, TR14, TR15, TR16, + TR111, TR2, TR2i, TR3, TR4, TR5, TR6, TR7, TR8, TR9, TRmorrie, _TR56 as T, + TRpower, hyper_as_trig, fu, process_common_addends, trig_split, + as_f_sign_1) +from sympy.core.random import verify_numerically +from sympy.abc import a, b, c, x, y, z + + +def test_TR1(): + assert TR1(2*csc(x) + sec(x)) == 1/cos(x) + 2/sin(x) + + +def test_TR2(): + assert TR2(tan(x)) == sin(x)/cos(x) + assert TR2(cot(x)) == cos(x)/sin(x) + assert TR2(tan(tan(x) - sin(x)/cos(x))) == 0 + + +def test_TR2i(): + # just a reminder that ratios of powers only simplify if both + # numerator and denominator satisfy the condition that each + # has a positive base or an integer exponent; e.g. the following, + # at y=-1, x=1/2 gives sqrt(2)*I != -sqrt(2)*I + assert powsimp(2**x/y**x) != (2/y)**x + + assert TR2i(sin(x)/cos(x)) == tan(x) + assert TR2i(sin(x)*sin(y)/cos(x)) == tan(x)*sin(y) + assert TR2i(1/(sin(x)/cos(x))) == 1/tan(x) + assert TR2i(1/(sin(x)*sin(y)/cos(x))) == 1/tan(x)/sin(y) + assert TR2i(sin(x)/2/(cos(x) + 1)) == sin(x)/(cos(x) + 1)/2 + + assert TR2i(sin(x)/2/(cos(x) + 1), half=True) == tan(x/2)/2 + assert TR2i(sin(1)/(cos(1) + 1), half=True) == tan(S.Half) + assert TR2i(sin(2)/(cos(2) + 1), half=True) == tan(1) + assert TR2i(sin(4)/(cos(4) + 1), half=True) == tan(2) + assert TR2i(sin(5)/(cos(5) + 1), half=True) == tan(5*S.Half) + assert TR2i((cos(1) + 1)/sin(1), half=True) == 1/tan(S.Half) + assert TR2i((cos(2) + 1)/sin(2), half=True) == 1/tan(1) + assert TR2i((cos(4) + 1)/sin(4), half=True) == 1/tan(2) + assert TR2i((cos(5) + 1)/sin(5), half=True) == 1/tan(5*S.Half) + assert TR2i((cos(1) + 1)**(-a)*sin(1)**a, half=True) == tan(S.Half)**a + assert TR2i((cos(2) + 1)**(-a)*sin(2)**a, half=True) == tan(1)**a + assert TR2i((cos(4) + 1)**(-a)*sin(4)**a, half=True) == (cos(4) + 1)**(-a)*sin(4)**a + assert TR2i((cos(5) + 1)**(-a)*sin(5)**a, half=True) == (cos(5) + 1)**(-a)*sin(5)**a + assert TR2i((cos(1) + 1)**a*sin(1)**(-a), half=True) == tan(S.Half)**(-a) + assert TR2i((cos(2) + 1)**a*sin(2)**(-a), half=True) == tan(1)**(-a) + assert TR2i((cos(4) + 1)**a*sin(4)**(-a), half=True) == (cos(4) + 1)**a*sin(4)**(-a) + assert TR2i((cos(5) + 1)**a*sin(5)**(-a), half=True) == (cos(5) + 1)**a*sin(5)**(-a) + + i = symbols('i', integer=True) + assert TR2i(((cos(5) + 1)**i*sin(5)**(-i)), half=True) == tan(5*S.Half)**(-i) + assert TR2i(1/((cos(5) + 1)**i*sin(5)**(-i)), half=True) == tan(5*S.Half)**i + + +def test_TR3(): + assert TR3(cos(y - x*(y - x))) == cos(x*(x - y) + y) + assert cos(pi/2 + x) == -sin(x) + assert cos(30*pi/2 + x) == -cos(x) + + for f in (cos, sin, tan, cot, csc, sec): + i = f(pi*Rational(3, 7)) + j = TR3(i) + assert verify_numerically(i, j) and i.func != j.func + + with evaluate(False): + eq = cos(9*pi/22) + assert eq.has(9*pi) and TR3(eq) == sin(pi/11) + + +def test_TR4(): + for i in [0, pi/6, pi/4, pi/3, pi/2]: + with evaluate(False): + eq = cos(i) + assert isinstance(eq, cos) and TR4(eq) == cos(i) + + +def test__TR56(): + h = lambda x: 1 - x + assert T(sin(x)**3, sin, cos, h, 4, False) == sin(x)*(-cos(x)**2 + 1) + assert T(sin(x)**10, sin, cos, h, 4, False) == sin(x)**10 + assert T(sin(x)**6, sin, cos, h, 6, False) == (-cos(x)**2 + 1)**3 + assert T(sin(x)**6, sin, cos, h, 6, True) == sin(x)**6 + assert T(sin(x)**8, sin, cos, h, 10, True) == (-cos(x)**2 + 1)**4 + + # issue 17137 + assert T(sin(x)**I, sin, cos, h, 4, True) == sin(x)**I + assert T(sin(x)**(2*I + 1), sin, cos, h, 4, True) == sin(x)**(2*I + 1) + + +def test_TR5(): + assert TR5(sin(x)**2) == -cos(x)**2 + 1 + assert TR5(sin(x)**-2) == sin(x)**(-2) + assert TR5(sin(x)**4) == (-cos(x)**2 + 1)**2 + + +def test_TR6(): + assert TR6(cos(x)**2) == -sin(x)**2 + 1 + assert TR6(cos(x)**-2) == cos(x)**(-2) + assert TR6(cos(x)**4) == (-sin(x)**2 + 1)**2 + + +def test_TR7(): + assert TR7(cos(x)**2) == cos(2*x)/2 + S.Half + assert TR7(cos(x)**2 + 1) == cos(2*x)/2 + Rational(3, 2) + + +def test_TR8(): + assert TR8(cos(2)*cos(3)) == cos(5)/2 + cos(1)/2 + assert TR8(cos(2)*sin(3)) == sin(5)/2 + sin(1)/2 + assert TR8(sin(2)*sin(3)) == -cos(5)/2 + cos(1)/2 + assert TR8(sin(1)*sin(2)*sin(3)) == sin(4)/4 - sin(6)/4 + sin(2)/4 + assert TR8(cos(2)*cos(3)*cos(4)*cos(5)) == \ + cos(4)/4 + cos(10)/8 + cos(2)/8 + cos(8)/8 + cos(14)/8 + \ + cos(6)/8 + Rational(1, 8) + assert TR8(cos(2)*cos(3)*cos(4)*cos(5)*cos(6)) == \ + cos(10)/8 + cos(4)/8 + 3*cos(2)/16 + cos(16)/16 + cos(8)/8 + \ + cos(14)/16 + cos(20)/16 + cos(12)/16 + Rational(1, 16) + cos(6)/8 + assert TR8(sin(pi*Rational(3, 7))**2*cos(pi*Rational(3, 7))**2/(16*sin(pi/7)**2)) == Rational(1, 64) + +def test_TR9(): + a = S.Half + b = 3*a + assert TR9(a) == a + assert TR9(cos(1) + cos(2)) == 2*cos(a)*cos(b) + assert TR9(cos(1) - cos(2)) == 2*sin(a)*sin(b) + assert TR9(sin(1) - sin(2)) == -2*sin(a)*cos(b) + assert TR9(sin(1) + sin(2)) == 2*sin(b)*cos(a) + assert TR9(cos(1) + 2*sin(1) + 2*sin(2)) == cos(1) + 4*sin(b)*cos(a) + assert TR9(cos(4) + cos(2) + 2*cos(1)*cos(3)) == 4*cos(1)*cos(3) + assert TR9((cos(4) + cos(2))/cos(3)/2 + cos(3)) == 2*cos(1)*cos(2) + assert TR9(cos(3) + cos(4) + cos(5) + cos(6)) == \ + 4*cos(S.Half)*cos(1)*cos(Rational(9, 2)) + assert TR9(cos(3) + cos(3)*cos(2)) == cos(3) + cos(2)*cos(3) + assert TR9(-cos(y) + cos(x*y)) == -2*sin(x*y/2 - y/2)*sin(x*y/2 + y/2) + assert TR9(-sin(y) + sin(x*y)) == 2*sin(x*y/2 - y/2)*cos(x*y/2 + y/2) + c = cos(x) + s = sin(x) + for si in ((1, 1), (1, -1), (-1, 1), (-1, -1)): + for a in ((c, s), (s, c), (cos(x), cos(x*y)), (sin(x), sin(x*y))): + args = zip(si, a) + ex = Add(*[Mul(*ai) for ai in args]) + t = TR9(ex) + assert not (a[0].func == a[1].func and ( + not verify_numerically(ex, t.expand(trig=True)) or t.is_Add) + or a[1].func != a[0].func and ex != t) + + +def test_TR10(): + assert TR10(cos(a + b)) == -sin(a)*sin(b) + cos(a)*cos(b) + assert TR10(sin(a + b)) == sin(a)*cos(b) + sin(b)*cos(a) + assert TR10(sin(a + b + c)) == \ + (-sin(a)*sin(b) + cos(a)*cos(b))*sin(c) + \ + (sin(a)*cos(b) + sin(b)*cos(a))*cos(c) + assert TR10(cos(a + b + c)) == \ + (-sin(a)*sin(b) + cos(a)*cos(b))*cos(c) - \ + (sin(a)*cos(b) + sin(b)*cos(a))*sin(c) + + +def test_TR10i(): + assert TR10i(cos(1)*cos(3) + sin(1)*sin(3)) == cos(2) + assert TR10i(cos(1)*cos(3) - sin(1)*sin(3)) == cos(4) + assert TR10i(cos(1)*sin(3) - sin(1)*cos(3)) == sin(2) + assert TR10i(cos(1)*sin(3) + sin(1)*cos(3)) == sin(4) + assert TR10i(cos(1)*sin(3) + sin(1)*cos(3) + 7) == sin(4) + 7 + assert TR10i(cos(1)*sin(3) + sin(1)*cos(3) + cos(3)) == cos(3) + sin(4) + assert TR10i(2*cos(1)*sin(3) + 2*sin(1)*cos(3) + cos(3)) == \ + 2*sin(4) + cos(3) + assert TR10i(cos(2)*cos(3) + sin(2)*(cos(1)*sin(2) + cos(2)*sin(1))) == \ + cos(1) + eq = (cos(2)*cos(3) + sin(2)*( + cos(1)*sin(2) + cos(2)*sin(1)))*cos(5) + sin(1)*sin(5) + assert TR10i(eq) == TR10i(eq.expand()) == cos(4) + assert TR10i(sqrt(2)*cos(x)*x + sqrt(6)*sin(x)*x) == \ + 2*sqrt(2)*x*sin(x + pi/6) + assert TR10i(cos(x)/sqrt(6) + sin(x)/sqrt(2) + + cos(x)/sqrt(6)/3 + sin(x)/sqrt(2)/3) == 4*sqrt(6)*sin(x + pi/6)/9 + assert TR10i(cos(x)/sqrt(6) + sin(x)/sqrt(2) + + cos(y)/sqrt(6)/3 + sin(y)/sqrt(2)/3) == \ + sqrt(6)*sin(x + pi/6)/3 + sqrt(6)*sin(y + pi/6)/9 + assert TR10i(cos(x) + sqrt(3)*sin(x) + 2*sqrt(3)*cos(x + pi/6)) == 4*cos(x) + assert TR10i(cos(x) + sqrt(3)*sin(x) + + 2*sqrt(3)*cos(x + pi/6) + 4*sin(x)) == 4*sqrt(2)*sin(x + pi/4) + assert TR10i(cos(2)*sin(3) + sin(2)*cos(4)) == \ + sin(2)*cos(4) + sin(3)*cos(2) + + A = Symbol('A', commutative=False) + assert TR10i(sqrt(2)*cos(x)*A + sqrt(6)*sin(x)*A) == \ + 2*sqrt(2)*sin(x + pi/6)*A + + + c = cos(x) + s = sin(x) + h = sin(y) + r = cos(y) + for si in ((1, 1), (1, -1), (-1, 1), (-1, -1)): + for argsi in ((c*r, s*h), (c*h, s*r)): # explicit 2-args + args = zip(si, argsi) + ex = Add(*[Mul(*ai) for ai in args]) + t = TR10i(ex) + assert not (ex - t.expand(trig=True) or t.is_Add) + + c = cos(x) + s = sin(x) + h = sin(pi/6) + r = cos(pi/6) + for si in ((1, 1), (1, -1), (-1, 1), (-1, -1)): + for argsi in ((c*r, s*h), (c*h, s*r)): # induced + args = zip(si, argsi) + ex = Add(*[Mul(*ai) for ai in args]) + t = TR10i(ex) + assert not (ex - t.expand(trig=True) or t.is_Add) + + +def test_TR11(): + + assert TR11(sin(2*x)) == 2*sin(x)*cos(x) + assert TR11(sin(4*x)) == 4*((-sin(x)**2 + cos(x)**2)*sin(x)*cos(x)) + assert TR11(sin(x*Rational(4, 3))) == \ + 4*((-sin(x/3)**2 + cos(x/3)**2)*sin(x/3)*cos(x/3)) + + assert TR11(cos(2*x)) == -sin(x)**2 + cos(x)**2 + assert TR11(cos(4*x)) == \ + (-sin(x)**2 + cos(x)**2)**2 - 4*sin(x)**2*cos(x)**2 + + assert TR11(cos(2)) == cos(2) + + assert TR11(cos(pi*Rational(3, 7)), pi*Rational(2, 7)) == -cos(pi*Rational(2, 7))**2 + sin(pi*Rational(2, 7))**2 + assert TR11(cos(4), 2) == -sin(2)**2 + cos(2)**2 + assert TR11(cos(6), 2) == cos(6) + assert TR11(sin(x)/cos(x/2), x/2) == 2*sin(x/2) + +def test__TR11(): + + assert _TR11(sin(x/3)*sin(2*x)*sin(x/4)/(cos(x/6)*cos(x/8))) == \ + 4*sin(x/8)*sin(x/6)*sin(2*x),_TR11(sin(x/3)*sin(2*x)*sin(x/4)/(cos(x/6)*cos(x/8))) + assert _TR11(sin(x/3)/cos(x/6)) == 2*sin(x/6) + + assert _TR11(cos(x/6)/sin(x/3)) == 1/(2*sin(x/6)) + assert _TR11(sin(2*x)*cos(x/8)/sin(x/4)) == sin(2*x)/(2*sin(x/8)), _TR11(sin(2*x)*cos(x/8)/sin(x/4)) + assert _TR11(sin(x)/sin(x/2)) == 2*cos(x/2) + + +def test_TR12(): + assert TR12(tan(x + y)) == (tan(x) + tan(y))/(-tan(x)*tan(y) + 1) + assert TR12(tan(x + y + z)) ==\ + (tan(z) + (tan(x) + tan(y))/(-tan(x)*tan(y) + 1))/( + 1 - (tan(x) + tan(y))*tan(z)/(-tan(x)*tan(y) + 1)) + assert TR12(tan(x*y)) == tan(x*y) + + +def test_TR13(): + assert TR13(tan(3)*tan(2)) == -tan(2)/tan(5) - tan(3)/tan(5) + 1 + assert TR13(cot(3)*cot(2)) == 1 + cot(3)*cot(5) + cot(2)*cot(5) + assert TR13(tan(1)*tan(2)*tan(3)) == \ + (-tan(2)/tan(5) - tan(3)/tan(5) + 1)*tan(1) + assert TR13(tan(1)*tan(2)*cot(3)) == \ + (-tan(2)/tan(3) + 1 - tan(1)/tan(3))*cot(3) + + +def test_L(): + assert L(cos(x) + sin(x)) == 2 + + +def test_fu(): + + assert fu(sin(50)**2 + cos(50)**2 + sin(pi/6)) == Rational(3, 2) + assert fu(sqrt(6)*cos(x) + sqrt(2)*sin(x)) == 2*sqrt(2)*sin(x + pi/3) + + + eq = sin(x)**4 - cos(y)**2 + sin(y)**2 + 2*cos(x)**2 + assert fu(eq) == cos(x)**4 - 2*cos(y)**2 + 2 + + assert fu(S.Half - cos(2*x)/2) == sin(x)**2 + + assert fu(sin(a)*(cos(b) - sin(b)) + cos(a)*(sin(b) + cos(b))) == \ + sqrt(2)*sin(a + b + pi/4) + + assert fu(sqrt(3)*cos(x)/2 + sin(x)/2) == sin(x + pi/3) + + assert fu(1 - sin(2*x)**2/4 - sin(y)**2 - cos(x)**4) == \ + -cos(x)**2 + cos(y)**2 + + assert fu(cos(pi*Rational(4, 9))) == sin(pi/18) + assert fu(cos(pi/9)*cos(pi*Rational(2, 9))*cos(pi*Rational(3, 9))*cos(pi*Rational(4, 9))) == Rational(1, 16) + + assert fu( + tan(pi*Rational(7, 18)) + tan(pi*Rational(5, 18)) - sqrt(3)*tan(pi*Rational(5, 18))*tan(pi*Rational(7, 18))) == \ + -sqrt(3) + + assert fu(tan(1)*tan(2)) == tan(1)*tan(2) + + expr = Mul(*[cos(2**i) for i in range(10)]) + assert fu(expr) == sin(1024)/(1024*sin(1)) + + # issue #18059: + assert fu(cos(x) + sqrt(sin(x)**2)) == cos(x) + sqrt(sin(x)**2) + + assert fu((-14*sin(x)**3 + 35*sin(x) + 6*sqrt(3)*cos(x)**3 + 9*sqrt(3)*cos(x))/((cos(2*x) + 4))) == \ + 7*sin(x) + 3*sqrt(3)*cos(x) + + +def test_objective(): + assert fu(sin(x)/cos(x), measure=lambda x: x.count_ops()) == \ + tan(x) + assert fu(sin(x)/cos(x), measure=lambda x: -x.count_ops()) == \ + sin(x)/cos(x) + + +def test_process_common_addends(): + # this tests that the args are not evaluated as they are given to do + # and that key2 works when key1 is False + do = lambda x: Add(*[i**(i%2) for i in x.args]) + assert process_common_addends(Add(*[1, 2, 3, 4], evaluate=False), do, + key2=lambda x: x%2, key1=False) == 1**1 + 3**1 + 2**0 + 4**0 + + +def test_trig_split(): + assert trig_split(cos(x), cos(y)) == (1, 1, 1, x, y, True) + assert trig_split(2*cos(x), -2*cos(y)) == (2, 1, -1, x, y, True) + assert trig_split(cos(x)*sin(y), cos(y)*sin(y)) == \ + (sin(y), 1, 1, x, y, True) + + assert trig_split(cos(x), -sqrt(3)*sin(x), two=True) == \ + (2, 1, -1, x, pi/6, False) + assert trig_split(cos(x), sin(x), two=True) == \ + (sqrt(2), 1, 1, x, pi/4, False) + assert trig_split(cos(x), -sin(x), two=True) == \ + (sqrt(2), 1, -1, x, pi/4, False) + assert trig_split(sqrt(2)*cos(x), -sqrt(6)*sin(x), two=True) == \ + (2*sqrt(2), 1, -1, x, pi/6, False) + assert trig_split(-sqrt(6)*cos(x), -sqrt(2)*sin(x), two=True) == \ + (-2*sqrt(2), 1, 1, x, pi/3, False) + assert trig_split(cos(x)/sqrt(6), sin(x)/sqrt(2), two=True) == \ + (sqrt(6)/3, 1, 1, x, pi/6, False) + assert trig_split(-sqrt(6)*cos(x)*sin(y), + -sqrt(2)*sin(x)*sin(y), two=True) == \ + (-2*sqrt(2)*sin(y), 1, 1, x, pi/3, False) + + assert trig_split(cos(x), sin(x)) is None + assert trig_split(cos(x), sin(z)) is None + assert trig_split(2*cos(x), -sin(x)) is None + assert trig_split(cos(x), -sqrt(3)*sin(x)) is None + assert trig_split(cos(x)*cos(y), sin(x)*sin(z)) is None + assert trig_split(cos(x)*cos(y), sin(x)*sin(y)) is None + assert trig_split(-sqrt(6)*cos(x), sqrt(2)*sin(x)*sin(y), two=True) is \ + None + + assert trig_split(sqrt(3)*sqrt(x), cos(3), two=True) is None + assert trig_split(sqrt(3)*root(x, 3), sin(3)*cos(2), two=True) is None + assert trig_split(cos(5)*cos(6), cos(7)*sin(5), two=True) is None + + +def test_TRmorrie(): + assert TRmorrie(7*Mul(*[cos(i) for i in range(10)])) == \ + 7*sin(12)*sin(16)*cos(5)*cos(7)*cos(9)/(64*sin(1)*sin(3)) + assert TRmorrie(x) == x + assert TRmorrie(2*x) == 2*x + e = cos(pi/7)*cos(pi*Rational(2, 7))*cos(pi*Rational(4, 7)) + assert TR8(TRmorrie(e)) == Rational(-1, 8) + e = Mul(*[cos(2**i*pi/17) for i in range(1, 17)]) + assert TR8(TR3(TRmorrie(e))) == Rational(1, 65536) + # issue 17063 + eq = cos(x)/cos(x/2) + assert TRmorrie(eq) == eq + # issue #20430 + eq = cos(x/2)*sin(x/2)*cos(x)**3 + assert TRmorrie(eq) == sin(2*x)*cos(x)**2/4 + + +def test_TRpower(): + assert TRpower(1/sin(x)**2) == 1/sin(x)**2 + assert TRpower(cos(x)**3*sin(x/2)**4) == \ + (3*cos(x)/4 + cos(3*x)/4)*(-cos(x)/2 + cos(2*x)/8 + Rational(3, 8)) + for k in range(2, 8): + assert verify_numerically(sin(x)**k, TRpower(sin(x)**k)) + assert verify_numerically(cos(x)**k, TRpower(cos(x)**k)) + + +def test_hyper_as_trig(): + from sympy.simplify.fu import _osborne, _osbornei + + eq = sinh(x)**2 + cosh(x)**2 + t, f = hyper_as_trig(eq) + assert f(fu(t)) == cosh(2*x) + e, f = hyper_as_trig(tanh(x + y)) + assert f(TR12(e)) == (tanh(x) + tanh(y))/(tanh(x)*tanh(y) + 1) + + d = Dummy() + assert _osborne(sinh(x), d) == I*sin(x*d) + assert _osborne(tanh(x), d) == I*tan(x*d) + assert _osborne(coth(x), d) == cot(x*d)/I + assert _osborne(cosh(x), d) == cos(x*d) + assert _osborne(sech(x), d) == sec(x*d) + assert _osborne(csch(x), d) == csc(x*d)/I + for func in (sinh, cosh, tanh, coth, sech, csch): + h = func(pi) + assert _osbornei(_osborne(h, d), d) == h + # /!\ the _osborne functions are not meant to work + # in the o(i(trig, d), d) direction so we just check + # that they work as they are supposed to work + assert _osbornei(cos(x*y + z), y) == cosh(x + z*I) + assert _osbornei(sin(x*y + z), y) == sinh(x + z*I)/I + assert _osbornei(tan(x*y + z), y) == tanh(x + z*I)/I + assert _osbornei(cot(x*y + z), y) == coth(x + z*I)*I + assert _osbornei(sec(x*y + z), y) == sech(x + z*I) + assert _osbornei(csc(x*y + z), y) == csch(x + z*I)*I + + +def test_TR12i(): + ta, tb, tc = [tan(i) for i in (a, b, c)] + assert TR12i((ta + tb)/(-ta*tb + 1)) == tan(a + b) + assert TR12i((ta + tb)/(ta*tb - 1)) == -tan(a + b) + assert TR12i((-ta - tb)/(ta*tb - 1)) == tan(a + b) + eq = (ta + tb)/(-ta*tb + 1)**2*(-3*ta - 3*tc)/(2*(ta*tc - 1)) + assert TR12i(eq.expand()) == \ + -3*tan(a + b)*tan(a + c)/(tan(a) + tan(b) - 1)/2 + assert TR12i(tan(x)/sin(x)) == tan(x)/sin(x) + eq = (ta + cos(2))/(-ta*tb + 1) + assert TR12i(eq) == eq + eq = (ta + tb + 2)**2/(-ta*tb + 1) + assert TR12i(eq) == eq + eq = ta/(-ta*tb + 1) + assert TR12i(eq) == eq + eq = (((ta + tb)*(a + 1)).expand())**2/(ta*tb - 1) + assert TR12i(eq) == -(a + 1)**2*tan(a + b) + + +def test_TR14(): + eq = (cos(x) - 1)*(cos(x) + 1) + ans = -sin(x)**2 + assert TR14(eq) == ans + assert TR14(1/eq) == 1/ans + assert TR14((cos(x) - 1)**2*(cos(x) + 1)**2) == ans**2 + assert TR14((cos(x) - 1)**2*(cos(x) + 1)**3) == ans**2*(cos(x) + 1) + assert TR14((cos(x) - 1)**3*(cos(x) + 1)**2) == ans**2*(cos(x) - 1) + eq = (cos(x) - 1)**y*(cos(x) + 1)**y + assert TR14(eq) == eq + eq = (cos(x) - 2)**y*(cos(x) + 1) + assert TR14(eq) == eq + eq = (tan(x) - 2)**2*(cos(x) + 1) + assert TR14(eq) == eq + i = symbols('i', integer=True) + assert TR14((cos(x) - 1)**i*(cos(x) + 1)**i) == ans**i + assert TR14((sin(x) - 1)**i*(sin(x) + 1)**i) == (-cos(x)**2)**i + # could use extraction in this case + eq = (cos(x) - 1)**(i + 1)*(cos(x) + 1)**i + assert TR14(eq) in [(cos(x) - 1)*ans**i, eq] + + assert TR14((sin(x) - 1)*(sin(x) + 1)) == -cos(x)**2 + p1 = (cos(x) + 1)*(cos(x) - 1) + p2 = (cos(y) - 1)*2*(cos(y) + 1) + p3 = (3*(cos(y) - 1))*(3*(cos(y) + 1)) + assert TR14(p1*p2*p3*(x - 1)) == -18*((x - 1)*sin(x)**2*sin(y)**4) + + +def test_TR15_16_17(): + assert TR15(1 - 1/sin(x)**2) == -cot(x)**2 + assert TR16(1 - 1/cos(x)**2) == -tan(x)**2 + assert TR111(1 - 1/tan(x)**2) == 1 - cot(x)**2 + + +def test_as_f_sign_1(): + assert as_f_sign_1(x + 1) == (1, x, 1) + assert as_f_sign_1(x - 1) == (1, x, -1) + assert as_f_sign_1(-x + 1) == (-1, x, -1) + assert as_f_sign_1(-x - 1) == (-1, x, 1) + assert as_f_sign_1(2*x + 2) == (2, x, 1) + assert as_f_sign_1(x*y - y) == (y, x, -1) + assert as_f_sign_1(-x*y + y) == (-y, x, -1) + + +def test_issue_25590(): + A = Symbol('A', commutative=False) + B = Symbol('B', commutative=False) + + assert TR8(2*cos(x)*sin(x)*B*A) == sin(2*x)*B*A + assert TR13(tan(2)*tan(3)*B*A) == (-tan(2)/tan(5) - tan(3)/tan(5) + 1)*B*A + + # XXX The result may not be optimal than + # sin(2*x)*B*A + cos(x)**2 and may change in the future + assert (2*cos(x)*sin(x)*B*A + cos(x)**2).simplify() == sin(2*x)*B*A + cos(2*x)/2 + S.One/2 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_function.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_function.py new file mode 100644 index 0000000000000000000000000000000000000000..441b9faf1bb3c5e7f2279b2a61066d050e45f773 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_function.py @@ -0,0 +1,54 @@ +""" Unit tests for Hyper_Function""" +from sympy.core import symbols, Dummy, Tuple, S, Rational +from sympy.functions import hyper + +from sympy.simplify.hyperexpand import Hyper_Function + +def test_attrs(): + a, b = symbols('a, b', cls=Dummy) + f = Hyper_Function([2, a], [b]) + assert f.ap == Tuple(2, a) + assert f.bq == Tuple(b) + assert f.args == (Tuple(2, a), Tuple(b)) + assert f.sizes == (2, 1) + +def test_call(): + a, b, x = symbols('a, b, x', cls=Dummy) + f = Hyper_Function([2, a], [b]) + assert f(x) == hyper([2, a], [b], x) + +def test_has(): + a, b, c = symbols('a, b, c', cls=Dummy) + f = Hyper_Function([2, -a], [b]) + assert f.has(a) + assert f.has(Tuple(b)) + assert not f.has(c) + +def test_eq(): + assert Hyper_Function([1], []) == Hyper_Function([1], []) + assert (Hyper_Function([1], []) != Hyper_Function([1], [])) is False + assert Hyper_Function([1], []) != Hyper_Function([2], []) + assert Hyper_Function([1], []) != Hyper_Function([1, 2], []) + assert Hyper_Function([1], []) != Hyper_Function([1], [2]) + +def test_gamma(): + assert Hyper_Function([2, 3], [-1]).gamma == 0 + assert Hyper_Function([-2, -3], [-1]).gamma == 2 + n = Dummy(integer=True) + assert Hyper_Function([-1, n, 1], []).gamma == 1 + assert Hyper_Function([-1, -n, 1], []).gamma == 1 + p = Dummy(integer=True, positive=True) + assert Hyper_Function([-1, p, 1], []).gamma == 1 + assert Hyper_Function([-1, -p, 1], []).gamma == 2 + +def test_suitable_origin(): + assert Hyper_Function((S.Half,), (Rational(3, 2),))._is_suitable_origin() is True + assert Hyper_Function((S.Half,), (S.Half,))._is_suitable_origin() is False + assert Hyper_Function((S.Half,), (Rational(-1, 2),))._is_suitable_origin() is False + assert Hyper_Function((S.Half,), (0,))._is_suitable_origin() is False + assert Hyper_Function((S.Half,), (-1, 1,))._is_suitable_origin() is False + assert Hyper_Function((S.Half, 0), (1,))._is_suitable_origin() is False + assert Hyper_Function((S.Half, 1), + (2, Rational(-2, 3)))._is_suitable_origin() is True + assert Hyper_Function((S.Half, 1), + (2, Rational(-2, 3), Rational(3, 2)))._is_suitable_origin() is True diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_gammasimp.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_gammasimp.py new file mode 100644 index 0000000000000000000000000000000000000000..e4c73093250b279510e3c2274db22818a9adffd8 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_gammasimp.py @@ -0,0 +1,127 @@ +from sympy.core.function import Function +from sympy.core.numbers import (Rational, pi) +from sympy.core.singleton import S +from sympy.core.symbol import symbols +from sympy.functions.combinatorial.factorials import (rf, binomial, factorial) +from sympy.functions.elementary.exponential import exp +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.piecewise import Piecewise +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.functions.special.gamma_functions import gamma +from sympy.simplify.gammasimp import gammasimp +from sympy.simplify.powsimp import powsimp +from sympy.simplify.simplify import simplify + +from sympy.abc import x, y, n, k + + +def test_gammasimp(): + R = Rational + + # was part of test_combsimp_gamma() in test_combsimp.py + assert gammasimp(gamma(x)) == gamma(x) + assert gammasimp(gamma(x + 1)/x) == gamma(x) + assert gammasimp(gamma(x)/(x - 1)) == gamma(x - 1) + assert gammasimp(x*gamma(x)) == gamma(x + 1) + assert gammasimp((x + 1)*gamma(x + 1)) == gamma(x + 2) + assert gammasimp(gamma(x + y)*(x + y)) == gamma(x + y + 1) + assert gammasimp(x/gamma(x + 1)) == 1/gamma(x) + assert gammasimp((x + 1)**2/gamma(x + 2)) == (x + 1)/gamma(x + 1) + assert gammasimp(x*gamma(x) + gamma(x + 3)/(x + 2)) == \ + (x + 2)*gamma(x + 1) + + assert gammasimp(gamma(2*x)*x) == gamma(2*x + 1)/2 + assert gammasimp(gamma(2*x)/(x - S.Half)) == 2*gamma(2*x - 1) + + assert gammasimp(gamma(x)*gamma(1 - x)) == pi/sin(pi*x) + assert gammasimp(gamma(x)*gamma(-x)) == -pi/(x*sin(pi*x)) + assert gammasimp(1/gamma(x + 3)/gamma(1 - x)) == \ + sin(pi*x)/(pi*x*(x + 1)*(x + 2)) + + assert gammasimp(factorial(n + 2)) == gamma(n + 3) + assert gammasimp(binomial(n, k)) == \ + gamma(n + 1)/(gamma(k + 1)*gamma(-k + n + 1)) + + assert powsimp(gammasimp( + gamma(x)*gamma(x + S.Half)*gamma(y)/gamma(x + y))) == \ + 2**(-2*x + 1)*sqrt(pi)*gamma(2*x)*gamma(y)/gamma(x + y) + assert gammasimp(1/gamma(x)/gamma(x - Rational(1, 3))/gamma(x + Rational(1, 3))) == \ + 3**(3*x - Rational(3, 2))/(2*pi*gamma(3*x - 1)) + assert simplify( + gamma(S.Half + x/2)*gamma(1 + x/2)/gamma(1 + x)/sqrt(pi)*2**x) == 1 + assert gammasimp(gamma(Rational(-1, 4))*gamma(Rational(-3, 4))) == 16*sqrt(2)*pi/3 + + assert powsimp(gammasimp(gamma(2*x)/gamma(x))) == \ + 2**(2*x - 1)*gamma(x + S.Half)/sqrt(pi) + + # issue 6792 + e = (-gamma(k)*gamma(k + 2) + gamma(k + 1)**2)/gamma(k)**2 + assert gammasimp(e) == -k + assert gammasimp(1/e) == -1/k + e = (gamma(x) + gamma(x + 1))/gamma(x) + assert gammasimp(e) == x + 1 + assert gammasimp(1/e) == 1/(x + 1) + e = (gamma(x) + gamma(x + 2))*(gamma(x - 1) + gamma(x))/gamma(x) + assert gammasimp(e) == (x**2 + x + 1)*gamma(x + 1)/(x - 1) + e = (-gamma(k)*gamma(k + 2) + gamma(k + 1)**2)/gamma(k)**2 + assert gammasimp(e**2) == k**2 + assert gammasimp(e**2/gamma(k + 1)) == k/gamma(k) + a = R(1, 2) + R(1, 3) + b = a + R(1, 3) + assert gammasimp(gamma(2*k)/gamma(k)*gamma(k + a)*gamma(k + b) + ) == 3*2**(2*k + 1)*3**(-3*k - 2)*sqrt(pi)*gamma(3*k + R(3, 2))/2 + + # issue 9699 + assert gammasimp((x + 1)*factorial(x)/gamma(y)) == gamma(x + 2)/gamma(y) + assert gammasimp(rf(x + n, k)*binomial(n, k)).simplify() == Piecewise( + (gamma(n + 1)*gamma(k + n + x)/(gamma(k + 1)*gamma(n + x)*gamma(-k + n + 1)), n > -x), + ((-1)**k*gamma(n + 1)*gamma(-n - x + 1)/(gamma(k + 1)*gamma(-k + n + 1)*gamma(-k - n - x + 1)), True)) + + A, B = symbols('A B', commutative=False) + assert gammasimp(e*B*A) == gammasimp(e)*B*A + + # check iteration + assert gammasimp(gamma(2*k)/gamma(k)*gamma(-k - R(1, 2))) == ( + -2**(2*k + 1)*sqrt(pi)/(2*((2*k + 1)*cos(pi*k)))) + assert gammasimp( + gamma(k)*gamma(k + R(1, 3))*gamma(k + R(2, 3))/gamma(k*R(3, 2))) == ( + 3*2**(3*k + 1)*3**(-3*k - S.Half)*sqrt(pi)*gamma(k*R(3, 2) + S.Half)/2) + + # issue 6153 + assert gammasimp(gamma(Rational(1, 4))/gamma(Rational(5, 4))) == 4 + + # was part of test_combsimp() in test_combsimp.py + assert gammasimp(binomial(n + 2, k + S.Half)) == gamma(n + 3)/ \ + (gamma(k + R(3, 2))*gamma(-k + n + R(5, 2))) + assert gammasimp(binomial(n + 2, k + 2.0)) == \ + gamma(n + 3)/(gamma(k + 3.0)*gamma(-k + n + 1)) + + # issue 11548 + assert gammasimp(binomial(0, x)) == sin(pi*x)/(pi*x) + + e = gamma(n + Rational(1, 3))*gamma(n + R(2, 3)) + assert gammasimp(e) == e + assert gammasimp(gamma(4*n + S.Half)/gamma(2*n - R(3, 4))) == \ + 2**(4*n - R(5, 2))*(8*n - 3)*gamma(2*n + R(3, 4))/sqrt(pi) + + i, m = symbols('i m', integer = True) + e = gamma(exp(i)) + assert gammasimp(e) == e + e = gamma(m + 3) + assert gammasimp(e) == e + e = gamma(m + 1)/(gamma(i + 1)*gamma(-i + m + 1)) + assert gammasimp(e) == e + + p = symbols("p", integer=True, positive=True) + assert gammasimp(gamma(-p + 4)) == gamma(-p + 4) + + +def test_issue_22606(): + fx = Function('f')(x) + eq = x + gamma(y) + # seems like ans should be `eq`, not `(x*y + gamma(y + 1))/y` + ans = gammasimp(eq) + assert gammasimp(eq.subs(x, fx)).subs(fx, x) == ans + assert gammasimp(eq.subs(x, cos(x))).subs(cos(x), x) == ans + assert 1/gammasimp(1/eq) == ans + assert gammasimp(fx.subs(x, eq)).args[0] == ans diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_hyperexpand.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_hyperexpand.py new file mode 100644 index 0000000000000000000000000000000000000000..c703c228a13201de13cfd4c3413fc75a2cf5bdb6 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_hyperexpand.py @@ -0,0 +1,1063 @@ +from sympy.core.random import randrange + +from sympy.simplify.hyperexpand import (ShiftA, ShiftB, UnShiftA, UnShiftB, + MeijerShiftA, MeijerShiftB, MeijerShiftC, MeijerShiftD, + MeijerUnShiftA, MeijerUnShiftB, MeijerUnShiftC, + MeijerUnShiftD, + ReduceOrder, reduce_order, apply_operators, + devise_plan, make_derivative_operator, Formula, + hyperexpand, Hyper_Function, G_Function, + reduce_order_meijer, + build_hypergeometric_formula) +from sympy.concrete.summations import Sum +from sympy.core.containers import Tuple +from sympy.core.expr import Expr +from sympy.core.numbers import I +from sympy.core.singleton import S +from sympy.core.symbol import symbols +from sympy.functions.combinatorial.factorials import binomial +from sympy.functions.elementary.piecewise import Piecewise +from sympy.functions.special.hyper import (hyper, meijerg) +from sympy.abc import z, a, b, c +from sympy.testing.pytest import XFAIL, raises, slow, tooslow +from sympy.core.random import verify_numerically as tn + +from sympy.core.numbers import (Rational, pi) +from sympy.functions.elementary.exponential import (exp, exp_polar, log) +from sympy.functions.elementary.hyperbolic import atanh +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (asin, cos, sin) +from sympy.functions.special.bessel import besseli +from sympy.functions.special.error_functions import erf +from sympy.functions.special.gamma_functions import (gamma, lowergamma) + + +def test_branch_bug(): + assert hyperexpand(hyper((Rational(-1, 3), S.Half), (Rational(2, 3), Rational(3, 2)), -z)) == \ + -z**S('1/3')*lowergamma(exp_polar(I*pi)/3, z)/5 \ + + sqrt(pi)*erf(sqrt(z))/(5*sqrt(z)) + assert hyperexpand(meijerg([Rational(7, 6), 1], [], [Rational(2, 3)], [Rational(1, 6), 0], z)) == \ + 2*z**S('2/3')*(2*sqrt(pi)*erf(sqrt(z))/sqrt(z) - 2*lowergamma( + Rational(2, 3), z)/z**S('2/3'))*gamma(Rational(2, 3))/gamma(Rational(5, 3)) + + +def test_hyperexpand(): + # Luke, Y. L. (1969), The Special Functions and Their Approximations, + # Volume 1, section 6.2 + + assert hyperexpand(hyper([], [], z)) == exp(z) + assert hyperexpand(hyper([1, 1], [2], -z)*z) == log(1 + z) + assert hyperexpand(hyper([], [S.Half], -z**2/4)) == cos(z) + assert hyperexpand(z*hyper([], [S('3/2')], -z**2/4)) == sin(z) + assert hyperexpand(hyper([S('1/2'), S('1/2')], [S('3/2')], z**2)*z) \ + == asin(z) + assert isinstance(Sum(binomial(2, z)*z**2, (z, 0, a)).doit(), Expr) + + +def can_do(ap, bq, numerical=True, div=1, lowerplane=False): + r = hyperexpand(hyper(ap, bq, z)) + if r.has(hyper): + return False + if not numerical: + return True + repl = {} + randsyms = r.free_symbols - {z} + while randsyms: + # Only randomly generated parameters are checked. + for n, ai in enumerate(randsyms): + repl[ai] = randcplx(n)/div + if not any(b.is_Integer and b <= 0 for b in Tuple(*bq).subs(repl)): + break + [a, b, c, d] = [2, -1, 3, 1] + if lowerplane: + [a, b, c, d] = [2, -2, 3, -1] + return tn( + hyper(ap, bq, z).subs(repl), + r.replace(exp_polar, exp).subs(repl), + z, a=a, b=b, c=c, d=d) + + +def test_roach(): + # Kelly B. Roach. Meijer G Function Representations. + # Section "Gallery" + assert can_do([S.Half], [Rational(9, 2)]) + assert can_do([], [1, Rational(5, 2), 4]) + assert can_do([Rational(-1, 2), 1, 2], [3, 4]) + assert can_do([Rational(1, 3)], [Rational(-2, 3), Rational(-1, 2), S.Half, 1]) + assert can_do([Rational(-3, 2), Rational(-1, 2)], [Rational(-5, 2), 1]) + assert can_do([Rational(-3, 2), ], [Rational(-1, 2), S.Half]) # shine-integral + assert can_do([Rational(-3, 2), Rational(-1, 2)], [2]) # elliptic integrals + + +@XFAIL +def test_roach_fail(): + assert can_do([Rational(-1, 2), 1], [Rational(1, 4), S.Half, Rational(3, 4)]) # PFDD + assert can_do([Rational(3, 2)], [Rational(5, 2), 5]) # struve function + assert can_do([Rational(-1, 2), S.Half, 1], [Rational(3, 2), Rational(5, 2)]) # polylog, pfdd + assert can_do([1, 2, 3], [S.Half, 4]) # XXX ? + assert can_do([S.Half], [Rational(-1, 3), Rational(-1, 2), Rational(-2, 3)]) # PFDD ? + +# For the long table tests, see end of file + + +def test_polynomial(): + from sympy.core.numbers import oo + assert hyperexpand(hyper([], [-1], z)) is oo + assert hyperexpand(hyper([-2], [-1], z)) is oo + assert hyperexpand(hyper([0, 0], [-1], z)) == 1 + assert can_do([-5, -2, randcplx(), randcplx()], [-10, randcplx()]) + assert hyperexpand(hyper((-1, 1), (-2,), z)) == 1 + z/2 + + +def test_hyperexpand_bases(): + assert hyperexpand(hyper([2], [a], z)) == \ + a + z**(-a + 1)*(-a**2 + 3*a + z*(a - 1) - 2)*exp(z)* \ + lowergamma(a - 1, z) - 1 + # TODO [a+1, aRational(-1, 2)], [2*a] + assert hyperexpand(hyper([1, 2], [3], z)) == -2/z - 2*log(-z + 1)/z**2 + assert hyperexpand(hyper([S.Half, 2], [Rational(3, 2)], z)) == \ + -1/(2*z - 2) + atanh(sqrt(z))/sqrt(z)/2 + assert hyperexpand(hyper([S.Half, S.Half], [Rational(5, 2)], z)) == \ + (-3*z + 3)/4/(z*sqrt(-z + 1)) \ + + (6*z - 3)*asin(sqrt(z))/(4*z**Rational(3, 2)) + assert hyperexpand(hyper([1, 2], [Rational(3, 2)], z)) == -1/(2*z - 2) \ + - asin(sqrt(z))/(sqrt(z)*(2*z - 2)*sqrt(-z + 1)) + assert hyperexpand(hyper([Rational(-1, 2) - 1, 1, 2], [S.Half, 3], z)) == \ + sqrt(z)*(z*Rational(6, 7) - Rational(6, 5))*atanh(sqrt(z)) \ + + (-30*z**2 + 32*z - 6)/35/z - 6*log(-z + 1)/(35*z**2) + assert hyperexpand(hyper([1 + S.Half, 1, 1], [2, 2], z)) == \ + -4*log(sqrt(-z + 1)/2 + S.Half)/z + # TODO hyperexpand(hyper([a], [2*a + 1], z)) + # TODO [S.Half, a], [Rational(3, 2), a+1] + assert hyperexpand(hyper([2], [b, 1], z)) == \ + z**(-b/2 + S.Half)*besseli(b - 1, 2*sqrt(z))*gamma(b) \ + + z**(-b/2 + 1)*besseli(b, 2*sqrt(z))*gamma(b) + # TODO [a], [a - S.Half, 2*a] + + +def test_hyperexpand_parametric(): + assert hyperexpand(hyper([a, S.Half + a], [S.Half], z)) \ + == (1 + sqrt(z))**(-2*a)/2 + (1 - sqrt(z))**(-2*a)/2 + assert hyperexpand(hyper([a, Rational(-1, 2) + a], [2*a], z)) \ + == 2**(2*a - 1)*((-z + 1)**S.Half + 1)**(-2*a + 1) + + +def test_shifted_sum(): + from sympy.simplify.simplify import simplify + assert simplify(hyperexpand(z**4*hyper([2], [3, S('3/2')], -z**2))) \ + == z*sin(2*z) + (-z**2 + S.Half)*cos(2*z) - S.Half + + +def _randrat(): + """ Steer clear of integers. """ + return S(randrange(25) + 10)/50 + + +def randcplx(offset=-1): + """ Polys is not good with real coefficients. """ + return _randrat() + I*_randrat() + I*(1 + offset) + + +@slow +def test_formulae(): + from sympy.simplify.hyperexpand import FormulaCollection + formulae = FormulaCollection().formulae + for formula in formulae: + h = formula.func(formula.z) + rep = {} + for n, sym in enumerate(formula.symbols): + rep[sym] = randcplx(n) + + # NOTE hyperexpand returns truly branched functions. We know we are + # on the main sheet, but numerical evaluation can still go wrong + # (e.g. if exp_polar cannot be evalf'd). + # Just replace all exp_polar by exp, this usually works. + + # first test if the closed-form is actually correct + h = h.subs(rep) + closed_form = formula.closed_form.subs(rep).rewrite('nonrepsmall') + z = formula.z + assert tn(h, closed_form.replace(exp_polar, exp), z) + + # now test the computed matrix + cl = (formula.C * formula.B)[0].subs(rep).rewrite('nonrepsmall') + assert tn(closed_form.replace( + exp_polar, exp), cl.replace(exp_polar, exp), z) + deriv1 = z*formula.B.applyfunc(lambda t: t.rewrite( + 'nonrepsmall')).diff(z) + deriv2 = formula.M * formula.B + for d1, d2 in zip(deriv1, deriv2): + assert tn(d1.subs(rep).replace(exp_polar, exp), + d2.subs(rep).rewrite('nonrepsmall').replace(exp_polar, exp), z) + + +def test_meijerg_formulae(): + from sympy.simplify.hyperexpand import MeijerFormulaCollection + formulae = MeijerFormulaCollection().formulae + for sig in formulae: + for formula in formulae[sig]: + g = meijerg(formula.func.an, formula.func.ap, + formula.func.bm, formula.func.bq, + formula.z) + rep = {} + for sym in formula.symbols: + rep[sym] = randcplx() + + # first test if the closed-form is actually correct + g = g.subs(rep) + closed_form = formula.closed_form.subs(rep) + z = formula.z + assert tn(g, closed_form, z) + + # now test the computed matrix + cl = (formula.C * formula.B)[0].subs(rep) + assert tn(closed_form, cl, z) + deriv1 = z*formula.B.diff(z) + deriv2 = formula.M * formula.B + for d1, d2 in zip(deriv1, deriv2): + assert tn(d1.subs(rep), d2.subs(rep), z) + + +def op(f): + return z*f.diff(z) + + +def test_plan(): + assert devise_plan(Hyper_Function([0], ()), + Hyper_Function([0], ()), z) == [] + with raises(ValueError): + devise_plan(Hyper_Function([1], ()), Hyper_Function((), ()), z) + with raises(ValueError): + devise_plan(Hyper_Function([2], [1]), Hyper_Function([2], [2]), z) + with raises(ValueError): + devise_plan(Hyper_Function([2], []), Hyper_Function([S("1/2")], []), z) + + # We cannot use pi/(10000 + n) because polys is insanely slow. + a1, a2, b1 = (randcplx(n) for n in range(3)) + b1 += 2*I + h = hyper([a1, a2], [b1], z) + + h2 = hyper((a1 + 1, a2), [b1], z) + assert tn(apply_operators(h, + devise_plan(Hyper_Function((a1 + 1, a2), [b1]), + Hyper_Function((a1, a2), [b1]), z), op), + h2, z) + + h2 = hyper((a1 + 1, a2 - 1), [b1], z) + assert tn(apply_operators(h, + devise_plan(Hyper_Function((a1 + 1, a2 - 1), [b1]), + Hyper_Function((a1, a2), [b1]), z), op), + h2, z) + + +def test_plan_derivatives(): + a1, a2, a3 = 1, 2, S('1/2') + b1, b2 = 3, S('5/2') + h = Hyper_Function((a1, a2, a3), (b1, b2)) + h2 = Hyper_Function((a1 + 1, a2 + 1, a3 + 2), (b1 + 1, b2 + 1)) + ops = devise_plan(h2, h, z) + f = Formula(h, z, h(z), []) + deriv = make_derivative_operator(f.M, z) + assert tn((apply_operators(f.C, ops, deriv)*f.B)[0], h2(z), z) + + h2 = Hyper_Function((a1, a2 - 1, a3 - 2), (b1 - 1, b2 - 1)) + ops = devise_plan(h2, h, z) + assert tn((apply_operators(f.C, ops, deriv)*f.B)[0], h2(z), z) + + +def test_reduction_operators(): + a1, a2, b1 = (randcplx(n) for n in range(3)) + h = hyper([a1], [b1], z) + + assert ReduceOrder(2, 0) is None + assert ReduceOrder(2, -1) is None + assert ReduceOrder(1, S('1/2')) is None + + h2 = hyper((a1, a2), (b1, a2), z) + assert tn(ReduceOrder(a2, a2).apply(h, op), h2, z) + + h2 = hyper((a1, a2 + 1), (b1, a2), z) + assert tn(ReduceOrder(a2 + 1, a2).apply(h, op), h2, z) + + h2 = hyper((a2 + 4, a1), (b1, a2), z) + assert tn(ReduceOrder(a2 + 4, a2).apply(h, op), h2, z) + + # test several step order reduction + ap = (a2 + 4, a1, b1 + 1) + bq = (a2, b1, b1) + func, ops = reduce_order(Hyper_Function(ap, bq)) + assert func.ap == (a1,) + assert func.bq == (b1,) + assert tn(apply_operators(h, ops, op), hyper(ap, bq, z), z) + + +def test_shift_operators(): + a1, a2, b1, b2, b3 = (randcplx(n) for n in range(5)) + h = hyper((a1, a2), (b1, b2, b3), z) + + raises(ValueError, lambda: ShiftA(0)) + raises(ValueError, lambda: ShiftB(1)) + + assert tn(ShiftA(a1).apply(h, op), hyper((a1 + 1, a2), (b1, b2, b3), z), z) + assert tn(ShiftA(a2).apply(h, op), hyper((a1, a2 + 1), (b1, b2, b3), z), z) + assert tn(ShiftB(b1).apply(h, op), hyper((a1, a2), (b1 - 1, b2, b3), z), z) + assert tn(ShiftB(b2).apply(h, op), hyper((a1, a2), (b1, b2 - 1, b3), z), z) + assert tn(ShiftB(b3).apply(h, op), hyper((a1, a2), (b1, b2, b3 - 1), z), z) + + +def test_ushift_operators(): + a1, a2, b1, b2, b3 = (randcplx(n) for n in range(5)) + h = hyper((a1, a2), (b1, b2, b3), z) + + raises(ValueError, lambda: UnShiftA((1,), (), 0, z)) + raises(ValueError, lambda: UnShiftB((), (-1,), 0, z)) + raises(ValueError, lambda: UnShiftA((1,), (0, -1, 1), 0, z)) + raises(ValueError, lambda: UnShiftB((0, 1), (1,), 0, z)) + + s = UnShiftA((a1, a2), (b1, b2, b3), 0, z) + assert tn(s.apply(h, op), hyper((a1 - 1, a2), (b1, b2, b3), z), z) + s = UnShiftA((a1, a2), (b1, b2, b3), 1, z) + assert tn(s.apply(h, op), hyper((a1, a2 - 1), (b1, b2, b3), z), z) + + s = UnShiftB((a1, a2), (b1, b2, b3), 0, z) + assert tn(s.apply(h, op), hyper((a1, a2), (b1 + 1, b2, b3), z), z) + s = UnShiftB((a1, a2), (b1, b2, b3), 1, z) + assert tn(s.apply(h, op), hyper((a1, a2), (b1, b2 + 1, b3), z), z) + s = UnShiftB((a1, a2), (b1, b2, b3), 2, z) + assert tn(s.apply(h, op), hyper((a1, a2), (b1, b2, b3 + 1), z), z) + + +def can_do_meijer(a1, a2, b1, b2, numeric=True): + """ + This helper function tries to hyperexpand() the meijer g-function + corresponding to the parameters a1, a2, b1, b2. + It returns False if this expansion still contains g-functions. + If numeric is True, it also tests the so-obtained formula numerically + (at random values) and returns False if the test fails. + Else it returns True. + """ + from sympy.core.function import expand + from sympy.functions.elementary.complexes import unpolarify + r = hyperexpand(meijerg(a1, a2, b1, b2, z)) + if r.has(meijerg): + return False + # NOTE hyperexpand() returns a truly branched function, whereas numerical + # evaluation only works on the main branch. Since we are evaluating on + # the main branch, this should not be a problem, but expressions like + # exp_polar(I*pi/2*x)**a are evaluated incorrectly. We thus have to get + # rid of them. The expand heuristically does this... + r = unpolarify(expand(r, force=True, power_base=True, power_exp=False, + mul=False, log=False, multinomial=False, basic=False)) + + if not numeric: + return True + + repl = {} + for n, ai in enumerate(meijerg(a1, a2, b1, b2, z).free_symbols - {z}): + repl[ai] = randcplx(n) + return tn(meijerg(a1, a2, b1, b2, z).subs(repl), r.subs(repl), z) + + +@slow +def test_meijerg_expand(): + from sympy.simplify.gammasimp import gammasimp + from sympy.simplify.simplify import simplify + # from mpmath docs + assert hyperexpand(meijerg([[], []], [[0], []], -z)) == exp(z) + + assert hyperexpand(meijerg([[1, 1], []], [[1], [0]], z)) == \ + log(z + 1) + assert hyperexpand(meijerg([[1, 1], []], [[1], [1]], z)) == \ + z/(z + 1) + assert hyperexpand(meijerg([[], []], [[S.Half], [0]], (z/2)**2)) \ + == sin(z)/sqrt(pi) + assert hyperexpand(meijerg([[], []], [[0], [S.Half]], (z/2)**2)) \ + == cos(z)/sqrt(pi) + assert can_do_meijer([], [a], [a - 1, a - S.Half], []) + assert can_do_meijer([], [], [a/2], [-a/2], False) # branches... + assert can_do_meijer([a], [b], [a], [b, a - 1]) + + # wikipedia + assert hyperexpand(meijerg([1], [], [], [0], z)) == \ + Piecewise((0, abs(z) < 1), (1, abs(1/z) < 1), + (meijerg([1], [], [], [0], z), True)) + assert hyperexpand(meijerg([], [1], [0], [], z)) == \ + Piecewise((1, abs(z) < 1), (0, abs(1/z) < 1), + (meijerg([], [1], [0], [], z), True)) + + # The Special Functions and their Approximations + assert can_do_meijer([], [], [a + b/2], [a, a - b/2, a + S.Half]) + assert can_do_meijer( + [], [], [a], [b], False) # branches only agree for small z + assert can_do_meijer([], [S.Half], [a], [-a]) + assert can_do_meijer([], [], [a, b], []) + assert can_do_meijer([], [], [a, b], []) + assert can_do_meijer([], [], [a, a + S.Half], [b, b + S.Half]) + assert can_do_meijer([], [], [a, -a], [0, S.Half], False) # dito + assert can_do_meijer([], [], [a, a + S.Half, b, b + S.Half], []) + assert can_do_meijer([S.Half], [], [0], [a, -a]) + assert can_do_meijer([S.Half], [], [a], [0, -a], False) # dito + assert can_do_meijer([], [a - S.Half], [a, b], [a - S.Half], False) + assert can_do_meijer([], [a + S.Half], [a + b, a - b, a], [], False) + assert can_do_meijer([a + S.Half], [], [b, 2*a - b, a], [], False) + + # This for example is actually zero. + assert can_do_meijer([], [], [], [a, b]) + + # Testing a bug: + assert hyperexpand(meijerg([0, 2], [], [], [-1, 1], z)) == \ + Piecewise((0, abs(z) < 1), + (z*(1 - 1/z**2)/2, abs(1/z) < 1), + (meijerg([0, 2], [], [], [-1, 1], z), True)) + + # Test that the simplest possible answer is returned: + assert gammasimp(simplify(hyperexpand( + meijerg([1], [1 - a], [-a/2, -a/2 + S.Half], [], 1/z)))) == \ + -2*sqrt(pi)*(sqrt(z + 1) + 1)**a/a + + # Test that hyper is returned + assert hyperexpand(meijerg([1], [], [a], [0, 0], z)) == hyper( + (a,), (a + 1, a + 1), z*exp_polar(I*pi))*z**a*gamma(a)/gamma(a + 1)**2 + + # Test place option + f = meijerg(((0, 1), ()), ((S.Half,), (0,)), z**2) + assert hyperexpand(f) == sqrt(pi)/sqrt(1 + z**(-2)) + assert hyperexpand(f, place=0) == sqrt(pi)*z/sqrt(z**2 + 1) + + +def test_meijerg_lookup(): + from sympy.functions.special.error_functions import (Ci, Si) + from sympy.functions.special.gamma_functions import uppergamma + assert hyperexpand(meijerg([a], [], [b, a], [], z)) == \ + z**b*exp(z)*gamma(-a + b + 1)*uppergamma(a - b, z) + assert hyperexpand(meijerg([0], [], [0, 0], [], z)) == \ + exp(z)*uppergamma(0, z) + assert can_do_meijer([a], [], [b, a + 1], []) + assert can_do_meijer([a], [], [b + 2, a], []) + assert can_do_meijer([a], [], [b - 2, a], []) + + assert hyperexpand(meijerg([a], [], [a, a, a - S.Half], [], z)) == \ + -sqrt(pi)*z**(a - S.Half)*(2*cos(2*sqrt(z))*(Si(2*sqrt(z)) - pi/2) + - 2*sin(2*sqrt(z))*Ci(2*sqrt(z))) == \ + hyperexpand(meijerg([a], [], [a, a - S.Half, a], [], z)) == \ + hyperexpand(meijerg([a], [], [a - S.Half, a, a], [], z)) + assert can_do_meijer([a - 1], [], [a + 2, a - Rational(3, 2), a + 1], []) + + +@XFAIL +def test_meijerg_expand_fail(): + # These basically test hyper([], [1/2 - a, 1/2 + 1, 1/2], z), + # which is *very* messy. But since the meijer g actually yields a + # sum of bessel functions, things can sometimes be simplified a lot and + # are then put into tables... + assert can_do_meijer([], [], [a + S.Half], [a, a - b/2, a + b/2]) + assert can_do_meijer([], [], [0, S.Half], [a, -a]) + assert can_do_meijer([], [], [3*a - S.Half, a, -a - S.Half], [a - S.Half]) + assert can_do_meijer([], [], [0, a - S.Half, -a - S.Half], [S.Half]) + assert can_do_meijer([], [], [a, b + S.Half, b], [2*b - a]) + assert can_do_meijer([], [], [a, b + S.Half, b, 2*b - a]) + assert can_do_meijer([S.Half], [], [-a, a], [0]) + + +@slow +def test_meijerg(): + # carefully set up the parameters. + # NOTE: this used to fail sometimes. I believe it is fixed, but if you + # hit an inexplicable test failure here, please let me know the seed. + a1, a2 = (randcplx(n) - 5*I - n*I for n in range(2)) + b1, b2 = (randcplx(n) + 5*I + n*I for n in range(2)) + b3, b4, b5, a3, a4, a5 = (randcplx() for n in range(6)) + g = meijerg([a1], [a3, a4], [b1], [b3, b4], z) + + assert ReduceOrder.meijer_minus(3, 4) is None + assert ReduceOrder.meijer_plus(4, 3) is None + + g2 = meijerg([a1, a2], [a3, a4], [b1], [b3, b4, a2], z) + assert tn(ReduceOrder.meijer_plus(a2, a2).apply(g, op), g2, z) + + g2 = meijerg([a1, a2], [a3, a4], [b1], [b3, b4, a2 + 1], z) + assert tn(ReduceOrder.meijer_plus(a2, a2 + 1).apply(g, op), g2, z) + + g2 = meijerg([a1, a2 - 1], [a3, a4], [b1], [b3, b4, a2 + 2], z) + assert tn(ReduceOrder.meijer_plus(a2 - 1, a2 + 2).apply(g, op), g2, z) + + g2 = meijerg([a1], [a3, a4, b2 - 1], [b1, b2 + 2], [b3, b4], z) + assert tn(ReduceOrder.meijer_minus( + b2 + 2, b2 - 1).apply(g, op), g2, z, tol=1e-6) + + # test several-step reduction + an = [a1, a2] + bq = [b3, b4, a2 + 1] + ap = [a3, a4, b2 - 1] + bm = [b1, b2 + 1] + niq, ops = reduce_order_meijer(G_Function(an, ap, bm, bq)) + assert niq.an == (a1,) + assert set(niq.ap) == {a3, a4} + assert niq.bm == (b1,) + assert set(niq.bq) == {b3, b4} + assert tn(apply_operators(g, ops, op), meijerg(an, ap, bm, bq, z), z) + + +def test_meijerg_shift_operators(): + # carefully set up the parameters. XXX this still fails sometimes + a1, a2, a3, a4, a5, b1, b2, b3, b4, b5 = (randcplx(n) for n in range(10)) + g = meijerg([a1], [a3, a4], [b1], [b3, b4], z) + + assert tn(MeijerShiftA(b1).apply(g, op), + meijerg([a1], [a3, a4], [b1 + 1], [b3, b4], z), z) + assert tn(MeijerShiftB(a1).apply(g, op), + meijerg([a1 - 1], [a3, a4], [b1], [b3, b4], z), z) + assert tn(MeijerShiftC(b3).apply(g, op), + meijerg([a1], [a3, a4], [b1], [b3 + 1, b4], z), z) + assert tn(MeijerShiftD(a3).apply(g, op), + meijerg([a1], [a3 - 1, a4], [b1], [b3, b4], z), z) + + s = MeijerUnShiftA([a1], [a3, a4], [b1], [b3, b4], 0, z) + assert tn( + s.apply(g, op), meijerg([a1], [a3, a4], [b1 - 1], [b3, b4], z), z) + + s = MeijerUnShiftC([a1], [a3, a4], [b1], [b3, b4], 0, z) + assert tn( + s.apply(g, op), meijerg([a1], [a3, a4], [b1], [b3 - 1, b4], z), z) + + s = MeijerUnShiftB([a1], [a3, a4], [b1], [b3, b4], 0, z) + assert tn( + s.apply(g, op), meijerg([a1 + 1], [a3, a4], [b1], [b3, b4], z), z) + + s = MeijerUnShiftD([a1], [a3, a4], [b1], [b3, b4], 0, z) + assert tn( + s.apply(g, op), meijerg([a1], [a3 + 1, a4], [b1], [b3, b4], z), z) + + +@slow +def test_meijerg_confluence(): + def t(m, a, b): + from sympy.core.sympify import sympify + a, b = sympify([a, b]) + m_ = m + m = hyperexpand(m) + if not m == Piecewise((a, abs(z) < 1), (b, abs(1/z) < 1), (m_, True)): + return False + if not (m.args[0].args[0] == a and m.args[1].args[0] == b): + return False + z0 = randcplx()/10 + if abs(m.subs(z, z0).n() - a.subs(z, z0).n()).n() > 1e-10: + return False + if abs(m.subs(z, 1/z0).n() - b.subs(z, 1/z0).n()).n() > 1e-10: + return False + return True + + assert t(meijerg([], [1, 1], [0, 0], [], z), -log(z), 0) + assert t(meijerg( + [], [3, 1], [0, 0], [], z), -z**2/4 + z - log(z)/2 - Rational(3, 4), 0) + assert t(meijerg([], [3, 1], [-1, 0], [], z), + z**2/12 - z/2 + log(z)/2 + Rational(1, 4) + 1/(6*z), 0) + assert t(meijerg([], [1, 1, 1, 1], [0, 0, 0, 0], [], z), -log(z)**3/6, 0) + assert t(meijerg([1, 1], [], [], [0, 0], z), 0, -log(1/z)) + assert t(meijerg([1, 1], [2, 2], [1, 1], [0, 0], z), + -z*log(z) + 2*z, -log(1/z) + 2) + assert t(meijerg([S.Half], [1, 1], [0, 0], [Rational(3, 2)], z), log(z)/2 - 1, 0) + + def u(an, ap, bm, bq): + m = meijerg(an, ap, bm, bq, z) + m2 = hyperexpand(m, allow_hyper=True) + if m2.has(meijerg) and not (m2.is_Piecewise and len(m2.args) == 3): + return False + return tn(m, m2, z) + assert u([], [1], [0, 0], []) + assert u([1, 1], [], [], [0]) + assert u([1, 1], [2, 2, 5], [1, 1, 6], [0, 0]) + assert u([1, 1], [2, 2, 5], [1, 1, 6], [0]) + + +def test_meijerg_with_Floats(): + # see issue #10681 + from sympy.polys.domains.realfield import RR + f = meijerg(((3.0, 1), ()), ((Rational(3, 2),), (0,)), z) + a = -2.3632718012073 + g = a*z**Rational(3, 2)*hyper((-0.5, Rational(3, 2)), (Rational(5, 2),), z*exp_polar(I*pi)) + assert RR.almosteq((hyperexpand(f)/g).n(), 1.0, 1e-12) + + +def test_lerchphi(): + from sympy.functions.special.zeta_functions import (lerchphi, polylog) + from sympy.simplify.gammasimp import gammasimp + assert hyperexpand(hyper([1, a], [a + 1], z)/a) == lerchphi(z, 1, a) + assert hyperexpand( + hyper([1, a, a], [a + 1, a + 1], z)/a**2) == lerchphi(z, 2, a) + assert hyperexpand(hyper([1, a, a, a], [a + 1, a + 1, a + 1], z)/a**3) == \ + lerchphi(z, 3, a) + assert hyperexpand(hyper([1] + [a]*10, [a + 1]*10, z)/a**10) == \ + lerchphi(z, 10, a) + assert gammasimp(hyperexpand(meijerg([0, 1 - a], [], [0], + [-a], exp_polar(-I*pi)*z))) == lerchphi(z, 1, a) + assert gammasimp(hyperexpand(meijerg([0, 1 - a, 1 - a], [], [0], + [-a, -a], exp_polar(-I*pi)*z))) == lerchphi(z, 2, a) + assert gammasimp(hyperexpand(meijerg([0, 1 - a, 1 - a, 1 - a], [], [0], + [-a, -a, -a], exp_polar(-I*pi)*z))) == lerchphi(z, 3, a) + + assert hyperexpand(z*hyper([1, 1], [2], z)) == -log(1 + -z) + assert hyperexpand(z*hyper([1, 1, 1], [2, 2], z)) == polylog(2, z) + assert hyperexpand(z*hyper([1, 1, 1, 1], [2, 2, 2], z)) == polylog(3, z) + + assert hyperexpand(hyper([1, a, 1 + S.Half], [a + 1, S.Half], z)) == \ + -2*a/(z - 1) + (-2*a**2 + a)*lerchphi(z, 1, a) + + # Now numerical tests. These make sure reductions etc are carried out + # correctly + + # a rational function (polylog at negative integer order) + assert can_do([2, 2, 2], [1, 1]) + + # NOTE these contain log(1-x) etc ... better make sure we have |z| < 1 + # reduction of order for polylog + assert can_do([1, 1, 1, b + 5], [2, 2, b], div=10) + + # reduction of order for lerchphi + # XXX lerchphi in mpmath is flaky + assert can_do( + [1, a, a, a, b + 5], [a + 1, a + 1, a + 1, b], numerical=False) + + # test a bug + from sympy.functions.elementary.complexes import Abs + assert hyperexpand(hyper([S.Half, S.Half, S.Half, 1], + [Rational(3, 2), Rational(3, 2), Rational(3, 2)], Rational(1, 4))) == \ + Abs(-polylog(3, exp_polar(I*pi)/2) + polylog(3, S.Half)) + + +def test_partial_simp(): + # First test that hypergeometric function formulae work. + a, b, c, d, e = (randcplx() for _ in range(5)) + for func in [Hyper_Function([a, b, c], [d, e]), + Hyper_Function([], [a, b, c, d, e])]: + f = build_hypergeometric_formula(func) + z = f.z + assert f.closed_form == func(z) + deriv1 = f.B.diff(z)*z + deriv2 = f.M*f.B + for func1, func2 in zip(deriv1, deriv2): + assert tn(func1, func2, z) + + # Now test that formulae are partially simplified. + a, b, z = symbols('a b z') + assert hyperexpand(hyper([3, a], [1, b], z)) == \ + (-a*b/2 + a*z/2 + 2*a)*hyper([a + 1], [b], z) \ + + (a*b/2 - 2*a + 1)*hyper([a], [b], z) + assert tn( + hyperexpand(hyper([3, d], [1, e], z)), hyper([3, d], [1, e], z), z) + assert hyperexpand(hyper([3], [1, a, b], z)) == \ + hyper((), (a, b), z) \ + + z*hyper((), (a + 1, b), z)/(2*a) \ + - z*(b - 4)*hyper((), (a + 1, b + 1), z)/(2*a*b) + assert tn( + hyperexpand(hyper([3], [1, d, e], z)), hyper([3], [1, d, e], z), z) + + +def test_hyperexpand_special(): + assert hyperexpand(hyper([a, b], [c], 1)) == \ + gamma(c)*gamma(c - a - b)/gamma(c - a)/gamma(c - b) + assert hyperexpand(hyper([a, b], [1 + a - b], -1)) == \ + gamma(1 + a/2)*gamma(1 + a - b)/gamma(1 + a)/gamma(1 + a/2 - b) + assert hyperexpand(hyper([a, b], [1 + b - a], -1)) == \ + gamma(1 + b/2)*gamma(1 + b - a)/gamma(1 + b)/gamma(1 + b/2 - a) + assert hyperexpand(meijerg([1 - z - a/2], [1 - z + a/2], [b/2], [-b/2], 1)) == \ + gamma(1 - 2*z)*gamma(z + a/2 + b/2)/gamma(1 - z + a/2 - b/2) \ + /gamma(1 - z - a/2 + b/2)/gamma(1 - z + a/2 + b/2) + assert hyperexpand(hyper([a], [b], 0)) == 1 + assert hyper([a], [b], 0) != 0 + + +def test_Mod1_behavior(): + from sympy.core.symbol import Symbol + from sympy.simplify.simplify import simplify + n = Symbol('n', integer=True) + # Note: this should not hang. + assert simplify(hyperexpand(meijerg([1], [], [n + 1], [0], z))) == \ + lowergamma(n + 1, z) + + +@slow +def test_prudnikov_misc(): + assert can_do([1, (3 + I)/2, (3 - I)/2], [Rational(3, 2), 2]) + assert can_do([S.Half, a - 1], [Rational(3, 2), a + 1], lowerplane=True) + assert can_do([], [b + 1]) + assert can_do([a], [a - 1, b + 1]) + + assert can_do([a], [a - S.Half, 2*a]) + assert can_do([a], [a - S.Half, 2*a + 1]) + assert can_do([a], [a - S.Half, 2*a - 1]) + assert can_do([a], [a + S.Half, 2*a]) + assert can_do([a], [a + S.Half, 2*a + 1]) + assert can_do([a], [a + S.Half, 2*a - 1]) + assert can_do([S.Half], [b, 2 - b]) + assert can_do([S.Half], [b, 3 - b]) + assert can_do([1], [2, b]) + + assert can_do([a, a + S.Half], [2*a, b, 2*a - b + 1]) + assert can_do([a, a + S.Half], [S.Half, 2*a, 2*a + S.Half]) + assert can_do([a], [a + 1], lowerplane=True) # lowergamma + + +def test_prudnikov_1(): + # A. P. Prudnikov, Yu. A. Brychkov and O. I. Marichev (1990). + # Integrals and Series: More Special Functions, Vol. 3,. + # Gordon and Breach Science Publisher + + # 7.3.1 + assert can_do([a, -a], [S.Half]) + assert can_do([a, 1 - a], [S.Half]) + assert can_do([a, 1 - a], [Rational(3, 2)]) + assert can_do([a, 2 - a], [S.Half]) + assert can_do([a, 2 - a], [Rational(3, 2)]) + assert can_do([a, 2 - a], [Rational(3, 2)]) + assert can_do([a, a + S.Half], [2*a - 1]) + assert can_do([a, a + S.Half], [2*a]) + assert can_do([a, a + S.Half], [2*a + 1]) + assert can_do([a, a + S.Half], [S.Half]) + assert can_do([a, a + S.Half], [Rational(3, 2)]) + assert can_do([a, a/2 + 1], [a/2]) + assert can_do([1, b], [2]) + assert can_do([1, b], [b + 1], numerical=False) # Lerch Phi + # NOTE: branches are complicated for |z| > 1 + + assert can_do([a], [2*a]) + assert can_do([a], [2*a + 1]) + assert can_do([a], [2*a - 1]) + + +@slow +def test_prudnikov_2(): + h = S.Half + assert can_do([-h, -h], [h]) + assert can_do([-h, h], [3*h]) + assert can_do([-h, h], [5*h]) + assert can_do([-h, h], [7*h]) + assert can_do([-h, 1], [h]) + + for p in [-h, h]: + for n in [-h, h, 1, 3*h, 2, 5*h, 3, 7*h, 4]: + for m in [-h, h, 3*h, 5*h, 7*h]: + assert can_do([p, n], [m]) + for n in [1, 2, 3, 4]: + for m in [1, 2, 3, 4]: + assert can_do([p, n], [m]) + + +def test_prudnikov_3(): + h = S.Half + assert can_do([Rational(1, 4), Rational(3, 4)], [h]) + assert can_do([Rational(1, 4), Rational(3, 4)], [3*h]) + assert can_do([Rational(1, 3), Rational(2, 3)], [3*h]) + assert can_do([Rational(3, 4), Rational(5, 4)], [h]) + assert can_do([Rational(3, 4), Rational(5, 4)], [3*h]) + + +@tooslow +def test_prudnikov_3_slow(): + # XXX: This is marked as tooslow and hence skipped in CI. None of the + # individual cases below fails or hangs. Some cases are slow and the loops + # below generate 280 different cases. Is it really necessary to test all + # 280 cases here? + h = S.Half + for p in [1, 2, 3, 4]: + for n in [-h, h, 1, 3*h, 2, 5*h, 3, 7*h, 4, 9*h]: + for m in [1, 3*h, 2, 5*h, 3, 7*h, 4]: + assert can_do([p, m], [n]) + + +@slow +def test_prudnikov_4(): + h = S.Half + for p in [3*h, 5*h, 7*h]: + for n in [-h, h, 3*h, 5*h, 7*h]: + for m in [3*h, 2, 5*h, 3, 7*h, 4]: + assert can_do([p, m], [n]) + for n in [1, 2, 3, 4]: + for m in [2, 3, 4]: + assert can_do([p, m], [n]) + + +@slow +def test_prudnikov_5(): + h = S.Half + + for p in [1, 2, 3]: + for q in range(p, 4): + for r in [1, 2, 3]: + for s in range(r, 4): + assert can_do([-h, p, q], [r, s]) + + for p in [h, 1, 3*h, 2, 5*h, 3]: + for q in [h, 3*h, 5*h]: + for r in [h, 3*h, 5*h]: + for s in [h, 3*h, 5*h]: + if s <= q and s <= r: + assert can_do([-h, p, q], [r, s]) + + for p in [h, 1, 3*h, 2, 5*h, 3]: + for q in [1, 2, 3]: + for r in [h, 3*h, 5*h]: + for s in [1, 2, 3]: + assert can_do([-h, p, q], [r, s]) + + +@slow +def test_prudnikov_6(): + h = S.Half + + for m in [3*h, 5*h]: + for n in [1, 2, 3]: + for q in [h, 1, 2]: + for p in [1, 2, 3]: + assert can_do([h, q, p], [m, n]) + for q in [1, 2, 3]: + for p in [3*h, 5*h]: + assert can_do([h, q, p], [m, n]) + + for q in [1, 2]: + for p in [1, 2, 3]: + for m in [1, 2, 3]: + for n in [1, 2, 3]: + assert can_do([h, q, p], [m, n]) + + assert can_do([h, h, 5*h], [3*h, 3*h]) + assert can_do([h, 1, 5*h], [3*h, 3*h]) + assert can_do([h, 2, 2], [1, 3]) + + # pages 435 to 457 contain more PFDD and stuff like this + + +@slow +def test_prudnikov_7(): + assert can_do([3], [6]) + + h = S.Half + for n in [h, 3*h, 5*h, 7*h]: + assert can_do([-h], [n]) + for m in [-h, h, 1, 3*h, 2, 5*h, 3, 7*h, 4]: # HERE + for n in [-h, h, 3*h, 5*h, 7*h, 1, 2, 3, 4]: + assert can_do([m], [n]) + + +@slow +def test_prudnikov_8(): + h = S.Half + + # 7.12.2 + for ai in [1, 2, 3]: + for bi in [1, 2, 3]: + for ci in range(1, ai + 1): + for di in [h, 1, 3*h, 2, 5*h, 3]: + assert can_do([ai, bi], [ci, di]) + for bi in [3*h, 5*h]: + for ci in [h, 1, 3*h, 2, 5*h, 3]: + for di in [1, 2, 3]: + assert can_do([ai, bi], [ci, di]) + + for ai in [-h, h, 3*h, 5*h]: + for bi in [1, 2, 3]: + for ci in [h, 1, 3*h, 2, 5*h, 3]: + for di in [1, 2, 3]: + assert can_do([ai, bi], [ci, di]) + for bi in [h, 3*h, 5*h]: + for ci in [h, 3*h, 5*h, 3]: + for di in [h, 1, 3*h, 2, 5*h, 3]: + if ci <= bi: + assert can_do([ai, bi], [ci, di]) + + +def test_prudnikov_9(): + # 7.13.1 [we have a general formula ... so this is a bit pointless] + for i in range(9): + assert can_do([], [(S(i) + 1)/2]) + for i in range(5): + assert can_do([], [-(2*S(i) + 1)/2]) + + +@slow +def test_prudnikov_10(): + # 7.14.2 + h = S.Half + for p in [-h, h, 1, 3*h, 2, 5*h, 3, 7*h, 4]: + for m in [1, 2, 3, 4]: + for n in range(m, 5): + assert can_do([p], [m, n]) + + for p in [1, 2, 3, 4]: + for n in [h, 3*h, 5*h, 7*h]: + for m in [1, 2, 3, 4]: + assert can_do([p], [n, m]) + + for p in [3*h, 5*h, 7*h]: + for m in [h, 1, 2, 5*h, 3, 7*h, 4]: + assert can_do([p], [h, m]) + assert can_do([p], [3*h, m]) + + for m in [h, 1, 2, 5*h, 3, 7*h, 4]: + assert can_do([7*h], [5*h, m]) + + assert can_do([Rational(-1, 2)], [S.Half, S.Half]) # shine-integral shi + + +def test_prudnikov_11(): + # 7.15 + assert can_do([a, a + S.Half], [2*a, b, 2*a - b]) + assert can_do([a, a + S.Half], [Rational(3, 2), 2*a, 2*a - S.Half]) + + assert can_do([Rational(1, 4), Rational(3, 4)], [S.Half, S.Half, 1]) + assert can_do([Rational(5, 4), Rational(3, 4)], [Rational(3, 2), S.Half, 2]) + assert can_do([Rational(5, 4), Rational(3, 4)], [Rational(3, 2), Rational(3, 2), 1]) + assert can_do([Rational(5, 4), Rational(7, 4)], [Rational(3, 2), Rational(5, 2), 2]) + + assert can_do([1, 1], [Rational(3, 2), 2, 2]) # cosh-integral chi + + +def test_prudnikov_12(): + # 7.16 + assert can_do( + [], [a, a + S.Half, 2*a], False) # branches only agree for some z! + assert can_do([], [a, a + S.Half, 2*a + 1], False) # dito + assert can_do([], [S.Half, a, a + S.Half]) + assert can_do([], [Rational(3, 2), a, a + S.Half]) + + assert can_do([], [Rational(1, 4), S.Half, Rational(3, 4)]) + assert can_do([], [S.Half, S.Half, 1]) + assert can_do([], [S.Half, Rational(3, 2), 1]) + assert can_do([], [Rational(3, 4), Rational(3, 2), Rational(5, 4)]) + assert can_do([], [1, 1, Rational(3, 2)]) + assert can_do([], [1, 2, Rational(3, 2)]) + assert can_do([], [1, Rational(3, 2), Rational(3, 2)]) + assert can_do([], [Rational(5, 4), Rational(3, 2), Rational(7, 4)]) + assert can_do([], [2, Rational(3, 2), Rational(3, 2)]) + + +@slow +def test_prudnikov_2F1(): + h = S.Half + # Elliptic integrals + for p in [-h, h]: + for m in [h, 3*h, 5*h, 7*h]: + for n in [1, 2, 3, 4]: + assert can_do([p, m], [n]) + + +@XFAIL +def test_prudnikov_fail_2F1(): + assert can_do([a, b], [b + 1]) # incomplete beta function + assert can_do([-1, b], [c]) # Poly. also -2, -3 etc + + # TODO polys + + # Legendre functions: + assert can_do([a, b], [a + b + S.Half]) + assert can_do([a, b], [a + b - S.Half]) + assert can_do([a, b], [a + b + Rational(3, 2)]) + assert can_do([a, b], [(a + b + 1)/2]) + assert can_do([a, b], [(a + b)/2 + 1]) + assert can_do([a, b], [a - b + 1]) + assert can_do([a, b], [a - b + 2]) + assert can_do([a, b], [2*b]) + assert can_do([a, b], [S.Half]) + assert can_do([a, b], [Rational(3, 2)]) + assert can_do([a, 1 - a], [c]) + assert can_do([a, 2 - a], [c]) + assert can_do([a, 3 - a], [c]) + assert can_do([a, a + S.Half], [c]) + assert can_do([1, b], [c]) + assert can_do([1, b], [Rational(3, 2)]) + + assert can_do([Rational(1, 4), Rational(3, 4)], [1]) + + # PFDD + o = S.One + assert can_do([o/8, 1], [o/8*9]) + assert can_do([o/6, 1], [o/6*7]) + assert can_do([o/6, 1], [o/6*13]) + assert can_do([o/5, 1], [o/5*6]) + assert can_do([o/5, 1], [o/5*11]) + assert can_do([o/4, 1], [o/4*5]) + assert can_do([o/4, 1], [o/4*9]) + assert can_do([o/3, 1], [o/3*4]) + assert can_do([o/3, 1], [o/3*7]) + assert can_do([o/8*3, 1], [o/8*11]) + assert can_do([o/5*2, 1], [o/5*7]) + assert can_do([o/5*2, 1], [o/5*12]) + assert can_do([o/5*3, 1], [o/5*8]) + assert can_do([o/5*3, 1], [o/5*13]) + assert can_do([o/8*5, 1], [o/8*13]) + assert can_do([o/4*3, 1], [o/4*7]) + assert can_do([o/4*3, 1], [o/4*11]) + assert can_do([o/3*2, 1], [o/3*5]) + assert can_do([o/3*2, 1], [o/3*8]) + assert can_do([o/5*4, 1], [o/5*9]) + assert can_do([o/5*4, 1], [o/5*14]) + assert can_do([o/6*5, 1], [o/6*11]) + assert can_do([o/6*5, 1], [o/6*17]) + assert can_do([o/8*7, 1], [o/8*15]) + + +@XFAIL +def test_prudnikov_fail_3F2(): + assert can_do([a, a + Rational(1, 3), a + Rational(2, 3)], [Rational(1, 3), Rational(2, 3)]) + assert can_do([a, a + Rational(1, 3), a + Rational(2, 3)], [Rational(2, 3), Rational(4, 3)]) + assert can_do([a, a + Rational(1, 3), a + Rational(2, 3)], [Rational(4, 3), Rational(5, 3)]) + + # page 421 + assert can_do([a, a + Rational(1, 3), a + Rational(2, 3)], [a*Rational(3, 2), (3*a + 1)/2]) + + # pages 422 ... + assert can_do([Rational(-1, 2), S.Half, S.Half], [1, 1]) # elliptic integrals + assert can_do([Rational(-1, 2), S.Half, 1], [Rational(3, 2), Rational(3, 2)]) + # TODO LOTS more + + # PFDD + assert can_do([Rational(1, 8), Rational(3, 8), 1], [Rational(9, 8), Rational(11, 8)]) + assert can_do([Rational(1, 8), Rational(5, 8), 1], [Rational(9, 8), Rational(13, 8)]) + assert can_do([Rational(1, 8), Rational(7, 8), 1], [Rational(9, 8), Rational(15, 8)]) + assert can_do([Rational(1, 6), Rational(1, 3), 1], [Rational(7, 6), Rational(4, 3)]) + assert can_do([Rational(1, 6), Rational(2, 3), 1], [Rational(7, 6), Rational(5, 3)]) + assert can_do([Rational(1, 6), Rational(2, 3), 1], [Rational(5, 3), Rational(13, 6)]) + assert can_do([S.Half, 1, 1], [Rational(1, 4), Rational(3, 4)]) + # LOTS more + + +@XFAIL +def test_prudnikov_fail_other(): + # 7.11.2 + + # 7.12.1 + assert can_do([1, a], [b, 1 - 2*a + b]) # ??? + + # 7.14.2 + assert can_do([Rational(-1, 2)], [S.Half, 1]) # struve + assert can_do([1], [S.Half, S.Half]) # struve + assert can_do([Rational(1, 4)], [S.Half, Rational(5, 4)]) # PFDD + assert can_do([Rational(3, 4)], [Rational(3, 2), Rational(7, 4)]) # PFDD + assert can_do([1], [Rational(1, 4), Rational(3, 4)]) # PFDD + assert can_do([1], [Rational(3, 4), Rational(5, 4)]) # PFDD + assert can_do([1], [Rational(5, 4), Rational(7, 4)]) # PFDD + # TODO LOTS more + + # 7.15.2 + assert can_do([S.Half, 1], [Rational(3, 4), Rational(5, 4), Rational(3, 2)]) # PFDD + assert can_do([S.Half, 1], [Rational(7, 4), Rational(5, 4), Rational(3, 2)]) # PFDD + + # 7.16.1 + assert can_do([], [Rational(1, 3), S(2/3)]) # PFDD + assert can_do([], [Rational(2, 3), S(4/3)]) # PFDD + assert can_do([], [Rational(5, 3), S(4/3)]) # PFDD + + # XXX this does not *evaluate* right?? + assert can_do([], [a, a + S.Half, 2*a - 1]) + + +def test_bug(): + h = hyper([-1, 1], [z], -1) + assert hyperexpand(h) == (z + 1)/z + + +def test_omgissue_203(): + h = hyper((-5, -3, -4), (-6, -6), 1) + assert hyperexpand(h) == Rational(1, 30) + h = hyper((-6, -7, -5), (-6, -6), 1) + assert hyperexpand(h) == Rational(-1, 6) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_powsimp.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_powsimp.py new file mode 100644 index 0000000000000000000000000000000000000000..61bdc93d052baf4b1e80da8f5864cf22b8fa383e --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_powsimp.py @@ -0,0 +1,368 @@ +from sympy.core.function import Function +from sympy.core.mul import Mul +from sympy.core.numbers import (E, I, Rational, oo, pi) +from sympy.core.singleton import S +from sympy.core.symbol import (Dummy, Symbol, symbols) +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.miscellaneous import (root, sqrt) +from sympy.functions.elementary.trigonometric import sin +from sympy.functions.special.gamma_functions import gamma +from sympy.functions.special.hyper import hyper +from sympy.matrices.expressions.matexpr import MatrixSymbol +from sympy.simplify.powsimp import (powdenest, powsimp) +from sympy.simplify.simplify import (signsimp, simplify) +from sympy.core.symbol import Str + +from sympy.abc import x, y, z, a, b + + +def test_powsimp(): + x, y, z, n = symbols('x,y,z,n') + f = Function('f') + assert powsimp( 4**x * 2**(-x) * 2**(-x) ) == 1 + assert powsimp( (-4)**x * (-2)**(-x) * 2**(-x) ) == 1 + + assert powsimp( + f(4**x * 2**(-x) * 2**(-x)) ) == f(4**x * 2**(-x) * 2**(-x)) + assert powsimp( f(4**x * 2**(-x) * 2**(-x)), deep=True ) == f(1) + assert exp(x)*exp(y) == exp(x)*exp(y) + assert powsimp(exp(x)*exp(y)) == exp(x + y) + assert powsimp(exp(x)*exp(y)*2**x*2**y) == (2*E)**(x + y) + assert powsimp(exp(x)*exp(y)*2**x*2**y, combine='exp') == \ + exp(x + y)*2**(x + y) + assert powsimp(exp(x)*exp(y)*exp(2)*sin(x) + sin(y) + 2**x*2**y) == \ + exp(2 + x + y)*sin(x) + sin(y) + 2**(x + y) + assert powsimp(sin(exp(x)*exp(y))) == sin(exp(x)*exp(y)) + assert powsimp(sin(exp(x)*exp(y)), deep=True) == sin(exp(x + y)) + assert powsimp(x**2*x**y) == x**(2 + y) + # This should remain factored, because 'exp' with deep=True is supposed + # to act like old automatic exponent combining. + assert powsimp((1 + E*exp(E))*exp(-E), combine='exp', deep=True) == \ + (1 + exp(1 + E))*exp(-E) + assert powsimp((1 + E*exp(E))*exp(-E), deep=True) == \ + (1 + exp(1 + E))*exp(-E) + assert powsimp((1 + E*exp(E))*exp(-E)) == (1 + exp(1 + E))*exp(-E) + assert powsimp((1 + E*exp(E))*exp(-E), combine='exp') == \ + (1 + exp(1 + E))*exp(-E) + assert powsimp((1 + E*exp(E))*exp(-E), combine='base') == \ + (1 + E*exp(E))*exp(-E) + x, y = symbols('x,y', nonnegative=True) + n = Symbol('n', real=True) + assert powsimp(y**n * (y/x)**(-n)) == x**n + assert powsimp(x**(x**(x*y)*y**(x*y))*y**(x**(x*y)*y**(x*y)), deep=True) \ + == (x*y)**(x*y)**(x*y) + assert powsimp(2**(2**(2*x)*x), deep=False) == 2**(2**(2*x)*x) + assert powsimp(2**(2**(2*x)*x), deep=True) == 2**(x*4**x) + assert powsimp( + exp(-x + exp(-x)*exp(-x*log(x))), deep=False, combine='exp') == \ + exp(-x + exp(-x)*exp(-x*log(x))) + assert powsimp( + exp(-x + exp(-x)*exp(-x*log(x))), deep=False, combine='exp') == \ + exp(-x + exp(-x)*exp(-x*log(x))) + assert powsimp((x + y)/(3*z), deep=False, combine='exp') == (x + y)/(3*z) + assert powsimp((x/3 + y/3)/z, deep=True, combine='exp') == (x/3 + y/3)/z + assert powsimp(exp(x)/(1 + exp(x)*exp(y)), deep=True) == \ + exp(x)/(1 + exp(x + y)) + assert powsimp(x*y**(z**x*z**y), deep=True) == x*y**(z**(x + y)) + assert powsimp((z**x*z**y)**x, deep=True) == (z**(x + y))**x + assert powsimp(x*(z**x*z**y)**x, deep=True) == x*(z**(x + y))**x + p = symbols('p', positive=True) + assert powsimp((1/x)**log(2)/x) == (1/x)**(1 + log(2)) + assert powsimp((1/p)**log(2)/p) == p**(-1 - log(2)) + + # coefficient of exponent can only be simplified for positive bases + assert powsimp(2**(2*x)) == 4**x + assert powsimp((-1)**(2*x)) == (-1)**(2*x) + i = symbols('i', integer=True) + assert powsimp((-1)**(2*i)) == 1 + assert powsimp((-1)**(-x)) != (-1)**x # could be 1/((-1)**x), but is not + # force=True overrides assumptions + assert powsimp((-1)**(2*x), force=True) == 1 + + # rational exponents allow combining of negative terms + w, n, m = symbols('w n m', negative=True) + e = i/a # not a rational exponent if `a` is unknown + ex = w**e*n**e*m**e + assert powsimp(ex) == m**(i/a)*n**(i/a)*w**(i/a) + e = i/3 + ex = w**e*n**e*m**e + assert powsimp(ex) == (-1)**i*(-m*n*w)**(i/3) + e = (3 + i)/i + ex = w**e*n**e*m**e + assert powsimp(ex) == (-1)**(3*e)*(-m*n*w)**e + + eq = x**(a*Rational(2, 3)) + # eq != (x**a)**(2/3) (try x = -1 and a = 3 to see) + assert powsimp(eq).exp == eq.exp == a*Rational(2, 3) + # powdenest goes the other direction + assert powsimp(2**(2*x)) == 4**x + + assert powsimp(exp(p/2)) == exp(p/2) + + # issue 6368 + eq = Mul(*[sqrt(Dummy(imaginary=True)) for i in range(3)]) + assert powsimp(eq) == eq and eq.is_Mul + + assert all(powsimp(e) == e for e in (sqrt(x**a), sqrt(x**2))) + + # issue 8836 + assert str( powsimp(exp(I*pi/3)*root(-1,3)) ) == '(-1)**(2/3)' + + # issue 9183 + assert powsimp(-0.1**x) == -0.1**x + + # issue 10095 + assert powsimp((1/(2*E))**oo) == (exp(-1)/2)**oo + + # PR 13131 + eq = sin(2*x)**2*sin(2.0*x)**2 + assert powsimp(eq) == eq + + # issue 14615 + assert powsimp(x**2*y**3*(x*y**2)**Rational(3, 2) + ) == x*y*(x*y**2)**Rational(5, 2) + + #issue 27380 + assert powsimp(1.0**(x+1)/1.0**x) == 1.0 + +def test_powsimp_negated_base(): + assert powsimp((-x + y)/sqrt(x - y)) == -sqrt(x - y) + assert powsimp((-x + y)*(-z + y)/sqrt(x - y)/sqrt(z - y)) == sqrt(x - y)*sqrt(z - y) + p = symbols('p', positive=True) + reps = {p: 2, a: S.Half} + assert powsimp((-p)**a/p**a).subs(reps) == ((-1)**a).subs(reps) + assert powsimp((-p)**a*p**a).subs(reps) == ((-p**2)**a).subs(reps) + n = symbols('n', negative=True) + reps = {p: -2, a: S.Half} + assert powsimp((-n)**a/n**a).subs(reps) == (-1)**(-a).subs(a, S.Half) + assert powsimp((-n)**a*n**a).subs(reps) == ((-n**2)**a).subs(reps) + # if x is 0 then the lhs is 0**a*oo**a which is not (-1)**a + eq = (-x)**a/x**a + assert powsimp(eq) == eq + + +def test_powsimp_nc(): + x, y, z = symbols('x,y,z') + A, B, C = symbols('A B C', commutative=False) + + assert powsimp(A**x*A**y, combine='all') == A**(x + y) + assert powsimp(A**x*A**y, combine='base') == A**x*A**y + assert powsimp(A**x*A**y, combine='exp') == A**(x + y) + + assert powsimp(A**x*B**x, combine='all') == A**x*B**x + assert powsimp(A**x*B**x, combine='base') == A**x*B**x + assert powsimp(A**x*B**x, combine='exp') == A**x*B**x + + assert powsimp(B**x*A**x, combine='all') == B**x*A**x + assert powsimp(B**x*A**x, combine='base') == B**x*A**x + assert powsimp(B**x*A**x, combine='exp') == B**x*A**x + + assert powsimp(A**x*A**y*A**z, combine='all') == A**(x + y + z) + assert powsimp(A**x*A**y*A**z, combine='base') == A**x*A**y*A**z + assert powsimp(A**x*A**y*A**z, combine='exp') == A**(x + y + z) + + assert powsimp(A**x*B**x*C**x, combine='all') == A**x*B**x*C**x + assert powsimp(A**x*B**x*C**x, combine='base') == A**x*B**x*C**x + assert powsimp(A**x*B**x*C**x, combine='exp') == A**x*B**x*C**x + + assert powsimp(B**x*A**x*C**x, combine='all') == B**x*A**x*C**x + assert powsimp(B**x*A**x*C**x, combine='base') == B**x*A**x*C**x + assert powsimp(B**x*A**x*C**x, combine='exp') == B**x*A**x*C**x + + +def test_issue_6440(): + assert powsimp(16*2**a*8**b) == 2**(a + 3*b + 4) + + +def test_powdenest(): + x, y = symbols('x,y') + p, q = symbols('p q', positive=True) + i, j = symbols('i,j', integer=True) + + assert powdenest(x) == x + assert powdenest(x + 2*(x**(a*Rational(2, 3)))**(3*x)) == (x + 2*(x**(a*Rational(2, 3)))**(3*x)) + assert powdenest((exp(a*Rational(2, 3)))**(3*x)) # -X-> (exp(a/3))**(6*x) + assert powdenest((x**(a*Rational(2, 3)))**(3*x)) == ((x**(a*Rational(2, 3)))**(3*x)) + assert powdenest(exp(3*x*log(2))) == 2**(3*x) + assert powdenest(sqrt(p**2)) == p + eq = p**(2*i)*q**(4*i) + assert powdenest(eq) == (p*q**2)**(2*i) + # -X-> (x**x)**i*(x**x)**j == x**(x*(i + j)) + assert powdenest((x**x)**(i + j)) + assert powdenest(exp(3*y*log(x))) == x**(3*y) + assert powdenest(exp(y*(log(a) + log(b)))) == (a*b)**y + assert powdenest(exp(3*(log(a) + log(b)))) == a**3*b**3 + assert powdenest(((x**(2*i))**(3*y))**x) == ((x**(2*i))**(3*y))**x + assert powdenest(((x**(2*i))**(3*y))**x, force=True) == x**(6*i*x*y) + assert powdenest(((x**(a*Rational(2, 3)))**(3*y/i))**x) == \ + (((x**(a*Rational(2, 3)))**(3*y/i))**x) + assert powdenest((x**(2*i)*y**(4*i))**z, force=True) == (x*y**2)**(2*i*z) + assert powdenest((p**(2*i)*q**(4*i))**j) == (p*q**2)**(2*i*j) + e = ((p**(2*a))**(3*y))**x + assert powdenest(e) == e + e = ((x**2*y**4)**a)**(x*y) + assert powdenest(e) == e + e = (((x**2*y**4)**a)**(x*y))**3 + assert powdenest(e) == ((x**2*y**4)**a)**(3*x*y) + assert powdenest((((x**2*y**4)**a)**(x*y)), force=True) == \ + (x*y**2)**(2*a*x*y) + assert powdenest((((x**2*y**4)**a)**(x*y))**3, force=True) == \ + (x*y**2)**(6*a*x*y) + assert powdenest((x**2*y**6)**i) != (x*y**3)**(2*i) + x, y = symbols('x,y', positive=True) + assert powdenest((x**2*y**6)**i) == (x*y**3)**(2*i) + + assert powdenest((x**(i*Rational(2, 3))*y**(i/2))**(2*i)) == (x**Rational(4, 3)*y)**(i**2) + assert powdenest(sqrt(x**(2*i)*y**(6*i))) == (x*y**3)**i + + assert powdenest(4**x) == 2**(2*x) + assert powdenest((4**x)**y) == 2**(2*x*y) + assert powdenest(4**x*y) == 2**(2*x)*y + + +def test_powdenest_polar(): + x, y, z = symbols('x y z', polar=True) + a, b, c = symbols('a b c') + assert powdenest((x*y*z)**a) == x**a*y**a*z**a + assert powdenest((x**a*y**b)**c) == x**(a*c)*y**(b*c) + assert powdenest(((x**a)**b*y**c)**c) == x**(a*b*c)*y**(c**2) + + +def test_issue_5805(): + arg = ((gamma(x)*hyper((), (), x))*pi)**2 + assert powdenest(arg) == (pi*gamma(x)*hyper((), (), x))**2 + assert arg.is_positive is None + + +def test_issue_9324_powsimp_on_matrix_symbol(): + M = MatrixSymbol('M', 10, 10) + expr = powsimp(M, deep=True) + assert expr == M + assert expr.args[0] == Str('M') + + +def test_issue_6367(): + z = -5*sqrt(2)/(2*sqrt(2*sqrt(29) + 29)) + sqrt(-sqrt(29)/29 + S.Half) + assert Mul(*[powsimp(a) for a in Mul.make_args(z.normal())]) == 0 + assert powsimp(z.normal()) == 0 + assert simplify(z) == 0 + assert powsimp(sqrt(2 + sqrt(3))*sqrt(2 - sqrt(3)) + 1) == 2 + assert powsimp(z) != 0 + + +def test_powsimp_polar(): + from sympy.functions.elementary.complexes import polar_lift + from sympy.functions.elementary.exponential import exp_polar + x, y, z = symbols('x y z') + p, q, r = symbols('p q r', polar=True) + + assert (polar_lift(-1))**(2*x) == exp_polar(2*pi*I*x) + assert powsimp(p**x * q**x) == (p*q)**x + assert p**x * (1/p)**x == 1 + assert (1/p)**x == p**(-x) + + assert exp_polar(x)*exp_polar(y) == exp_polar(x)*exp_polar(y) + assert powsimp(exp_polar(x)*exp_polar(y)) == exp_polar(x + y) + assert powsimp(exp_polar(x)*exp_polar(y)*p**x*p**y) == \ + (p*exp_polar(1))**(x + y) + assert powsimp(exp_polar(x)*exp_polar(y)*p**x*p**y, combine='exp') == \ + exp_polar(x + y)*p**(x + y) + assert powsimp( + exp_polar(x)*exp_polar(y)*exp_polar(2)*sin(x) + sin(y) + p**x*p**y) \ + == p**(x + y) + sin(x)*exp_polar(2 + x + y) + sin(y) + assert powsimp(sin(exp_polar(x)*exp_polar(y))) == \ + sin(exp_polar(x)*exp_polar(y)) + assert powsimp(sin(exp_polar(x)*exp_polar(y)), deep=True) == \ + sin(exp_polar(x + y)) + + +def test_issue_5728(): + b = x*sqrt(y) + a = sqrt(b) + c = sqrt(sqrt(x)*y) + assert powsimp(a*b) == sqrt(b)**3 + assert powsimp(a*b**2*sqrt(y)) == sqrt(y)*a**5 + assert powsimp(a*x**2*c**3*y) == c**3*a**5 + assert powsimp(a*x*c**3*y**2) == c**7*a + assert powsimp(x*c**3*y**2) == c**7 + assert powsimp(x*c**3*y) == x*y*c**3 + assert powsimp(sqrt(x)*c**3*y) == c**5 + assert powsimp(sqrt(x)*a**3*sqrt(y)) == sqrt(x)*sqrt(y)*a**3 + assert powsimp(Mul(sqrt(x)*c**3*sqrt(y), y, evaluate=False)) == \ + sqrt(x)*sqrt(y)**3*c**3 + assert powsimp(a**2*a*x**2*y) == a**7 + + # symbolic powers work, too + b = x**y*y + a = b*sqrt(b) + assert a.is_Mul is True + assert powsimp(a) == sqrt(b)**3 + + # as does exp + a = x*exp(y*Rational(2, 3)) + assert powsimp(a*sqrt(a)) == sqrt(a)**3 + assert powsimp(a**2*sqrt(a)) == sqrt(a)**5 + assert powsimp(a**2*sqrt(sqrt(a))) == sqrt(sqrt(a))**9 + + +def test_issue_from_PR1599(): + n1, n2, n3, n4 = symbols('n1 n2 n3 n4', negative=True) + assert (powsimp(sqrt(n1)*sqrt(n2)*sqrt(n3)) == + -I*sqrt(-n1)*sqrt(-n2)*sqrt(-n3)) + assert (powsimp(root(n1, 3)*root(n2, 3)*root(n3, 3)*root(n4, 3)) == + -(-1)**Rational(1, 3)* + (-n1)**Rational(1, 3)*(-n2)**Rational(1, 3)*(-n3)**Rational(1, 3)*(-n4)**Rational(1, 3)) + + +def test_issue_10195(): + a = Symbol('a', integer=True) + l = Symbol('l', even=True, nonzero=True) + n = Symbol('n', odd=True) + e_x = (-1)**(n/2 - S.Half) - (-1)**(n*Rational(3, 2) - S.Half) + assert powsimp((-1)**(l/2)) == I**l + assert powsimp((-1)**(n/2)) == I**n + assert powsimp((-1)**(n*Rational(3, 2))) == -I**n + assert powsimp(e_x) == (-1)**(n/2 - S.Half) + (-1)**(n*Rational(3, 2) + + S.Half) + assert powsimp((-1)**(a*Rational(3, 2))) == (-I)**a + +def test_issue_15709(): + assert powsimp(3**x*Rational(2, 3)) == 2*3**(x-1) + assert powsimp(2*3**x/3) == 2*3**(x-1) + + +def test_issue_11981(): + x, y = symbols('x y', commutative=False) + assert powsimp((x*y)**2 * (y*x)**2) == (x*y)**2 * (y*x)**2 + + +def test_issue_17524(): + a = symbols("a", real=True) + e = (-1 - a**2)*sqrt(1 + a**2) + assert signsimp(powsimp(e)) == signsimp(e) == -(a**2 + 1)**(S(3)/2) + + +def test_issue_19627(): + # if you use force the user must verify + assert powdenest(sqrt(sin(x)**2), force=True) == sin(x) + assert powdenest((x**(S.Half/y))**(2*y), force=True) == x + from sympy.core.function import expand_power_base + e = 1 - a + expr = (exp(z/e)*x**(b/e)*y**((1 - b)/e))**e + assert powdenest(expand_power_base(expr, force=True), force=True + ) == x**b*y**(1 - b)*exp(z) + + +def test_issue_22546(): + p1, p2 = symbols('p1, p2', positive=True) + ref = powsimp(p1**z/p2**z) + e = z + 1 + ans = ref.subs(z, e) + assert ans.is_Pow + assert powsimp(p1**e/p2**e) == ans + i = symbols('i', integer=True) + ref = powsimp(x**i/y**i) + e = i + 1 + ans = ref.subs(i, e) + assert ans.is_Pow + assert powsimp(x**e/y**e) == ans diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_radsimp.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_radsimp.py new file mode 100644 index 0000000000000000000000000000000000000000..f8ff955e48a34536c1752c565c0864dedae6a214 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_radsimp.py @@ -0,0 +1,498 @@ +from sympy.core.add import Add +from sympy.core.function import (Derivative, Function, diff) +from sympy.core.mul import Mul +from sympy.core.numbers import (I, Rational) +from sympy.core.power import Pow +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, Wild, symbols) +from sympy.functions.elementary.complexes import Abs +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.miscellaneous import (root, sqrt) +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.polys.polytools import factor +from sympy.series.order import O +from sympy.simplify.radsimp import (collect, collect_const, fraction, radsimp, rcollect) + +from sympy.core.expr import unchanged +from sympy.core.mul import _unevaluated_Mul as umul +from sympy.simplify.radsimp import (_unevaluated_Add, + collect_sqrt, fraction_expand, collect_abs) +from sympy.testing.pytest import raises + +from sympy.abc import x, y, z, a, b, c, d + + +def test_radsimp(): + r2 = sqrt(2) + r3 = sqrt(3) + r5 = sqrt(5) + r7 = sqrt(7) + assert fraction(radsimp(1/r2)) == (sqrt(2), 2) + assert radsimp(1/(1 + r2)) == \ + -1 + sqrt(2) + assert radsimp(1/(r2 + r3)) == \ + -sqrt(2) + sqrt(3) + assert fraction(radsimp(1/(1 + r2 + r3))) == \ + (-sqrt(6) + sqrt(2) + 2, 4) + assert fraction(radsimp(1/(r2 + r3 + r5))) == \ + (-sqrt(30) + 2*sqrt(3) + 3*sqrt(2), 12) + assert fraction(radsimp(1/(1 + r2 + r3 + r5))) == ( + (-34*sqrt(10) - 26*sqrt(15) - 55*sqrt(3) - 61*sqrt(2) + 14*sqrt(30) + + 93 + 46*sqrt(6) + 53*sqrt(5), 71)) + assert fraction(radsimp(1/(r2 + r3 + r5 + r7))) == ( + (-50*sqrt(42) - 133*sqrt(5) - 34*sqrt(70) - 145*sqrt(3) + 22*sqrt(105) + + 185*sqrt(2) + 62*sqrt(30) + 135*sqrt(7), 215)) + z = radsimp(1/(1 + r2/3 + r3/5 + r5 + r7)) + assert len((3616791619821680643598*z).args) == 16 + assert radsimp(1/z) == 1/z + assert radsimp(1/z, max_terms=20).expand() == 1 + r2/3 + r3/5 + r5 + r7 + assert radsimp(1/(r2*3)) == \ + sqrt(2)/6 + assert radsimp(1/(r2*a + r3 + r5 + r7)) == ( + (8*sqrt(2)*a**7 - 8*sqrt(7)*a**6 - 8*sqrt(5)*a**6 - 8*sqrt(3)*a**6 - + 180*sqrt(2)*a**5 + 8*sqrt(30)*a**5 + 8*sqrt(42)*a**5 + 8*sqrt(70)*a**5 + - 24*sqrt(105)*a**4 + 84*sqrt(3)*a**4 + 100*sqrt(5)*a**4 + + 116*sqrt(7)*a**4 - 72*sqrt(70)*a**3 - 40*sqrt(42)*a**3 - + 8*sqrt(30)*a**3 + 782*sqrt(2)*a**3 - 462*sqrt(3)*a**2 - + 302*sqrt(7)*a**2 - 254*sqrt(5)*a**2 + 120*sqrt(105)*a**2 - + 795*sqrt(2)*a - 62*sqrt(30)*a + 82*sqrt(42)*a + 98*sqrt(70)*a - + 118*sqrt(105) + 59*sqrt(7) + 295*sqrt(5) + 531*sqrt(3))/(16*a**8 - + 480*a**6 + 3128*a**4 - 6360*a**2 + 3481)) + assert radsimp(1/(r2*a + r2*b + r3 + r7)) == ( + (sqrt(2)*a*(a + b)**2 - 5*sqrt(2)*a + sqrt(42)*a + sqrt(2)*b*(a + + b)**2 - 5*sqrt(2)*b + sqrt(42)*b - sqrt(7)*(a + b)**2 - sqrt(3)*(a + + b)**2 - 2*sqrt(3) + 2*sqrt(7))/(2*a**4 + 8*a**3*b + 12*a**2*b**2 - + 20*a**2 + 8*a*b**3 - 40*a*b + 2*b**4 - 20*b**2 + 8)) + assert radsimp(1/(r2*a + r2*b + r2*c + r2*d)) == \ + sqrt(2)/(2*a + 2*b + 2*c + 2*d) + assert radsimp(1/(1 + r2*a + r2*b + r2*c + r2*d)) == ( + (sqrt(2)*a + sqrt(2)*b + sqrt(2)*c + sqrt(2)*d - 1)/(2*a**2 + 4*a*b + + 4*a*c + 4*a*d + 2*b**2 + 4*b*c + 4*b*d + 2*c**2 + 4*c*d + 2*d**2 - 1)) + assert radsimp((y**2 - x)/(y - sqrt(x))) == \ + sqrt(x) + y + assert radsimp(-(y**2 - x)/(y - sqrt(x))) == \ + -(sqrt(x) + y) + assert radsimp(1/(1 - I + a*I)) == \ + (-I*a + 1 + I)/(a**2 - 2*a + 2) + assert radsimp(1/((-x + y)*(x - sqrt(y)))) == \ + (-x - sqrt(y))/((x - y)*(x**2 - y)) + e = (3 + 3*sqrt(2))*x*(3*x - 3*sqrt(y)) + assert radsimp(e) == x*(3 + 3*sqrt(2))*(3*x - 3*sqrt(y)) + assert radsimp(1/e) == ( + (-9*x + 9*sqrt(2)*x - 9*sqrt(y) + 9*sqrt(2)*sqrt(y))/(9*x*(9*x**2 - + 9*y))) + assert radsimp(1 + 1/(1 + sqrt(3))) == \ + Mul(S.Half, -1 + sqrt(3), evaluate=False) + 1 + A = symbols("A", commutative=False) + assert radsimp(x**2 + sqrt(2)*x**2 - sqrt(2)*x*A) == \ + x**2 + sqrt(2)*x**2 - sqrt(2)*x*A + assert radsimp(1/sqrt(5 + 2 * sqrt(6))) == -sqrt(2) + sqrt(3) + assert radsimp(1/sqrt(5 + 2 * sqrt(6))**3) == -(-sqrt(3) + sqrt(2))**3 + + # issue 6532 + assert fraction(radsimp(1/sqrt(x))) == (sqrt(x), x) + assert fraction(radsimp(1/sqrt(2*x + 3))) == (sqrt(2*x + 3), 2*x + 3) + assert fraction(radsimp(1/sqrt(2*(x + 3)))) == (sqrt(2*x + 6), 2*x + 6) + + # issue 5994 + e = S('-(2 + 2*sqrt(2) + 4*2**(1/4))/' + '(1 + 2**(3/4) + 3*2**(1/4) + 3*sqrt(2))') + assert radsimp(e).expand() == -2*2**Rational(3, 4) - 2*2**Rational(1, 4) + 2 + 2*sqrt(2) + + # issue 5986 (modifications to radimp didn't initially recognize this so + # the test is included here) + assert radsimp(1/(-sqrt(5)/2 - S.Half + (-sqrt(5)/2 - S.Half)**2)) == 1 + + # from issue 5934 + eq = ( + (-240*sqrt(2)*sqrt(sqrt(5) + 5)*sqrt(8*sqrt(5) + 40) - + 360*sqrt(2)*sqrt(-8*sqrt(5) + 40)*sqrt(-sqrt(5) + 5) - + 120*sqrt(10)*sqrt(-8*sqrt(5) + 40)*sqrt(-sqrt(5) + 5) + + 120*sqrt(2)*sqrt(-sqrt(5) + 5)*sqrt(8*sqrt(5) + 40) + + 120*sqrt(2)*sqrt(-8*sqrt(5) + 40)*sqrt(sqrt(5) + 5) + + 120*sqrt(10)*sqrt(-sqrt(5) + 5)*sqrt(8*sqrt(5) + 40) + + 120*sqrt(10)*sqrt(-8*sqrt(5) + 40)*sqrt(sqrt(5) + 5))/(-36000 - + 7200*sqrt(5) + (12*sqrt(10)*sqrt(sqrt(5) + 5) + + 24*sqrt(10)*sqrt(-sqrt(5) + 5))**2)) + assert radsimp(eq) is S.NaN # it's 0/0 + + # work with normal form + e = 1/sqrt(sqrt(7)/7 + 2*sqrt(2) + 3*sqrt(3) + 5*sqrt(5)) + 3 + assert radsimp(e) == ( + -sqrt(sqrt(7) + 14*sqrt(2) + 21*sqrt(3) + + 35*sqrt(5))*(-11654899*sqrt(35) - 1577436*sqrt(210) - 1278438*sqrt(15) + - 1346996*sqrt(10) + 1635060*sqrt(6) + 5709765 + 7539830*sqrt(14) + + 8291415*sqrt(21))/1300423175 + 3) + + # obey power rules + base = sqrt(3) - sqrt(2) + assert radsimp(1/base**3) == (sqrt(3) + sqrt(2))**3 + assert radsimp(1/(-base)**3) == -(sqrt(2) + sqrt(3))**3 + assert radsimp(1/(-base)**x) == (-base)**(-x) + assert radsimp(1/base**x) == (sqrt(2) + sqrt(3))**x + assert radsimp(root(1/(-1 - sqrt(2)), -x)) == (-1)**(-1/x)*(1 + sqrt(2))**(1/x) + + # recurse + e = cos(1/(1 + sqrt(2))) + assert radsimp(e) == cos(-sqrt(2) + 1) + assert radsimp(e/2) == cos(-sqrt(2) + 1)/2 + assert radsimp(1/e) == 1/cos(-sqrt(2) + 1) + assert radsimp(2/e) == 2/cos(-sqrt(2) + 1) + assert fraction(radsimp(e/sqrt(x))) == (sqrt(x)*cos(-sqrt(2)+1), x) + + # test that symbolic denominators are not processed + r = 1 + sqrt(2) + assert radsimp(x/r, symbolic=False) == -x*(-sqrt(2) + 1) + assert radsimp(x/(y + r), symbolic=False) == x/(y + 1 + sqrt(2)) + assert radsimp(x/(y + r)/r, symbolic=False) == \ + -x*(-sqrt(2) + 1)/(y + 1 + sqrt(2)) + + # issue 7408 + eq = sqrt(x)/sqrt(y) + assert radsimp(eq) == umul(sqrt(x), sqrt(y), 1/y) + assert radsimp(eq, symbolic=False) == eq + + # issue 7498 + assert radsimp(sqrt(x)/sqrt(y)**3) == umul(sqrt(x), sqrt(y**3), 1/y**3) + + # for coverage + eq = sqrt(x)/y**2 + assert radsimp(eq) == eq + + # handle non-Expr args + from sympy.integrals.integrals import Integral + eq = Integral(x/(sqrt(2) - 1), (x, 0, 1/(sqrt(2) + 1))) + assert radsimp(eq) == Integral((sqrt(2) + 1)*x , (x, 0, sqrt(2) - 1)) + + from sympy.sets import FiniteSet + eq = FiniteSet(x/(sqrt(2) - 1)) + assert radsimp(eq) == FiniteSet((sqrt(2) + 1)*x) + +def test_radsimp_issue_3214(): + c, p = symbols('c p', positive=True) + s = sqrt(c**2 - p**2) + b = (c + I*p - s)/(c + I*p + s) + assert radsimp(b) == -I*(c + I*p - sqrt(c**2 - p**2))**2/(2*c*p) + + +def test_collect_1(): + """Collect with respect to Symbol""" + x, y, z, n = symbols('x,y,z,n') + assert collect(1, x) == 1 + assert collect( x + y*x, x ) == x * (1 + y) + assert collect( x + x**2, x ) == x + x**2 + assert collect( x**2 + y*x**2, x ) == (x**2)*(1 + y) + assert collect( x**2 + y*x, x ) == x*y + x**2 + assert collect( 2*x**2 + y*x**2 + 3*x*y, [x] ) == x**2*(2 + y) + 3*x*y + assert collect( 2*x**2 + y*x**2 + 3*x*y, [y] ) == 2*x**2 + y*(x**2 + 3*x) + + assert collect( ((1 + y + x)**4).expand(), x) == ((1 + y)**4).expand() + \ + x*(4*(1 + y)**3).expand() + x**2*(6*(1 + y)**2).expand() + \ + x**3*(4*(1 + y)).expand() + x**4 + # symbols can be given as any iterable + expr = x + y + assert collect(expr, expr.free_symbols) == expr + assert collect(x*exp(x) + sin(x)*y + sin(x)*2 + 3*x, x, exact=None + ) == x*exp(x) + 3*x + (y + 2)*sin(x) + assert collect(x*exp(x) + sin(x)*y + sin(x)*2 + 3*x + y*x + + y*x*exp(x), x, exact=None + ) == x*exp(x)*(y + 1) + (3 + y)*x + (y + 2)*sin(x) + + +def test_collect_2(): + """Collect with respect to a sum""" + a, b, x = symbols('a,b,x') + assert collect(a*(cos(x) + sin(x)) + b*(cos(x) + sin(x)), + sin(x) + cos(x)) == (a + b)*(cos(x) + sin(x)) + + +def test_collect_3(): + """Collect with respect to a product""" + a, b, c = symbols('a,b,c') + f = Function('f') + x, y, z, n = symbols('x,y,z,n') + + assert collect(-x/8 + x*y, -x) == x*(y - Rational(1, 8)) + + assert collect( 1 + x*(y**2), x*y ) == 1 + x*(y**2) + assert collect( x*y + a*x*y, x*y) == x*y*(1 + a) + assert collect( 1 + x*y + a*x*y, x*y) == 1 + x*y*(1 + a) + assert collect(a*x*f(x) + b*(x*f(x)), x*f(x)) == x*(a + b)*f(x) + + assert collect(a*x*log(x) + b*(x*log(x)), x*log(x)) == x*(a + b)*log(x) + assert collect(a*x**2*log(x)**2 + b*(x*log(x))**2, x*log(x)) == \ + x**2*log(x)**2*(a + b) + + # with respect to a product of three symbols + assert collect(y*x*z + a*x*y*z, x*y*z) == (1 + a)*x*y*z + + +def test_collect_4(): + """Collect with respect to a power""" + a, b, c, x = symbols('a,b,c,x') + + assert collect(a*x**c + b*x**c, x**c) == x**c*(a + b) + # issue 6096: 2 stays with c (unless c is integer or x is positive0 + assert collect(a*x**(2*c) + b*x**(2*c), x**c) == x**(2*c)*(a + b) + + +def test_collect_5(): + """Collect with respect to a tuple""" + a, x, y, z, n = symbols('a,x,y,z,n') + assert collect(x**2*y**4 + z*(x*y**2)**2 + z + a*z, [x*y**2, z]) in [ + z*(1 + a + x**2*y**4) + x**2*y**4, + z*(1 + a) + x**2*y**4*(1 + z) ] + assert collect((1 + (x + y) + (x + y)**2).expand(), + [x, y]) == 1 + y + x*(1 + 2*y) + x**2 + y**2 + + +def test_collect_pr19431(): + """Unevaluated collect with respect to a product""" + a = symbols('a') + assert collect(a**2*(a**2 + 1), a**2, evaluate=False)[a**2] == (a**2 + 1) + + +def test_collect_D(): + D = Derivative + f = Function('f') + x, a, b = symbols('x,a,b') + fx = D(f(x), x) + fxx = D(f(x), x, x) + + assert collect(a*fx + b*fx, fx) == (a + b)*fx + assert collect(a*D(fx, x) + b*D(fx, x), fx) == (a + b)*D(fx, x) + assert collect(a*fxx + b*fxx, fx) == (a + b)*D(fx, x) + # issue 4784 + assert collect(5*f(x) + 3*fx, fx) == 5*f(x) + 3*fx + assert collect(f(x) + f(x)*diff(f(x), x) + x*diff(f(x), x)*f(x), f(x).diff(x)) == \ + (x*f(x) + f(x))*D(f(x), x) + f(x) + assert collect(f(x) + f(x)*diff(f(x), x) + x*diff(f(x), x)*f(x), f(x).diff(x), exact=True) == \ + (x*f(x) + f(x))*D(f(x), x) + f(x) + assert collect(1/f(x) + 1/f(x)*diff(f(x), x) + x*diff(f(x), x)/f(x), f(x).diff(x), exact=True) == \ + (1/f(x) + x/f(x))*D(f(x), x) + 1/f(x) + e = (1 + x*fx + fx)/f(x) + assert collect(e.expand(), fx) == fx*(x/f(x) + 1/f(x)) + 1/f(x) + + +def test_collect_func(): + f = ((x + a + 1)**3).expand() + + assert collect(f, x) == a**3 + 3*a**2 + 3*a + x**3 + x**2*(3*a + 3) + \ + x*(3*a**2 + 6*a + 3) + 1 + assert collect(f, x, factor) == x**3 + 3*x**2*(a + 1) + 3*x*(a + 1)**2 + \ + (a + 1)**3 + + assert collect(f, x, evaluate=False) == { + S.One: a**3 + 3*a**2 + 3*a + 1, + x: 3*a**2 + 6*a + 3, x**2: 3*a + 3, + x**3: 1 + } + + assert collect(f, x, factor, evaluate=False) == { + S.One: (a + 1)**3, x: 3*(a + 1)**2, + x**2: umul(S(3), a + 1), x**3: 1} + + +def test_collect_order(): + a, b, x, t = symbols('a,b,x,t') + + assert collect(t + t*x + t*x**2 + O(x**3), t) == t*(1 + x + x**2 + O(x**3)) + assert collect(t + t*x + x**2 + O(x**3), t) == \ + t*(1 + x + O(x**3)) + x**2 + O(x**3) + + f = a*x + b*x + c*x**2 + d*x**2 + O(x**3) + g = x*(a + b) + x**2*(c + d) + O(x**3) + + assert collect(f, x) == g + assert collect(f, x, distribute_order_term=False) == g + + f = sin(a + b).series(b, 0, 10) + + assert collect(f, [sin(a), cos(a)]) == \ + sin(a)*cos(b).series(b, 0, 10) + cos(a)*sin(b).series(b, 0, 10) + assert collect(f, [sin(a), cos(a)], distribute_order_term=False) == \ + sin(a)*cos(b).series(b, 0, 10).removeO() + \ + cos(a)*sin(b).series(b, 0, 10).removeO() + O(b**10) + + +def test_rcollect(): + assert rcollect((x**2*y + x*y + x + y)/(x + y), y) == \ + (x + y*(1 + x + x**2))/(x + y) + assert rcollect(sqrt(-((x + 1)*(y + 1))), z) == sqrt(-((x + 1)*(y + 1))) + + +def test_collect_D_0(): + D = Derivative + f = Function('f') + x, a, b = symbols('x,a,b') + fxx = D(f(x), x, x) + + assert collect(a*fxx + b*fxx, fxx) == (a + b)*fxx + + +def test_collect_Wild(): + """Collect with respect to functions with Wild argument""" + a, b, x, y = symbols('a b x y') + f = Function('f') + w1 = Wild('.1') + w2 = Wild('.2') + assert collect(f(x) + a*f(x), f(w1)) == (1 + a)*f(x) + assert collect(f(x, y) + a*f(x, y), f(w1)) == f(x, y) + a*f(x, y) + assert collect(f(x, y) + a*f(x, y), f(w1, w2)) == (1 + a)*f(x, y) + assert collect(f(x, y) + a*f(x, y), f(w1, w1)) == f(x, y) + a*f(x, y) + assert collect(f(x, x) + a*f(x, x), f(w1, w1)) == (1 + a)*f(x, x) + assert collect(a*(x + 1)**y + (x + 1)**y, w1**y) == (1 + a)*(x + 1)**y + assert collect(a*(x + 1)**y + (x + 1)**y, w1**b) == \ + a*(x + 1)**y + (x + 1)**y + assert collect(a*(x + 1)**y + (x + 1)**y, (x + 1)**w2) == \ + (1 + a)*(x + 1)**y + assert collect(a*(x + 1)**y + (x + 1)**y, w1**w2) == (1 + a)*(x + 1)**y + + +def test_collect_const(): + # coverage not provided by above tests + assert collect_const(2*sqrt(3) + 4*a*sqrt(5)) == \ + 2*(2*sqrt(5)*a + sqrt(3)) # let the primitive reabsorb + assert collect_const(2*sqrt(3) + 4*a*sqrt(5), sqrt(3)) == \ + 2*sqrt(3) + 4*a*sqrt(5) + assert collect_const(sqrt(2)*(1 + sqrt(2)) + sqrt(3) + x*sqrt(2)) == \ + sqrt(2)*(x + 1 + sqrt(2)) + sqrt(3) + + # issue 5290 + assert collect_const(2*x + 2*y + 1, 2) == \ + collect_const(2*x + 2*y + 1) == \ + Add(S.One, Mul(2, x + y, evaluate=False), evaluate=False) + assert collect_const(-y - z) == Mul(-1, y + z, evaluate=False) + assert collect_const(2*x - 2*y - 2*z, 2) == \ + Mul(2, x - y - z, evaluate=False) + assert collect_const(2*x - 2*y - 2*z, -2) == \ + _unevaluated_Add(2*x, Mul(-2, y + z, evaluate=False)) + + # this is why the content_primitive is used + eq = (sqrt(15 + 5*sqrt(2))*x + sqrt(3 + sqrt(2))*y)*2 + assert collect_sqrt(eq + 2) == \ + 2*sqrt(sqrt(2) + 3)*(sqrt(5)*x + y) + 2 + + # issue 16296 + assert collect_const(a + b + x/2 + y/2) == a + b + Mul(S.Half, x + y, evaluate=False) + + +def test_issue_13143(): + f = Function('f') + fx = f(x).diff(x) + e = f(x) + fx + f(x)*fx + # collect function before derivative + assert collect(e, Wild('w')) == f(x)*(fx + 1) + fx + e = f(x) + f(x)*fx + x*fx*f(x) + assert collect(e, fx) == (x*f(x) + f(x))*fx + f(x) + assert collect(e, f(x)) == (x*fx + fx + 1)*f(x) + e = f(x) + fx + f(x)*fx + assert collect(e, [f(x), fx]) == f(x)*(1 + fx) + fx + assert collect(e, [fx, f(x)]) == fx*(1 + f(x)) + f(x) + + +def test_issue_6097(): + assert collect(a*y**(2.0*x) + b*y**(2.0*x), y**x) == (a + b)*(y**x)**2.0 + assert collect(a*2**(2.0*x) + b*2**(2.0*x), 2**x) == (a + b)*(2**x)**2.0 + + +def test_fraction_expand(): + eq = (x + y)*y/x + assert eq.expand(frac=True) == fraction_expand(eq) == (x*y + y**2)/x + assert eq.expand() == y + y**2/x + + +def test_fraction(): + x, y, z = map(Symbol, 'xyz') + A = Symbol('A', commutative=False) + + assert fraction(S.Half) == (1, 2) + + assert fraction(x) == (x, 1) + assert fraction(1/x) == (1, x) + assert fraction(x/y) == (x, y) + assert fraction(x/2) == (x, 2) + + assert fraction(x*y/z) == (x*y, z) + assert fraction(x/(y*z)) == (x, y*z) + + assert fraction(1/y**2) == (1, y**2) + assert fraction(x/y**2) == (x, y**2) + + assert fraction((x**2 + 1)/y) == (x**2 + 1, y) + assert fraction(x*(y + 1)/y**7) == (x*(y + 1), y**7) + + assert fraction(exp(-x), exact=True) == (exp(-x), 1) + assert fraction((1/(x + y))/2, exact=True) == (1, Mul(2,(x + y), evaluate=False)) + + assert fraction(x*A/y) == (x*A, y) + assert fraction(x*A**-1/y) == (x*A**-1, y) + + n = symbols('n', negative=True) + assert fraction(exp(n)) == (1, exp(-n)) + assert fraction(exp(-n)) == (exp(-n), 1) + + p = symbols('p', positive=True) + assert fraction(exp(-p)*log(p), exact=True) == (exp(-p)*log(p), 1) + + m = Mul(1, 1, S.Half, evaluate=False) + assert fraction(m) == (1, 2) + assert fraction(m, exact=True) == (Mul(1, 1, evaluate=False), 2) + + m = Mul(1, 1, S.Half, S.Half, Pow(1, -1, evaluate=False), evaluate=False) + assert fraction(m) == (1, 4) + assert fraction(m, exact=True) == \ + (Mul(1, 1, evaluate=False), Mul(2, 2, 1, evaluate=False)) + + +def test_issue_5615(): + aA, Re, a, b, D = symbols('aA Re a b D') + e = ((D**3*a + b*aA**3)/Re).expand() + assert collect(e, [aA**3/Re, a]) == e + + +def test_issue_5933(): + from sympy.geometry.polygon import (Polygon, RegularPolygon) + from sympy.simplify.radsimp import denom + x = Polygon(*RegularPolygon((0, 0), 1, 5).vertices).centroid.x + assert abs(denom(x).n()) > 1e-12 + assert abs(denom(radsimp(x))) > 1e-12 # in case simplify didn't handle it + + +def test_issue_14608(): + a, b = symbols('a b', commutative=False) + x, y = symbols('x y') + raises(AttributeError, lambda: collect(a*b + b*a, a)) + assert collect(x*y + y*(x+1), a) == x*y + y*(x+1) + assert collect(x*y + y*(x+1) + a*b + b*a, y) == y*(2*x + 1) + a*b + b*a + + +def test_collect_abs(): + s = abs(x) + abs(y) + assert collect_abs(s) == s + assert unchanged(Mul, abs(x), abs(y)) + ans = Abs(x*y) + assert isinstance(ans, Abs) + assert collect_abs(abs(x)*abs(y)) == ans + assert collect_abs(1 + exp(abs(x)*abs(y))) == 1 + exp(ans) + + # See https://github.com/sympy/sympy/issues/12910 + p = Symbol('p', positive=True) + assert collect_abs(p/abs(1-p)).is_commutative is True + + +def test_issue_19149(): + eq = exp(3*x/4) + assert collect(eq, exp(x)) == eq + +def test_issue_19719(): + a, b = symbols('a, b') + expr = a**2 * (b + 1) + (7 + 1/b)/a + collected = collect(expr, (a**2, 1/a), evaluate=False) + # Would return {_Dummy_20**(-2): b + 1, 1/a: 7 + 1/b} without xreplace + assert collected == {a**2: b + 1, 1/a: 7 + 1/b} + + +def test_issue_21355(): + assert radsimp(1/(x + sqrt(x**2))) == 1/(x + sqrt(x**2)) + assert radsimp(1/(x - sqrt(x**2))) == 1/(x - sqrt(x**2)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_ratsimp.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_ratsimp.py new file mode 100644 index 0000000000000000000000000000000000000000..14e84fd2b227518baff1bda4e5b27ecc40a8bcdd --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_ratsimp.py @@ -0,0 +1,78 @@ +from sympy.core.numbers import (Rational, pi) +from sympy.functions.elementary.exponential import log +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.special.error_functions import erf +from sympy.polys.domains import GF +from sympy.simplify.ratsimp import (ratsimp, ratsimpmodprime) + +from sympy.abc import x, y, z, t, a, b, c, d, e + + +def test_ratsimp(): + f, g = 1/x + 1/y, (x + y)/(x*y) + + assert f != g and ratsimp(f) == g + + f, g = 1/(1 + 1/x), 1 - 1/(x + 1) + + assert f != g and ratsimp(f) == g + + f, g = x/(x + y) + y/(x + y), 1 + + assert f != g and ratsimp(f) == g + + f, g = -x - y - y**2/(x + y) + x**2/(x + y), -2*y + + assert f != g and ratsimp(f) == g + + f = (a*c*x*y + a*c*z - b*d*x*y - b*d*z - b*t*x*y - b*t*x - b*t*z + + e*x)/(x*y + z) + G = [a*c - b*d - b*t + (-b*t*x + e*x)/(x*y + z), + a*c - b*d - b*t - ( b*t*x - e*x)/(x*y + z)] + + assert f != g and ratsimp(f) in G + + A = sqrt(pi) + + B = log(erf(x) - 1) + C = log(erf(x) + 1) + + D = 8 - 8*erf(x) + + f = A*B/D - A*C/D + A*C*erf(x)/D - A*B*erf(x)/D + 2*A/D + + assert ratsimp(f) == A*B/8 - A*C/8 - A/(4*erf(x) - 4) + + +def test_ratsimpmodprime(): + a = y**5 + x + y + b = x - y + F = [x*y**5 - x - y] + assert ratsimpmodprime(a/b, F, x, y, order='lex') == \ + (-x**2 - x*y - x - y) / (-x**2 + x*y) + + a = x + y**2 - 2 + b = x + y**2 - y - 1 + F = [x*y - 1] + assert ratsimpmodprime(a/b, F, x, y, order='lex') == \ + (1 + y - x)/(y - x) + + a = 5*x**3 + 21*x**2 + 4*x*y + 23*x + 12*y + 15 + b = 7*x**3 - y*x**2 + 31*x**2 + 2*x*y + 15*y + 37*x + 21 + F = [x**2 + y**2 - 1] + assert ratsimpmodprime(a/b, F, x, y, order='lex') == \ + (1 + 5*y - 5*x)/(8*y - 6*x) + + a = x*y - x - 2*y + 4 + b = x + y**2 - 2*y + F = [x - 2, y - 3] + assert ratsimpmodprime(a/b, F, x, y, order='lex') == \ + Rational(2, 5) + + # Test a bug where denominators would be dropped + assert ratsimpmodprime(x, [y - 2*x], order='lex') == \ + y/2 + + a = (x**5 + 2*x**4 + 2*x**3 + 2*x**2 + x + 2/x + x**(-2)) + assert ratsimpmodprime(a, [x + 1], domain=GF(2)) == 1 + assert ratsimpmodprime(a, [x + 1], domain=GF(3)) == -1 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_rewrite.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_rewrite.py new file mode 100644 index 0000000000000000000000000000000000000000..56d2fb7a85bd959bd4accc2f36127429efbdbe70 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_rewrite.py @@ -0,0 +1,31 @@ +from sympy.core.numbers import I +from sympy.core.symbol import symbols +from sympy.functions.elementary.exponential import exp +from sympy.functions.elementary.trigonometric import (cos, cot, sin) +from sympy.testing.pytest import _both_exp_pow + +x, y, z, n = symbols('x,y,z,n') + + +@_both_exp_pow +def test_has(): + assert cot(x).has(x) + assert cot(x).has(cot) + assert not cot(x).has(sin) + assert sin(x).has(x) + assert sin(x).has(sin) + assert not sin(x).has(cot) + assert exp(x).has(exp) + + +@_both_exp_pow +def test_sin_exp_rewrite(): + assert sin(x).rewrite(sin, exp) == -I/2*(exp(I*x) - exp(-I*x)) + assert sin(x).rewrite(sin, exp).rewrite(exp, sin) == sin(x) + assert cos(x).rewrite(cos, exp).rewrite(exp, cos) == cos(x) + assert (sin(5*y) - sin( + 2*x)).rewrite(sin, exp).rewrite(exp, sin) == sin(5*y) - sin(2*x) + assert sin(x + y).rewrite(sin, exp).rewrite(exp, sin) == sin(x + y) + assert cos(x + y).rewrite(cos, exp).rewrite(exp, cos) == cos(x + y) + # This next test currently passes... not clear whether it should or not? + assert cos(x).rewrite(cos, exp).rewrite(exp, sin) == cos(x) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_simplify.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_simplify.py new file mode 100644 index 0000000000000000000000000000000000000000..a5bf469f68adf5c5dfbdf7559414681e2fb28ba7 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_simplify.py @@ -0,0 +1,1093 @@ +from sympy.concrete.summations import Sum +from sympy.core.add import Add +from sympy.core.basic import Basic +from sympy.core.expr import unchanged +from sympy.core.function import (count_ops, diff, expand, expand_multinomial, Function, Derivative) +from sympy.core.mul import Mul, _keep_coeff +from sympy.core import GoldenRatio +from sympy.core.numbers import (E, Float, I, oo, pi, Rational, zoo) +from sympy.core.relational import (Eq, Lt, Gt, Ge, Le) +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.core.sympify import sympify +from sympy.functions.combinatorial.factorials import (binomial, factorial) +from sympy.functions.elementary.complexes import (Abs, sign) +from sympy.functions.elementary.exponential import (exp, exp_polar, log) +from sympy.functions.elementary.hyperbolic import (cosh, csch, sinh) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.piecewise import Piecewise +from sympy.functions.elementary.trigonometric import (acos, asin, atan, cos, sin, sinc, tan) +from sympy.functions.special.error_functions import erf +from sympy.functions.special.gamma_functions import gamma +from sympy.functions.special.hyper import hyper +from sympy.functions.special.tensor_functions import KroneckerDelta +from sympy.geometry.polygon import rad +from sympy.integrals.integrals import (Integral, integrate) +from sympy.logic.boolalg import (And, Or) +from sympy.matrices.dense import (Matrix, eye) +from sympy.matrices.expressions.matexpr import MatrixSymbol +from sympy.polys.polytools import (factor, Poly) +from sympy.simplify.simplify import (besselsimp, hypersimp, inversecombine, logcombine, nsimplify, nthroot, posify, separatevars, signsimp, simplify) +from sympy.solvers.solvers import solve + +from sympy.testing.pytest import XFAIL, slow, _both_exp_pow +from sympy.abc import x, y, z, t, a, b, c, d, e, f, g, h, i, n + + +def test_issue_7263(): + assert abs((simplify(30.8**2 - 82.5**2 * sin(rad(11.6))**2)).evalf() - \ + 673.447451402970) < 1e-12 + + +def test_factorial_simplify(): + # There are more tests in test_factorials.py. + x = Symbol('x') + assert simplify(factorial(x)/x) == gamma(x) + assert simplify(factorial(factorial(x))) == factorial(factorial(x)) + + +def test_simplify_expr(): + x, y, z, k, n, m, w, s, A = symbols('x,y,z,k,n,m,w,s,A') + f = Function('f') + + assert all(simplify(tmp) == tmp for tmp in [I, E, oo, x, -x, -oo, -E, -I]) + + e = 1/x + 1/y + assert e != (x + y)/(x*y) + assert simplify(e) == (x + y)/(x*y) + + e = A**2*s**4/(4*pi*k*m**3) + assert simplify(e) == e + + e = (4 + 4*x - 2*(2 + 2*x))/(2 + 2*x) + assert simplify(e) == 0 + + e = (-4*x*y**2 - 2*y**3 - 2*x**2*y)/(x + y)**2 + assert simplify(e) == -2*y + + e = -x - y - (x + y)**(-1)*y**2 + (x + y)**(-1)*x**2 + assert simplify(e) == -2*y + + e = (x + x*y)/x + assert simplify(e) == 1 + y + + e = (f(x) + y*f(x))/f(x) + assert simplify(e) == 1 + y + + e = (2 * (1/n - cos(n * pi)/n))/pi + assert simplify(e) == (-cos(pi*n) + 1)/(pi*n)*2 + + e = integrate(1/(x**3 + 1), x).diff(x) + assert simplify(e) == 1/(x**3 + 1) + + e = integrate(x/(x**2 + 3*x + 1), x).diff(x) + assert simplify(e) == x/(x**2 + 3*x + 1) + + f = Symbol('f') + A = Matrix([[2*k - m*w**2, -k], [-k, k - m*w**2]]).inv() + assert simplify((A*Matrix([0, f]))[1] - + (-f*(2*k - m*w**2)/(k**2 - (k - m*w**2)*(2*k - m*w**2)))) == 0 + + f = -x + y/(z + t) + z*x/(z + t) + z*a/(z + t) + t*x/(z + t) + assert simplify(f) == (y + a*z)/(z + t) + + # issue 10347 + expr = -x*(y**2 - 1)*(2*y**2*(x**2 - 1)/(a*(x**2 - y**2)**2) + (x**2 - 1) + /(a*(x**2 - y**2)))/(a*(x**2 - y**2)) + x*(-2*x**2*sqrt(-x**2*y**2 + x**2 + + y**2 - 1)*sin(z)/(a*(x**2 - y**2)**2) - x**2*sqrt(-x**2*y**2 + x**2 + + y**2 - 1)*sin(z)/(a*(x**2 - 1)*(x**2 - y**2)) + (x**2*sqrt((-x**2 + 1)* + (y**2 - 1))*sqrt(-x**2*y**2 + x**2 + y**2 - 1)*sin(z)/(x**2 - 1) + sqrt( + (-x**2 + 1)*(y**2 - 1))*(x*(-x*y**2 + x)/sqrt(-x**2*y**2 + x**2 + y**2 - + 1) + sqrt(-x**2*y**2 + x**2 + y**2 - 1))*sin(z))/(a*sqrt((-x**2 + 1)*( + y**2 - 1))*(x**2 - y**2)))*sqrt(-x**2*y**2 + x**2 + y**2 - 1)*sin(z)/(a* + (x**2 - y**2)) + x*(-2*x**2*sqrt(-x**2*y**2 + x**2 + y**2 - 1)*cos(z)/(a* + (x**2 - y**2)**2) - x**2*sqrt(-x**2*y**2 + x**2 + y**2 - 1)*cos(z)/(a* + (x**2 - 1)*(x**2 - y**2)) + (x**2*sqrt((-x**2 + 1)*(y**2 - 1))*sqrt(-x**2 + *y**2 + x**2 + y**2 - 1)*cos(z)/(x**2 - 1) + x*sqrt((-x**2 + 1)*(y**2 - + 1))*(-x*y**2 + x)*cos(z)/sqrt(-x**2*y**2 + x**2 + y**2 - 1) + sqrt((-x**2 + + 1)*(y**2 - 1))*sqrt(-x**2*y**2 + x**2 + y**2 - 1)*cos(z))/(a*sqrt((-x**2 + + 1)*(y**2 - 1))*(x**2 - y**2)))*sqrt(-x**2*y**2 + x**2 + y**2 - 1)*cos( + z)/(a*(x**2 - y**2)) - y*sqrt((-x**2 + 1)*(y**2 - 1))*(-x*y*sqrt(-x**2* + y**2 + x**2 + y**2 - 1)*sin(z)/(a*(x**2 - y**2)*(y**2 - 1)) + 2*x*y*sqrt( + -x**2*y**2 + x**2 + y**2 - 1)*sin(z)/(a*(x**2 - y**2)**2) + (x*y*sqrt(( + -x**2 + 1)*(y**2 - 1))*sqrt(-x**2*y**2 + x**2 + y**2 - 1)*sin(z)/(y**2 - + 1) + x*sqrt((-x**2 + 1)*(y**2 - 1))*(-x**2*y + y)*sin(z)/sqrt(-x**2*y**2 + + x**2 + y**2 - 1))/(a*sqrt((-x**2 + 1)*(y**2 - 1))*(x**2 - y**2)))*sin( + z)/(a*(x**2 - y**2)) + y*(x**2 - 1)*(-2*x*y*(x**2 - 1)/(a*(x**2 - y**2) + **2) + 2*x*y/(a*(x**2 - y**2)))/(a*(x**2 - y**2)) + y*(x**2 - 1)*(y**2 - + 1)*(-x*y*sqrt(-x**2*y**2 + x**2 + y**2 - 1)*cos(z)/(a*(x**2 - y**2)*(y**2 + - 1)) + 2*x*y*sqrt(-x**2*y**2 + x**2 + y**2 - 1)*cos(z)/(a*(x**2 - y**2) + **2) + (x*y*sqrt((-x**2 + 1)*(y**2 - 1))*sqrt(-x**2*y**2 + x**2 + y**2 - + 1)*cos(z)/(y**2 - 1) + x*sqrt((-x**2 + 1)*(y**2 - 1))*(-x**2*y + y)*cos( + z)/sqrt(-x**2*y**2 + x**2 + y**2 - 1))/(a*sqrt((-x**2 + 1)*(y**2 - 1) + )*(x**2 - y**2)))*cos(z)/(a*sqrt((-x**2 + 1)*(y**2 - 1))*(x**2 - y**2) + ) - x*sqrt((-x**2 + 1)*(y**2 - 1))*sqrt(-x**2*y**2 + x**2 + y**2 - 1)*sin( + z)**2/(a**2*(x**2 - 1)*(x**2 - y**2)*(y**2 - 1)) - x*sqrt((-x**2 + 1)*( + y**2 - 1))*sqrt(-x**2*y**2 + x**2 + y**2 - 1)*cos(z)**2/(a**2*(x**2 - 1)*( + x**2 - y**2)*(y**2 - 1)) + assert simplify(expr) == 2*x/(a**2*(x**2 - y**2)) + + #issue 17631 + assert simplify('((-1/2)*Boole(True)*Boole(False)-1)*Boole(True)') == \ + Mul(sympify('(2 + Boole(True)*Boole(False))'), sympify('-Boole(True)/2')) + + A, B = symbols('A,B', commutative=False) + + assert simplify(A*B - B*A) == A*B - B*A + assert simplify(A/(1 + y/x)) == x*A/(x + y) + assert simplify(A*(1/x + 1/y)) == A/x + A/y #(x + y)*A/(x*y) + + assert simplify(log(2) + log(3)) == log(6) + assert simplify(log(2*x) - log(2)) == log(x) + + assert simplify(hyper([], [], x)) == exp(x) + + +def test_issue_3557(): + f_1 = x*a + y*b + z*c - 1 + f_2 = x*d + y*e + z*f - 1 + f_3 = x*g + y*h + z*i - 1 + + solutions = solve([f_1, f_2, f_3], x, y, z, simplify=False) + + assert simplify(solutions[y]) == \ + (a*i + c*d + f*g - a*f - c*g - d*i)/ \ + (a*e*i + b*f*g + c*d*h - a*f*h - b*d*i - c*e*g) + + +def test_simplify_other(): + assert simplify(sin(x)**2 + cos(x)**2) == 1 + assert simplify(gamma(x + 1)/gamma(x)) == x + assert simplify(sin(x)**2 + cos(x)**2 + factorial(x)/gamma(x)) == 1 + x + assert simplify( + Eq(sin(x)**2 + cos(x)**2, factorial(x)/gamma(x))) == Eq(x, 1) + nc = symbols('nc', commutative=False) + assert simplify(x + x*nc) == x*(1 + nc) + # issue 6123 + # f = exp(-I*(k*sqrt(t) + x/(2*sqrt(t)))**2) + # ans = integrate(f, (k, -oo, oo), conds='none') + ans = I*(-pi*x*exp(I*pi*Rational(-3, 4) + I*x**2/(4*t))*erf(x*exp(I*pi*Rational(-3, 4))/ + (2*sqrt(t)))/(2*sqrt(t)) + pi*x*exp(I*pi*Rational(-3, 4) + I*x**2/(4*t))/ + (2*sqrt(t)))*exp(-I*x**2/(4*t))/(sqrt(pi)*x) - I*sqrt(pi) * \ + (-erf(x*exp(I*pi/4)/(2*sqrt(t))) + 1)*exp(I*pi/4)/(2*sqrt(t)) + assert simplify(ans) == -(-1)**Rational(3, 4)*sqrt(pi)/sqrt(t) + # issue 6370 + assert simplify(2**(2 + x)/4) == 2**x + + +@_both_exp_pow +def test_simplify_complex(): + cosAsExp = cos(x)._eval_rewrite_as_exp(x) + tanAsExp = tan(x)._eval_rewrite_as_exp(x) + assert simplify(cosAsExp*tanAsExp) == sin(x) # issue 4341 + + # issue 10124 + assert simplify(exp(Matrix([[0, -1], [1, 0]]))) == Matrix([[cos(1), + -sin(1)], [sin(1), cos(1)]]) + + +def test_simplify_ratio(): + # roots of x**3-3*x+5 + roots = ['(1/2 - sqrt(3)*I/2)*(sqrt(21)/2 + 5/2)**(1/3) + 1/((1/2 - ' + 'sqrt(3)*I/2)*(sqrt(21)/2 + 5/2)**(1/3))', + '1/((1/2 + sqrt(3)*I/2)*(sqrt(21)/2 + 5/2)**(1/3)) + ' + '(1/2 + sqrt(3)*I/2)*(sqrt(21)/2 + 5/2)**(1/3)', + '-(sqrt(21)/2 + 5/2)**(1/3) - 1/(sqrt(21)/2 + 5/2)**(1/3)'] + + for r in roots: + r = S(r) + assert count_ops(simplify(r, ratio=1)) <= count_ops(r) + # If ratio=oo, simplify() is always applied: + assert simplify(r, ratio=oo) is not r + + +def test_simplify_measure(): + measure1 = lambda expr: len(str(expr)) + measure2 = lambda expr: -count_ops(expr) + # Return the most complicated result + expr = (x + 1)/(x + sin(x)**2 + cos(x)**2) + assert measure1(simplify(expr, measure=measure1)) <= measure1(expr) + assert measure2(simplify(expr, measure=measure2)) <= measure2(expr) + + expr2 = Eq(sin(x)**2 + cos(x)**2, 1) + assert measure1(simplify(expr2, measure=measure1)) <= measure1(expr2) + assert measure2(simplify(expr2, measure=measure2)) <= measure2(expr2) + + +def test_simplify_rational(): + expr = 2**x*2.**y + assert simplify(expr, rational = True) == 2**(x+y) + assert simplify(expr, rational = None) == 2.0**(x+y) + assert simplify(expr, rational = False) == expr + assert simplify('0.9 - 0.8 - 0.1', rational = True) == 0 + + +def test_simplify_issue_1308(): + assert simplify(exp(Rational(-1, 2)) + exp(Rational(-3, 2))) == \ + (1 + E)*exp(Rational(-3, 2)) + + +def test_issue_5652(): + assert simplify(E + exp(-E)) == exp(-E) + E + n = symbols('n', commutative=False) + assert simplify(n + n**(-n)) == n + n**(-n) + +def test_issue_27380(): + assert simplify(1.0**(x+1)/1.0**x) == 1.0 + +def test_simplify_fail1(): + x = Symbol('x') + y = Symbol('y') + e = (x + y)**2/(-4*x*y**2 - 2*y**3 - 2*x**2*y) + assert simplify(e) == 1 / (-2*y) + + +def test_nthroot(): + assert nthroot(90 + 34*sqrt(7), 3) == sqrt(7) + 3 + q = 1 + sqrt(2) - 2*sqrt(3) + sqrt(6) + sqrt(7) + assert nthroot(expand_multinomial(q**3), 3) == q + assert nthroot(41 + 29*sqrt(2), 5) == 1 + sqrt(2) + assert nthroot(-41 - 29*sqrt(2), 5) == -1 - sqrt(2) + expr = 1320*sqrt(10) + 4216 + 2576*sqrt(6) + 1640*sqrt(15) + assert nthroot(expr, 5) == 1 + sqrt(6) + sqrt(15) + q = 1 + sqrt(2) + sqrt(3) + sqrt(5) + assert expand_multinomial(nthroot(expand_multinomial(q**5), 5)) == q + q = 1 + sqrt(2) + 7*sqrt(6) + 2*sqrt(10) + assert nthroot(expand_multinomial(q**5), 5, 8) == q + q = 1 + sqrt(2) - 2*sqrt(3) + 1171*sqrt(6) + assert nthroot(expand_multinomial(q**3), 3) == q + assert nthroot(expand_multinomial(q**6), 6) == q + + +def test_nthroot1(): + q = 1 + sqrt(2) + sqrt(3) + S.One/10**20 + p = expand_multinomial(q**5) + assert nthroot(p, 5) == q + q = 1 + sqrt(2) + sqrt(3) + S.One/10**30 + p = expand_multinomial(q**5) + assert nthroot(p, 5) == q + + +@_both_exp_pow +def test_separatevars(): + x, y, z, n = symbols('x,y,z,n') + assert separatevars(2*n*x*z + 2*x*y*z) == 2*x*z*(n + y) + assert separatevars(x*z + x*y*z) == x*z*(1 + y) + assert separatevars(pi*x*z + pi*x*y*z) == pi*x*z*(1 + y) + assert separatevars(x*y**2*sin(x) + x*sin(x)*sin(y)) == \ + x*(sin(y) + y**2)*sin(x) + assert separatevars(x*exp(x + y) + x*exp(x)) == x*(1 + exp(y))*exp(x) + assert separatevars((x*(y + 1))**z).is_Pow # != x**z*(1 + y)**z + assert separatevars(1 + x + y + x*y) == (x + 1)*(y + 1) + assert separatevars(y/pi*exp(-(z - x)/cos(n))) == \ + y*exp(x/cos(n))*exp(-z/cos(n))/pi + assert separatevars((x + y)*(x - y) + y**2 + 2*x + 1) == (x + 1)**2 + # issue 4858 + p = Symbol('p', positive=True) + assert separatevars(sqrt(p**2 + x*p**2)) == p*sqrt(1 + x) + assert separatevars(sqrt(y*(p**2 + x*p**2))) == p*sqrt(y*(1 + x)) + assert separatevars(sqrt(y*(p**2 + x*p**2)), force=True) == \ + p*sqrt(y)*sqrt(1 + x) + # issue 4865 + assert separatevars(sqrt(x*y)).is_Pow + assert separatevars(sqrt(x*y), force=True) == sqrt(x)*sqrt(y) + # issue 4957 + # any type sequence for symbols is fine + assert separatevars(((2*x + 2)*y), dict=True, symbols=()) == \ + {'coeff': 1, x: 2*x + 2, y: y} + # separable + assert separatevars(((2*x + 2)*y), dict=True, symbols=[x]) == \ + {'coeff': y, x: 2*x + 2} + assert separatevars(((2*x + 2)*y), dict=True, symbols=[]) == \ + {'coeff': 1, x: 2*x + 2, y: y} + assert separatevars(((2*x + 2)*y), dict=True) == \ + {'coeff': 1, x: 2*x + 2, y: y} + assert separatevars(((2*x + 2)*y), dict=True, symbols=None) == \ + {'coeff': y*(2*x + 2)} + # not separable + assert separatevars(3, dict=True) is None + assert separatevars(2*x + y, dict=True, symbols=()) is None + assert separatevars(2*x + y, dict=True) is None + assert separatevars(2*x + y, dict=True, symbols=None) == {'coeff': 2*x + y} + # issue 4808 + n, m = symbols('n,m', commutative=False) + assert separatevars(m + n*m) == (1 + n)*m + assert separatevars(x + x*n) == x*(1 + n) + # issue 4910 + f = Function('f') + assert separatevars(f(x) + x*f(x)) == f(x) + x*f(x) + # a noncommutable object present + eq = x*(1 + hyper((), (), y*z)) + assert separatevars(eq) == eq + + s = separatevars(abs(x*y)) + assert s == abs(x)*abs(y) and s.is_Mul + z = cos(1)**2 + sin(1)**2 - 1 + a = abs(x*z) + s = separatevars(a) + assert not a.is_Mul and s.is_Mul and s == abs(x)*abs(z) + s = separatevars(abs(x*y*z)) + assert s == abs(x)*abs(y)*abs(z) + + # abs(x+y)/abs(z) would be better but we test this here to + # see that it doesn't raise + assert separatevars(abs((x+y)/z)) == abs((x+y)/z) + + +def test_separatevars_advanced_factor(): + x, y, z = symbols('x,y,z') + assert separatevars(1 + log(x)*log(y) + log(x) + log(y)) == \ + (log(x) + 1)*(log(y) + 1) + assert separatevars(1 + x - log(z) - x*log(z) - exp(y)*log(z) - + x*exp(y)*log(z) + x*exp(y) + exp(y)) == \ + -((x + 1)*(log(z) - 1)*(exp(y) + 1)) + x, y = symbols('x,y', positive=True) + assert separatevars(1 + log(x**log(y)) + log(x*y)) == \ + (log(x) + 1)*(log(y) + 1) + + +def test_hypersimp(): + n, k = symbols('n,k', integer=True) + + assert hypersimp(factorial(k), k) == k + 1 + assert hypersimp(factorial(k**2), k) is None + + assert hypersimp(1/factorial(k), k) == 1/(k + 1) + + assert hypersimp(2**k/factorial(k)**2, k) == 2/(k + 1)**2 + + assert hypersimp(binomial(n, k), k) == (n - k)/(k + 1) + assert hypersimp(binomial(n + 1, k), k) == (n - k + 1)/(k + 1) + + term = (4*k + 1)*factorial(k)/factorial(2*k + 1) + assert hypersimp(term, k) == S.Half*((4*k + 5)/(3 + 14*k + 8*k**2)) + + term = 1/((2*k - 1)*factorial(2*k + 1)) + assert hypersimp(term, k) == (k - S.Half)/((k + 1)*(2*k + 1)*(2*k + 3)) + + term = binomial(n, k)*(-1)**k/factorial(k) + assert hypersimp(term, k) == (k - n)/(k + 1)**2 + + +def test_nsimplify(): + x = Symbol("x") + assert nsimplify(0) == 0 + assert nsimplify(-1) == -1 + assert nsimplify(1) == 1 + assert nsimplify(1 + x) == 1 + x + assert nsimplify(2.7) == Rational(27, 10) + assert nsimplify(1 - GoldenRatio) == (1 - sqrt(5))/2 + assert nsimplify((1 + sqrt(5))/4, [GoldenRatio]) == GoldenRatio/2 + assert nsimplify(2/GoldenRatio, [GoldenRatio]) == 2*GoldenRatio - 2 + assert nsimplify(exp(pi*I*Rational(5, 3), evaluate=False)) == \ + sympify('1/2 - sqrt(3)*I/2') + assert nsimplify(sin(pi*Rational(3, 5), evaluate=False)) == \ + sympify('sqrt(sqrt(5)/8 + 5/8)') + assert nsimplify(sqrt(atan('1', evaluate=False))*(2 + I), [pi]) == \ + sqrt(pi) + sqrt(pi)/2*I + assert nsimplify(2 + exp(2*atan('1/4')*I)) == sympify('49/17 + 8*I/17') + assert nsimplify(pi, tolerance=0.01) == Rational(22, 7) + assert nsimplify(pi, tolerance=0.001) == Rational(355, 113) + assert nsimplify(0.33333, tolerance=1e-4) == Rational(1, 3) + assert nsimplify(2.0**(1/3.), tolerance=0.001) == Rational(635, 504) + assert nsimplify(2.0**(1/3.), tolerance=0.001, full=True) == \ + 2**Rational(1, 3) + assert nsimplify(x + .5, rational=True) == S.Half + x + assert nsimplify(1/.3 + x, rational=True) == Rational(10, 3) + x + assert nsimplify(log(3).n(), rational=True) == \ + sympify('109861228866811/100000000000000') + assert nsimplify(Float(0.272198261287950), [pi, log(2)]) == pi*log(2)/8 + assert nsimplify(Float(0.272198261287950).n(3), [pi, log(2)]) == \ + -pi/4 - log(2) + Rational(7, 4) + assert nsimplify(x/7.0) == x/7 + assert nsimplify(pi/1e2) == pi/100 + assert nsimplify(pi/1e2, rational=False) == pi/100.0 + assert nsimplify(pi/1e-7) == 10000000*pi + assert not nsimplify( + factor(-3.0*z**2*(z**2)**(-2.5) + 3*(z**2)**(-1.5))).atoms(Float) + e = x**0.0 + assert e.is_Pow and nsimplify(x**0.0) == 1 + assert nsimplify(3.333333, tolerance=0.1, rational=True) == Rational(10, 3) + assert nsimplify(3.333333, tolerance=0.01, rational=True) == Rational(10, 3) + assert nsimplify(3.666666, tolerance=0.1, rational=True) == Rational(11, 3) + assert nsimplify(3.666666, tolerance=0.01, rational=True) == Rational(11, 3) + assert nsimplify(33, tolerance=10, rational=True) == Rational(33) + assert nsimplify(33.33, tolerance=10, rational=True) == Rational(30) + assert nsimplify(37.76, tolerance=10, rational=True) == Rational(40) + assert nsimplify(-203.1) == Rational(-2031, 10) + assert nsimplify(.2, tolerance=0) == Rational(1, 5) + assert nsimplify(-.2, tolerance=0) == Rational(-1, 5) + assert nsimplify(.2222, tolerance=0) == Rational(1111, 5000) + assert nsimplify(-.2222, tolerance=0) == Rational(-1111, 5000) + # issue 7211, PR 4112 + assert nsimplify(S(2e-8)) == Rational(1, 50000000) + # issue 7322 direct test + assert nsimplify(1e-42, rational=True) != 0 + # issue 10336 + inf = Float('inf') + infs = (-oo, oo, inf, -inf) + for zi in infs: + ans = sign(zi)*oo + assert nsimplify(zi) == ans + assert nsimplify(zi + x) == x + ans + + assert nsimplify(0.33333333, rational=True, rational_conversion='exact') == Rational(0.33333333) + + # Make sure nsimplify on expressions uses full precision + assert nsimplify(pi.evalf(100)*x, rational_conversion='exact').evalf(100) == pi.evalf(100)*x + + +def test_issue_9448(): + tmp = sympify("1/(1 - (-1)**(2/3) - (-1)**(1/3)) + 1/(1 + (-1)**(2/3) + (-1)**(1/3))") + assert nsimplify(tmp) == S.Half + + +def test_extract_minus_sign(): + x = Symbol("x") + y = Symbol("y") + a = Symbol("a") + b = Symbol("b") + assert simplify(-x/-y) == x/y + assert simplify(-x/y) == -x/y + assert simplify(x/y) == x/y + assert simplify(x/-y) == -x/y + assert simplify(-x/0) == zoo*x + assert simplify(Rational(-5, 0)) is zoo + assert simplify(-a*x/(-y - b)) == a*x/(b + y) + + +def test_diff(): + x = Symbol("x") + y = Symbol("y") + f = Function("f") + g = Function("g") + assert simplify(g(x).diff(x)*f(x).diff(x) - f(x).diff(x)*g(x).diff(x)) == 0 + assert simplify(2*f(x)*f(x).diff(x) - diff(f(x)**2, x)) == 0 + assert simplify(diff(1/f(x), x) + f(x).diff(x)/f(x)**2) == 0 + assert simplify(f(x).diff(x, y) - f(x).diff(y, x)) == 0 + + +def test_logcombine_1(): + x, y = symbols("x,y") + a = Symbol("a") + z, w = symbols("z,w", positive=True) + b = Symbol("b", real=True) + assert logcombine(log(x) + 2*log(y)) == log(x) + 2*log(y) + assert logcombine(log(x) + 2*log(y), force=True) == log(x*y**2) + assert logcombine(a*log(w) + log(z)) == a*log(w) + log(z) + assert logcombine(b*log(z) + b*log(x)) == log(z**b) + b*log(x) + assert logcombine(b*log(z) - log(w)) == log(z**b/w) + assert logcombine(log(x)*log(z)) == log(x)*log(z) + assert logcombine(log(w)*log(x)) == log(w)*log(x) + assert logcombine(cos(-2*log(z) + b*log(w))) in [cos(log(w**b/z**2)), + cos(log(z**2/w**b))] + assert logcombine(log(log(x) - log(y)) - log(z), force=True) == \ + log(log(x/y)/z) + assert logcombine((2 + I)*log(x), force=True) == (2 + I)*log(x) + assert logcombine((x**2 + log(x) - log(y))/(x*y), force=True) == \ + (x**2 + log(x/y))/(x*y) + # the following could also give log(z*x**log(y**2)), what we + # are testing is that a canonical result is obtained + assert logcombine(log(x)*2*log(y) + log(z), force=True) == \ + log(z*y**log(x**2)) + assert logcombine((x*y + sqrt(x**4 + y**4) + log(x) - log(y))/(pi*x**Rational(2, 3)* + sqrt(y)**3), force=True) == ( + x*y + sqrt(x**4 + y**4) + log(x/y))/(pi*x**Rational(2, 3)*y**Rational(3, 2)) + assert logcombine(gamma(-log(x/y))*acos(-log(x/y)), force=True) == \ + acos(-log(x/y))*gamma(-log(x/y)) + + assert logcombine(2*log(z)*log(w)*log(x) + log(z) + log(w)) == \ + log(z**log(w**2))*log(x) + log(w*z) + assert logcombine(3*log(w) + 3*log(z)) == log(w**3*z**3) + assert logcombine(x*(y + 1) + log(2) + log(3)) == x*(y + 1) + log(6) + assert logcombine((x + y)*log(w) + (-x - y)*log(3)) == (x + y)*log(w/3) + # a single unknown can combine + assert logcombine(log(x) + log(2)) == log(2*x) + eq = log(abs(x)) + log(abs(y)) + assert logcombine(eq) == eq + reps = {x: 0, y: 0} + assert log(abs(x)*abs(y)).subs(reps) != eq.subs(reps) + + +def test_logcombine_complex_coeff(): + i = Integral((sin(x**2) + cos(x**3))/x, x) + assert logcombine(i, force=True) == i + assert logcombine(i + 2*log(x), force=True) == \ + i + log(x**2) + + +def test_issue_5950(): + x, y = symbols("x,y", positive=True) + assert logcombine(log(3) - log(2)) == log(Rational(3,2), evaluate=False) + assert logcombine(log(x) - log(y)) == log(x/y) + assert logcombine(log(Rational(3,2), evaluate=False) - log(2)) == \ + log(Rational(3,4), evaluate=False) + + +def test_posify(): + x = symbols('x') + + assert str(posify( + x + + Symbol('p', positive=True) + + Symbol('n', negative=True))) == '(_x + n + p, {_x: x})' + + eq, rep = posify(1/x) + assert log(eq).expand().subs(rep) == -log(x) + assert str(posify([x, 1 + x])) == '([_x, _x + 1], {_x: x})' + + p = symbols('p', positive=True) + n = symbols('n', negative=True) + orig = [x, n, p] + modified, reps = posify(orig) + assert str(modified) == '[_x, n, p]' + assert [w.subs(reps) for w in modified] == orig + + assert str(Integral(posify(1/x + y)[0], (y, 1, 3)).expand()) == \ + 'Integral(1/_x, (y, 1, 3)) + Integral(_y, (y, 1, 3))' + assert str(Sum(posify(1/x**n)[0], (n,1,3)).expand()) == \ + 'Sum(_x**(-n), (n, 1, 3))' + + A = Matrix([[1, 2, 3], [4, 5, 6 * Abs(x)]]) + Ap, rep = posify(A) + assert Ap == A.subs(*reversed(rep.popitem())) + + # issue 16438 + k = Symbol('k', finite=True) + eq, rep = posify(k) + assert eq.assumptions0 == {'positive': True, 'zero': False, 'imaginary': False, + 'nonpositive': False, 'commutative': True, 'hermitian': True, 'real': True, 'nonzero': True, + 'nonnegative': True, 'negative': False, 'complex': True, 'finite': True, + 'infinite': False, 'extended_real':True, 'extended_negative': False, + 'extended_nonnegative': True, 'extended_nonpositive': False, + 'extended_nonzero': True, 'extended_positive': True} + + +def test_issue_4194(): + # simplify should call cancel + f = Function('f') + assert simplify((4*x + 6*f(y))/(2*x + 3*f(y))) == 2 + + +@XFAIL +def test_simplify_float_vs_integer(): + # Test for issue 4473: + # https://github.com/sympy/sympy/issues/4473 + assert simplify(x**2.0 - x**2) == 0 + assert simplify(x**2 - x**2.0) == 0 + + +def test_as_content_primitive(): + assert (x/2 + y).as_content_primitive() == (S.Half, x + 2*y) + assert (x/2 + y).as_content_primitive(clear=False) == (S.One, x/2 + y) + assert (y*(x/2 + y)).as_content_primitive() == (S.Half, y*(x + 2*y)) + assert (y*(x/2 + y)).as_content_primitive(clear=False) == (S.One, y*(x/2 + y)) + + # although the _as_content_primitive methods do not alter the underlying structure, + # the as_content_primitive function will touch up the expression and join + # bases that would otherwise have not been joined. + assert (x*(2 + 2*x)*(3*x + 3)**2).as_content_primitive() == \ + (18, x*(x + 1)**3) + assert (2 + 2*x + 2*y*(3 + 3*y)).as_content_primitive() == \ + (2, x + 3*y*(y + 1) + 1) + assert ((2 + 6*x)**2).as_content_primitive() == \ + (4, (3*x + 1)**2) + assert ((2 + 6*x)**(2*y)).as_content_primitive() == \ + (1, (_keep_coeff(S(2), (3*x + 1)))**(2*y)) + assert (5 + 10*x + 2*y*(3 + 3*y)).as_content_primitive() == \ + (1, 10*x + 6*y*(y + 1) + 5) + assert (5*(x*(1 + y)) + 2*x*(3 + 3*y)).as_content_primitive() == \ + (11, x*(y + 1)) + assert ((5*(x*(1 + y)) + 2*x*(3 + 3*y))**2).as_content_primitive() == \ + (121, x**2*(y + 1)**2) + assert (y**2).as_content_primitive() == \ + (1, y**2) + assert (S.Infinity).as_content_primitive() == (1, oo) + eq = x**(2 + y) + assert (eq).as_content_primitive() == (1, eq) + assert (S.Half**(2 + x)).as_content_primitive() == (Rational(1, 4), 2**-x) + assert (Rational(-1, 2)**(2 + x)).as_content_primitive() == \ + (Rational(1, 4), (Rational(-1, 2))**x) + assert (Rational(-1, 2)**(2 + x)).as_content_primitive() == \ + (Rational(1, 4), Rational(-1, 2)**x) + assert (4**((1 + y)/2)).as_content_primitive() == (2, 4**(y/2)) + assert (3**((1 + y)/2)).as_content_primitive() == \ + (1, 3**(Mul(S.Half, 1 + y, evaluate=False))) + assert (5**Rational(3, 4)).as_content_primitive() == (1, 5**Rational(3, 4)) + assert (5**Rational(7, 4)).as_content_primitive() == (5, 5**Rational(3, 4)) + assert Add(z*Rational(5, 7), 0.5*x, y*Rational(3, 2), evaluate=False).as_content_primitive() == \ + (Rational(1, 14), 7.0*x + 21*y + 10*z) + assert (2**Rational(3, 4) + 2**Rational(1, 4)*sqrt(3)).as_content_primitive(radical=True) == \ + (1, 2**Rational(1, 4)*(sqrt(2) + sqrt(3))) + + +def test_signsimp(): + e = x*(-x + 1) + x*(x - 1) + assert signsimp(Eq(e, 0)) is S.true + assert Abs(x - 1) == Abs(1 - x) + assert signsimp(y - x) == y - x + assert signsimp(y - x, evaluate=False) == Mul(-1, x - y, evaluate=False) + + +def test_besselsimp(): + from sympy.functions.special.bessel import (besseli, besselj, bessely) + from sympy.integrals.transforms import cosine_transform + assert besselsimp(exp(-I*pi*y/2)*besseli(y, z*exp_polar(I*pi/2))) == \ + besselj(y, z) + assert besselsimp(exp(-I*pi*a/2)*besseli(a, 2*sqrt(x)*exp_polar(I*pi/2))) == \ + besselj(a, 2*sqrt(x)) + assert besselsimp(sqrt(2)*sqrt(pi)*x**Rational(1, 4)*exp(I*pi/4)*exp(-I*pi*a/2) * + besseli(Rational(-1, 2), sqrt(x)*exp_polar(I*pi/2)) * + besseli(a, sqrt(x)*exp_polar(I*pi/2))/2) == \ + besselj(a, sqrt(x)) * cos(sqrt(x)) + assert besselsimp(besseli(Rational(-1, 2), z)) == \ + sqrt(2)*cosh(z)/(sqrt(pi)*sqrt(z)) + assert besselsimp(besseli(a, z*exp_polar(-I*pi/2))) == \ + exp(-I*pi*a/2)*besselj(a, z) + assert cosine_transform(1/t*sin(a/t), t, y) == \ + sqrt(2)*sqrt(pi)*besselj(0, 2*sqrt(a)*sqrt(y))/2 + + assert besselsimp(x**2*(a*(-2*besselj(5*I, x) + besselj(-2 + 5*I, x) + + besselj(2 + 5*I, x)) + b*(-2*bessely(5*I, x) + bessely(-2 + 5*I, x) + + bessely(2 + 5*I, x)))/4 + x*(a*(besselj(-1 + 5*I, x)/2 - besselj(1 + 5*I, x)/2) + + b*(bessely(-1 + 5*I, x)/2 - bessely(1 + 5*I, x)/2)) + (x**2 + 25)*(a*besselj(5*I, x) + + b*bessely(5*I, x))) == 0 + + assert besselsimp(81*x**2*(a*(besselj(Rational(-5, 3), 9*x) - 2*besselj(Rational(1, 3), 9*x) + besselj(Rational(7, 3), 9*x)) + + b*(bessely(Rational(-5, 3), 9*x) - 2*bessely(Rational(1, 3), 9*x) + bessely(Rational(7, 3), 9*x)))/4 + x*(a*(9*besselj(Rational(-2, 3), 9*x)/2 + - 9*besselj(Rational(4, 3), 9*x)/2) + b*(9*bessely(Rational(-2, 3), 9*x)/2 - 9*bessely(Rational(4, 3), 9*x)/2)) + + (81*x**2 - Rational(1, 9))*(a*besselj(Rational(1, 3), 9*x) + b*bessely(Rational(1, 3), 9*x))) == 0 + + assert besselsimp(besselj(a-1,x) + besselj(a+1, x) - 2*a*besselj(a, x)/x) == 0 + + assert besselsimp(besselj(a-1,x) + besselj(a+1, x) + besselj(a, x)) == (2*a + x)*besselj(a, x)/x + + assert besselsimp(x**2* besselj(a,x) + x**3*besselj(a+1, x) + besselj(a+2, x)) == \ + 2*a*x*besselj(a + 1, x) + x**3*besselj(a + 1, x) - x**2*besselj(a + 2, x) + 2*x*besselj(a + 1, x) + besselj(a + 2, x) + +def test_Piecewise(): + e1 = x*(x + y) - y*(x + y) + e2 = sin(x)**2 + cos(x)**2 + e3 = expand((x + y)*y/x) + s1 = simplify(e1) + s2 = simplify(e2) + s3 = simplify(e3) + assert simplify(Piecewise((e1, x < e2), (e3, True))) == \ + Piecewise((s1, x < s2), (s3, True)) + + +def test_polymorphism(): + class A(Basic): + def _eval_simplify(x, **kwargs): + return S.One + + a = A(S(5), S(2)) + assert simplify(a) == 1 + + +def test_issue_from_PR1599(): + n1, n2, n3, n4 = symbols('n1 n2 n3 n4', negative=True) + assert simplify(I*sqrt(n1)) == -sqrt(-n1) + + +def test_issue_6811(): + eq = (x + 2*y)*(2*x + 2) + assert simplify(eq) == (x + 1)*(x + 2*y)*2 + # reject the 2-arg Mul -- these are a headache for test writing + assert simplify(eq.expand()) == \ + 2*x**2 + 4*x*y + 2*x + 4*y + + +def test_issue_6920(): + e = [cos(x) + I*sin(x), cos(x) - I*sin(x), + cosh(x) - sinh(x), cosh(x) + sinh(x)] + ok = [exp(I*x), exp(-I*x), exp(-x), exp(x)] + # wrap in f to show that the change happens wherever ei occurs + f = Function('f') + assert [simplify(f(ei)).args[0] for ei in e] == ok + + +def test_issue_7001(): + from sympy.abc import r, R + assert simplify(-(r*Piecewise((pi*Rational(4, 3), r <= R), + (-8*pi*R**3/(3*r**3), True)) + 2*Piecewise((pi*r*Rational(4, 3), r <= R), + (4*pi*R**3/(3*r**2), True)))/(4*pi*r)) == \ + Piecewise((-1, r <= R), (0, True)) + + +def test_inequality_no_auto_simplify(): + # no simplify on creation but can be simplified + lhs = cos(x)**2 + sin(x)**2 + rhs = 2 + e = Lt(lhs, rhs, evaluate=False) + assert e is not S.true + assert simplify(e) + + +def test_issue_9398(): + from sympy.core.numbers import Number + from sympy.polys.polytools import cancel + assert cancel(1e-14) != 0 + assert cancel(1e-14*I) != 0 + + assert simplify(1e-14) != 0 + assert simplify(1e-14*I) != 0 + + assert (I*Number(1.)*Number(10)**Number(-14)).simplify() != 0 + + assert cancel(1e-20) != 0 + assert cancel(1e-20*I) != 0 + + assert simplify(1e-20) != 0 + assert simplify(1e-20*I) != 0 + + assert cancel(1e-100) != 0 + assert cancel(1e-100*I) != 0 + + assert simplify(1e-100) != 0 + assert simplify(1e-100*I) != 0 + + f = Float("1e-1000") + assert cancel(f) != 0 + assert cancel(f*I) != 0 + + assert simplify(f) != 0 + assert simplify(f*I) != 0 + + +def test_issue_9324_simplify(): + M = MatrixSymbol('M', 10, 10) + e = M[0, 0] + M[5, 4] + 1304 + assert simplify(e) == e + + +def test_issue_9817_simplify(): + # simplify on trace of substituted explicit quadratic form of matrix + # expressions (a scalar) should return without errors (AttributeError) + # See issue #9817 and #9190 for the original bug more discussion on this + from sympy.matrices.expressions import Identity, trace + v = MatrixSymbol('v', 3, 1) + A = MatrixSymbol('A', 3, 3) + x = Matrix([i + 1 for i in range(3)]) + X = Identity(3) + quadratic = v.T * A * v + assert simplify((trace(quadratic.as_explicit())).xreplace({v:x, A:X})) == 14 + + +def test_issue_13474(): + x = Symbol('x') + assert simplify(x + csch(sinc(1))) == x + csch(sinc(1)) + + +@_both_exp_pow +def test_simplify_function_inverse(): + # "inverse" attribute does not guarantee that f(g(x)) is x + # so this simplification should not happen automatically. + # See issue #12140 + x, y = symbols('x, y') + g = Function('g') + + class f(Function): + def inverse(self, argindex=1): + return g + + assert simplify(f(g(x))) == f(g(x)) + assert inversecombine(f(g(x))) == x + assert simplify(f(g(x)), inverse=True) == x + assert simplify(f(g(sin(x)**2 + cos(x)**2)), inverse=True) == 1 + assert simplify(f(g(x, y)), inverse=True) == f(g(x, y)) + assert unchanged(asin, sin(x)) + assert simplify(asin(sin(x))) == asin(sin(x)) + assert simplify(2*asin(sin(3*x)), inverse=True) == 6*x + assert simplify(log(exp(x))) == log(exp(x)) + assert simplify(log(exp(x)), inverse=True) == x + assert simplify(exp(log(x)), inverse=True) == x + assert simplify(log(exp(x), 2), inverse=True) == x/log(2) + assert simplify(log(exp(x), 2, evaluate=False), inverse=True) == x/log(2) + + +def test_clear_coefficients(): + from sympy.simplify.simplify import clear_coefficients + assert clear_coefficients(4*y*(6*x + 3)) == (y*(2*x + 1), 0) + assert clear_coefficients(4*y*(6*x + 3) - 2) == (y*(2*x + 1), Rational(1, 6)) + assert clear_coefficients(4*y*(6*x + 3) - 2, x) == (y*(2*x + 1), x/12 + Rational(1, 6)) + assert clear_coefficients(sqrt(2) - 2) == (sqrt(2), 2) + assert clear_coefficients(4*sqrt(2) - 2) == (sqrt(2), S.Half) + assert clear_coefficients(S(3), x) == (0, x - 3) + assert clear_coefficients(S.Infinity, x) == (S.Infinity, x) + assert clear_coefficients(-S.Pi, x) == (S.Pi, -x) + assert clear_coefficients(2 - S.Pi/3, x) == (pi, -3*x + 6) + +def test_nc_simplify(): + from sympy.simplify.simplify import nc_simplify + from sympy.matrices.expressions import MatPow, Identity + from sympy.core import Pow + from functools import reduce + + a, b, c, d = symbols('a b c d', commutative = False) + x = Symbol('x') + A = MatrixSymbol("A", x, x) + B = MatrixSymbol("B", x, x) + C = MatrixSymbol("C", x, x) + D = MatrixSymbol("D", x, x) + subst = {a: A, b: B, c: C, d:D} + funcs = {Add: lambda x,y: x+y, Mul: lambda x,y: x*y } + + def _to_matrix(expr): + if expr in subst: + return subst[expr] + if isinstance(expr, Pow): + return MatPow(_to_matrix(expr.args[0]), expr.args[1]) + elif isinstance(expr, (Add, Mul)): + return reduce(funcs[expr.func],[_to_matrix(a) for a in expr.args]) + else: + return expr*Identity(x) + + def _check(expr, simplified, deep=True, matrix=True): + assert nc_simplify(expr, deep=deep) == simplified + assert expand(expr) == expand(simplified) + if matrix: + m_simp = _to_matrix(simplified).doit(inv_expand=False) + assert nc_simplify(_to_matrix(expr), deep=deep) == m_simp + + _check(a*b*a*b*a*b*c*(a*b)**3*c, ((a*b)**3*c)**2) + _check(a*b*(a*b)**-2*a*b, 1) + _check(a**2*b*a*b*a*b*(a*b)**-1, a*(a*b)**2, matrix=False) + _check(b*a*b**2*a*b**2*a*b**2, b*(a*b**2)**3) + _check(a*b*a**2*b*a**2*b*a**3, (a*b*a)**3*a**2) + _check(a**2*b*a**4*b*a**4*b*a**2, (a**2*b*a**2)**3) + _check(a**3*b*a**4*b*a**4*b*a, a**3*(b*a**4)**3*a**-3) + _check(a*b*a*b + a*b*c*x*a*b*c, (a*b)**2 + x*(a*b*c)**2) + _check(a*b*a*b*c*a*b*a*b*c, ((a*b)**2*c)**2) + _check(b**-1*a**-1*(a*b)**2, a*b) + _check(a**-1*b*c**-1, (c*b**-1*a)**-1) + expr = a**3*b*a**4*b*a**4*b*a**2*b*a**2*(b*a**2)**2*b*a**2*b*a**2 + for _ in range(10): + expr *= a*b + _check(expr, a**3*(b*a**4)**2*(b*a**2)**6*(a*b)**10) + _check((a*b*a*b)**2, (a*b*a*b)**2, deep=False) + _check(a*b*(c*d)**2, a*b*(c*d)**2) + expr = b**-1*(a**-1*b**-1 - a**-1*c*b**-1)**-1*a**-1 + assert nc_simplify(expr) == (1-c)**-1 + # commutative expressions should be returned without an error + assert nc_simplify(2*x**2) == 2*x**2 + +def test_issue_15965(): + A = Sum(z*x**y, (x, 1, a)) + anew = z*Sum(x**y, (x, 1, a)) + B = Integral(x*y, x) + bdo = x**2*y/2 + assert simplify(A + B) == anew + bdo + assert simplify(A) == anew + assert simplify(B) == bdo + assert simplify(B, doit=False) == y*Integral(x, x) + + +def test_issue_17137(): + assert simplify(cos(x)**I) == cos(x)**I + assert simplify(cos(x)**(2 + 3*I)) == cos(x)**(2 + 3*I) + + +def test_issue_21869(): + x = Symbol('x', real=True) + y = Symbol('y', real=True) + expr = And(Eq(x**2, 4), Le(x, y)) + assert expr.simplify() == expr + + expr = And(Eq(x**2, 4), Eq(x, 2)) + assert expr.simplify() == Eq(x, 2) + + expr = And(Eq(x**3, x**2), Eq(x, 1)) + assert expr.simplify() == Eq(x, 1) + + expr = And(Eq(sin(x), x**2), Eq(x, 0)) + assert expr.simplify() == Eq(x, 0) + + expr = And(Eq(x**3, x**2), Eq(x, 2)) + assert expr.simplify() == S.false + + expr = And(Eq(y, x**2), Eq(x, 1)) + assert expr.simplify() == And(Eq(y,1), Eq(x, 1)) + + expr = And(Eq(y**2, 1), Eq(y, x**2), Eq(x, 1)) + assert expr.simplify() == And(Eq(y,1), Eq(x, 1)) + + expr = And(Eq(y**2, 4), Eq(y, 2*x**2), Eq(x, 1)) + assert expr.simplify() == And(Eq(y,2), Eq(x, 1)) + + expr = And(Eq(y**2, 4), Eq(y, x**2), Eq(x, 1)) + assert expr.simplify() == S.false + + +def test_issue_7971_21740(): + z = Integral(x, (x, 1, 1)) + assert z != 0 + assert simplify(z) is S.Zero + assert simplify(S.Zero) is S.Zero + z = simplify(Float(0)) + assert z is not S.Zero and z == 0.0 + + +@slow +def test_issue_17141_slow(): + # Should not give RecursionError + assert simplify((2**acos(I+1)**2).rewrite('log')) == 2**((pi + 2*I*log(-1 + + sqrt(1 - 2*I) + I))**2/4) + + +def test_issue_17141(): + # Check that there is no RecursionError + assert simplify(x**(1 / acos(I))) == x**(2/(pi - 2*I*log(1 + sqrt(2)))) + assert simplify(acos(-I)**2*acos(I)**2) == \ + log(1 + sqrt(2))**4 + pi**2*log(1 + sqrt(2))**2/2 + pi**4/16 + assert simplify(2**acos(I)**2) == 2**((pi - 2*I*log(1 + sqrt(2)))**2/4) + p = 2**acos(I+1)**2 + assert simplify(p) == p + + +def test_simplify_kroneckerdelta(): + i, j = symbols("i j") + K = KroneckerDelta + + assert simplify(K(i, j)) == K(i, j) + assert simplify(K(0, j)) == K(0, j) + assert simplify(K(i, 0)) == K(i, 0) + + assert simplify(K(0, j).rewrite(Piecewise) * K(1, j)) == 0 + assert simplify(K(1, i) + Piecewise((1, Eq(j, 2)), (0, True))) == K(1, i) + K(2, j) + + # issue 17214 + assert simplify(K(0, j) * K(1, j)) == 0 + + n = Symbol('n', integer=True) + assert simplify(K(0, n) * K(1, n)) == 0 + + M = Matrix(4, 4, lambda i, j: K(j - i, n) if i <= j else 0) + assert simplify(M**2) == Matrix([[K(0, n), 0, K(1, n), 0], + [0, K(0, n), 0, K(1, n)], + [0, 0, K(0, n), 0], + [0, 0, 0, K(0, n)]]) + assert simplify(eye(1) * KroneckerDelta(0, n) * + KroneckerDelta(1, n)) == Matrix([[0]]) + + assert simplify(S.Infinity * KroneckerDelta(0, n) * + KroneckerDelta(1, n)) is S.NaN + + +def test_issue_17292(): + assert simplify(abs(x)/abs(x**2)) == 1/abs(x) + # this is bigger than the issue: check that deep processing works + assert simplify(5*abs((x**2 - 1)/(x - 1))) == 5*Abs(x + 1) + + +def test_issue_19822(): + expr = And(Gt(n-2, 1), Gt(n, 1)) + assert simplify(expr) == Gt(n, 3) + + +def test_issue_18645(): + expr = And(Ge(x, 3), Le(x, 3)) + assert simplify(expr) == Eq(x, 3) + expr = And(Eq(x, 3), Le(x, 3)) + assert simplify(expr) == Eq(x, 3) + + +@XFAIL +def test_issue_18642(): + i = Symbol("i", integer=True) + n = Symbol("n", integer=True) + expr = And(Eq(i, 2 * n), Le(i, 2*n -1)) + assert simplify(expr) == S.false + + +@XFAIL +def test_issue_18389(): + n = Symbol("n", integer=True) + expr = Eq(n, 0) | (n >= 1) + assert simplify(expr) == Ge(n, 0) + + +def test_issue_8373(): + x = Symbol('x', real=True) + assert simplify(Or(x < 1, x >= 1)) == S.true + + +def test_issue_7950(): + expr = And(Eq(x, 1), Eq(x, 2)) + assert simplify(expr) == S.false + + +def test_issue_22020(): + expr = I*pi/2 -oo + assert simplify(expr) == expr + # Used to throw an error + + +def test_issue_19484(): + assert simplify(sign(x) * Abs(x)) == x + + e = x + sign(x + x**3) + assert simplify(Abs(x + x**3)*e) == x**3 + x*Abs(x**3 + x) + x + + e = x**2 + sign(x**3 + 1) + assert simplify(Abs(x**3 + 1) * e) == x**3 + x**2*Abs(x**3 + 1) + 1 + + f = Function('f') + e = x + sign(x + f(x)**3) + assert simplify(Abs(x + f(x)**3) * e) == x*Abs(x + f(x)**3) + x + f(x)**3 + + +def test_issue_23543(): + # Used to give an error + x, y, z = symbols("x y z", commutative=False) + assert (x*(y + z/2)).simplify() == x*(2*y + z)/2 + + +def test_issue_11004(): + + def f(n): + return sqrt(2*pi*n) * (n/E)**n + + def m(n, k): + return f(n) / (f(n/k)**k) + + def p(n,k): + return m(n, k) / (k**n) + + N, k = symbols('N k') + half = Float('0.5', 4) + z = log(p(n, k) / p(n, k + 1)).expand(force=True) + r = simplify(z.subs(n, N).n(4)) + assert r == ( + half*k*log(k) + - half*k*log(k + 1) + + half*log(N) + - half*log(k + 1) + + Float(0.9189224, 4) + ) + + +def test_issue_19161(): + polynomial = Poly('x**2').simplify() + assert (polynomial-x**2).simplify() == 0 + + +def test_issue_22210(): + d = Symbol('d', integer=True) + expr = 2*Derivative(sin(x), (x, d)) + assert expr.simplify() == expr + + +def test_reduce_inverses_nc_pow(): + x, y = symbols("x y", commutative=True) + Z = symbols("Z", commutative=False) + assert simplify(2**Z * y**Z) == 2**Z * y**Z + assert simplify(x**Z * y**Z) == x**Z * y**Z + x, y = symbols("x y", positive=True) + assert expand((x*y)**Z) == x**Z * y**Z + assert simplify(x**Z * y**Z) == expand((x*y)**Z) + +def test_nc_recursion_coeff(): + X = symbols("X", commutative = False) + assert (2 * cos(pi/3) * X).simplify() == X + assert (2.0 * cos(pi/3) * X).simplify() == X diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_sqrtdenest.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_sqrtdenest.py new file mode 100644 index 0000000000000000000000000000000000000000..41c771bb2055a1199d349ae3649f33927d79313a --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_sqrtdenest.py @@ -0,0 +1,204 @@ +from sympy.core.mul import Mul +from sympy.core.numbers import (I, Integer, Rational) +from sympy.core.symbol import Symbol +from sympy.functions.elementary.miscellaneous import (root, sqrt) +from sympy.functions.elementary.trigonometric import cos +from sympy.integrals.integrals import Integral +from sympy.simplify.sqrtdenest import sqrtdenest +from sympy.simplify.sqrtdenest import ( + _subsets as subsets, _sqrt_numeric_denest) + +r2, r3, r5, r6, r7, r10, r15, r29 = [sqrt(x) for x in (2, 3, 5, 6, 7, 10, + 15, 29)] + + +def test_sqrtdenest(): + d = {sqrt(5 + 2 * r6): r2 + r3, + sqrt(5. + 2 * r6): sqrt(5. + 2 * r6), + sqrt(5. + 4*sqrt(5 + 2 * r6)): sqrt(5.0 + 4*r2 + 4*r3), + sqrt(r2): sqrt(r2), + sqrt(5 + r7): sqrt(5 + r7), + sqrt(3 + sqrt(5 + 2*r7)): + 3*r2*(5 + 2*r7)**Rational(1, 4)/(2*sqrt(6 + 3*r7)) + + r2*sqrt(6 + 3*r7)/(2*(5 + 2*r7)**Rational(1, 4)), + sqrt(3 + 2*r3): 3**Rational(3, 4)*(r6/2 + 3*r2/2)/3} + for i in d: + assert sqrtdenest(i) == d[i], i + + +def test_sqrtdenest2(): + assert sqrtdenest(sqrt(16 - 2*r29 + 2*sqrt(55 - 10*r29))) == \ + r5 + sqrt(11 - 2*r29) + e = sqrt(-r5 + sqrt(-2*r29 + 2*sqrt(-10*r29 + 55) + 16)) + assert sqrtdenest(e) == root(-2*r29 + 11, 4) + r = sqrt(1 + r7) + assert sqrtdenest(sqrt(1 + r)) == sqrt(1 + r) + e = sqrt(((1 + sqrt(1 + 2*sqrt(3 + r2 + r5)))**2).expand()) + assert sqrtdenest(e) == 1 + sqrt(1 + 2*sqrt(r2 + r5 + 3)) + + assert sqrtdenest(sqrt(5*r3 + 6*r2)) == \ + sqrt(2)*root(3, 4) + root(3, 4)**3 + + assert sqrtdenest(sqrt(((1 + r5 + sqrt(1 + r3))**2).expand())) == \ + 1 + r5 + sqrt(1 + r3) + + assert sqrtdenest(sqrt(((1 + r5 + r7 + sqrt(1 + r3))**2).expand())) == \ + 1 + sqrt(1 + r3) + r5 + r7 + + e = sqrt(((1 + cos(2) + cos(3) + sqrt(1 + r3))**2).expand()) + assert sqrtdenest(e) == cos(3) + cos(2) + 1 + sqrt(1 + r3) + + e = sqrt(-2*r10 + 2*r2*sqrt(-2*r10 + 11) + 14) + assert sqrtdenest(e) == sqrt(-2*r10 - 2*r2 + 4*r5 + 14) + + # check that the result is not more complicated than the input + z = sqrt(-2*r29 + cos(2) + 2*sqrt(-10*r29 + 55) + 16) + assert sqrtdenest(z) == z + + assert sqrtdenest(sqrt(r6 + sqrt(15))) == sqrt(r6 + sqrt(15)) + + z = sqrt(15 - 2*sqrt(31) + 2*sqrt(55 - 10*r29)) + assert sqrtdenest(z) == z + + +def test_sqrtdenest_rec(): + assert sqrtdenest(sqrt(-4*sqrt(14) - 2*r6 + 4*sqrt(21) + 33)) == \ + -r2 + r3 + 2*r7 + assert sqrtdenest(sqrt(-28*r7 - 14*r5 + 4*sqrt(35) + 82)) == \ + -7 + r5 + 2*r7 + assert sqrtdenest(sqrt(6*r2/11 + 2*sqrt(22)/11 + 6*sqrt(11)/11 + 2)) == \ + sqrt(11)*(r2 + 3 + sqrt(11))/11 + assert sqrtdenest(sqrt(468*r3 + 3024*r2 + 2912*r6 + 19735)) == \ + 9*r3 + 26 + 56*r6 + z = sqrt(-490*r3 - 98*sqrt(115) - 98*sqrt(345) - 2107) + assert sqrtdenest(z) == sqrt(-1)*(7*r5 + 7*r15 + 7*sqrt(23)) + z = sqrt(-4*sqrt(14) - 2*r6 + 4*sqrt(21) + 34) + assert sqrtdenest(z) == z + assert sqrtdenest(sqrt(-8*r2 - 2*r5 + 18)) == -r10 + 1 + r2 + r5 + assert sqrtdenest(sqrt(8*r2 + 2*r5 - 18)) == \ + sqrt(-1)*(-r10 + 1 + r2 + r5) + assert sqrtdenest(sqrt(8*r2/3 + 14*r5/3 + Rational(154, 9))) == \ + -r10/3 + r2 + r5 + 3 + assert sqrtdenest(sqrt(sqrt(2*r6 + 5) + sqrt(2*r7 + 8))) == \ + sqrt(1 + r2 + r3 + r7) + assert sqrtdenest(sqrt(4*r15 + 8*r5 + 12*r3 + 24)) == 1 + r3 + r5 + r15 + + w = 1 + r2 + r3 + r5 + r7 + assert sqrtdenest(sqrt((w**2).expand())) == w + z = sqrt((w**2).expand() + 1) + assert sqrtdenest(z) == z + + z = sqrt(2*r10 + 6*r2 + 4*r5 + 12 + 10*r15 + 30*r3) + assert sqrtdenest(z) == z + + +def test_issue_6241(): + z = sqrt( -320 + 32*sqrt(5) + 64*r15) + assert sqrtdenest(z) == z + + +def test_sqrtdenest3(): + z = sqrt(13 - 2*r10 + 2*r2*sqrt(-2*r10 + 11)) + assert sqrtdenest(z) == -1 + r2 + r10 + assert sqrtdenest(z, max_iter=1) == -1 + sqrt(2) + sqrt(10) + z = sqrt(sqrt(r2 + 2) + 2) + assert sqrtdenest(z) == z + assert sqrtdenest(sqrt(-2*r10 + 4*r2*sqrt(-2*r10 + 11) + 20)) == \ + sqrt(-2*r10 - 4*r2 + 8*r5 + 20) + assert sqrtdenest(sqrt((112 + 70*r2) + (46 + 34*r2)*r5)) == \ + r10 + 5 + 4*r2 + 3*r5 + z = sqrt(5 + sqrt(2*r6 + 5)*sqrt(-2*r29 + 2*sqrt(-10*r29 + 55) + 16)) + r = sqrt(-2*r29 + 11) + assert sqrtdenest(z) == sqrt(r2*r + r3*r + r10 + r15 + 5) + + n = sqrt(2*r6/7 + 2*r7/7 + 2*sqrt(42)/7 + 2) + d = sqrt(16 - 2*r29 + 2*sqrt(55 - 10*r29)) + assert sqrtdenest(n/d) == r7*(1 + r6 + r7)/(Mul(7, (sqrt(-2*r29 + 11) + r5), + evaluate=False)) + + +def test_sqrtdenest4(): + # see Denest_en.pdf in https://github.com/sympy/sympy/issues/3192 + z = sqrt(8 - r2*sqrt(5 - r5) - sqrt(3)*(1 + r5)) + z1 = sqrtdenest(z) + c = sqrt(-r5 + 5) + z1 = ((-r15*c - r3*c + c + r5*c - r6 - r2 + r10 + sqrt(30))/4).expand() + assert sqrtdenest(z) == z1 + + z = sqrt(2*r2*sqrt(r2 + 2) + 5*r2 + 4*sqrt(r2 + 2) + 8) + assert sqrtdenest(z) == r2 + sqrt(r2 + 2) + 2 + + w = 2 + r2 + r3 + (1 + r3)*sqrt(2 + r2 + 5*r3) + z = sqrt((w**2).expand()) + assert sqrtdenest(z) == w.expand() + + +def test_sqrt_symbolic_denest(): + x = Symbol('x') + z = sqrt(((1 + sqrt(sqrt(2 + x) + 3))**2).expand()) + assert sqrtdenest(z) == sqrt((1 + sqrt(sqrt(2 + x) + 3))**2) + z = sqrt(((1 + sqrt(sqrt(2 + cos(1)) + 3))**2).expand()) + assert sqrtdenest(z) == 1 + sqrt(sqrt(2 + cos(1)) + 3) + z = ((1 + cos(2))**4 + 1).expand() + assert sqrtdenest(z) == z + z = sqrt(((1 + sqrt(sqrt(2 + cos(3*x)) + 3))**2 + 1).expand()) + assert sqrtdenest(z) == z + c = cos(3) + c2 = c**2 + assert sqrtdenest(sqrt(2*sqrt(1 + r3)*c + c2 + 1 + r3*c2)) == \ + -1 - sqrt(1 + r3)*c + ra = sqrt(1 + r3) + z = sqrt(20*ra*sqrt(3 + 3*r3) + 12*r3*ra*sqrt(3 + 3*r3) + 64*r3 + 112) + assert sqrtdenest(z) == z + + +def test_issue_5857(): + from sympy.abc import x, y + z = sqrt(1/(4*r3 + 7) + 1) + ans = (r2 + r6)/(r3 + 2) + assert sqrtdenest(z) == ans + assert sqrtdenest(1 + z) == 1 + ans + assert sqrtdenest(Integral(z + 1, (x, 1, 2))) == \ + Integral(1 + ans, (x, 1, 2)) + assert sqrtdenest(x + sqrt(y)) == x + sqrt(y) + ans = (r2 + r6)/(r3 + 2) + assert sqrtdenest(z) == ans + assert sqrtdenest(1 + z) == 1 + ans + assert sqrtdenest(Integral(z + 1, (x, 1, 2))) == \ + Integral(1 + ans, (x, 1, 2)) + assert sqrtdenest(x + sqrt(y)) == x + sqrt(y) + + +def test_subsets(): + assert subsets(1) == [[1]] + assert subsets(4) == [ + [1, 0, 0, 0], [0, 1, 0, 0], [1, 1, 0, 0], [0, 0, 1, 0], [1, 0, 1, 0], + [0, 1, 1, 0], [1, 1, 1, 0], [0, 0, 0, 1], [1, 0, 0, 1], [0, 1, 0, 1], + [1, 1, 0, 1], [0, 0, 1, 1], [1, 0, 1, 1], [0, 1, 1, 1], [1, 1, 1, 1]] + + +def test_issue_5653(): + assert sqrtdenest( + sqrt(2 + sqrt(2 + sqrt(2)))) == sqrt(2 + sqrt(2 + sqrt(2))) + +def test_issue_12420(): + assert sqrtdenest((3 - sqrt(2)*sqrt(4 + 3*I) + 3*I)/2) == I + e = 3 - sqrt(2)*sqrt(4 + I) + 3*I + assert sqrtdenest(e) == e + +def test_sqrt_ratcomb(): + assert sqrtdenest(sqrt(1 + r3) + sqrt(3 + 3*r3) - sqrt(10 + 6*r3)) == 0 + +def test_issue_18041(): + e = -sqrt(-2 + 2*sqrt(3)*I) + assert sqrtdenest(e) == -1 - sqrt(3)*I + +def test_issue_19914(): + a = Integer(-8) + b = Integer(-1) + r = Integer(63) + d2 = a*a - b*b*r + + assert _sqrt_numeric_denest(a, b, r, d2) == \ + sqrt(14)*I/2 + 3*sqrt(2)*I/2 + assert sqrtdenest(sqrt(-8-sqrt(63))) == sqrt(14)*I/2 + 3*sqrt(2)*I/2 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_trigsimp.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_trigsimp.py new file mode 100644 index 0000000000000000000000000000000000000000..ea091ec8a6c7d654405968e3d035c2bbe02ccdf7 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/simplify/tests/test_trigsimp.py @@ -0,0 +1,520 @@ +from itertools import product +from sympy.core.function import (Subs, count_ops, diff, expand) +from sympy.core.numbers import (E, I, Rational, pi) +from sympy.core.singleton import S +from sympy.core.symbol import (Symbol, symbols) +from sympy.functions.elementary.exponential import (exp, log) +from sympy.functions.elementary.hyperbolic import (cosh, coth, sinh, tanh) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.piecewise import Piecewise +from sympy.functions.elementary.trigonometric import (cos, cot, sin, tan) +from sympy.functions.elementary.trigonometric import (acos, asin, atan2) +from sympy.functions.elementary.trigonometric import (asec, acsc) +from sympy.functions.elementary.trigonometric import (acot, atan) +from sympy.integrals.integrals import integrate +from sympy.matrices.dense import Matrix +from sympy.simplify.simplify import simplify +from sympy.simplify.trigsimp import (exptrigsimp, trigsimp) + +from sympy.testing.pytest import XFAIL + +from sympy.abc import x, y + + + +def test_trigsimp1(): + x, y = symbols('x,y') + + assert trigsimp(1 - sin(x)**2) == cos(x)**2 + assert trigsimp(1 - cos(x)**2) == sin(x)**2 + assert trigsimp(sin(x)**2 + cos(x)**2) == 1 + assert trigsimp(1 + tan(x)**2) == 1/cos(x)**2 + assert trigsimp(1/cos(x)**2 - 1) == tan(x)**2 + assert trigsimp(1/cos(x)**2 - tan(x)**2) == 1 + assert trigsimp(1 + cot(x)**2) == 1/sin(x)**2 + assert trigsimp(1/sin(x)**2 - 1) == 1/tan(x)**2 + assert trigsimp(1/sin(x)**2 - cot(x)**2) == 1 + + assert trigsimp(5*cos(x)**2 + 5*sin(x)**2) == 5 + assert trigsimp(5*cos(x/2)**2 + 2*sin(x/2)**2) == 3*cos(x)/2 + Rational(7, 2) + + assert trigsimp(sin(x)/cos(x)) == tan(x) + assert trigsimp(2*tan(x)*cos(x)) == 2*sin(x) + assert trigsimp(cot(x)**3*sin(x)**3) == cos(x)**3 + assert trigsimp(y*tan(x)**2/sin(x)**2) == y/cos(x)**2 + assert trigsimp(cot(x)/cos(x)) == 1/sin(x) + + assert trigsimp(sin(x + y) + sin(x - y)) == 2*sin(x)*cos(y) + assert trigsimp(sin(x + y) - sin(x - y)) == 2*sin(y)*cos(x) + assert trigsimp(cos(x + y) + cos(x - y)) == 2*cos(x)*cos(y) + assert trigsimp(cos(x + y) - cos(x - y)) == -2*sin(x)*sin(y) + assert trigsimp(tan(x + y) - tan(x)/(1 - tan(x)*tan(y))) == \ + sin(y)/(-sin(y)*tan(x) + cos(y)) # -tan(y)/(tan(x)*tan(y) - 1) + + assert trigsimp(sinh(x + y) + sinh(x - y)) == 2*sinh(x)*cosh(y) + assert trigsimp(sinh(x + y) - sinh(x - y)) == 2*sinh(y)*cosh(x) + assert trigsimp(cosh(x + y) + cosh(x - y)) == 2*cosh(x)*cosh(y) + assert trigsimp(cosh(x + y) - cosh(x - y)) == 2*sinh(x)*sinh(y) + assert trigsimp(tanh(x + y) - tanh(x)/(1 + tanh(x)*tanh(y))) == \ + sinh(y)/(sinh(y)*tanh(x) + cosh(y)) + + assert trigsimp(cos(0.12345)**2 + sin(0.12345)**2) == 1.0 + e = 2*sin(x)**2 + 2*cos(x)**2 + assert trigsimp(log(e)) == log(2) + + +def test_trigsimp1a(): + assert trigsimp(sin(2)**2*cos(3)*exp(2)/cos(2)**2) == tan(2)**2*cos(3)*exp(2) + assert trigsimp(tan(2)**2*cos(3)*exp(2)*cos(2)**2) == sin(2)**2*cos(3)*exp(2) + assert trigsimp(cot(2)*cos(3)*exp(2)*sin(2)) == cos(3)*exp(2)*cos(2) + assert trigsimp(tan(2)*cos(3)*exp(2)/sin(2)) == cos(3)*exp(2)/cos(2) + assert trigsimp(cot(2)*cos(3)*exp(2)/cos(2)) == cos(3)*exp(2)/sin(2) + assert trigsimp(cot(2)*cos(3)*exp(2)*tan(2)) == cos(3)*exp(2) + assert trigsimp(sinh(2)*cos(3)*exp(2)/cosh(2)) == tanh(2)*cos(3)*exp(2) + assert trigsimp(tanh(2)*cos(3)*exp(2)*cosh(2)) == sinh(2)*cos(3)*exp(2) + assert trigsimp(coth(2)*cos(3)*exp(2)*sinh(2)) == cosh(2)*cos(3)*exp(2) + assert trigsimp(tanh(2)*cos(3)*exp(2)/sinh(2)) == cos(3)*exp(2)/cosh(2) + assert trigsimp(coth(2)*cos(3)*exp(2)/cosh(2)) == cos(3)*exp(2)/sinh(2) + assert trigsimp(coth(2)*cos(3)*exp(2)*tanh(2)) == cos(3)*exp(2) + + +def test_trigsimp2(): + x, y = symbols('x,y') + assert trigsimp(cos(x)**2*sin(y)**2 + cos(x)**2*cos(y)**2 + sin(x)**2, + recursive=True) == 1 + assert trigsimp(sin(x)**2*sin(y)**2 + sin(x)**2*cos(y)**2 + cos(x)**2, + recursive=True) == 1 + assert trigsimp( + Subs(x, x, sin(y)**2 + cos(y)**2)) == Subs(x, x, 1) + + +def test_issue_4373(): + x = Symbol("x") + assert abs(trigsimp(2.0*sin(x)**2 + 2.0*cos(x)**2) - 2.0) < 1e-10 + + +def test_trigsimp3(): + x, y = symbols('x,y') + assert trigsimp(sin(x)/cos(x)) == tan(x) + assert trigsimp(sin(x)**2/cos(x)**2) == tan(x)**2 + assert trigsimp(sin(x)**3/cos(x)**3) == tan(x)**3 + assert trigsimp(sin(x)**10/cos(x)**10) == tan(x)**10 + + assert trigsimp(cos(x)/sin(x)) == 1/tan(x) + assert trigsimp(cos(x)**2/sin(x)**2) == 1/tan(x)**2 + assert trigsimp(cos(x)**10/sin(x)**10) == 1/tan(x)**10 + + assert trigsimp(tan(x)) == trigsimp(sin(x)/cos(x)) + + +def test_issue_4661(): + a, x, y = symbols('a x y') + eq = -4*sin(x)**4 + 4*cos(x)**4 - 8*cos(x)**2 + assert trigsimp(eq) == -4 + n = sin(x)**6 + 4*sin(x)**4*cos(x)**2 + 5*sin(x)**2*cos(x)**4 + 2*cos(x)**6 + d = -sin(x)**2 - 2*cos(x)**2 + assert simplify(n/d) == -1 + assert trigsimp(-2*cos(x)**2 + cos(x)**4 - sin(x)**4) == -1 + eq = (- sin(x)**3/4)*cos(x) + (cos(x)**3/4)*sin(x) - sin(2*x)*cos(2*x)/8 + assert trigsimp(eq) == 0 + + +def test_issue_4494(): + a, b = symbols('a b') + eq = sin(a)**2*sin(b)**2 + cos(a)**2*cos(b)**2*tan(a)**2 + cos(a)**2 + assert trigsimp(eq) == 1 + + +def test_issue_5948(): + a, x, y = symbols('a x y') + assert trigsimp(diff(integrate(cos(x)/sin(x)**7, x), x)) == \ + cos(x)/sin(x)**7 + + +def test_issue_4775(): + a, x, y = symbols('a x y') + assert trigsimp(sin(x)*cos(y)+cos(x)*sin(y)) == sin(x + y) + assert trigsimp(sin(x)*cos(y)+cos(x)*sin(y)+3) == sin(x + y) + 3 + + +def test_issue_4280(): + a, x, y = symbols('a x y') + assert trigsimp(cos(x)**2 + cos(y)**2*sin(x)**2 + sin(y)**2*sin(x)**2) == 1 + assert trigsimp(a**2*sin(x)**2 + a**2*cos(y)**2*cos(x)**2 + a**2*cos(x)**2*sin(y)**2) == a**2 + assert trigsimp(a**2*cos(y)**2*sin(x)**2 + a**2*sin(y)**2*sin(x)**2) == a**2*sin(x)**2 + + +def test_issue_3210(): + eqs = (sin(2)*cos(3) + sin(3)*cos(2), + -sin(2)*sin(3) + cos(2)*cos(3), + sin(2)*cos(3) - sin(3)*cos(2), + sin(2)*sin(3) + cos(2)*cos(3), + sin(2)*sin(3) + cos(2)*cos(3) + cos(2), + sinh(2)*cosh(3) + sinh(3)*cosh(2), + sinh(2)*sinh(3) + cosh(2)*cosh(3), + ) + assert [trigsimp(e) for e in eqs] == [ + sin(5), + cos(5), + -sin(1), + cos(1), + cos(1) + cos(2), + sinh(5), + cosh(5), + ] + + +def test_trigsimp_issues(): + a, x, y = symbols('a x y') + + # issue 4625 - factor_terms works, too + assert trigsimp(sin(x)**3 + cos(x)**2*sin(x)) == sin(x) + + # issue 5948 + assert trigsimp(diff(integrate(cos(x)/sin(x)**3, x), x)) == \ + cos(x)/sin(x)**3 + assert trigsimp(diff(integrate(sin(x)/cos(x)**3, x), x)) == \ + sin(x)/cos(x)**3 + + # check integer exponents + e = sin(x)**y/cos(x)**y + assert trigsimp(e) == e + assert trigsimp(e.subs(y, 2)) == tan(x)**2 + assert trigsimp(e.subs(x, 1)) == tan(1)**y + + # check for multiple patterns + assert (cos(x)**2/sin(x)**2*cos(y)**2/sin(y)**2).trigsimp() == \ + 1/tan(x)**2/tan(y)**2 + assert trigsimp(cos(x)/sin(x)*cos(x+y)/sin(x+y)) == \ + 1/(tan(x)*tan(x + y)) + + eq = cos(2)*(cos(3) + 1)**2/(cos(3) - 1)**2 + assert trigsimp(eq) == eq.factor() # factor makes denom (-1 + cos(3))**2 + assert trigsimp(cos(2)*(cos(3) + 1)**2*(cos(3) - 1)**2) == \ + cos(2)*sin(3)**4 + + # issue 6789; this generates an expression that formerly caused + # trigsimp to hang + assert cot(x).equals(tan(x)) is False + + # nan or the unchanged expression is ok, but not sin(1) + z = cos(x)**2 + sin(x)**2 - 1 + z1 = tan(x)**2 - 1/cot(x)**2 + n = (1 + z1/z) + assert trigsimp(sin(n)) != sin(1) + eq = x*(n - 1) - x*n + assert trigsimp(eq) is S.NaN + assert trigsimp(eq, recursive=True) is S.NaN + assert trigsimp(1).is_Integer + + assert trigsimp(-sin(x)**4 - 2*sin(x)**2*cos(x)**2 - cos(x)**4) == -1 + + +def test_trigsimp_issue_2515(): + x = Symbol('x') + assert trigsimp(x*cos(x)*tan(x)) == x*sin(x) + assert trigsimp(-sin(x) + cos(x)*tan(x)) == 0 + + +def test_trigsimp_issue_3826(): + assert trigsimp(tan(2*x).expand(trig=True)) == tan(2*x) + + +def test_trigsimp_issue_4032(): + n = Symbol('n', integer=True, positive=True) + assert trigsimp(2**(n/2)*cos(pi*n/4)/2 + 2**(n - 1)/2) == \ + 2**(n/2)*cos(pi*n/4)/2 + 2**n/4 + + +def test_trigsimp_issue_7761(): + assert trigsimp(cosh(pi/4)) == cosh(pi/4) + + +def test_trigsimp_noncommutative(): + x, y = symbols('x,y') + A, B = symbols('A,B', commutative=False) + + assert trigsimp(A - A*sin(x)**2) == A*cos(x)**2 + assert trigsimp(A - A*cos(x)**2) == A*sin(x)**2 + assert trigsimp(A*sin(x)**2 + A*cos(x)**2) == A + assert trigsimp(A + A*tan(x)**2) == A/cos(x)**2 + assert trigsimp(A/cos(x)**2 - A) == A*tan(x)**2 + assert trigsimp(A/cos(x)**2 - A*tan(x)**2) == A + assert trigsimp(A + A*cot(x)**2) == A/sin(x)**2 + assert trigsimp(A/sin(x)**2 - A) == A/tan(x)**2 + assert trigsimp(A/sin(x)**2 - A*cot(x)**2) == A + + assert trigsimp(y*A*cos(x)**2 + y*A*sin(x)**2) == y*A + + assert trigsimp(A*sin(x)/cos(x)) == A*tan(x) + assert trigsimp(A*tan(x)*cos(x)) == A*sin(x) + assert trigsimp(A*cot(x)**3*sin(x)**3) == A*cos(x)**3 + assert trigsimp(y*A*tan(x)**2/sin(x)**2) == y*A/cos(x)**2 + assert trigsimp(A*cot(x)/cos(x)) == A/sin(x) + + assert trigsimp(A*sin(x + y) + A*sin(x - y)) == 2*A*sin(x)*cos(y) + assert trigsimp(A*sin(x + y) - A*sin(x - y)) == 2*A*sin(y)*cos(x) + assert trigsimp(A*cos(x + y) + A*cos(x - y)) == 2*A*cos(x)*cos(y) + assert trigsimp(A*cos(x + y) - A*cos(x - y)) == -2*A*sin(x)*sin(y) + + assert trigsimp(A*sinh(x + y) + A*sinh(x - y)) == 2*A*sinh(x)*cosh(y) + assert trigsimp(A*sinh(x + y) - A*sinh(x - y)) == 2*A*sinh(y)*cosh(x) + assert trigsimp(A*cosh(x + y) + A*cosh(x - y)) == 2*A*cosh(x)*cosh(y) + assert trigsimp(A*cosh(x + y) - A*cosh(x - y)) == 2*A*sinh(x)*sinh(y) + + assert trigsimp(A*cos(0.12345)**2 + A*sin(0.12345)**2) == 1.0*A + + +def test_hyperbolic_simp(): + x, y = symbols('x,y') + + assert trigsimp(sinh(x)**2 + 1) == cosh(x)**2 + assert trigsimp(cosh(x)**2 - 1) == sinh(x)**2 + assert trigsimp(cosh(x)**2 - sinh(x)**2) == 1 + assert trigsimp(1 - tanh(x)**2) == 1/cosh(x)**2 + assert trigsimp(1 - 1/cosh(x)**2) == tanh(x)**2 + assert trigsimp(tanh(x)**2 + 1/cosh(x)**2) == 1 + assert trigsimp(coth(x)**2 - 1) == 1/sinh(x)**2 + assert trigsimp(1/sinh(x)**2 + 1) == 1/tanh(x)**2 + assert trigsimp(coth(x)**2 - 1/sinh(x)**2) == 1 + + assert trigsimp(5*cosh(x)**2 - 5*sinh(x)**2) == 5 + assert trigsimp(5*cosh(x/2)**2 - 2*sinh(x/2)**2) == 3*cosh(x)/2 + Rational(7, 2) + + assert trigsimp(sinh(x)/cosh(x)) == tanh(x) + assert trigsimp(tanh(x)) == trigsimp(sinh(x)/cosh(x)) + assert trigsimp(cosh(x)/sinh(x)) == 1/tanh(x) + assert trigsimp(2*tanh(x)*cosh(x)) == 2*sinh(x) + assert trigsimp(coth(x)**3*sinh(x)**3) == cosh(x)**3 + assert trigsimp(y*tanh(x)**2/sinh(x)**2) == y/cosh(x)**2 + assert trigsimp(coth(x)/cosh(x)) == 1/sinh(x) + + for a in (pi/6*I, pi/4*I, pi/3*I): + assert trigsimp(sinh(a)*cosh(x) + cosh(a)*sinh(x)) == sinh(x + a) + assert trigsimp(-sinh(a)*cosh(x) + cosh(a)*sinh(x)) == sinh(x - a) + + e = 2*cosh(x)**2 - 2*sinh(x)**2 + assert trigsimp(log(e)) == log(2) + + # issue 19535: + assert trigsimp(sqrt(cosh(x)**2 - 1)) == sqrt(sinh(x)**2) + + assert trigsimp(cosh(x)**2*cosh(y)**2 - cosh(x)**2*sinh(y)**2 - sinh(x)**2, + recursive=True) == 1 + assert trigsimp(sinh(x)**2*sinh(y)**2 - sinh(x)**2*cosh(y)**2 + cosh(x)**2, + recursive=True) == 1 + + assert abs(trigsimp(2.0*cosh(x)**2 - 2.0*sinh(x)**2) - 2.0) < 1e-10 + + assert trigsimp(sinh(x)**2/cosh(x)**2) == tanh(x)**2 + assert trigsimp(sinh(x)**3/cosh(x)**3) == tanh(x)**3 + assert trigsimp(sinh(x)**10/cosh(x)**10) == tanh(x)**10 + assert trigsimp(cosh(x)**3/sinh(x)**3) == 1/tanh(x)**3 + + assert trigsimp(cosh(x)/sinh(x)) == 1/tanh(x) + assert trigsimp(cosh(x)**2/sinh(x)**2) == 1/tanh(x)**2 + assert trigsimp(cosh(x)**10/sinh(x)**10) == 1/tanh(x)**10 + + assert trigsimp(x*cosh(x)*tanh(x)) == x*sinh(x) + assert trigsimp(-sinh(x) + cosh(x)*tanh(x)) == 0 + + assert tan(x) != 1/cot(x) # cot doesn't auto-simplify + + assert trigsimp(tan(x) - 1/cot(x)) == 0 + assert trigsimp(3*tanh(x)**7 - 2/coth(x)**7) == tanh(x)**7 + + +def test_trigsimp_groebner(): + from sympy.simplify.trigsimp import trigsimp_groebner + + c = cos(x) + s = sin(x) + ex = (4*s*c + 12*s + 5*c**3 + 21*c**2 + 23*c + 15)/( + -s*c**2 + 2*s*c + 15*s + 7*c**3 + 31*c**2 + 37*c + 21) + resnum = (5*s - 5*c + 1) + resdenom = (8*s - 6*c) + results = [resnum/resdenom, (-resnum)/(-resdenom)] + assert trigsimp_groebner(ex) in results + assert trigsimp_groebner(s/c, hints=[tan]) == tan(x) + assert trigsimp_groebner(c*s) == c*s + assert trigsimp((-s + 1)/c + c/(-s + 1), + method='groebner') == 2/c + assert trigsimp((-s + 1)/c + c/(-s + 1), + method='groebner', polynomial=True) == 2/c + + # Test quick=False works + assert trigsimp_groebner(ex, hints=[2]) in results + assert trigsimp_groebner(ex, hints=[int(2)]) in results + + # test "I" + assert trigsimp_groebner(sin(I*x)/cos(I*x), hints=[tanh]) == I*tanh(x) + + # test hyperbolic / sums + assert trigsimp_groebner((tanh(x)+tanh(y))/(1+tanh(x)*tanh(y)), + hints=[(tanh, x, y)]) == tanh(x + y) + + +def test_issue_2827_trigsimp_methods(): + measure1 = lambda expr: len(str(expr)) + measure2 = lambda expr: -count_ops(expr) + # Return the most complicated result + expr = (x + 1)/(x + sin(x)**2 + cos(x)**2) + ans = Matrix([1]) + M = Matrix([expr]) + assert trigsimp(M, method='fu', measure=measure1) == ans + assert trigsimp(M, method='fu', measure=measure2) != ans + # all methods should work with Basic expressions even if they + # aren't Expr + M = Matrix.eye(1) + assert all(trigsimp(M, method=m) == M for m in + 'fu matching groebner old'.split()) + # watch for E in exptrigsimp, not only exp() + eq = 1/sqrt(E) + E + assert exptrigsimp(eq) == eq + +def test_issue_15129_trigsimp_methods(): + t1 = Matrix([sin(Rational(1, 50)), cos(Rational(1, 50)), 0]) + t2 = Matrix([sin(Rational(1, 25)), cos(Rational(1, 25)), 0]) + t3 = Matrix([cos(Rational(1, 25)), sin(Rational(1, 25)), 0]) + r1 = t1.dot(t2) + r2 = t1.dot(t3) + assert trigsimp(r1) == cos(Rational(1, 50)) + assert trigsimp(r2) == sin(Rational(3, 50)) + +def test_exptrigsimp(): + def valid(a, b): + from sympy.core.random import verify_numerically as tn + if not (tn(a, b) and a == b): + return False + return True + + assert exptrigsimp(exp(x) + exp(-x)) == 2*cosh(x) + assert exptrigsimp(exp(x) - exp(-x)) == 2*sinh(x) + assert exptrigsimp((2*exp(x)-2*exp(-x))/(exp(x)+exp(-x))) == 2*tanh(x) + assert exptrigsimp((2*exp(2*x)-2)/(exp(2*x)+1)) == 2*tanh(x) + e = [cos(x) + I*sin(x), cos(x) - I*sin(x), + cosh(x) - sinh(x), cosh(x) + sinh(x)] + ok = [exp(I*x), exp(-I*x), exp(-x), exp(x)] + assert all(valid(i, j) for i, j in zip( + [exptrigsimp(ei) for ei in e], ok)) + + ue = [cos(x) + sin(x), cos(x) - sin(x), + cosh(x) + I*sinh(x), cosh(x) - I*sinh(x)] + assert [exptrigsimp(ei) == ei for ei in ue] + + res = [] + ok = [y*tanh(1), 1/(y*tanh(1)), I*y*tan(1), -I/(y*tan(1)), + y*tanh(x), 1/(y*tanh(x)), I*y*tan(x), -I/(y*tan(x)), + y*tanh(1 + I), 1/(y*tanh(1 + I))] + for a in (1, I, x, I*x, 1 + I): + w = exp(a) + eq = y*(w - 1/w)/(w + 1/w) + res.append(simplify(eq)) + res.append(simplify(1/eq)) + assert all(valid(i, j) for i, j in zip(res, ok)) + + for a in range(1, 3): + w = exp(a) + e = w + 1/w + s = simplify(e) + assert s == exptrigsimp(e) + assert valid(s, 2*cosh(a)) + e = w - 1/w + s = simplify(e) + assert s == exptrigsimp(e) + assert valid(s, 2*sinh(a)) + +def test_exptrigsimp_noncommutative(): + a,b = symbols('a b', commutative=False) + x = Symbol('x', commutative=True) + assert exp(a + x) == exptrigsimp(exp(a)*exp(x)) + p = exp(a)*exp(b) - exp(b)*exp(a) + assert p == exptrigsimp(p) != 0 + +def test_powsimp_on_numbers(): + assert 2**(Rational(1, 3) - 2) == 2**Rational(1, 3)/4 + + +@XFAIL +def test_issue_6811_fail(): + # from doc/src/modules/physics/mechanics/examples.rst, the current `eq` + # at Line 576 (in different variables) was formerly the equivalent and + # shorter expression given below...it would be nice to get the short one + # back again + xp, y, x, z = symbols('xp, y, x, z') + eq = 4*(-19*sin(x)*y + 5*sin(3*x)*y + 15*cos(2*x)*z - 21*z)*xp/(9*cos(x) - 5*cos(3*x)) + assert trigsimp(eq) == -2*(2*cos(x)*tan(x)*y + 3*z)*xp/cos(x) + + +def test_Piecewise(): + e1 = x*(x + y) - y*(x + y) + e2 = sin(x)**2 + cos(x)**2 + e3 = expand((x + y)*y/x) + # s1 = simplify(e1) + s2 = simplify(e2) + # s3 = simplify(e3) + + # trigsimp tries not to touch non-trig containing args + assert trigsimp(Piecewise((e1, e3 < e2), (e3, True))) == \ + Piecewise((e1, e3 < s2), (e3, True)) + + +def test_issue_21594(): + assert simplify(exp(Rational(1,2)) + exp(Rational(-1,2))) == cosh(S.Half)*2 + + +def test_trigsimp_old(): + x, y = symbols('x,y') + + assert trigsimp(1 - sin(x)**2, old=True) == cos(x)**2 + assert trigsimp(1 - cos(x)**2, old=True) == sin(x)**2 + assert trigsimp(sin(x)**2 + cos(x)**2, old=True) == 1 + assert trigsimp(1 + tan(x)**2, old=True) == 1/cos(x)**2 + assert trigsimp(1/cos(x)**2 - 1, old=True) == tan(x)**2 + assert trigsimp(1/cos(x)**2 - tan(x)**2, old=True) == 1 + assert trigsimp(1 + cot(x)**2, old=True) == 1/sin(x)**2 + assert trigsimp(1/sin(x)**2 - cot(x)**2, old=True) == 1 + + assert trigsimp(5*cos(x)**2 + 5*sin(x)**2, old=True) == 5 + + assert trigsimp(sin(x)/cos(x), old=True) == tan(x) + assert trigsimp(2*tan(x)*cos(x), old=True) == 2*sin(x) + assert trigsimp(cot(x)**3*sin(x)**3, old=True) == cos(x)**3 + assert trigsimp(y*tan(x)**2/sin(x)**2, old=True) == y/cos(x)**2 + assert trigsimp(cot(x)/cos(x), old=True) == 1/sin(x) + + assert trigsimp(sin(x + y) + sin(x - y), old=True) == 2*sin(x)*cos(y) + assert trigsimp(sin(x + y) - sin(x - y), old=True) == 2*sin(y)*cos(x) + assert trigsimp(cos(x + y) + cos(x - y), old=True) == 2*cos(x)*cos(y) + assert trigsimp(cos(x + y) - cos(x - y), old=True) == -2*sin(x)*sin(y) + + assert trigsimp(sinh(x + y) + sinh(x - y), old=True) == 2*sinh(x)*cosh(y) + assert trigsimp(sinh(x + y) - sinh(x - y), old=True) == 2*sinh(y)*cosh(x) + assert trigsimp(cosh(x + y) + cosh(x - y), old=True) == 2*cosh(x)*cosh(y) + assert trigsimp(cosh(x + y) - cosh(x - y), old=True) == 2*sinh(x)*sinh(y) + + assert trigsimp(cos(0.12345)**2 + sin(0.12345)**2, old=True) == 1.0 + + assert trigsimp(sin(x)/cos(x), old=True, method='combined') == tan(x) + assert trigsimp(sin(x)/cos(x), old=True, method='groebner') == sin(x)/cos(x) + assert trigsimp(sin(x)/cos(x), old=True, method='groebner', hints=[tan]) == tan(x) + + assert trigsimp(1-sin(sin(x)**2+cos(x)**2)**2, old=True, deep=True) == cos(1)**2 + + +def test_trigsimp_inverse(): + alpha = symbols('alpha') + s, c = sin(alpha), cos(alpha) + + for finv in [asin, acos, asec, acsc, atan, acot]: + f = finv.inverse(None) + assert alpha == trigsimp(finv(f(alpha)), inverse=True) + + # test atan2(cos, sin), atan2(sin, cos), etc... + for a, b in [[c, s], [s, c]]: + for i, j in product([-1, 1], repeat=2): + angle = atan2(i*b, j*a) + angle_inverted = trigsimp(angle, inverse=True) + assert angle_inverted != angle # assures simplification happened + assert sin(angle_inverted) == trigsimp(sin(angle)) + assert cos(angle_inverted) == trigsimp(cos(angle)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1694f232ac8628e5f3bff62717124adb34b36463 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/__pycache__/core.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/__pycache__/core.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aea81367a1855b484c3b028cc3d63033a7b67356 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/__pycache__/core.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/__pycache__/rl.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/__pycache__/rl.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..721641bd00517df55ff355d32b617b2a11866986 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/__pycache__/rl.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/__pycache__/tools.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/__pycache__/tools.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bd27a4caa61a0a7b605ec47c6a8f9d7e0fe3c8df Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/__pycache__/tools.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/__pycache__/traverse.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/__pycache__/traverse.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b66c37be8b8b67d80a26cfc4dd24280ad011a7bf Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/__pycache__/traverse.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/__pycache__/tree.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/__pycache__/tree.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5cdc01b4f82f649b5b9ab2143d811f7cda8e19e2 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/__pycache__/tree.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/__pycache__/util.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/__pycache__/util.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c6e331b594c0183b08e8486456237b10b8a42362 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/__pycache__/util.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..fec5afe84a58f3d887a8c762692a3673a2b6d4c8 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/__init__.py @@ -0,0 +1,14 @@ +from . import traverse +from .core import ( + condition, debug, multiplex, exhaust, notempty, + chain, onaction, sfilter, yieldify, do_one, identity) +from .tools import canon + +__all__ = [ + 'traverse', + + 'condition', 'debug', 'multiplex', 'exhaust', 'notempty', 'chain', + 'onaction', 'sfilter', 'yieldify', 'do_one', 'identity', + + 'canon', +] diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6580439112312973896a31680adcbf8630a45fde Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/__pycache__/core.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/__pycache__/core.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1d559a5e91df4f5fe615d20e0d3d77efb9198068 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/__pycache__/core.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/__pycache__/tools.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/__pycache__/tools.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3ca299672bdea6a2001fda7861dbce39248fa4a3 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/__pycache__/tools.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/__pycache__/traverse.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/__pycache__/traverse.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fcd10739bdd764c04ca499cae410118ab8cd9348 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/__pycache__/traverse.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/core.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/core.py new file mode 100644 index 0000000000000000000000000000000000000000..2dabaef69b60d994799f71414699223f84e1809b --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/core.py @@ -0,0 +1,116 @@ +""" Generic SymPy-Independent Strategies """ + + +def identity(x): + yield x + + +def exhaust(brule): + """ Apply a branching rule repeatedly until it has no effect """ + def exhaust_brl(expr): + seen = {expr} + for nexpr in brule(expr): + if nexpr not in seen: + seen.add(nexpr) + yield from exhaust_brl(nexpr) + if seen == {expr}: + yield expr + return exhaust_brl + + +def onaction(brule, fn): + def onaction_brl(expr): + for result in brule(expr): + if result != expr: + fn(brule, expr, result) + yield result + return onaction_brl + + +def debug(brule, file=None): + """ Print the input and output expressions at each rule application """ + if not file: + from sys import stdout + file = stdout + + def write(brl, expr, result): + file.write("Rule: %s\n" % brl.__name__) + file.write("In: %s\nOut: %s\n\n" % (expr, result)) + + return onaction(brule, write) + + +def multiplex(*brules): + """ Multiplex many branching rules into one """ + def multiplex_brl(expr): + seen = set() + for brl in brules: + for nexpr in brl(expr): + if nexpr not in seen: + seen.add(nexpr) + yield nexpr + return multiplex_brl + + +def condition(cond, brule): + """ Only apply branching rule if condition is true """ + def conditioned_brl(expr): + if cond(expr): + yield from brule(expr) + else: + pass + return conditioned_brl + + +def sfilter(pred, brule): + """ Yield only those results which satisfy the predicate """ + def filtered_brl(expr): + yield from filter(pred, brule(expr)) + return filtered_brl + + +def notempty(brule): + def notempty_brl(expr): + yielded = False + for nexpr in brule(expr): + yielded = True + yield nexpr + if not yielded: + yield expr + return notempty_brl + + +def do_one(*brules): + """ Execute one of the branching rules """ + def do_one_brl(expr): + yielded = False + for brl in brules: + for nexpr in brl(expr): + yielded = True + yield nexpr + if yielded: + return + return do_one_brl + + +def chain(*brules): + """ + Compose a sequence of brules so that they apply to the expr sequentially + """ + def chain_brl(expr): + if not brules: + yield expr + return + + head, tail = brules[0], brules[1:] + for nexpr in head(expr): + yield from chain(*tail)(nexpr) + + return chain_brl + + +def yieldify(rl): + """ Turn a rule into a branching rule """ + def brl(expr): + yield rl(expr) + return brl diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a41bcbbe18c817d2387b29358d076abbffdb51bc Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/tests/__pycache__/test_core.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/tests/__pycache__/test_core.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a377d466a55ac7d74811433574c38bbeca93e0a3 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/tests/__pycache__/test_core.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/tests/__pycache__/test_tools.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/tests/__pycache__/test_tools.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dc0784c69e4f3491283a155186f6b45acd2e9f46 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/tests/__pycache__/test_tools.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/tests/__pycache__/test_traverse.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/tests/__pycache__/test_traverse.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..21bd6fa13900e1a90d1ce76cff744585dee6d18c Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/tests/__pycache__/test_traverse.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/tests/test_core.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/tests/test_core.py new file mode 100644 index 0000000000000000000000000000000000000000..ac620b0afb6dbadc4d97b29ddbb341cd920b6588 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/tests/test_core.py @@ -0,0 +1,117 @@ +from sympy.strategies.branch.core import ( + exhaust, debug, multiplex, condition, notempty, chain, onaction, sfilter, + yieldify, do_one, identity) + + +def posdec(x): + if x > 0: + yield x - 1 + else: + yield x + + +def branch5(x): + if 0 < x < 5: + yield x - 1 + elif 5 < x < 10: + yield x + 1 + elif x == 5: + yield x + 1 + yield x - 1 + else: + yield x + + +def even(x): + return x % 2 == 0 + + +def inc(x): + yield x + 1 + + +def one_to_n(n): + yield from range(n) + + +def test_exhaust(): + brl = exhaust(branch5) + assert set(brl(3)) == {0} + assert set(brl(7)) == {10} + assert set(brl(5)) == {0, 10} + + +def test_debug(): + from io import StringIO + file = StringIO() + rl = debug(posdec, file) + list(rl(5)) + log = file.getvalue() + file.close() + + assert posdec.__name__ in log + assert '5' in log + assert '4' in log + + +def test_multiplex(): + brl = multiplex(posdec, branch5) + assert set(brl(3)) == {2} + assert set(brl(7)) == {6, 8} + assert set(brl(5)) == {4, 6} + + +def test_condition(): + brl = condition(even, branch5) + assert set(brl(4)) == set(branch5(4)) + assert set(brl(5)) == set() + + +def test_sfilter(): + brl = sfilter(even, one_to_n) + assert set(brl(10)) == {0, 2, 4, 6, 8} + + +def test_notempty(): + def ident_if_even(x): + if even(x): + yield x + + brl = notempty(ident_if_even) + assert set(brl(4)) == {4} + assert set(brl(5)) == {5} + + +def test_chain(): + assert list(chain()(2)) == [2] # identity + assert list(chain(inc, inc)(2)) == [4] + assert list(chain(branch5, inc)(4)) == [4] + assert set(chain(branch5, inc)(5)) == {5, 7} + assert list(chain(inc, branch5)(5)) == [7] + + +def test_onaction(): + L = [] + + def record(fn, input, output): + L.append((input, output)) + + list(onaction(inc, record)(2)) + assert L == [(2, 3)] + + list(onaction(identity, record)(2)) + assert L == [(2, 3)] + + +def test_yieldify(): + yinc = yieldify(lambda x: x + 1) + assert list(yinc(3)) == [4] + + +def test_do_one(): + def bad(expr): + raise ValueError + + assert list(do_one(inc)(3)) == [4] + assert list(do_one(inc, bad)(3)) == [4] + assert list(do_one(inc, posdec)(3)) == [4] diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/tests/test_tools.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/tests/test_tools.py new file mode 100644 index 0000000000000000000000000000000000000000..c2bd224030c337f0a000d94f6e7e65f3b8bd118f --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/tests/test_tools.py @@ -0,0 +1,42 @@ +from sympy.strategies.branch.tools import canon +from sympy.core.basic import Basic +from sympy.core.numbers import Integer +from sympy.core.singleton import S + + +def posdec(x): + if isinstance(x, Integer) and x > 0: + yield x - 1 + else: + yield x + + +def branch5(x): + if isinstance(x, Integer): + if 0 < x < 5: + yield x - 1 + elif 5 < x < 10: + yield x + 1 + elif x == 5: + yield x + 1 + yield x - 1 + else: + yield x + + +def test_zero_ints(): + expr = Basic(S(2), Basic(S(5), S(3)), S(8)) + expected = {Basic(S(0), Basic(S(0), S(0)), S(0))} + + brl = canon(posdec) + assert set(brl(expr)) == expected + + +def test_split5(): + expr = Basic(S(2), Basic(S(5), S(3)), S(8)) + expected = { + Basic(S(0), Basic(S(0), S(0)), S(10)), + Basic(S(0), Basic(S(10), S(0)), S(10))} + + brl = canon(branch5) + assert set(brl(expr)) == expected diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/tests/test_traverse.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/tests/test_traverse.py new file mode 100644 index 0000000000000000000000000000000000000000..e051928210981223004de28b8c617d0438e11ac6 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/tests/test_traverse.py @@ -0,0 +1,53 @@ +from sympy.core.basic import Basic +from sympy.core.numbers import Integer +from sympy.core.singleton import S +from sympy.strategies.branch.traverse import top_down, sall +from sympy.strategies.branch.core import do_one, identity + + +def inc(x): + if isinstance(x, Integer): + yield x + 1 + + +def test_top_down_easy(): + expr = Basic(S(1), S(2)) + expected = Basic(S(2), S(3)) + brl = top_down(inc) + + assert set(brl(expr)) == {expected} + + +def test_top_down_big_tree(): + expr = Basic(S(1), Basic(S(2)), Basic(S(3), Basic(S(4)), S(5))) + expected = Basic(S(2), Basic(S(3)), Basic(S(4), Basic(S(5)), S(6))) + brl = top_down(inc) + + assert set(brl(expr)) == {expected} + + +def test_top_down_harder_function(): + def split5(x): + if x == 5: + yield x - 1 + yield x + 1 + + expr = Basic(Basic(S(5), S(6)), S(1)) + expected = {Basic(Basic(S(4), S(6)), S(1)), Basic(Basic(S(6), S(6)), S(1))} + brl = top_down(split5) + + assert set(brl(expr)) == expected + + +def test_sall(): + expr = Basic(S(1), S(2)) + expected = Basic(S(2), S(3)) + brl = sall(inc) + + assert list(brl(expr)) == [expected] + + expr = Basic(S(1), S(2), Basic(S(3), S(4))) + expected = Basic(S(2), S(3), Basic(S(3), S(4))) + brl = sall(do_one(inc, identity)) + + assert list(brl(expr)) == [expected] diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/tools.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/tools.py new file mode 100644 index 0000000000000000000000000000000000000000..a6c9097323a7962080ae4497ead976818e386518 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/tools.py @@ -0,0 +1,12 @@ +from .core import exhaust, multiplex +from .traverse import top_down + + +def canon(*rules): + """ Strategy for canonicalization + + Apply each branching rule in a top-down fashion through the tree. + Multiplex through all branching rule traversals + Keep doing this until there is no change. + """ + return exhaust(multiplex(*map(top_down, rules))) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/traverse.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/traverse.py new file mode 100644 index 0000000000000000000000000000000000000000..28b7098dbda401fc0f0b6d27988d8c37e2f231ae --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/branch/traverse.py @@ -0,0 +1,25 @@ +""" Branching Strategies to Traverse a Tree """ +from itertools import product +from sympy.strategies.util import basic_fns +from .core import chain, identity, do_one + + +def top_down(brule, fns=basic_fns): + """ Apply a rule down a tree running it on the top nodes first """ + return chain(do_one(brule, identity), + lambda expr: sall(top_down(brule, fns), fns)(expr)) + + +def sall(brule, fns=basic_fns): + """ Strategic all - apply rule to args """ + op, new, children, leaf = map(fns.get, ('op', 'new', 'children', 'leaf')) + + def all_rl(expr): + if leaf(expr): + yield expr + else: + myop = op(expr) + argss = product(*map(brule, children(expr))) + for args in argss: + yield new(myop, *args) + return all_rl diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9a2fda9d6ba26d650873ef9a6671f897f99d7712 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/__pycache__/test_core.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/__pycache__/test_core.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..71b53bc6b991652c150e8d35603eccbef3086f7e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/__pycache__/test_core.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/__pycache__/test_rl.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/__pycache__/test_rl.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2b7e7fb4966dd170e0c7b594f25c35610d949774 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/__pycache__/test_rl.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/__pycache__/test_tools.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/__pycache__/test_tools.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f9240a950c86a4ce96d56a27e285f679920a2aac Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/__pycache__/test_tools.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/__pycache__/test_traverse.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/__pycache__/test_traverse.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8f689b1e1e6788e4da1bd09a7a429b6f5b3aacc7 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/__pycache__/test_traverse.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/__pycache__/test_tree.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/__pycache__/test_tree.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fc1938726c3755c55dc5e5edfa72db26be789b40 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/__pycache__/test_tree.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/test_core.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/test_core.py new file mode 100644 index 0000000000000000000000000000000000000000..1e19bcab1940c476a8996b7ba92e7645a6230034 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/test_core.py @@ -0,0 +1,118 @@ +from __future__ import annotations +from sympy.core.singleton import S +from sympy.core.basic import Basic +from sympy.strategies.core import ( + null_safe, exhaust, memoize, condition, + chain, tryit, do_one, debug, switch, minimize) +from io import StringIO + + +def posdec(x: int) -> int: + if x > 0: + return x - 1 + return x + + +def inc(x: int) -> int: + return x + 1 + + +def dec(x: int) -> int: + return x - 1 + + +def test_null_safe(): + def rl(expr: int) -> int | None: + if expr == 1: + return 2 + return None + + safe_rl = null_safe(rl) + assert rl(1) == safe_rl(1) + assert rl(3) is None + assert safe_rl(3) == 3 + + +def test_exhaust(): + sink = exhaust(posdec) + assert sink(5) == 0 + assert sink(10) == 0 + + +def test_memoize(): + rl = memoize(posdec) + assert rl(5) == posdec(5) + assert rl(5) == posdec(5) + assert rl(-2) == posdec(-2) + + +def test_condition(): + rl = condition(lambda x: x % 2 == 0, posdec) + assert rl(5) == 5 + assert rl(4) == 3 + + +def test_chain(): + rl = chain(posdec, posdec) + assert rl(5) == 3 + assert rl(1) == 0 + + +def test_tryit(): + def rl(expr: Basic) -> Basic: + assert False + + safe_rl = tryit(rl, AssertionError) + assert safe_rl(S(1)) == S(1) + + +def test_do_one(): + rl = do_one(posdec, posdec) + assert rl(5) == 4 + + def rl1(x: int) -> int: + if x == 1: + return 2 + return x + + def rl2(x: int) -> int: + if x == 2: + return 3 + return x + + rule = do_one(rl1, rl2) + assert rule(1) == 2 + assert rule(rule(1)) == 3 + + +def test_debug(): + file = StringIO() + rl = debug(posdec, file) + rl(5) + log = file.getvalue() + file.close() + + assert posdec.__name__ in log + assert '5' in log + assert '4' in log + + +def test_switch(): + def key(x: int) -> int: + return x % 3 + + rl = switch(key, {0: inc, 1: dec}) + assert rl(3) == 4 + assert rl(4) == 3 + assert rl(5) == 5 + + +def test_minimize(): + def key(x: int) -> int: + return -x + + rl = minimize(inc, dec) + assert rl(4) == 3 + + rl = minimize(inc, dec, objective=key) + assert rl(4) == 5 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/test_rl.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/test_rl.py new file mode 100644 index 0000000000000000000000000000000000000000..8bfa90ad4d970b21396e0e1b6427b5a5c68fe381 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/test_rl.py @@ -0,0 +1,78 @@ +from sympy.core.singleton import S +from sympy.strategies.rl import ( + rm_id, glom, flatten, unpack, sort, distribute, subs, rebuild) +from sympy.core.basic import Basic +from sympy.core.add import Add +from sympy.core.mul import Mul +from sympy.core.symbol import symbols +from sympy.abc import x + + +def test_rm_id(): + rmzeros = rm_id(lambda x: x == 0) + assert rmzeros(Basic(S(0), S(1))) == Basic(S(1)) + assert rmzeros(Basic(S(0), S(0))) == Basic(S(0)) + assert rmzeros(Basic(S(2), S(1))) == Basic(S(2), S(1)) + + +def test_glom(): + def key(x): + return x.as_coeff_Mul()[1] + + def count(x): + return x.as_coeff_Mul()[0] + + def newargs(cnt, arg): + return cnt * arg + + rl = glom(key, count, newargs) + + result = rl(Add(x, -x, 3 * x, 2, 3, evaluate=False)) + expected = Add(3 * x, 5) + assert set(result.args) == set(expected.args) + + +def test_flatten(): + assert flatten(Basic(S(1), S(2), Basic(S(3), S(4)))) == \ + Basic(S(1), S(2), S(3), S(4)) + + +def test_unpack(): + assert unpack(Basic(S(2))) == 2 + assert unpack(Basic(S(2), S(3))) == Basic(S(2), S(3)) + + +def test_sort(): + assert sort(str)(Basic(S(3), S(1), S(2))) == Basic(S(1), S(2), S(3)) + + +def test_distribute(): + class T1(Basic): + pass + + class T2(Basic): + pass + + distribute_t12 = distribute(T1, T2) + assert distribute_t12(T1(S(1), S(2), T2(S(3), S(4)), S(5))) == \ + T2(T1(S(1), S(2), S(3), S(5)), T1(S(1), S(2), S(4), S(5))) + assert distribute_t12(T1(S(1), S(2), S(3))) == T1(S(1), S(2), S(3)) + + +def test_distribute_add_mul(): + x, y = symbols('x, y') + expr = Mul(2, Add(x, y), evaluate=False) + expected = Add(Mul(2, x), Mul(2, y)) + distribute_mul = distribute(Mul, Add) + assert distribute_mul(expr) == expected + + +def test_subs(): + rl = subs(1, 2) + assert rl(1) == 2 + assert rl(3) == 3 + + +def test_rebuild(): + expr = Basic.__new__(Add, S(1), S(2)) + assert rebuild(expr) == 3 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/test_tools.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/test_tools.py new file mode 100644 index 0000000000000000000000000000000000000000..89774aeb92ead5781966e4f48ad32dc63e1bf7e2 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/test_tools.py @@ -0,0 +1,32 @@ +from sympy.strategies.tools import subs, typed +from sympy.strategies.rl import rm_id +from sympy.core.basic import Basic +from sympy.core.singleton import S + + +def test_subs(): + from sympy.core.symbol import symbols + a, b, c, d, e, f = symbols('a,b,c,d,e,f') + mapping = {a: d, d: a, Basic(e): Basic(f)} + expr = Basic(a, Basic(b, c), Basic(d, Basic(e))) + result = Basic(d, Basic(b, c), Basic(a, Basic(f))) + assert subs(mapping)(expr) == result + + +def test_subs_empty(): + assert subs({})(Basic(S(1), S(2))) == Basic(S(1), S(2)) + + +def test_typed(): + class A(Basic): + pass + + class B(Basic): + pass + + rmzeros = rm_id(lambda x: x == S(0)) + rmones = rm_id(lambda x: x == S(1)) + remove_something = typed({A: rmzeros, B: rmones}) + + assert remove_something(A(S(0), S(1))) == A(S(1)) + assert remove_something(B(S(0), S(1))) == B(S(0)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/test_traverse.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/test_traverse.py new file mode 100644 index 0000000000000000000000000000000000000000..ee2409616a8b4f750af8baea149b2ea52c56be9d --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/test_traverse.py @@ -0,0 +1,84 @@ +from sympy.strategies.traverse import ( + top_down, bottom_up, sall, top_down_once, bottom_up_once, basic_fns) +from sympy.strategies.rl import rebuild +from sympy.strategies.util import expr_fns +from sympy.core.add import Add +from sympy.core.basic import Basic +from sympy.core.numbers import Integer +from sympy.core.singleton import S +from sympy.core.symbol import Str, Symbol +from sympy.abc import x, y, z + + +def zero_symbols(expression): + return S.Zero if isinstance(expression, Symbol) else expression + + +def test_sall(): + zero_onelevel = sall(zero_symbols) + + assert zero_onelevel(Basic(x, y, Basic(x, z))) == \ + Basic(S(0), S(0), Basic(x, z)) + + +def test_bottom_up(): + _test_global_traversal(bottom_up) + _test_stop_on_non_basics(bottom_up) + + +def test_top_down(): + _test_global_traversal(top_down) + _test_stop_on_non_basics(top_down) + + +def _test_global_traversal(trav): + zero_all_symbols = trav(zero_symbols) + + assert zero_all_symbols(Basic(x, y, Basic(x, z))) == \ + Basic(S(0), S(0), Basic(S(0), S(0))) + + +def _test_stop_on_non_basics(trav): + def add_one_if_can(expr): + try: + return expr + 1 + except TypeError: + return expr + + expr = Basic(S(1), Str('a'), Basic(S(2), Str('b'))) + expected = Basic(S(2), Str('a'), Basic(S(3), Str('b'))) + rl = trav(add_one_if_can) + + assert rl(expr) == expected + + +class Basic2(Basic): + pass + + +def rl(x): + if x.args and not isinstance(x.args[0], Integer): + return Basic2(*x.args) + return x + + +def test_top_down_once(): + top_rl = top_down_once(rl) + + assert top_rl(Basic(S(1.0), S(2.0), Basic(S(3), S(4)))) == \ + Basic2(S(1.0), S(2.0), Basic(S(3), S(4))) + + +def test_bottom_up_once(): + bottom_rl = bottom_up_once(rl) + + assert bottom_rl(Basic(S(1), S(2), Basic(S(3.0), S(4.0)))) == \ + Basic(S(1), S(2), Basic2(S(3.0), S(4.0))) + + +def test_expr_fns(): + expr = x + y**3 + e = bottom_up(lambda v: v + 1, expr_fns)(expr) + b = bottom_up(lambda v: Basic.__new__(Add, v, S(1)), basic_fns)(expr) + + assert rebuild(b) == e diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/test_tree.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/test_tree.py new file mode 100644 index 0000000000000000000000000000000000000000..d5cdde747fe3ab90c8fd181701194403bc526067 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/strategies/tests/test_tree.py @@ -0,0 +1,92 @@ +from sympy.strategies.tree import treeapply, greedy, allresults, brute +from functools import partial, reduce + + +def inc(x): + return x + 1 + + +def dec(x): + return x - 1 + + +def double(x): + return 2 * x + + +def square(x): + return x**2 + + +def add(*args): + return sum(args) + + +def mul(*args): + return reduce(lambda a, b: a * b, args, 1) + + +def test_treeapply(): + tree = ([3, 3], [4, 1], 2) + assert treeapply(tree, {list: min, tuple: max}) == 3 + assert treeapply(tree, {list: add, tuple: mul}) == 60 + + +def test_treeapply_leaf(): + assert treeapply(3, {}, leaf=lambda x: x**2) == 9 + tree = ([3, 3], [4, 1], 2) + treep1 = ([4, 4], [5, 2], 3) + assert treeapply(tree, {list: min, tuple: max}, leaf=lambda x: x + 1) == \ + treeapply(treep1, {list: min, tuple: max}) + + +def test_treeapply_strategies(): + from sympy.strategies import chain, minimize + join = {list: chain, tuple: minimize} + + assert treeapply(inc, join) == inc + assert treeapply((inc, dec), join)(5) == minimize(inc, dec)(5) + assert treeapply([inc, dec], join)(5) == chain(inc, dec)(5) + tree = (inc, [dec, double]) # either inc or dec-then-double + assert treeapply(tree, join)(5) == 6 + assert treeapply(tree, join)(1) == 0 + + maximize = partial(minimize, objective=lambda x: -x) + join = {list: chain, tuple: maximize} + fn = treeapply(tree, join) + assert fn(4) == 6 # highest value comes from the dec then double + assert fn(1) == 2 # highest value comes from the inc + + +def test_greedy(): + tree = [inc, (dec, double)] # either inc or dec-then-double + + fn = greedy(tree, objective=lambda x: -x) + assert fn(4) == 6 # highest value comes from the dec then double + assert fn(1) == 2 # highest value comes from the inc + + tree = [inc, dec, [inc, dec, [(inc, inc), (dec, dec)]]] + lowest = greedy(tree) + assert lowest(10) == 8 + + highest = greedy(tree, objective=lambda x: -x) + assert highest(10) == 12 + + +def test_allresults(): + # square = lambda x: x**2 + + assert set(allresults(inc)(3)) == {inc(3)} + assert set(allresults([inc, dec])(3)) == {2, 4} + assert set(allresults((inc, dec))(3)) == {3} + assert set(allresults([inc, (dec, double)])(4)) == {5, 6} + + +def test_brute(): + tree = ([inc, dec], square) + fn = brute(tree, lambda x: -x) + + assert fn(2) == (2 + 1)**2 + assert fn(-2) == (-2 - 1)**2 + + assert brute(inc)(1) == 2 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5540f6c06809fa7fd1070c53b7555501f7e1b032 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/__pycache__/matrices.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/__pycache__/matrices.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..85054b9b7344196ebbfa735f15a6b20f699be42f Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/__pycache__/matrices.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/__pycache__/pytest.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/__pycache__/pytest.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0790d2b991a9b08fedabea4daacdb97a487b8aa2 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/__pycache__/pytest.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/__pycache__/quality_unicode.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/__pycache__/quality_unicode.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c4b0e4c54f5738d4a86ccbc7cde7024aa39e3366 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/__pycache__/quality_unicode.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/__pycache__/randtest.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/__pycache__/randtest.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a9c81906037d52eda06aed3740bfdf80a5918e2e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/__pycache__/randtest.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/__pycache__/runtests.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/__pycache__/runtests.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..649474997166bba38583397a339b6f445ccb32ed Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/__pycache__/runtests.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/__pycache__/runtests_pytest.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/__pycache__/runtests_pytest.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8917891c92fbb4f9cc739035d507ca3335be271a Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/__pycache__/runtests_pytest.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/__pycache__/tmpfiles.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/__pycache__/tmpfiles.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..464f0611943d20f93d4a4c12f5e078fd900254e4 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/__pycache__/tmpfiles.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f9c2694bee851a2a42b2dca2805df9b47626dc80 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/__pycache__/diagnose_imports.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/__pycache__/diagnose_imports.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5449659c0cad681a71b99cef91705bfc8ff113d4 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/__pycache__/diagnose_imports.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/__pycache__/test_code_quality.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/__pycache__/test_code_quality.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..77c40840d632a0b1d14939bcef7c39bfbd192a58 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/__pycache__/test_code_quality.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/__pycache__/test_deprecated.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/__pycache__/test_deprecated.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5d09b469d64411c070c489aa4bee2d7e6fb191ec Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/__pycache__/test_deprecated.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/__pycache__/test_module_imports.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/__pycache__/test_module_imports.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7e7d96b84e3bd639344c69e9e6949b690121568e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/__pycache__/test_module_imports.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/__pycache__/test_pytest.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/__pycache__/test_pytest.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..23f46854ede93aaa969e7fdfe8a46a85f04616c4 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/__pycache__/test_pytest.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/__pycache__/test_runtests_pytest.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/__pycache__/test_runtests_pytest.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..811c97f5393ccb58322286b278069feb4b4e428a Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/__pycache__/test_runtests_pytest.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/diagnose_imports.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/diagnose_imports.py new file mode 100644 index 0000000000000000000000000000000000000000..a31b66c66690c082800ae36eee37dad6927e0b37 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/diagnose_imports.py @@ -0,0 +1,216 @@ +#!/usr/bin/env python + +""" +Import diagnostics. Run bin/diagnose_imports.py --help for details. +""" + +from __future__ import annotations + +if __name__ == "__main__": + + import sys + import inspect + import builtins + + import optparse + + from os.path import abspath, dirname, join, normpath + this_file = abspath(__file__) + sympy_dir = join(dirname(this_file), '..', '..', '..') + sympy_dir = normpath(sympy_dir) + sys.path.insert(0, sympy_dir) + + option_parser = optparse.OptionParser( + usage= + "Usage: %prog option [options]\n" + "\n" + "Import analysis for imports between SymPy modules.") + option_group = optparse.OptionGroup( + option_parser, + 'Analysis options', + 'Options that define what to do. Exactly one of these must be given.') + option_group.add_option( + '--problems', + help= + 'Print all import problems, that is: ' + 'If an import pulls in a package instead of a module ' + '(e.g. sympy.core instead of sympy.core.add); ' # see ##PACKAGE## + 'if it imports a symbol that is already present; ' # see ##DUPLICATE## + 'if it imports a symbol ' + 'from somewhere other than the defining module.', # see ##ORIGIN## + action='count') + option_group.add_option( + '--origins', + help= + 'For each imported symbol in each module, ' + 'print the module that defined it. ' + '(This is useful for import refactoring.)', + action='count') + option_parser.add_option_group(option_group) + option_group = optparse.OptionGroup( + option_parser, + 'Sort options', + 'These options define the sort order for output lines. ' + 'At most one of these options is allowed. ' + 'Unsorted output will reflect the order in which imports happened.') + option_group.add_option( + '--by-importer', + help='Sort output lines by name of importing module.', + action='count') + option_group.add_option( + '--by-origin', + help='Sort output lines by name of imported module.', + action='count') + option_parser.add_option_group(option_group) + (options, args) = option_parser.parse_args() + if args: + option_parser.error( + 'Unexpected arguments %s (try %s --help)' % (args, sys.argv[0])) + if options.problems > 1: + option_parser.error('--problems must not be given more than once.') + if options.origins > 1: + option_parser.error('--origins must not be given more than once.') + if options.by_importer > 1: + option_parser.error('--by-importer must not be given more than once.') + if options.by_origin > 1: + option_parser.error('--by-origin must not be given more than once.') + options.problems = options.problems == 1 + options.origins = options.origins == 1 + options.by_importer = options.by_importer == 1 + options.by_origin = options.by_origin == 1 + if not options.problems and not options.origins: + option_parser.error( + 'At least one of --problems and --origins is required') + if options.problems and options.origins: + option_parser.error( + 'At most one of --problems and --origins is allowed') + if options.by_importer and options.by_origin: + option_parser.error( + 'At most one of --by-importer and --by-origin is allowed') + options.by_process = not options.by_importer and not options.by_origin + + builtin_import = builtins.__import__ + + class Definition: + """Information about a symbol's definition.""" + def __init__(self, name, value, definer): + self.name = name + self.value = value + self.definer = definer + def __hash__(self): + return hash(self.name) + def __eq__(self, other): + return self.name == other.name and self.value == other.value + def __ne__(self, other): + return not (self == other) + def __repr__(self): + return 'Definition(%s, ..., %s)' % ( + repr(self.name), repr(self.definer)) + + # Maps each function/variable to name of module to define it + symbol_definers: dict[Definition, str] = {} + + def in_module(a, b): + """Is a the same module as or a submodule of b?""" + return a == b or a != None and b != None and a.startswith(b + '.') + + def relevant(module): + """Is module relevant for import checking? + + Only imports between relevant modules will be checked.""" + return in_module(module, 'sympy') + + sorted_messages = [] + + def msg(msg, *args): + if options.by_process: + print(msg % args) + else: + sorted_messages.append(msg % args) + + def tracking_import(module, globals=globals(), locals=[], fromlist=None, level=-1): + """__import__ wrapper - does not change imports at all, but tracks them. + + Default order is implemented by doing output directly. + All other orders are implemented by collecting output information into + a sorted list that will be emitted after all imports are processed. + + Indirect imports can only occur after the requested symbol has been + imported directly (because the indirect import would not have a module + to pick the symbol up from). + So this code detects indirect imports by checking whether the symbol in + question was already imported. + + Keeps the semantics of __import__ unchanged.""" + caller_frame = inspect.getframeinfo(sys._getframe(1)) + importer_filename = caller_frame.filename + importer_module = globals['__name__'] + if importer_filename == caller_frame.filename: + importer_reference = '%s line %s' % ( + importer_filename, str(caller_frame.lineno)) + else: + importer_reference = importer_filename + result = builtin_import(module, globals, locals, fromlist, level) + importee_module = result.__name__ + # We're only interested if importer and importee are in SymPy + if relevant(importer_module) and relevant(importee_module): + for symbol in result.__dict__.iterkeys(): + definition = Definition( + symbol, result.__dict__[symbol], importer_module) + if definition not in symbol_definers: + symbol_definers[definition] = importee_module + if hasattr(result, '__path__'): + ##PACKAGE## + # The existence of __path__ is documented in the tutorial on modules. + # Python 3.3 documents this in http://docs.python.org/3.3/reference/import.html + if options.by_origin: + msg('Error: %s (a package) is imported by %s', + module, importer_reference) + else: + msg('Error: %s contains package import %s', + importer_reference, module) + if fromlist != None: + symbol_list = fromlist + if '*' in symbol_list: + if (importer_filename.endswith(("__init__.py", "__init__.pyc", "__init__.pyo"))): + # We do not check starred imports inside __init__ + # That's the normal "please copy over its imports to my namespace" + symbol_list = [] + else: + symbol_list = result.__dict__.iterkeys() + for symbol in symbol_list: + if symbol not in result.__dict__: + if options.by_origin: + msg('Error: %s.%s is not defined (yet), but %s tries to import it', + importee_module, symbol, importer_reference) + else: + msg('Error: %s tries to import %s.%s, which did not define it (yet)', + importer_reference, importee_module, symbol) + else: + definition = Definition( + symbol, result.__dict__[symbol], importer_module) + symbol_definer = symbol_definers[definition] + if symbol_definer == importee_module: + ##DUPLICATE## + if options.by_origin: + msg('Error: %s.%s is imported again into %s', + importee_module, symbol, importer_reference) + else: + msg('Error: %s imports %s.%s again', + importer_reference, importee_module, symbol) + else: + ##ORIGIN## + if options.by_origin: + msg('Error: %s.%s is imported by %s, which should import %s.%s instead', + importee_module, symbol, importer_reference, symbol_definer, symbol) + else: + msg('Error: %s imports %s.%s but should import %s.%s instead', + importer_reference, importee_module, symbol, symbol_definer, symbol) + return result + + builtins.__import__ = tracking_import + __import__('sympy') + + sorted_messages.sort() + for message in sorted_messages: + print(message) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/test_code_quality.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/test_code_quality.py new file mode 100644 index 0000000000000000000000000000000000000000..9a9f363f0b9a802553f8643186b7d858d1ad0694 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/test_code_quality.py @@ -0,0 +1,510 @@ +# coding=utf-8 +from os import walk, sep, pardir +from os.path import split, join, abspath, exists, isfile +from glob import glob +import re +import random +import ast + +from sympy.testing.pytest import raises +from sympy.testing.quality_unicode import _test_this_file_encoding + +# System path separator (usually slash or backslash) to be +# used with excluded files, e.g. +# exclude = set([ +# "%(sep)smpmath%(sep)s" % sepd, +# ]) +sepd = {"sep": sep} + +# path and sympy_path +SYMPY_PATH = abspath(join(split(__file__)[0], pardir, pardir)) # go to sympy/ +assert exists(SYMPY_PATH) + +TOP_PATH = abspath(join(SYMPY_PATH, pardir)) +BIN_PATH = join(TOP_PATH, "bin") +EXAMPLES_PATH = join(TOP_PATH, "examples") + +# Error messages +message_space = "File contains trailing whitespace: %s, line %s." +message_implicit = "File contains an implicit import: %s, line %s." +message_tabs = "File contains tabs instead of spaces: %s, line %s." +message_carriage = "File contains carriage returns at end of line: %s, line %s" +message_str_raise = "File contains string exception: %s, line %s" +message_gen_raise = "File contains generic exception: %s, line %s" +message_old_raise = "File contains old-style raise statement: %s, line %s, \"%s\"" +message_eof = "File does not end with a newline: %s, line %s" +message_multi_eof = "File ends with more than 1 newline: %s, line %s" +message_test_suite_def = "Function should start with 'test_' or '_': %s, line %s" +message_duplicate_test = "This is a duplicate test function: %s, line %s" +message_self_assignments = "File contains assignments to self/cls: %s, line %s." +message_func_is = "File contains '.func is': %s, line %s." +message_bare_expr = "File contains bare expression: %s, line %s." + +implicit_test_re = re.compile(r'^\s*(>>> )?(\.\.\. )?from .* import .*\*') +str_raise_re = re.compile( + r'^\s*(>>> )?(\.\.\. )?raise(\s+(\'|\")|\s*(\(\s*)+(\'|\"))') +gen_raise_re = re.compile( + r'^\s*(>>> )?(\.\.\. )?raise(\s+Exception|\s*(\(\s*)+Exception)') +old_raise_re = re.compile(r'^\s*(>>> )?(\.\.\. )?raise((\s*\(\s*)|\s+)\w+\s*,') +test_suite_def_re = re.compile(r'^def\s+(?!(_|test))[^(]*\(\s*\)\s*:$') +test_ok_def_re = re.compile(r'^def\s+test_.*:$') +test_file_re = re.compile(r'.*[/\\]test_.*\.py$') +func_is_re = re.compile(r'\.\s*func\s+is') + + +def tab_in_leading(s): + """Returns True if there are tabs in the leading whitespace of a line, + including the whitespace of docstring code samples.""" + n = len(s) - len(s.lstrip()) + if not s[n:n + 3] in ['...', '>>>']: + check = s[:n] + else: + smore = s[n + 3:] + check = s[:n] + smore[:len(smore) - len(smore.lstrip())] + return not (check.expandtabs() == check) + + +def find_self_assignments(s): + """Returns a list of "bad" assignments: if there are instances + of assigning to the first argument of the class method (except + for staticmethod's). + """ + t = [n for n in ast.parse(s).body if isinstance(n, ast.ClassDef)] + + bad = [] + for c in t: + for n in c.body: + if not isinstance(n, ast.FunctionDef): + continue + if any(d.id == 'staticmethod' + for d in n.decorator_list if isinstance(d, ast.Name)): + continue + if n.name == '__new__': + continue + if not n.args.args: + continue + first_arg = n.args.args[0].arg + + for m in ast.walk(n): + if isinstance(m, ast.Assign): + for a in m.targets: + if isinstance(a, ast.Name) and a.id == first_arg: + bad.append(m) + elif (isinstance(a, ast.Tuple) and + any(q.id == first_arg for q in a.elts + if isinstance(q, ast.Name))): + bad.append(m) + + return bad + + +def check_directory_tree(base_path, file_check, exclusions=set(), pattern="*.py"): + """ + Checks all files in the directory tree (with base_path as starting point) + with the file_check function provided, skipping files that contain + any of the strings in the set provided by exclusions. + """ + if not base_path: + return + for root, dirs, files in walk(base_path): + check_files(glob(join(root, pattern)), file_check, exclusions) + + +def check_files(files, file_check, exclusions=set(), pattern=None): + """ + Checks all files with the file_check function provided, skipping files + that contain any of the strings in the set provided by exclusions. + """ + if not files: + return + for fname in files: + if not exists(fname) or not isfile(fname): + continue + if any(ex in fname for ex in exclusions): + continue + if pattern is None or re.match(pattern, fname): + file_check(fname) + + +class _Visit(ast.NodeVisitor): + """return the line number corresponding to the + line on which a bare expression appears if it is a binary op + or a comparison that is not in a with block. + + EXAMPLES + ======== + + >>> import ast + >>> class _Visit(ast.NodeVisitor): + ... def visit_Expr(self, node): + ... if isinstance(node.value, (ast.BinOp, ast.Compare)): + ... print(node.lineno) + ... def visit_With(self, node): + ... pass # no checking there + ... + >>> code='''x = 1 # line 1 + ... for i in range(3): + ... x == 2 # <-- 3 + ... if x == 2: + ... x == 3 # <-- 5 + ... x + 1 # <-- 6 + ... x = 1 + ... if x == 1: + ... print(1) + ... while x != 1: + ... x == 1 # <-- 11 + ... with raises(TypeError): + ... c == 1 + ... raise TypeError + ... assert x == 1 + ... ''' + >>> _Visit().visit(ast.parse(code)) + 3 + 5 + 6 + 11 + """ + def visit_Expr(self, node): + if isinstance(node.value, (ast.BinOp, ast.Compare)): + assert None, message_bare_expr % ('', node.lineno) + def visit_With(self, node): + pass + + +BareExpr = _Visit() + + +def line_with_bare_expr(code): + """return None or else 0-based line number of code on which + a bare expression appeared. + """ + tree = ast.parse(code) + try: + BareExpr.visit(tree) + except AssertionError as msg: + assert msg.args + msg = msg.args[0] + assert msg.startswith(message_bare_expr.split(':', 1)[0]) + return int(msg.rsplit(' ', 1)[1].rstrip('.')) # the line number + + +def test_files(): + """ + This test tests all files in SymPy and checks that: + o no lines contains a trailing whitespace + o no lines end with \r\n + o no line uses tabs instead of spaces + o that the file ends with a single newline + o there are no general or string exceptions + o there are no old style raise statements + o name of arg-less test suite functions start with _ or test_ + o no duplicate function names that start with test_ + o no assignments to self variable in class methods + o no lines contain ".func is" except in the test suite + o there is no do-nothing expression like `a == b` or `x + 1` + """ + + def test(fname): + with open(fname, encoding="utf8") as test_file: + test_this_file(fname, test_file) + with open(fname, encoding='utf8') as test_file: + _test_this_file_encoding(fname, test_file) + + def test_this_file(fname, test_file): + idx = None + code = test_file.read() + test_file.seek(0) # restore reader to head + py = fname if sep not in fname else fname.rsplit(sep, 1)[-1] + if py.startswith('test_'): + idx = line_with_bare_expr(code) + if idx is not None: + assert False, message_bare_expr % (fname, idx + 1) + + line = None # to flag the case where there were no lines in file + tests = 0 + test_set = set() + for idx, line in enumerate(test_file): + if test_file_re.match(fname): + if test_suite_def_re.match(line): + assert False, message_test_suite_def % (fname, idx + 1) + if test_ok_def_re.match(line): + tests += 1 + test_set.add(line[3:].split('(')[0].strip()) + if len(test_set) != tests: + assert False, message_duplicate_test % (fname, idx + 1) + if line.endswith((" \n", "\t\n")): + assert False, message_space % (fname, idx + 1) + if line.endswith("\r\n"): + assert False, message_carriage % (fname, idx + 1) + if tab_in_leading(line): + assert False, message_tabs % (fname, idx + 1) + if str_raise_re.search(line): + assert False, message_str_raise % (fname, idx + 1) + if gen_raise_re.search(line): + assert False, message_gen_raise % (fname, idx + 1) + if (implicit_test_re.search(line) and + not list(filter(lambda ex: ex in fname, import_exclude))): + assert False, message_implicit % (fname, idx + 1) + if func_is_re.search(line) and not test_file_re.search(fname): + assert False, message_func_is % (fname, idx + 1) + + result = old_raise_re.search(line) + + if result is not None: + assert False, message_old_raise % ( + fname, idx + 1, result.group(2)) + + if line is not None: + if line == '\n' and idx > 0: + assert False, message_multi_eof % (fname, idx + 1) + elif not line.endswith('\n'): + # eof newline check + assert False, message_eof % (fname, idx + 1) + + + # Files to test at top level + top_level_files = [join(TOP_PATH, file) for file in [ + "isympy.py", + "build.py", + "setup.py", + ]] + # Files to exclude from all tests + exclude = { + "%(sep)ssympy%(sep)sparsing%(sep)sautolev%(sep)s_antlr%(sep)sautolevparser.py" % sepd, + "%(sep)ssympy%(sep)sparsing%(sep)sautolev%(sep)s_antlr%(sep)sautolevlexer.py" % sepd, + "%(sep)ssympy%(sep)sparsing%(sep)sautolev%(sep)s_antlr%(sep)sautolevlistener.py" % sepd, + "%(sep)ssympy%(sep)sparsing%(sep)slatex%(sep)s_antlr%(sep)slatexparser.py" % sepd, + "%(sep)ssympy%(sep)sparsing%(sep)slatex%(sep)s_antlr%(sep)slatexlexer.py" % sepd, + } + # Files to exclude from the implicit import test + import_exclude = { + # glob imports are allowed in top-level __init__.py: + "%(sep)ssympy%(sep)s__init__.py" % sepd, + # these __init__.py should be fixed: + # XXX: not really, they use useful import pattern (DRY) + "%(sep)svector%(sep)s__init__.py" % sepd, + "%(sep)smechanics%(sep)s__init__.py" % sepd, + "%(sep)squantum%(sep)s__init__.py" % sepd, + "%(sep)spolys%(sep)s__init__.py" % sepd, + "%(sep)spolys%(sep)sdomains%(sep)s__init__.py" % sepd, + # interactive SymPy executes ``from sympy import *``: + "%(sep)sinteractive%(sep)ssession.py" % sepd, + # isympy.py executes ``from sympy import *``: + "%(sep)sisympy.py" % sepd, + # these two are import timing tests: + "%(sep)sbin%(sep)ssympy_time.py" % sepd, + "%(sep)sbin%(sep)ssympy_time_cache.py" % sepd, + # Taken from Python stdlib: + "%(sep)sparsing%(sep)ssympy_tokenize.py" % sepd, + # this one should be fixed: + "%(sep)splotting%(sep)spygletplot%(sep)s" % sepd, + # False positive in the docstring + "%(sep)sbin%(sep)stest_external_imports.py" % sepd, + "%(sep)sbin%(sep)stest_submodule_imports.py" % sepd, + # These are deprecated stubs that can be removed at some point: + "%(sep)sutilities%(sep)sruntests.py" % sepd, + "%(sep)sutilities%(sep)spytest.py" % sepd, + "%(sep)sutilities%(sep)srandtest.py" % sepd, + "%(sep)sutilities%(sep)stmpfiles.py" % sepd, + "%(sep)sutilities%(sep)squality_unicode.py" % sepd, + } + check_files(top_level_files, test) + check_directory_tree(BIN_PATH, test, {"~", ".pyc", ".sh"}, "*") + check_directory_tree(SYMPY_PATH, test, exclude) + check_directory_tree(EXAMPLES_PATH, test, exclude) + + +def _with_space(c): + # return c with a random amount of leading space + return random.randint(0, 10)*' ' + c + + +def test_raise_statement_regular_expression(): + candidates_ok = [ + "some text # raise Exception, 'text'", + "raise ValueError('text') # raise Exception, 'text'", + "raise ValueError('text')", + "raise ValueError", + "raise ValueError('text')", + "raise ValueError('text') #,", + # Talking about an exception in a docstring + ''''"""This function will raise ValueError, except when it doesn't"""''', + "raise (ValueError('text')", + ] + str_candidates_fail = [ + "raise 'exception'", + "raise 'Exception'", + 'raise "exception"', + 'raise "Exception"', + "raise 'ValueError'", + ] + gen_candidates_fail = [ + "raise Exception('text') # raise Exception, 'text'", + "raise Exception('text')", + "raise Exception", + "raise Exception('text')", + "raise Exception('text') #,", + "raise Exception, 'text'", + "raise Exception, 'text' # raise Exception('text')", + "raise Exception, 'text' # raise Exception, 'text'", + ">>> raise Exception, 'text'", + ">>> raise Exception, 'text' # raise Exception('text')", + ">>> raise Exception, 'text' # raise Exception, 'text'", + ] + old_candidates_fail = [ + "raise Exception, 'text'", + "raise Exception, 'text' # raise Exception('text')", + "raise Exception, 'text' # raise Exception, 'text'", + ">>> raise Exception, 'text'", + ">>> raise Exception, 'text' # raise Exception('text')", + ">>> raise Exception, 'text' # raise Exception, 'text'", + "raise ValueError, 'text'", + "raise ValueError, 'text' # raise Exception('text')", + "raise ValueError, 'text' # raise Exception, 'text'", + ">>> raise ValueError, 'text'", + ">>> raise ValueError, 'text' # raise Exception('text')", + ">>> raise ValueError, 'text' # raise Exception, 'text'", + "raise(ValueError,", + "raise (ValueError,", + "raise( ValueError,", + "raise ( ValueError,", + "raise(ValueError ,", + "raise (ValueError ,", + "raise( ValueError ,", + "raise ( ValueError ,", + ] + + for c in candidates_ok: + assert str_raise_re.search(_with_space(c)) is None, c + assert gen_raise_re.search(_with_space(c)) is None, c + assert old_raise_re.search(_with_space(c)) is None, c + for c in str_candidates_fail: + assert str_raise_re.search(_with_space(c)) is not None, c + for c in gen_candidates_fail: + assert gen_raise_re.search(_with_space(c)) is not None, c + for c in old_candidates_fail: + assert old_raise_re.search(_with_space(c)) is not None, c + + +def test_implicit_imports_regular_expression(): + candidates_ok = [ + "from sympy import something", + ">>> from sympy import something", + "from sympy.somewhere import something", + ">>> from sympy.somewhere import something", + "import sympy", + ">>> import sympy", + "import sympy.something.something", + "... import sympy", + "... import sympy.something.something", + "... from sympy import something", + "... from sympy.somewhere import something", + ">> from sympy import *", # To allow 'fake' docstrings + "# from sympy import *", + "some text # from sympy import *", + ] + candidates_fail = [ + "from sympy import *", + ">>> from sympy import *", + "from sympy.somewhere import *", + ">>> from sympy.somewhere import *", + "... from sympy import *", + "... from sympy.somewhere import *", + ] + for c in candidates_ok: + assert implicit_test_re.search(_with_space(c)) is None, c + for c in candidates_fail: + assert implicit_test_re.search(_with_space(c)) is not None, c + + +def test_test_suite_defs(): + candidates_ok = [ + " def foo():\n", + "def foo(arg):\n", + "def _foo():\n", + "def test_foo():\n", + ] + candidates_fail = [ + "def foo():\n", + "def foo() :\n", + "def foo( ):\n", + "def foo():\n", + ] + for c in candidates_ok: + assert test_suite_def_re.search(c) is None, c + for c in candidates_fail: + assert test_suite_def_re.search(c) is not None, c + + +def test_test_duplicate_defs(): + candidates_ok = [ + "def foo():\ndef foo():\n", + "def test():\ndef test_():\n", + "def test_():\ndef test__():\n", + ] + candidates_fail = [ + "def test_():\ndef test_ ():\n", + "def test_1():\ndef test_1():\n", + ] + ok = (None, 'check') + def check(file): + tests = 0 + test_set = set() + for idx, line in enumerate(file.splitlines()): + if test_ok_def_re.match(line): + tests += 1 + test_set.add(line[3:].split('(')[0].strip()) + if len(test_set) != tests: + return False, message_duplicate_test % ('check', idx + 1) + return None, 'check' + for c in candidates_ok: + assert check(c) == ok + for c in candidates_fail: + assert check(c) != ok + + +def test_find_self_assignments(): + candidates_ok = [ + "class A(object):\n def foo(self, arg): arg = self\n", + "class A(object):\n def foo(self, arg): self.prop = arg\n", + "class A(object):\n def foo(self, arg): obj, obj2 = arg, self\n", + "class A(object):\n @classmethod\n def bar(cls, arg): arg = cls\n", + "class A(object):\n def foo(var, arg): arg = var\n", + ] + candidates_fail = [ + "class A(object):\n def foo(self, arg): self = arg\n", + "class A(object):\n def foo(self, arg): obj, self = arg, arg\n", + "class A(object):\n def foo(self, arg):\n if arg: self = arg", + "class A(object):\n @classmethod\n def foo(cls, arg): cls = arg\n", + "class A(object):\n def foo(var, arg): var = arg\n", + ] + + for c in candidates_ok: + assert find_self_assignments(c) == [] + for c in candidates_fail: + assert find_self_assignments(c) != [] + + +def test_test_unicode_encoding(): + unicode_whitelist = ['foo'] + unicode_strict_whitelist = ['bar'] + + fname = 'abc' + test_file = ['α'] + raises(AssertionError, lambda: _test_this_file_encoding( + fname, test_file, unicode_whitelist, unicode_strict_whitelist)) + + fname = 'abc' + test_file = ['abc'] + _test_this_file_encoding( + fname, test_file, unicode_whitelist, unicode_strict_whitelist) + + fname = 'foo' + test_file = ['abc'] + raises(AssertionError, lambda: _test_this_file_encoding( + fname, test_file, unicode_whitelist, unicode_strict_whitelist)) + + fname = 'bar' + test_file = ['abc'] + _test_this_file_encoding( + fname, test_file, unicode_whitelist, unicode_strict_whitelist) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/test_deprecated.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/test_deprecated.py new file mode 100644 index 0000000000000000000000000000000000000000..696933d96d6232ea869da1002ec9ebee5309724d --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/test_deprecated.py @@ -0,0 +1,5 @@ +from sympy.testing.pytest import warns_deprecated_sympy + +def test_deprecated_testing_randtest(): + with warns_deprecated_sympy(): + import sympy.testing.randtest # noqa:F401 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/test_module_imports.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/test_module_imports.py new file mode 100644 index 0000000000000000000000000000000000000000..d16dbaa98156c287c18b46ff07c0ede5d26e069a --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/test_module_imports.py @@ -0,0 +1,42 @@ +""" +Checks that SymPy does not contain indirect imports. + +An indirect import is importing a symbol from a module that itself imported the +symbol from elsewhere. Such a constellation makes it harder to diagnose +inter-module dependencies and import order problems, and is therefore strongly +discouraged. + +(Indirect imports from end-user code is fine and in fact a best practice.) + +Implementation note: Forcing Python into actually unloading already-imported +submodules is a tricky and partly undocumented process. To avoid these issues, +the actual diagnostic code is in bin/diagnose_imports, which is run as a +separate, pristine Python process. +""" + +import subprocess +import sys +from os.path import abspath, dirname, join, normpath +import inspect + +from sympy.testing.pytest import XFAIL + +@XFAIL +def test_module_imports_are_direct(): + my_filename = abspath(inspect.getfile(inspect.currentframe())) + my_dirname = dirname(my_filename) + diagnose_imports_filename = join(my_dirname, 'diagnose_imports.py') + diagnose_imports_filename = normpath(diagnose_imports_filename) + + process = subprocess.Popen( + [ + sys.executable, + normpath(diagnose_imports_filename), + '--problems', + '--by-importer' + ], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + bufsize=-1) + output, _ = process.communicate() + assert output == '', "There are import problems:\n" + output.decode() diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/test_pytest.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/test_pytest.py new file mode 100644 index 0000000000000000000000000000000000000000..7080a4ed4602707a3efb4d9025e8e9cbe23a5ef8 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/test_pytest.py @@ -0,0 +1,211 @@ +import warnings + +from sympy.testing.pytest import (raises, warns, ignore_warnings, + warns_deprecated_sympy, Failed) +from sympy.utilities.exceptions import sympy_deprecation_warning + + + +# Test callables + + +def test_expected_exception_is_silent_callable(): + def f(): + raise ValueError() + raises(ValueError, f) + + +# Under pytest raises will raise Failed rather than AssertionError +def test_lack_of_exception_triggers_AssertionError_callable(): + try: + raises(Exception, lambda: 1 + 1) + assert False + except Failed as e: + assert "DID NOT RAISE" in str(e) + + +def test_unexpected_exception_is_passed_through_callable(): + def f(): + raise ValueError("some error message") + try: + raises(TypeError, f) + assert False + except ValueError as e: + assert str(e) == "some error message" + +# Test with statement + +def test_expected_exception_is_silent_with(): + with raises(ValueError): + raise ValueError() + + +def test_lack_of_exception_triggers_AssertionError_with(): + try: + with raises(Exception): + 1 + 1 + assert False + except Failed as e: + assert "DID NOT RAISE" in str(e) + + +def test_unexpected_exception_is_passed_through_with(): + try: + with raises(TypeError): + raise ValueError("some error message") + assert False + except ValueError as e: + assert str(e) == "some error message" + +# Now we can use raises() instead of try/catch +# to test that a specific exception class is raised + + +def test_second_argument_should_be_callable_or_string(): + raises(TypeError, lambda: raises("irrelevant", 42)) + + +def test_warns_catches_warning(): + with warnings.catch_warnings(record=True) as w: + with warns(UserWarning): + warnings.warn('this is the warning message') + assert len(w) == 0 + + +def test_warns_raises_without_warning(): + with raises(Failed): + with warns(UserWarning): + pass + + +def test_warns_hides_other_warnings(): + with raises(RuntimeWarning): + with warns(UserWarning): + warnings.warn('this is the warning message', UserWarning) + warnings.warn('this is the other message', RuntimeWarning) + + +def test_warns_continues_after_warning(): + with warnings.catch_warnings(record=True) as w: + finished = False + with warns(UserWarning): + warnings.warn('this is the warning message') + finished = True + assert finished + assert len(w) == 0 + + +def test_warns_many_warnings(): + with warns(UserWarning): + warnings.warn('this is the warning message', UserWarning) + warnings.warn('this is the other warning message', UserWarning) + + +def test_warns_match_matching(): + with warnings.catch_warnings(record=True) as w: + with warns(UserWarning, match='this is the warning message'): + warnings.warn('this is the warning message', UserWarning) + assert len(w) == 0 + + +def test_warns_match_non_matching(): + with warnings.catch_warnings(record=True) as w: + with raises(Failed): + with warns(UserWarning, match='this is the warning message'): + warnings.warn('this is not the expected warning message', UserWarning) + assert len(w) == 0 + +def _warn_sympy_deprecation(stacklevel=3): + sympy_deprecation_warning( + "feature", + active_deprecations_target="active-deprecations", + deprecated_since_version="0.0.0", + stacklevel=stacklevel, + ) + +def test_warns_deprecated_sympy_catches_warning(): + with warnings.catch_warnings(record=True) as w: + with warns_deprecated_sympy(): + _warn_sympy_deprecation() + assert len(w) == 0 + + +def test_warns_deprecated_sympy_raises_without_warning(): + with raises(Failed): + with warns_deprecated_sympy(): + pass + +def test_warns_deprecated_sympy_wrong_stacklevel(): + with raises(Failed): + with warns_deprecated_sympy(): + _warn_sympy_deprecation(stacklevel=1) + +def test_warns_deprecated_sympy_doesnt_hide_other_warnings(): + # Unlike pytest's deprecated_call, we should not hide other warnings. + with raises(RuntimeWarning): + with warns_deprecated_sympy(): + _warn_sympy_deprecation() + warnings.warn('this is the other message', RuntimeWarning) + + +def test_warns_deprecated_sympy_continues_after_warning(): + with warnings.catch_warnings(record=True) as w: + finished = False + with warns_deprecated_sympy(): + _warn_sympy_deprecation() + finished = True + assert finished + assert len(w) == 0 + +def test_ignore_ignores_warning(): + with warnings.catch_warnings(record=True) as w: + with ignore_warnings(UserWarning): + warnings.warn('this is the warning message') + assert len(w) == 0 + + +def test_ignore_does_not_raise_without_warning(): + with warnings.catch_warnings(record=True) as w: + with ignore_warnings(UserWarning): + pass + assert len(w) == 0 + + +def test_ignore_allows_other_warnings(): + with warnings.catch_warnings(record=True) as w: + # This is needed when pytest is run as -Werror + # the setting is reverted at the end of the catch_Warnings block. + warnings.simplefilter("always") + with ignore_warnings(UserWarning): + warnings.warn('this is the warning message', UserWarning) + warnings.warn('this is the other message', RuntimeWarning) + assert len(w) == 1 + assert isinstance(w[0].message, RuntimeWarning) + assert str(w[0].message) == 'this is the other message' + + +def test_ignore_continues_after_warning(): + with warnings.catch_warnings(record=True) as w: + finished = False + with ignore_warnings(UserWarning): + warnings.warn('this is the warning message') + finished = True + assert finished + assert len(w) == 0 + + +def test_ignore_many_warnings(): + with warnings.catch_warnings(record=True) as w: + # This is needed when pytest is run as -Werror + # the setting is reverted at the end of the catch_Warnings block. + warnings.simplefilter("always") + with ignore_warnings(UserWarning): + warnings.warn('this is the warning message', UserWarning) + warnings.warn('this is the other message', RuntimeWarning) + warnings.warn('this is the warning message', UserWarning) + warnings.warn('this is the other message', RuntimeWarning) + warnings.warn('this is the other message', RuntimeWarning) + assert len(w) == 3 + for wi in w: + assert isinstance(wi.message, RuntimeWarning) + assert str(wi.message) == 'this is the other message' diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/test_runtests_pytest.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/test_runtests_pytest.py new file mode 100644 index 0000000000000000000000000000000000000000..cd56d831f3618c9dbb8a1dffe63d95a0befc6adf --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/testing/tests/test_runtests_pytest.py @@ -0,0 +1,171 @@ +import pathlib +from typing import List + +import pytest + +from sympy.testing.runtests_pytest import ( + make_absolute_path, + sympy_dir, + update_args_with_paths, +) + + +class TestMakeAbsolutePath: + + @staticmethod + @pytest.mark.parametrize( + 'partial_path', ['sympy', 'sympy/core', 'sympy/nonexistant_directory'], + ) + def test_valid_partial_path(partial_path: str): + """Paths that start with `sympy` are valid.""" + _ = make_absolute_path(partial_path) + + @staticmethod + @pytest.mark.parametrize( + 'partial_path', ['not_sympy', 'also/not/sympy'], + ) + def test_invalid_partial_path_raises_value_error(partial_path: str): + """A `ValueError` is raises on paths that don't start with `sympy`.""" + with pytest.raises(ValueError): + _ = make_absolute_path(partial_path) + + +class TestUpdateArgsWithPaths: + + @staticmethod + def test_no_paths(): + """If no paths are passed, only `sympy` and `doc/src` are appended. + + `sympy` and `doc/src` are the `testpaths` stated in `pytest.ini`. They + need to be manually added as if any path-related arguments are passed + to `pytest.main` then the settings in `pytest.ini` may be ignored. + + """ + paths = [] + args = update_args_with_paths(paths=paths, keywords=None, args=[]) + expected = [ + str(pathlib.Path(sympy_dir(), 'sympy')), + str(pathlib.Path(sympy_dir(), 'doc/src')), + ] + assert args == expected + + @staticmethod + @pytest.mark.parametrize( + 'path', + ['sympy/core/tests/test_basic.py', '_basic'] + ) + def test_one_file(path: str): + """Single files/paths, full or partial, are matched correctly.""" + args = update_args_with_paths(paths=[path], keywords=None, args=[]) + expected = [ + str(pathlib.Path(sympy_dir(), 'sympy/core/tests/test_basic.py')), + ] + assert args == expected + + @staticmethod + def test_partial_path_from_root(): + """Partial paths from the root directly are matched correctly.""" + args = update_args_with_paths(paths=['sympy/functions'], keywords=None, args=[]) + expected = [str(pathlib.Path(sympy_dir(), 'sympy/functions'))] + assert args == expected + + @staticmethod + def test_multiple_paths_from_root(): + """Multiple paths, partial or full, are matched correctly.""" + paths = ['sympy/core/tests/test_basic.py', 'sympy/functions'] + args = update_args_with_paths(paths=paths, keywords=None, args=[]) + expected = [ + str(pathlib.Path(sympy_dir(), 'sympy/core/tests/test_basic.py')), + str(pathlib.Path(sympy_dir(), 'sympy/functions')), + ] + assert args == expected + + @staticmethod + @pytest.mark.parametrize( + 'paths, expected_paths', + [ + ( + ['/core', '/util'], + [ + 'doc/src/modules/utilities', + 'doc/src/reference/public/utilities', + 'sympy/core', + 'sympy/logic/utilities', + 'sympy/utilities', + ] + ), + ] + ) + def test_multiple_paths_from_non_root(paths: List[str], expected_paths: List[str]): + """Multiple partial paths are matched correctly.""" + args = update_args_with_paths(paths=paths, keywords=None, args=[]) + assert len(args) == len(expected_paths) + for arg, expected in zip(sorted(args), expected_paths): + assert expected in arg + + @staticmethod + @pytest.mark.parametrize( + 'paths', + [ + + [], + ['sympy/physics'], + ['sympy/physics/mechanics'], + ['sympy/physics/mechanics/tests'], + ['sympy/physics/mechanics/tests/test_kane3.py'], + ] + ) + def test_string_as_keyword(paths: List[str]): + """String keywords are matched correctly.""" + keywords = ('bicycle', ) + args = update_args_with_paths(paths=paths, keywords=keywords, args=[]) + expected_args = ['sympy/physics/mechanics/tests/test_kane3.py::test_bicycle'] + assert len(args) == len(expected_args) + for arg, expected in zip(sorted(args), expected_args): + assert expected in arg + + @staticmethod + @pytest.mark.parametrize( + 'paths', + [ + + [], + ['sympy/core'], + ['sympy/core/tests'], + ['sympy/core/tests/test_sympify.py'], + ] + ) + def test_integer_as_keyword(paths: List[str]): + """Integer keywords are matched correctly.""" + keywords = ('3538', ) + args = update_args_with_paths(paths=paths, keywords=keywords, args=[]) + expected_args = ['sympy/core/tests/test_sympify.py::test_issue_3538'] + assert len(args) == len(expected_args) + for arg, expected in zip(sorted(args), expected_args): + assert expected in arg + + @staticmethod + def test_multiple_keywords(): + """Multiple keywords are matched correctly.""" + keywords = ('bicycle', '3538') + args = update_args_with_paths(paths=[], keywords=keywords, args=[]) + expected_args = [ + 'sympy/core/tests/test_sympify.py::test_issue_3538', + 'sympy/physics/mechanics/tests/test_kane3.py::test_bicycle', + ] + assert len(args) == len(expected_args) + for arg, expected in zip(sorted(args), expected_args): + assert expected in arg + + @staticmethod + def test_keyword_match_in_multiple_files(): + """Keywords are matched across multiple files.""" + keywords = ('1130', ) + args = update_args_with_paths(paths=[], keywords=keywords, args=[]) + expected_args = [ + 'sympy/integrals/tests/test_heurisch.py::test_heurisch_symbolic_coeffs_1130', + 'sympy/utilities/tests/test_lambdify.py::test_python_div_zero_issue_11306', + ] + assert len(args) == len(expected_args) + for arg, expected in zip(sorted(args), expected_args): + assert expected in arg diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3cb25a22dcd2e18551b1a082a6b15f1ca46f670e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/autowrap.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/autowrap.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ae436d247219d29ebdaa10a7f1bd0517af61c6fc Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/autowrap.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/codegen.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/codegen.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a0a5e292626a19cb4aab6e3a4a1fd4611761ce51 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/codegen.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/decorator.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/decorator.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..741e67e489e5b03237123b129aa0cb05eb2065ba Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/decorator.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/enumerative.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/enumerative.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..305cdc66b544290aee451e204b33cd78b4cc9410 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/enumerative.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/exceptions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/exceptions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2d7b38b5e06ea880a4306c841615dc244f5c1b96 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/exceptions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/lambdify.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/lambdify.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6826194aced0e839b909d7da652c8784b23b3b80 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/lambdify.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/magic.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/magic.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..58c93cc12b3df564e04aa5494dee0be05fe26ce6 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/magic.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/matchpy_connector.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/matchpy_connector.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f63640af745888d442e5d7acab64c2223cf0c58c Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/matchpy_connector.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/memoization.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/memoization.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c08b71b4de1cf57b71bd05ce7078eee17e9d8c87 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/memoization.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/misc.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/misc.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1faf6ebe7712342c5e5b394e6f9285dc730fe90d Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/misc.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/pkgdata.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/pkgdata.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d5bd8507c63a6cac348787ca55993aacd06715bb Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/pkgdata.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/pytest.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/pytest.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..65de432cf02e0dde2a4aa15ae60ec0104983d276 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/pytest.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/randtest.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/randtest.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2ef43ce8941fb89b177848da4d8035d4fd169463 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/randtest.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/runtests.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/runtests.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bcf945b6064ff5a69011915a23f9163ae40c2503 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/runtests.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/source.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/source.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9550837a619caa6617cd0715adc171c08f8056b4 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/source.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/timeutils.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/timeutils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5e876e4c154878849fb22370b5cf94a224621b81 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/timeutils.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/tmpfiles.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/tmpfiles.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a0d2f7a414a75b162a9be58adfcad0e714202209 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/__pycache__/tmpfiles.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..d2c05ad48a93493bb5434256c88dfd614ac47b2d --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/__init__.py @@ -0,0 +1,22 @@ +""" This sub-module is private, i.e. external code should not depend on it. + +These functions are used by tests run as part of continuous integration. +Once the implementation is mature (it should support the major +platforms: Windows, OS X & Linux) it may become official API which + may be relied upon by downstream libraries. Until then API may break +without prior notice. + +TODO: +- (optionally) clean up after tempfile.mkdtemp() +- cross-platform testing +- caching of compiler choice and intermediate files + +""" + +from .compilation import compile_link_import_strings, compile_run_strings +from .availability import has_fortran, has_c, has_cxx + +__all__ = [ + 'compile_link_import_strings', 'compile_run_strings', + 'has_fortran', 'has_c', 'has_cxx', +] diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..12f9b3584663d3404036215d217b89a02b832888 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/__pycache__/availability.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/__pycache__/availability.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c60c2c353cb12a324c2eb2991de149c54f96ac95 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/__pycache__/availability.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/__pycache__/compilation.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/__pycache__/compilation.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..48e128a47c8d4b407cdb8a5dcce674258c91d1c3 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/__pycache__/compilation.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/__pycache__/runners.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/__pycache__/runners.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ee8a92882a699cefe82d8d51f79f99d1fc190019 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/__pycache__/runners.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/__pycache__/util.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/__pycache__/util.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c00c3ceb21f36165a78219b5bdd47e8217959f1a Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/__pycache__/util.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/availability.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/availability.py new file mode 100644 index 0000000000000000000000000000000000000000..dc97b3e7b8c7e7307c6c21352ed4035d977aabb3 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/availability.py @@ -0,0 +1,77 @@ +import os +from .compilation import compile_run_strings +from .util import CompilerNotFoundError + +def has_fortran(): + if not hasattr(has_fortran, 'result'): + try: + (stdout, stderr), info = compile_run_strings( + [('main.f90', ( + 'program foo\n' + 'print *, "hello world"\n' + 'end program' + ))], clean=True + ) + except CompilerNotFoundError: + has_fortran.result = False + if os.environ.get('SYMPY_STRICT_COMPILER_CHECKS', '0') == '1': + raise + else: + if info['exit_status'] != os.EX_OK or 'hello world' not in stdout: + if os.environ.get('SYMPY_STRICT_COMPILER_CHECKS', '0') == '1': + raise ValueError("Failed to compile test program:\n%s\n%s\n" % (stdout, stderr)) + has_fortran.result = False + else: + has_fortran.result = True + return has_fortran.result + + +def has_c(): + if not hasattr(has_c, 'result'): + try: + (stdout, stderr), info = compile_run_strings( + [('main.c', ( + '#include \n' + 'int main(){\n' + 'printf("hello world\\n");\n' + 'return 0;\n' + '}' + ))], clean=True + ) + except CompilerNotFoundError: + has_c.result = False + if os.environ.get('SYMPY_STRICT_COMPILER_CHECKS', '0') == '1': + raise + else: + if info['exit_status'] != os.EX_OK or 'hello world' not in stdout: + if os.environ.get('SYMPY_STRICT_COMPILER_CHECKS', '0') == '1': + raise ValueError("Failed to compile test program:\n%s\n%s\n" % (stdout, stderr)) + has_c.result = False + else: + has_c.result = True + return has_c.result + + +def has_cxx(): + if not hasattr(has_cxx, 'result'): + try: + (stdout, stderr), info = compile_run_strings( + [('main.cxx', ( + '#include \n' + 'int main(){\n' + 'std::cout << "hello world" << std::endl;\n' + '}' + ))], clean=True + ) + except CompilerNotFoundError: + has_cxx.result = False + if os.environ.get('SYMPY_STRICT_COMPILER_CHECKS', '0') == '1': + raise + else: + if info['exit_status'] != os.EX_OK or 'hello world' not in stdout: + if os.environ.get('SYMPY_STRICT_COMPILER_CHECKS', '0') == '1': + raise ValueError("Failed to compile test program:\n%s\n%s\n" % (stdout, stderr)) + has_cxx.result = False + else: + has_cxx.result = True + return has_cxx.result diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/compilation.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/compilation.py new file mode 100644 index 0000000000000000000000000000000000000000..2d50a20467c08086d6cb5fb5b0d478e7a953d720 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/compilation.py @@ -0,0 +1,657 @@ +import glob +import os +import shutil +import subprocess +import sys +import tempfile +import warnings +from pathlib import Path +from sysconfig import get_config_var, get_config_vars, get_path + +from .runners import ( + CCompilerRunner, + CppCompilerRunner, + FortranCompilerRunner +) +from .util import ( + get_abspath, make_dirs, copy, Glob, ArbitraryDepthGlob, + glob_at_depth, import_module_from_file, pyx_is_cplus, + sha256_of_string, sha256_of_file, CompileError +) + +if os.name == 'posix': + objext = '.o' +elif os.name == 'nt': + objext = '.obj' +else: + warnings.warn("Unknown os.name: {}".format(os.name)) + objext = '.o' + + +def compile_sources(files, Runner=None, destdir=None, cwd=None, keep_dir_struct=False, + per_file_kwargs=None, **kwargs): + """ Compile source code files to object files. + + Parameters + ========== + + files : iterable of str + Paths to source files, if ``cwd`` is given, the paths are taken as relative. + Runner: CompilerRunner subclass (optional) + Could be e.g. ``FortranCompilerRunner``. Will be inferred from filename + extensions if missing. + destdir: str + Output directory, if cwd is given, the path is taken as relative. + cwd: str + Working directory. Specify to have compiler run in other directory. + also used as root of relative paths. + keep_dir_struct: bool + Reproduce directory structure in `destdir`. default: ``False`` + per_file_kwargs: dict + Dict mapping instances in ``files`` to keyword arguments. + \\*\\*kwargs: dict + Default keyword arguments to pass to ``Runner``. + + Returns + ======= + List of strings (paths of object files). + """ + _per_file_kwargs = {} + + if per_file_kwargs is not None: + for k, v in per_file_kwargs.items(): + if isinstance(k, Glob): + for path in glob.glob(k.pathname): + _per_file_kwargs[path] = v + elif isinstance(k, ArbitraryDepthGlob): + for path in glob_at_depth(k.filename, cwd): + _per_file_kwargs[path] = v + else: + _per_file_kwargs[k] = v + + # Set up destination directory + destdir = destdir or '.' + if not os.path.isdir(destdir): + if os.path.exists(destdir): + raise OSError("{} is not a directory".format(destdir)) + else: + make_dirs(destdir) + if cwd is None: + cwd = '.' + for f in files: + copy(f, destdir, only_update=True, dest_is_dir=True) + + # Compile files and return list of paths to the objects + dstpaths = [] + for f in files: + if keep_dir_struct: + name, ext = os.path.splitext(f) + else: + name, ext = os.path.splitext(os.path.basename(f)) + file_kwargs = kwargs.copy() + file_kwargs.update(_per_file_kwargs.get(f, {})) + dstpaths.append(src2obj(f, Runner, cwd=cwd, **file_kwargs)) + return dstpaths + + +def get_mixed_fort_c_linker(vendor=None, cplus=False, cwd=None): + vendor = vendor or os.environ.get('SYMPY_COMPILER_VENDOR', 'gnu') + + if vendor.lower() == 'intel': + if cplus: + return (FortranCompilerRunner, + {'flags': ['-nofor_main', '-cxxlib']}, vendor) + else: + return (FortranCompilerRunner, + {'flags': ['-nofor_main']}, vendor) + elif vendor.lower() == 'gnu' or 'llvm': + if cplus: + return (CppCompilerRunner, + {'lib_options': ['fortran']}, vendor) + else: + return (FortranCompilerRunner, + {}, vendor) + else: + raise ValueError("No vendor found.") + + +def link(obj_files, out_file=None, shared=False, Runner=None, + cwd=None, cplus=False, fort=False, extra_objs=None, **kwargs): + """ Link object files. + + Parameters + ========== + + obj_files: iterable of str + Paths to object files. + out_file: str (optional) + Path to executable/shared library, if ``None`` it will be + deduced from the last item in obj_files. + shared: bool + Generate a shared library? + Runner: CompilerRunner subclass (optional) + If not given the ``cplus`` and ``fort`` flags will be inspected + (fallback is the C compiler). + cwd: str + Path to the root of relative paths and working directory for compiler. + cplus: bool + C++ objects? default: ``False``. + fort: bool + Fortran objects? default: ``False``. + extra_objs: list + List of paths to extra object files / static libraries. + \\*\\*kwargs: dict + Keyword arguments passed to ``Runner``. + + Returns + ======= + + The absolute path to the generated shared object / executable. + + """ + if out_file is None: + out_file, ext = os.path.splitext(os.path.basename(obj_files[-1])) + if shared: + out_file += get_config_var('EXT_SUFFIX') + + if not Runner: + if fort: + Runner, extra_kwargs, vendor = \ + get_mixed_fort_c_linker( + vendor=kwargs.get('vendor', None), + cplus=cplus, + cwd=cwd, + ) + for k, v in extra_kwargs.items(): + if k in kwargs: + kwargs[k].expand(v) + else: + kwargs[k] = v + else: + if cplus: + Runner = CppCompilerRunner + else: + Runner = CCompilerRunner + + flags = kwargs.pop('flags', []) + if shared: + if '-shared' not in flags: + flags.append('-shared') + run_linker = kwargs.pop('run_linker', True) + if not run_linker: + raise ValueError("run_linker was set to False (nonsensical).") + + out_file = get_abspath(out_file, cwd=cwd) + runner = Runner(obj_files+(extra_objs or []), out_file, flags, cwd=cwd, **kwargs) + runner.run() + return out_file + + +def link_py_so(obj_files, so_file=None, cwd=None, libraries=None, + cplus=False, fort=False, extra_objs=None, **kwargs): + """ Link Python extension module (shared object) for importing + + Parameters + ========== + + obj_files: iterable of str + Paths to object files to be linked. + so_file: str + Name (path) of shared object file to create. If not specified it will + have the basname of the last object file in `obj_files` but with the + extension '.so' (Unix). + cwd: path string + Root of relative paths and working directory of linker. + libraries: iterable of strings + Libraries to link against, e.g. ['m']. + cplus: bool + Any C++ objects? default: ``False``. + fort: bool + Any Fortran objects? default: ``False``. + extra_objs: list + List of paths of extra object files / static libraries to link against. + kwargs**: dict + Keyword arguments passed to ``link(...)``. + + Returns + ======= + + Absolute path to the generate shared object. + """ + libraries = libraries or [] + + include_dirs = kwargs.pop('include_dirs', []) + library_dirs = kwargs.pop('library_dirs', []) + + # Add Python include and library directories + # PY_LDFLAGS does not available on all python implementations + # e.g. when with pypy, so it's LDFLAGS we need to use + if sys.platform == "win32": + warnings.warn("Windows not yet supported.") + elif sys.platform == 'darwin': + cfgDict = get_config_vars() + kwargs['linkline'] = kwargs.get('linkline', []) + [cfgDict['LDFLAGS']] + library_dirs += [cfgDict['LIBDIR']] + + # In macOS, linker needs to compile frameworks + # e.g. "-framework CoreFoundation" + is_framework = False + for opt in cfgDict['LIBS'].split(): + if is_framework: + kwargs['linkline'] = kwargs.get('linkline', []) + ['-framework', opt] + is_framework = False + elif opt.startswith('-l'): + libraries.append(opt[2:]) + elif opt.startswith('-framework'): + is_framework = True + # The python library is not included in LIBS + libfile = cfgDict['LIBRARY'] + libname = ".".join(libfile.split('.')[:-1])[3:] + libraries.append(libname) + + elif sys.platform[:3] == 'aix': + # Don't use the default code below + pass + else: + if get_config_var('Py_ENABLE_SHARED'): + cfgDict = get_config_vars() + kwargs['linkline'] = kwargs.get('linkline', []) + [cfgDict['LDFLAGS']] + library_dirs += [cfgDict['LIBDIR']] + for opt in cfgDict['BLDLIBRARY'].split(): + if opt.startswith('-l'): + libraries += [opt[2:]] + else: + pass + + flags = kwargs.pop('flags', []) + needed_flags = ('-pthread',) + for flag in needed_flags: + if flag not in flags: + flags.append(flag) + + return link(obj_files, shared=True, flags=flags, cwd=cwd, cplus=cplus, fort=fort, + include_dirs=include_dirs, libraries=libraries, + library_dirs=library_dirs, extra_objs=extra_objs, **kwargs) + + +def simple_cythonize(src, destdir=None, cwd=None, **cy_kwargs): + """ Generates a C file from a Cython source file. + + Parameters + ========== + + src: str + Path to Cython source. + destdir: str (optional) + Path to output directory (default: '.'). + cwd: path string (optional) + Root of relative paths (default: '.'). + **cy_kwargs: + Second argument passed to cy_compile. Generates a .cpp file if ``cplus=True`` in ``cy_kwargs``, + else a .c file. + """ + from Cython.Compiler.Main import ( + default_options, CompilationOptions + ) + from Cython.Compiler.Main import compile as cy_compile + + assert src.lower().endswith('.pyx') or src.lower().endswith('.py') + cwd = cwd or '.' + destdir = destdir or '.' + + ext = '.cpp' if cy_kwargs.get('cplus', False) else '.c' + c_name = os.path.splitext(os.path.basename(src))[0] + ext + + dstfile = os.path.join(destdir, c_name) + + if cwd: + ori_dir = os.getcwd() + else: + ori_dir = '.' + os.chdir(cwd) + try: + cy_options = CompilationOptions(default_options) + cy_options.__dict__.update(cy_kwargs) + # Set language_level if not set by cy_kwargs + # as not setting it is deprecated + if 'language_level' not in cy_kwargs: + cy_options.__dict__['language_level'] = 3 + cy_result = cy_compile([src], cy_options) + if cy_result.num_errors > 0: + raise ValueError("Cython compilation failed.") + + # Move generated C file to destination + # In macOS, the generated C file is in the same directory as the source + # but the /var is a symlink to /private/var, so we need to use realpath + if os.path.realpath(os.path.dirname(src)) != os.path.realpath(destdir): + if os.path.exists(dstfile): + os.unlink(dstfile) + shutil.move(os.path.join(os.path.dirname(src), c_name), destdir) + finally: + os.chdir(ori_dir) + return dstfile + + +extension_mapping = { + '.c': (CCompilerRunner, None), + '.cpp': (CppCompilerRunner, None), + '.cxx': (CppCompilerRunner, None), + '.f': (FortranCompilerRunner, None), + '.for': (FortranCompilerRunner, None), + '.ftn': (FortranCompilerRunner, None), + '.f90': (FortranCompilerRunner, None), # ifort only knows about .f90 + '.f95': (FortranCompilerRunner, 'f95'), + '.f03': (FortranCompilerRunner, 'f2003'), + '.f08': (FortranCompilerRunner, 'f2008'), +} + + +def src2obj(srcpath, Runner=None, objpath=None, cwd=None, inc_py=False, **kwargs): + """ Compiles a source code file to an object file. + + Files ending with '.pyx' assumed to be cython files and + are dispatched to pyx2obj. + + Parameters + ========== + + srcpath: str + Path to source file. + Runner: CompilerRunner subclass (optional) + If ``None``: deduced from extension of srcpath. + objpath : str (optional) + Path to generated object. If ``None``: deduced from ``srcpath``. + cwd: str (optional) + Working directory and root of relative paths. If ``None``: current dir. + inc_py: bool + Add Python include path to kwarg "include_dirs". Default: False + \\*\\*kwargs: dict + keyword arguments passed to Runner or pyx2obj + + """ + name, ext = os.path.splitext(os.path.basename(srcpath)) + if objpath is None: + if os.path.isabs(srcpath): + objpath = '.' + else: + objpath = os.path.dirname(srcpath) + objpath = objpath or '.' # avoid objpath == '' + + if os.path.isdir(objpath): + objpath = os.path.join(objpath, name + objext) + + include_dirs = kwargs.pop('include_dirs', []) + if inc_py: + py_inc_dir = get_path('include') + if py_inc_dir not in include_dirs: + include_dirs.append(py_inc_dir) + + if ext.lower() == '.pyx': + return pyx2obj(srcpath, objpath=objpath, include_dirs=include_dirs, cwd=cwd, + **kwargs) + + if Runner is None: + Runner, std = extension_mapping[ext.lower()] + if 'std' not in kwargs: + kwargs['std'] = std + + flags = kwargs.pop('flags', []) + needed_flags = ('-fPIC',) + for flag in needed_flags: + if flag not in flags: + flags.append(flag) + + # src2obj implies not running the linker... + run_linker = kwargs.pop('run_linker', False) + if run_linker: + raise CompileError("src2obj called with run_linker=True") + + runner = Runner([srcpath], objpath, include_dirs=include_dirs, + run_linker=run_linker, cwd=cwd, flags=flags, **kwargs) + runner.run() + return objpath + + +def pyx2obj(pyxpath, objpath=None, destdir=None, cwd=None, + include_dirs=None, cy_kwargs=None, cplus=None, **kwargs): + """ + Convenience function + + If cwd is specified, pyxpath and dst are taken to be relative + If only_update is set to `True` the modification time is checked + and compilation is only run if the source is newer than the + destination + + Parameters + ========== + + pyxpath: str + Path to Cython source file. + objpath: str (optional) + Path to object file to generate. + destdir: str (optional) + Directory to put generated C file. When ``None``: directory of ``objpath``. + cwd: str (optional) + Working directory and root of relative paths. + include_dirs: iterable of path strings (optional) + Passed onto src2obj and via cy_kwargs['include_path'] + to simple_cythonize. + cy_kwargs: dict (optional) + Keyword arguments passed onto `simple_cythonize` + cplus: bool (optional) + Indicate whether C++ is used. default: auto-detect using ``.util.pyx_is_cplus``. + compile_kwargs: dict + keyword arguments passed onto src2obj + + Returns + ======= + + Absolute path of generated object file. + + """ + assert pyxpath.endswith('.pyx') + cwd = cwd or '.' + objpath = objpath or '.' + destdir = destdir or os.path.dirname(objpath) + + abs_objpath = get_abspath(objpath, cwd=cwd) + + if os.path.isdir(abs_objpath): + pyx_fname = os.path.basename(pyxpath) + name, ext = os.path.splitext(pyx_fname) + objpath = os.path.join(objpath, name + objext) + + cy_kwargs = cy_kwargs or {} + cy_kwargs['output_dir'] = cwd + if cplus is None: + cplus = pyx_is_cplus(pyxpath) + cy_kwargs['cplus'] = cplus + + interm_c_file = simple_cythonize(pyxpath, destdir=destdir, cwd=cwd, **cy_kwargs) + + include_dirs = include_dirs or [] + flags = kwargs.pop('flags', []) + needed_flags = ('-fwrapv', '-pthread', '-fPIC') + for flag in needed_flags: + if flag not in flags: + flags.append(flag) + + options = kwargs.pop('options', []) + + if kwargs.pop('strict_aliasing', False): + raise CompileError("Cython requires strict aliasing to be disabled.") + + # Let's be explicit about standard + if cplus: + std = kwargs.pop('std', 'c++98') + else: + std = kwargs.pop('std', 'c99') + + return src2obj(interm_c_file, objpath=objpath, cwd=cwd, + include_dirs=include_dirs, flags=flags, std=std, + options=options, inc_py=True, strict_aliasing=False, + **kwargs) + + +def _any_X(srcs, cls): + for src in srcs: + name, ext = os.path.splitext(src) + key = ext.lower() + if key in extension_mapping: + if extension_mapping[key][0] == cls: + return True + return False + + +def any_fortran_src(srcs): + return _any_X(srcs, FortranCompilerRunner) + + +def any_cplus_src(srcs): + return _any_X(srcs, CppCompilerRunner) + + +def compile_link_import_py_ext(sources, extname=None, build_dir='.', compile_kwargs=None, + link_kwargs=None, extra_objs=None): + """ Compiles sources to a shared object (Python extension) and imports it + + Sources in ``sources`` which is imported. If shared object is newer than the sources, they + are not recompiled but instead it is imported. + + Parameters + ========== + + sources : list of strings + List of paths to sources. + extname : string + Name of extension (default: ``None``). + If ``None``: taken from the last file in ``sources`` without extension. + build_dir: str + Path to directory in which objects files etc. are generated. + compile_kwargs: dict + keyword arguments passed to ``compile_sources`` + link_kwargs: dict + keyword arguments passed to ``link_py_so`` + extra_objs: list + List of paths to (prebuilt) object files / static libraries to link against. + + Returns + ======= + + The imported module from of the Python extension. + """ + if extname is None: + extname = os.path.splitext(os.path.basename(sources[-1]))[0] + + compile_kwargs = compile_kwargs or {} + link_kwargs = link_kwargs or {} + + try: + mod = import_module_from_file(os.path.join(build_dir, extname), sources) + except ImportError: + objs = compile_sources(list(map(get_abspath, sources)), destdir=build_dir, + cwd=build_dir, **compile_kwargs) + so = link_py_so(objs, cwd=build_dir, fort=any_fortran_src(sources), + cplus=any_cplus_src(sources), extra_objs=extra_objs, **link_kwargs) + mod = import_module_from_file(so) + return mod + + +def _write_sources_to_build_dir(sources, build_dir): + build_dir = build_dir or tempfile.mkdtemp() + if not os.path.isdir(build_dir): + raise OSError("Non-existent directory: ", build_dir) + + source_files = [] + for name, src in sources: + dest = os.path.join(build_dir, name) + differs = True + sha256_in_mem = sha256_of_string(src.encode('utf-8')).hexdigest() + if os.path.exists(dest): + if os.path.exists(dest + '.sha256'): + sha256_on_disk = Path(dest + '.sha256').read_text() + else: + sha256_on_disk = sha256_of_file(dest).hexdigest() + + differs = sha256_on_disk != sha256_in_mem + if differs: + with open(dest, 'wt') as fh: + fh.write(src) + with open(dest + '.sha256', 'wt') as fh: + fh.write(sha256_in_mem) + source_files.append(dest) + return source_files, build_dir + + +def compile_link_import_strings(sources, build_dir=None, **kwargs): + """ Compiles, links and imports extension module from source. + + Parameters + ========== + + sources : iterable of name/source pair tuples + build_dir : string (default: None) + Path. ``None`` implies use a temporary directory. + **kwargs: + Keyword arguments passed onto `compile_link_import_py_ext`. + + Returns + ======= + + mod : module + The compiled and imported extension module. + info : dict + Containing ``build_dir`` as 'build_dir'. + + """ + source_files, build_dir = _write_sources_to_build_dir(sources, build_dir) + mod = compile_link_import_py_ext(source_files, build_dir=build_dir, **kwargs) + info = {"build_dir": build_dir} + return mod, info + + +def compile_run_strings(sources, build_dir=None, clean=False, compile_kwargs=None, link_kwargs=None): + """ Compiles, links and runs a program built from sources. + + Parameters + ========== + + sources : iterable of name/source pair tuples + build_dir : string (default: None) + Path. ``None`` implies use a temporary directory. + clean : bool + Whether to remove build_dir after use. This will only have an + effect if ``build_dir`` is ``None`` (which creates a temporary directory). + Passing ``clean == True`` and ``build_dir != None`` raises a ``ValueError``. + This will also set ``build_dir`` in returned info dictionary to ``None``. + compile_kwargs: dict + Keyword arguments passed onto ``compile_sources`` + link_kwargs: dict + Keyword arguments passed onto ``link`` + + Returns + ======= + + (stdout, stderr): pair of strings + info: dict + Containing exit status as 'exit_status' and ``build_dir`` as 'build_dir' + + """ + if clean and build_dir is not None: + raise ValueError("Automatic removal of build_dir is only available for temporary directory.") + try: + source_files, build_dir = _write_sources_to_build_dir(sources, build_dir) + objs = compile_sources(list(map(get_abspath, source_files)), destdir=build_dir, + cwd=build_dir, **(compile_kwargs or {})) + prog = link(objs, cwd=build_dir, + fort=any_fortran_src(source_files), + cplus=any_cplus_src(source_files), **(link_kwargs or {})) + p = subprocess.Popen([prog], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + exit_status = p.wait() + stdout, stderr = [txt.decode('utf-8') for txt in p.communicate()] + finally: + if clean and os.path.isdir(build_dir): + shutil.rmtree(build_dir) + build_dir = None + info = {"exit_status": exit_status, "build_dir": build_dir} + return (stdout, stderr), info diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/runners.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/runners.py new file mode 100644 index 0000000000000000000000000000000000000000..1f37d6cf8ac47807da7f3f00dfc5cd847c03fa8d --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/runners.py @@ -0,0 +1,301 @@ +from __future__ import annotations +from typing import Callable, Optional + +from collections import OrderedDict +import os +import re +import subprocess +import warnings + +from .util import ( + find_binary_of_command, unique_list, CompileError +) + + +class CompilerRunner: + """ CompilerRunner base class. + + Parameters + ========== + + sources : list of str + Paths to sources. + out : str + flags : iterable of str + Compiler flags. + run_linker : bool + compiler_name_exe : (str, str) tuple + Tuple of compiler name & command to call. + cwd : str + Path of root of relative paths. + include_dirs : list of str + Include directories. + libraries : list of str + Libraries to link against. + library_dirs : list of str + Paths to search for shared libraries. + std : str + Standard string, e.g. ``'c++11'``, ``'c99'``, ``'f2003'``. + define: iterable of strings + macros to define + undef : iterable of strings + macros to undefine + preferred_vendor : string + name of preferred vendor e.g. 'gnu' or 'intel' + + Methods + ======= + + run(): + Invoke compilation as a subprocess. + + """ + + environ_key_compiler: str # e.g. 'CC', 'CXX', ... + environ_key_flags: str # e.g. 'CFLAGS', 'CXXFLAGS', ... + environ_key_ldflags: str = "LDFLAGS" # typically 'LDFLAGS' + + # Subclass to vendor/binary dict + compiler_dict: dict[str, str] + + # Standards should be a tuple of supported standards + # (first one will be the default) + standards: tuple[None | str, ...] + + # Subclass to dict of binary/formater-callback + std_formater: dict[str, Callable[[Optional[str]], str]] + + # subclass to be e.g. {'gcc': 'gnu', ...} + compiler_name_vendor_mapping: dict[str, str] + + def __init__(self, sources, out, flags=None, run_linker=True, compiler=None, cwd='.', + include_dirs=None, libraries=None, library_dirs=None, std=None, define=None, + undef=None, strict_aliasing=None, preferred_vendor=None, linkline=None, **kwargs): + if isinstance(sources, str): + raise ValueError("Expected argument sources to be a list of strings.") + self.sources = list(sources) + self.out = out + self.flags = flags or [] + if os.environ.get(self.environ_key_flags): + self.flags += os.environ[self.environ_key_flags].split() + self.cwd = cwd + if compiler: + self.compiler_name, self.compiler_binary = compiler + elif os.environ.get(self.environ_key_compiler): + self.compiler_binary = os.environ[self.environ_key_compiler] + for k, v in self.compiler_dict.items(): + if k in self.compiler_binary: + self.compiler_vendor = k + self.compiler_name = v + break + else: + self.compiler_vendor, self.compiler_name = list(self.compiler_dict.items())[0] + warnings.warn("failed to determine what kind of compiler %s is, assuming %s" % + (self.compiler_binary, self.compiler_name)) + else: + # Find a compiler + if preferred_vendor is None: + preferred_vendor = os.environ.get('SYMPY_COMPILER_VENDOR', None) + self.compiler_name, self.compiler_binary, self.compiler_vendor = self.find_compiler(preferred_vendor) + if self.compiler_binary is None: + raise ValueError("No compiler found (searched: {})".format(', '.join(self.compiler_dict.values()))) + self.define = define or [] + self.undef = undef or [] + self.include_dirs = include_dirs or [] + self.libraries = libraries or [] + self.library_dirs = library_dirs or [] + self.std = std or self.standards[0] + self.run_linker = run_linker + if self.run_linker: + # both gnu and intel compilers use '-c' for disabling linker + self.flags = list(filter(lambda x: x != '-c', self.flags)) + else: + if '-c' not in self.flags: + self.flags.append('-c') + + if self.std: + self.flags.append(self.std_formater[ + self.compiler_name](self.std)) + + self.linkline = (linkline or []) + [lf for lf in map( + str.strip, os.environ.get(self.environ_key_ldflags, "").split() + ) if lf != ""] + + if strict_aliasing is not None: + nsa_re = re.compile("no-strict-aliasing$") + sa_re = re.compile("strict-aliasing$") + if strict_aliasing is True: + if any(map(nsa_re.match, flags)): + raise CompileError("Strict aliasing cannot be both enforced and disabled") + elif any(map(sa_re.match, flags)): + pass # already enforced + else: + flags.append('-fstrict-aliasing') + elif strict_aliasing is False: + if any(map(nsa_re.match, flags)): + pass # already disabled + else: + if any(map(sa_re.match, flags)): + raise CompileError("Strict aliasing cannot be both enforced and disabled") + else: + flags.append('-fno-strict-aliasing') + else: + msg = "Expected argument strict_aliasing to be True/False, got {}" + raise ValueError(msg.format(strict_aliasing)) + + @classmethod + def find_compiler(cls, preferred_vendor=None): + """ Identify a suitable C/fortran/other compiler. """ + candidates = list(cls.compiler_dict.keys()) + if preferred_vendor: + if preferred_vendor in candidates: + candidates = [preferred_vendor]+candidates + else: + raise ValueError("Unknown vendor {}".format(preferred_vendor)) + name, path = find_binary_of_command([cls.compiler_dict[x] for x in candidates]) + return name, path, cls.compiler_name_vendor_mapping[name] + + def cmd(self): + """ List of arguments (str) to be passed to e.g. ``subprocess.Popen``. """ + cmd = ( + [self.compiler_binary] + + self.flags + + ['-U'+x for x in self.undef] + + ['-D'+x for x in self.define] + + ['-I'+x for x in self.include_dirs] + + self.sources + ) + if self.run_linker: + cmd += (['-L'+x for x in self.library_dirs] + + ['-l'+x for x in self.libraries] + + self.linkline) + counted = [] + for envvar in re.findall(r'\$\{(\w+)\}', ' '.join(cmd)): + if os.getenv(envvar) is None: + if envvar not in counted: + counted.append(envvar) + msg = "Environment variable '{}' undefined.".format(envvar) + raise CompileError(msg) + return cmd + + def run(self): + self.flags = unique_list(self.flags) + + # Append output flag and name to tail of flags + self.flags.extend(['-o', self.out]) + env = os.environ.copy() + env['PWD'] = self.cwd + + # NOTE: intel compilers seems to need shell=True + p = subprocess.Popen(' '.join(self.cmd()), + shell=True, + cwd=self.cwd, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + env=env) + comm = p.communicate() + try: + self.cmd_outerr = comm[0].decode('utf-8') + except UnicodeDecodeError: + self.cmd_outerr = comm[0].decode('iso-8859-1') # win32 + self.cmd_returncode = p.returncode + + # Error handling + if self.cmd_returncode != 0: + msg = "Error executing '{}' in {} (exited status {}):\n {}\n".format( + ' '.join(self.cmd()), self.cwd, str(self.cmd_returncode), self.cmd_outerr + ) + raise CompileError(msg) + + return self.cmd_outerr, self.cmd_returncode + + +class CCompilerRunner(CompilerRunner): + + environ_key_compiler = 'CC' + environ_key_flags = 'CFLAGS' + + compiler_dict = OrderedDict([ + ('gnu', 'gcc'), + ('intel', 'icc'), + ('llvm', 'clang'), + ]) + + standards = ('c89', 'c90', 'c99', 'c11') # First is default + + std_formater = { + 'gcc': '-std={}'.format, + 'icc': '-std={}'.format, + 'clang': '-std={}'.format, + } + + compiler_name_vendor_mapping = { + 'gcc': 'gnu', + 'icc': 'intel', + 'clang': 'llvm' + } + + +def _mk_flag_filter(cmplr_name): # helper for class initialization + not_welcome = {'g++': ("Wimplicit-interface",)} # "Wstrict-prototypes",)} + if cmplr_name in not_welcome: + def fltr(x): + for nw in not_welcome[cmplr_name]: + if nw in x: + return False + return True + else: + def fltr(x): + return True + return fltr + + +class CppCompilerRunner(CompilerRunner): + + environ_key_compiler = 'CXX' + environ_key_flags = 'CXXFLAGS' + + compiler_dict = OrderedDict([ + ('gnu', 'g++'), + ('intel', 'icpc'), + ('llvm', 'clang++'), + ]) + + # First is the default, c++0x == c++11 + standards = ('c++98', 'c++0x') + + std_formater = { + 'g++': '-std={}'.format, + 'icpc': '-std={}'.format, + 'clang++': '-std={}'.format, + } + + compiler_name_vendor_mapping = { + 'g++': 'gnu', + 'icpc': 'intel', + 'clang++': 'llvm' + } + + +class FortranCompilerRunner(CompilerRunner): + + environ_key_compiler = 'FC' + environ_key_flags = 'FFLAGS' + + standards = (None, 'f77', 'f95', 'f2003', 'f2008') + + std_formater = { + 'gfortran': lambda x: '-std=gnu' if x is None else '-std=legacy' if x == 'f77' else '-std={}'.format(x), + 'ifort': lambda x: '-stand f08' if x is None else '-stand f{}'.format(x[-2:]), # f2008 => f08 + } + + compiler_dict = OrderedDict([ + ('gnu', 'gfortran'), + ('intel', 'ifort'), + ]) + + compiler_name_vendor_mapping = { + 'gfortran': 'gnu', + 'ifort': 'intel', + } diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..05ceb248423b3265a199cfe51541ae459aea690e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/tests/__pycache__/test_compilation.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/tests/__pycache__/test_compilation.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e21fd0f9d75fbdb831f483f2295e26f4e99ef32d Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/tests/__pycache__/test_compilation.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/tests/test_compilation.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/tests/test_compilation.py new file mode 100644 index 0000000000000000000000000000000000000000..ff7cf86644a9645665e62b49cfc4e7ea73b2c1ab --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/_compilation/tests/test_compilation.py @@ -0,0 +1,104 @@ +import shutil +import os +import subprocess +import tempfile +from sympy.external import import_module +from sympy.testing.pytest import skip, skip_under_pyodide + +from sympy.utilities._compilation.compilation import compile_link_import_py_ext, compile_link_import_strings, compile_sources, get_abspath + +numpy = import_module('numpy') +cython = import_module('cython') + +_sources1 = [ + ('sigmoid.c', r""" +#include + +void sigmoid(int n, const double * const restrict in, + double * const restrict out, double lim){ + for (int i=0; i 0: + if not os.path.exists(parent): + make_dirs(parent) + + if not os.path.exists(path): + os.mkdir(path, 0o777) + else: + assert os.path.isdir(path) + +def missing_or_other_newer(path, other_path, cwd=None): + """ + Investigate if path is non-existent or older than provided reference + path. + + Parameters + ========== + path: string + path to path which might be missing or too old + other_path: string + reference path + cwd: string + working directory (root of relative paths) + + Returns + ======= + True if path is older or missing. + """ + cwd = cwd or '.' + path = get_abspath(path, cwd=cwd) + other_path = get_abspath(other_path, cwd=cwd) + if not os.path.exists(path): + return True + if os.path.getmtime(other_path) - 1e-6 >= os.path.getmtime(path): + # 1e-6 is needed because http://stackoverflow.com/questions/17086426/ + return True + return False + +def copy(src, dst, only_update=False, copystat=True, cwd=None, + dest_is_dir=False, create_dest_dirs=False): + """ Variation of ``shutil.copy`` with extra options. + + Parameters + ========== + + src : str + Path to source file. + dst : str + Path to destination. + only_update : bool + Only copy if source is newer than destination + (returns None if it was newer), default: ``False``. + copystat : bool + See ``shutil.copystat``. default: ``True``. + cwd : str + Path to working directory (root of relative paths). + dest_is_dir : bool + Ensures that dst is treated as a directory. default: ``False`` + create_dest_dirs : bool + Creates directories if needed. + + Returns + ======= + + Path to the copied file. + + """ + if cwd: # Handle working directory + if not os.path.isabs(src): + src = os.path.join(cwd, src) + if not os.path.isabs(dst): + dst = os.path.join(cwd, dst) + + if not os.path.exists(src): # Make sure source file exists + raise FileNotFoundError("Source: `{}` does not exist".format(src)) + + # We accept both (re)naming destination file _or_ + # passing a (possible non-existent) destination directory + if dest_is_dir: + if not dst[-1] == '/': + dst = dst+'/' + else: + if os.path.exists(dst) and os.path.isdir(dst): + dest_is_dir = True + + if dest_is_dir: + dest_dir = dst + dest_fname = os.path.basename(src) + dst = os.path.join(dest_dir, dest_fname) + else: + dest_dir = os.path.dirname(dst) + + if not os.path.exists(dest_dir): + if create_dest_dirs: + make_dirs(dest_dir) + else: + raise FileNotFoundError("You must create directory first.") + + if only_update: + if not missing_or_other_newer(dst, src): + return + + if os.path.islink(dst): + dst = os.path.abspath(os.path.realpath(dst), cwd=cwd) + + shutil.copy(src, dst) + if copystat: + shutil.copystat(src, dst) + + return dst + +Glob = namedtuple('Glob', 'pathname') +ArbitraryDepthGlob = namedtuple('ArbitraryDepthGlob', 'filename') + +def glob_at_depth(filename_glob, cwd=None): + if cwd is not None: + cwd = '.' + globbed = [] + for root, dirs, filenames in os.walk(cwd): + for fn in filenames: + # This is not tested: + if fnmatch.fnmatch(fn, filename_glob): + globbed.append(os.path.join(root, fn)) + return globbed + +def sha256_of_file(path, nblocks=128): + """ Computes the SHA256 hash of a file. + + Parameters + ========== + + path : string + Path to file to compute hash of. + nblocks : int + Number of blocks to read per iteration. + + Returns + ======= + + hashlib sha256 hash object. Use ``.digest()`` or ``.hexdigest()`` + on returned object to get binary or hex encoded string. + """ + sh = sha256() + with open(path, 'rb') as f: + for chunk in iter(lambda: f.read(nblocks*sh.block_size), b''): + sh.update(chunk) + return sh + + +def sha256_of_string(string): + """ Computes the SHA256 hash of a string. """ + sh = sha256() + sh.update(string) + return sh + + +def pyx_is_cplus(path): + """ + Inspect a Cython source file (.pyx) and look for comment line like: + + # distutils: language = c++ + + Returns True if such a file is present in the file, else False. + """ + with open(path) as fh: + for line in fh: + if line.startswith('#') and '=' in line: + splitted = line.split('=') + if len(splitted) != 2: + continue + lhs, rhs = splitted + if lhs.strip().split()[-1].lower() == 'language' and \ + rhs.strip().split()[0].lower() == 'c++': + return True + return False + +def import_module_from_file(filename, only_if_newer_than=None): + """ Imports Python extension (from shared object file) + + Provide a list of paths in `only_if_newer_than` to check + timestamps of dependencies. import_ raises an ImportError + if any is newer. + + Word of warning: The OS may cache shared objects which makes + reimporting same path of an shared object file very problematic. + + It will not detect the new time stamp, nor new checksum, but will + instead silently use old module. Use unique names for this reason. + + Parameters + ========== + + filename : str + Path to shared object. + only_if_newer_than : iterable of strings + Paths to dependencies of the shared object. + + Raises + ====== + + ``ImportError`` if any of the files specified in ``only_if_newer_than`` are newer + than the file given by filename. + """ + path, name = os.path.split(filename) + name, ext = os.path.splitext(name) + name = name.split('.')[0] + if sys.version_info[0] == 2: + from imp import find_module, load_module + fobj, filename, data = find_module(name, [path]) + if only_if_newer_than: + for dep in only_if_newer_than: + if os.path.getmtime(filename) < os.path.getmtime(dep): + raise ImportError("{} is newer than {}".format(dep, filename)) + mod = load_module(name, fobj, filename, data) + else: + import importlib.util + spec = importlib.util.spec_from_file_location(name, filename) + if spec is None: + raise ImportError("Failed to import: '%s'" % filename) + mod = importlib.util.module_from_spec(spec) + spec.loader.exec_module(mod) + return mod + + +def find_binary_of_command(candidates): + """ Finds binary first matching name among candidates. + + Calls ``which`` from shutils for provided candidates and returns + first hit. + + Parameters + ========== + + candidates : iterable of str + Names of candidate commands + + Raises + ====== + + CompilerNotFoundError if no candidates match. + """ + from shutil import which + for c in candidates: + binary_path = which(c) + if c and binary_path: + return c, binary_path + + raise CompilerNotFoundError('No binary located for candidates: {}'.format(candidates)) + + +def unique_list(l): + """ Uniquify a list (skip duplicate items). """ + result = [] + for x in l: + if x not in result: + result.append(x) + return result diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/mathml/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/mathml/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..eded44ee3c0f34ad1324765ba06ee9d6eb5e9899 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/mathml/__init__.py @@ -0,0 +1,122 @@ +"""Module with some functions for MathML, like transforming MathML +content in MathML presentation. + +To use this module, you will need lxml. +""" + +from pathlib import Path + +from sympy.utilities.decorator import doctest_depends_on + + +__doctest_requires__ = {('apply_xsl', 'c2p'): ['lxml']} + + +def add_mathml_headers(s): + return """""" + s + "" + + +def _read_binary(pkgname, filename): + import sys + + if sys.version_info >= (3, 10): + # files was added in Python 3.9 but only seems to work here in 3.10+ + from importlib.resources import files + return files(pkgname).joinpath(filename).read_bytes() + else: + # read_binary was deprecated in Python 3.11 + from importlib.resources import read_binary + return read_binary(pkgname, filename) + + +def _read_xsl(xsl): + # Previously these values were allowed: + if xsl == 'mathml/data/simple_mmlctop.xsl': + xsl = 'simple_mmlctop.xsl' + elif xsl == 'mathml/data/mmlctop.xsl': + xsl = 'mmlctop.xsl' + elif xsl == 'mathml/data/mmltex.xsl': + xsl = 'mmltex.xsl' + + if xsl in ['simple_mmlctop.xsl', 'mmlctop.xsl', 'mmltex.xsl']: + xslbytes = _read_binary('sympy.utilities.mathml.data', xsl) + else: + xslbytes = Path(xsl).read_bytes() + + return xslbytes + + +@doctest_depends_on(modules=('lxml',)) +def apply_xsl(mml, xsl): + """Apply a xsl to a MathML string. + + Parameters + ========== + + mml + A string with MathML code. + xsl + A string giving the name of an xsl (xml stylesheet) file which can be + found in sympy/utilities/mathml/data. The following files are supplied + with SymPy: + + - mmlctop.xsl + - mmltex.xsl + - simple_mmlctop.xsl + + Alternatively, a full path to an xsl file can be given. + + Examples + ======== + + >>> from sympy.utilities.mathml import apply_xsl + >>> xsl = 'simple_mmlctop.xsl' + >>> mml = ' a b ' + >>> res = apply_xsl(mml,xsl) + >>> print(res) + + + a + + + b + + """ + from lxml import etree + + parser = etree.XMLParser(resolve_entities=False) + ac = etree.XSLTAccessControl.DENY_ALL + + s = etree.XML(_read_xsl(xsl), parser=parser) + transform = etree.XSLT(s, access_control=ac) + doc = etree.XML(mml, parser=parser) + result = transform(doc) + s = str(result) + return s + + +@doctest_depends_on(modules=('lxml',)) +def c2p(mml, simple=False): + """Transforms a document in MathML content (like the one that sympy produces) + in one document in MathML presentation, more suitable for printing, and more + widely accepted + + Examples + ======== + + >>> from sympy.utilities.mathml import c2p + >>> mml = ' 2 ' + >>> c2p(mml,simple=True) != c2p(mml,simple=False) + True + + """ + + if not mml.startswith(' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + e + + + + + + + + + + + + + - + + + + + + + + &#x2062; + &#x2148; + + + + + + + + + + + + + - + + + + + + + + &#x2062; + &#x2148; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Polar + &#x2062; + + + + + + + + + + + + + + + Polar + &#x2062; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x2061; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [ + + + ] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x03BB; + &#x2061; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x2218; + + + + + + + + + + + + + + + + + + &#x2218; + + + + + + + + + + + + + + + + id + + + id + + + + + + + + + + + + + + domain + + + codomain + + + image + + &#x2061; + + + + + + + + + + + + + + + + + + + + + + + + + + + { + + + + + + + + if + + + + + + + + + + + otherwise + + + + + + + + + + + + + + + + + + + + + + + &#x230A; + + + + + + + + + + + + + + + + + + + &#x230B; + + + + + + + + + + + + &#x2147; + + + + + + + + + + + + + + + + + ! + + + + + + + + + + + + + + + + max + + + min + + + + + + + max + + + min + + + + + + + + + + + + + | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x2062; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + gcd + + + lcm + + + + + + gcd + + + lcm + + + + + &#x2061; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x2227; + &#x2061; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x2228; + &#x2061; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x22BB; + &#x2061; + + + + + + + + + + + + + + + + + + + + + + + &#x00AC; + &#x2061; + + + + + + + + + + + + + + + &#x00AC; + &#x2061; + + + + + + + + + + + + + + + + + + + &#x2200; + + + + + + + + + + + + : + + + + , + + + + + + + + + + + + + + &#x2203; + + + + + + + + + + + + : + + + + , + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x00AF; + + + + + + + + + + + + + + + + + &#x211C; + + + &#x2111; + + + &#x2061; + + + + + + + + + + + + + + + + + &#x230A; + + + &#x2308; + + + + + + &#x230B; + + + &#x2309; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x2260; + + + &#x2248; + + + &#x2223; + + + + + &#x2198; + + + &#x2197; + + + &#x2192; + + + + + &#x21D2; + + + &#x2208; + + + &#x2209; + + + &#x2284; + + + &#x2288; + + + + + + + + + + &#x2286; + + + &#x2282; + + + + + + + + + + + + &#x2265; + + + &#x2264; + + + &#x2261; + + + + + + + + + + + + + + + + + + + + + + ln + + + + + ln + + + + + + + + + + + + + + + + + + + + + + log + + + + + + log + + + + + + + + log + + + + log + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x2146; + + &#x2146; + + + + + + + + &#x2146; + + + + &#x2146; + + + + + + + + + + + + + + + + + + &#x2032; + + + + + + + + + + + + + + + + + &#x2145; + + + + + + + + &#x2202; + + + + + &#x2202; + + + + + + + + + + + + + + + + + + + &#x2202; + + + + &#x2202; + + + + + + + + + + &#x2202; + + &#x2202; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x2207; + 2 + + &#x2061; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x222A; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x2229; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x00D7; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x2211; + + + &#x220F; + + + + + = + + + + + + + + + + + &#x2211; + + + &#x220F; + + + + + + + + + + + &#x2211; + + + &#x220F; + + + + + + + + + + + + + + + + + + + + + + + + &#x222B; + + + + + + &#x222B; + + + + + + &#x222B; + + + + + + + + + + + + &#x222B; + + + + + + + + + &#x222B; + + + + + + + + + &#x2146; + + + + + + + + + + + + + + + + lim + + + + &#x2192; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x03C3; + + + + + + + + + + + + + + + + + &#x03C3; + + + + + + + 2 + + + + + + + + + + + + + median + + + + + + + + + + + + + + + + + mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + det + + + + + + + + + + + + + + + T + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x00D7; + + + &#x22C5; + + + &#x2297; + + + + + + + + + + + + &#x2124; + + + + &#x211D; + + + + &#x211A; + + + + &#x2115; + + + + &#x2102; + + + + &#x2119; + + + + &#x2147; + + + + &#x2148; + + + + NaN + + + + true + + + + false + + + + &#x2205; + + + + &#x03C0; + + + + &#x213D; + + + + &#x221E; + + + diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/mathml/data/mmltex.xsl b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/mathml/data/mmltex.xsl new file mode 100644 index 0000000000000000000000000000000000000000..5e6b85e02efd5196fe76b6ce4e10def27b9a8497 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/mathml/data/mmltex.xsl @@ -0,0 +1,2360 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $ + + $ + + + + + + + + + + + + + + + + i + + + + + / + + + + + + _{} + + + + + e^{i + + } + + + + + E + + + + + + + + \mathrm{} + + + + + + + + + + + + + ( + + + , + + ) + + + + + () + + + + + + + \left( + + \left[ + + + , + + + + \right) + + \right] + + + + + \left\{\right\} + + + + + ^{(-1)} + + + + + + + + \mathrm{lambda}\: + + .\: + + + + + + + + + + \circ + + + + +\mathrm{id} + + + + \mathop{\mathrm{ + + }} + + + + + + + + \begin{cases} + + + \end{cases} + + + + + & \text{if $ + + $} + \\ + + + + + & \text{otherwise} + + + + + \left\lfloor\frac{ + + }{ + + }\right\rfloor + + + + + + + + ! + + + + + + + \left( + \frac{ + + + }{ + + + } + \right) + + + + + \ + + \{ + + + + , + + + + + + , + + + + \} + + + + + - + + + + + + + + + - + + + + + + + + + + ( + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) + + + + + + + + + ^{ + + + + } + + + + + + + \mod + + + + + + + + + + ( + + + + \times + + + + + + + + + + ) + + + + + \sqrt + + [ + + ] + + { + + } + + + +\gcd + + + + + + + + \land + + + + + + + + + + \lor + + + + + + + + + + \mathop{\mathrm{xor}} + + + + + + \neg + + + + + + + + + + \implies + + + + + + + + \ + + + + + , + + + \colon + + + + + + + \left| + + \right| + + + + + \overline{} + + + +\Re + + +\Im + + + + \left\lfloor + + \right\rfloor + + + + + \left\lceil + + \right\rceil + + + + + + + + + = + + + + + + + + + + \neq + + + + + + + + + + > + + + + + + + + + + < + + + + + + + + + + \ge + + + + + + + + + + \le + + + + + + + + + + \equiv + + + + + + + + + + \approx + + + + + + + + | + + + + + + + + \int + + _{ + + } + + + ^{ + + } + + + + \,d + + + + + + + ^\prime + + + + \frac{ + + + d^{ + + } + + }{d + + ^{ + + } + + + d + + }{d + + } + + + } + + + + + D_{ + + + , + + } + + + + + \frac{\partial^{ + + + + + + + + + + + + + + + + + + + + + } + + }{ + + \partial + + + ^{ + + } + + + } + + + + + + + + + , + + + +\mathop{\mathrm{div}} + + +\nabla^2 + + + + \{\} + + + + + \left[\right] + + + + + + + \colon + + + + + + , + + + + + + + + + + + + \cup + + + + + + + + + + \cap + + + + + + + + \in + + + + + + + + + + \notin + + + + + + + + + + + + \subseteq + + + + + + + + + + \subset + + + + + + + + + + \nsubseteq + + + + + + + + + + \not\subset + + + + + + + + + + \setminus + + + + + + | + + | + + + + + + + + + \times + + + + + + + + ^{ + + } + + + + + \sum + + + + + \prod + + + + + _{ + + + = + + + } + + + ^{ + + } + + + + + + + + \lim_{ + + } + + + + + + \to + + + + + + + + + + + + \searrow + \nearrow + \rightarrow + \to + + + + + + + + \ + + + + + + + + + \ + + + + + + \mathrm{ + + \,} + + + + + + + \mathrm{ + + } + + + + + e^{} + + + + + \lg + + + + + + + \log_{ + + } + + + + + + + + \left\langle + + + , + + \right\rangle + + + +\sigma + + + + \sigma( + + )^2 + + + + + \left\langle + + ^{ + + }\right\rangle + + _{ + + } + + + + + + + \left(\begin{array}{c} + + + \\ + + \end{array}\right) + + + + + \begin{pmatrix} + + \end{pmatrix} + + + + + + + & + + \\ + + + + + \det + + + + + + + \begin{vmatrix} + + \end{vmatrix} + + + + + + + + ^T + + + + + + + + _{ + + + , + + } + + + + + + + + + \dot + + + + + + + + + + + +\mathbb{Z} + + +\mathbb{R} + + +\mathbb{Q} + + +\mathbb{N} + + +\mathbb{C} + + +\mathbb{P} + + +e + + +i + + +NaN + + +\mbox{true} + + +\mbox{false} + + +\emptyset + + +\pi + + +\gamma + + +\infty + + + + + + + ( + + + + + + + + + ) + + + + + + + ( + + + + + + + + ) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \multicolumn{ + + }{c}{ + + } + + & + + + + + + + \hfill + + + + \hfill + + + + & + + + + + + + \\ + + + + + \begin{array}{ + + | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | + + } + + \hline + + + + \\ \hline + + \end{array} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \overline{ + + + + + } + + + \overbrace{ + + + + + } + + + \underline{ + + + + + + } + + + \underbrace{ + + + + + + } + + + + + _{ + + }^{ + + } + + + \underset{ + + }{\overset{ + + }{ + + }} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \overline{ + + } + + + \overbrace{ + + } + + + + + ^{ + + } + + + \stackrel{ + + }{ + + } + + + + + + + + + + + \underline{ + + } + + + \underbrace{ + + } + + + + + _{ + + } + + + \underset{ + + }{ + + } + + + + + + { + + }_{ + + }^{ + + } + + + + { + + }^{ + + } + + + + { + + }_{ + + } + + + + + + {}_{ + + } + + + {}^{ + + } + + + + + + {} + + + _{ + + } + + + ^{ + + } + + + + + + + + + + + + + + {} + + + _{ + + } + + + ^{ + + } + + + + + + + + + + + + + + + + + + \genfrac{}{}{ + + + + ex + + + .05ex + + + + .2ex + + + + + + }{}{ + + + \frac{ + + + + \hfill + + + + \hfill + + }{ + + \hfill + + + + \hfill + + } + + + + + + \sqrt[ + + ]{ + + } + + + + exception 25: + \text{exception 25:} + + + + + + \sqrt{ + + } + + + + + + + \left + + + \ + + + + \left( + + + + + + + + + + + , + + + + + + + + + + + + + + + + + + + + + + + + \right + + + \ + + + + \right) + + + + + \phantom{ + + } + + + + + + \overline{ + + \hspace{.2em}|} + + + \sqrt{ + + } + + + \overline{) + + } + + + + + + + + + + + \colorbox[rgb]{ + + + + }{$ + + + \textcolor[rgb]{ + + + + }{ + + + + } + + + $} + + + + + + + + + + + + + + + + + + + + + \mathrm{ + + } + + + + + + + + + + + + + + + + + + + + + + \text{ + + } + + + + \phantom{\rule + + [- + + ] + + { + + 0ex + + + }{ + + 0ex + + + }} + + + + + + " + + + " + + + + + + \colorbox[rgb]{ + + + + }{$ + + + \textcolor[rgb]{ + + + + }{ + + + + + \mathrm{ + + + \mathbf{ + + + \mathit{ + + + \mathbit{ + + + \mathbb{ + + + { + + + \mathcal{ + + + \mathsc{ + + + \mathfrak{ + + + \mathsf{ + + + \mathbsf{ + + + \mathsfit{ + + + \mathbsfit{ + + + \mathtt{ + + + { + + + + + + } + + + } + + + $} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + , + + + + + + , + + + + + + + + + + + + + + + + + + + , + + + + + + + + + + + , + + + + + + + + + + + + + + 0,1,1 + 0,0,0 + 0,0,1 + 1,0,1 + .5,.5,.5 + 0,.5,0 + 0,1,0 + .5,0,0 + 0,0,.5 + .5,.5,0 + .5,0,.5 + 1,0,0 + .75,.75,.75 + 0,.5,.5 + 1,1,1 + 1,1,0 + + Exception at color template + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Exception at Hex2Decimal template + + + + + + + + + + + diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/mathml/data/simple_mmlctop.xsl b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/mathml/data/simple_mmlctop.xsl new file mode 100644 index 0000000000000000000000000000000000000000..0cd73bccc24c963ed9c6c4121cc410997b94261c --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/mathml/data/simple_mmlctop.xsl @@ -0,0 +1,3166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + e + + + + + + + + + + + + + - + + + + + + + + &#x2062; + &#x2148; + + + + + + + + + + + + + - + + + + + + + + &#x2062; + &#x2148; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Polar + &#x2062; + + + + + + + + + + + + + + + Polar + &#x2062; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x2061; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [ + + + ] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x03BB; + &#x2061; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x2218; + + + + + + + + + + + + + + + + + + &#x2218; + + + + + + + + + + + + + + + + id + + + id + + + + + + + + + + + + + + domain + + + codomain + + + image + + &#x2061; + + + + + + + + + + + + + + + + + + + + + + + + + + + { + + + + + + + + if + + + + + + + + + + + otherwise + + + + + + + + + + + + + + + + + + + + + + + &#x230A; + + + + + + + + + + + + + + + + + + + &#x230B; + + + + + + + + + + + + e + + + + + + + + + + + + + + + + + ! + + + + + + + + + + + + + + + + max + + + min + + + + + + + max + + + min + + + + + + + + + + + + + | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x2062; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + gcd + + + lcm + + + + + + gcd + + + lcm + + + + + &#x2061; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x2227; + &#x2061; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x2228; + &#x2061; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x22BB; + &#x2061; + + + + + + + + + + + + + + + + + + + + + + + &#x00AC; + &#x2061; + + + + + + + + + + + + + + + &#x00AC; + &#x2061; + + + + + + + + + + + + + + + + + + + &#x2200; + + + + + + + + + + + + : + + + + , + + + + + + + + + + + + + + &#x2203; + + + + + + + + + + + + : + + + + , + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x00AF; + + + + + + + + + + + + + + + + + &#x211C; + + + &#x2111; + + + &#x2061; + + + + + + + + + + + + + + + + + &#x230A; + + + &#x2308; + + + + + + &#x230B; + + + &#x2309; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x2260; + + + &#x2248; + + + &#x2223; + + + + + &#x2198; + + + &#x2197; + + + &#x2192; + + + + + &#x21D2; + + + &#x2208; + + + &#x2209; + + + &#x2284; + + + &#x2288; + + + + + + + + + + &#x2286; + + + &#x2282; + + + + + + + + + + + + &#x2265; + + + &#x2264; + + + &#x2261; + + + + + + + + + + + + + + + + + + + + + + ln + + + + + ln + + + + + + + + + + + + + + + + + + + + + + log + + + + + + log + + + + + + + + log + + + + log + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + d + + d + + + + + + + + d + + + + d + + + + + + + + + + + + + + + + + + &#x2032; + + + + + + + + + + + + + + + + + &#x2145; + + + + + + + + &#x2202; + + + + + &#x2202; + + + + + + + + + + + + + + + + + + + &#x2202; + + + + &#x2202; + + + + + + + + + + &#x2202; + + &#x2202; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x2207; + 2 + + &#x2061; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x222A; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x2229; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x00D7; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x2211; + + + &#x220F; + + + + + = + + + + + + + + + + + &#x2211; + + + &#x220F; + + + + + + + + + + + &#x2211; + + + &#x220F; + + + + + + + + + + + + + + + + + + + + + + + + &#x222B; + + + + + + &#x222B; + + + + + + &#x222B; + + + + + + + + + + + + &#x222B; + + + + + + + + + &#x222B; + + + + + + + + + d + + + + + + + + + + + + + + + + lim + + + + &#x2192; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x03C3; + + + + + + + + + + + + + + + + + &#x03C3; + + + + + + + 2 + + + + + + + + + + + + + median + + + + + + + + + + + + + + + + + mode + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + det + + + + + + + + + + + + + + + T + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + &#x00D7; + + + &#x22C5; + + + &#x2297; + + + + + + + + + + + + &#x2124; + + + + &#x211D; + + + + &#x211A; + + + + &#x2115; + + + + &#x2102; + + + + &#x2119; + + + + e + + + + &#x2148; + + + + NaN + + + + true + + + + false + + + + &#x2205; + + + + &#x03C0; + + + + &#x213D; + + + + &#x221E; + + + diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..35b3975475c6b88a4efe2a90209ea509cc9b8920 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_autowrap.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_autowrap.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..64153ea893307233b1d67601457d7c212f0d8dfe Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_autowrap.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_codegen.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_codegen.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7ff30ec230c66df129f7ad1c23de67854cd3eb53 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_codegen.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_codegen_julia.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_codegen_julia.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..19066a8d73f9dd6f637726a510c6d722b36e5967 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_codegen_julia.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_codegen_octave.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_codegen_octave.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..75ed022790faa8c33be36f50d913f87895eb1a4b Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_codegen_octave.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_codegen_rust.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_codegen_rust.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f044928e68f7722ff85ed385a31877132fd58f23 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_codegen_rust.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_decorator.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_decorator.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0017248d1c45b7b8f2a73a7c5a8be0dbee215501 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_decorator.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_deprecated.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_deprecated.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5a898ac7a460f1711e08a5a3dca625a38ae9890e Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_deprecated.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_enumerative.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_enumerative.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c0d846dad3bbe20dcaaf105ff65d6d1cd65c5fd2 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_enumerative.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_exceptions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_exceptions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3204683a1ffddbf2837bf9d893d6069c4e315ddf Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_exceptions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_iterables.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_iterables.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2cd25147097f41f82785116812972d91cd0b5752 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_iterables.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_matchpy_connector.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_matchpy_connector.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a085be48ffb4f25acdb847ab7905baccbe175da9 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_matchpy_connector.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_mathml.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_mathml.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b9691aed14a9850372b31144ef5dc6fd3eb7c100 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_mathml.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_misc.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_misc.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fb7e660c2868faa1198de63afc1727d9085982ed Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_misc.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_pickling.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_pickling.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..394fbcc5b4fd52f73c008e4ace5ff6e11d23da25 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_pickling.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_source.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_source.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..751ce9fc30f47e5da27a9c700609362d4c3a40a6 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_source.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_timeutils.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_timeutils.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5eb59a31879718082e91f9af23b6ebb0f7b7cbe7 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_timeutils.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_xxe.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_xxe.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..daf79a0085656e2ea06db8fb95cdf3aed5bd0da4 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/__pycache__/test_xxe.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_autowrap.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_autowrap.py new file mode 100644 index 0000000000000000000000000000000000000000..b5a33d77adb46710cfa3cfeb1ea39402e35c76cf --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_autowrap.py @@ -0,0 +1,467 @@ +# Tests that require installed backends go into +# sympy/test_external/test_autowrap + +import os +import tempfile +import shutil +from io import StringIO +from pathlib import Path + +from sympy.core import symbols, Eq +from sympy.utilities.autowrap import (autowrap, binary_function, + CythonCodeWrapper, UfuncifyCodeWrapper, CodeWrapper) +from sympy.utilities.codegen import ( + CCodeGen, C99CodeGen, CodeGenArgumentListError, make_routine +) +from sympy.testing.pytest import raises +from sympy.testing.tmpfiles import TmpFileManager + + +def get_string(dump_fn, routines, prefix="file", **kwargs): + """Wrapper for dump_fn. dump_fn writes its results to a stream object and + this wrapper returns the contents of that stream as a string. This + auxiliary function is used by many tests below. + + The header and the empty lines are not generator to facilitate the + testing of the output. + """ + output = StringIO() + dump_fn(routines, output, prefix, **kwargs) + source = output.getvalue() + output.close() + return source + + +def test_cython_wrapper_scalar_function(): + x, y, z = symbols('x,y,z') + expr = (x + y)*z + routine = make_routine("test", expr) + code_gen = CythonCodeWrapper(CCodeGen()) + source = get_string(code_gen.dump_pyx, [routine]) + + expected = ( + "cdef extern from 'file.h':\n" + " double test(double x, double y, double z)\n" + "\n" + "def test_c(double x, double y, double z):\n" + "\n" + " return test(x, y, z)") + assert source == expected + + +def test_cython_wrapper_outarg(): + from sympy.core.relational import Equality + x, y, z = symbols('x,y,z') + code_gen = CythonCodeWrapper(C99CodeGen()) + + routine = make_routine("test", Equality(z, x + y)) + source = get_string(code_gen.dump_pyx, [routine]) + expected = ( + "cdef extern from 'file.h':\n" + " void test(double x, double y, double *z)\n" + "\n" + "def test_c(double x, double y):\n" + "\n" + " cdef double z = 0\n" + " test(x, y, &z)\n" + " return z") + assert source == expected + + +def test_cython_wrapper_inoutarg(): + from sympy.core.relational import Equality + x, y, z = symbols('x,y,z') + code_gen = CythonCodeWrapper(C99CodeGen()) + routine = make_routine("test", Equality(z, x + y + z)) + source = get_string(code_gen.dump_pyx, [routine]) + expected = ( + "cdef extern from 'file.h':\n" + " void test(double x, double y, double *z)\n" + "\n" + "def test_c(double x, double y, double z):\n" + "\n" + " test(x, y, &z)\n" + " return z") + assert source == expected + + +def test_cython_wrapper_compile_flags(): + from sympy.core.relational import Equality + x, y, z = symbols('x,y,z') + routine = make_routine("test", Equality(z, x + y)) + + code_gen = CythonCodeWrapper(CCodeGen()) + + expected = """\ +from setuptools import setup +from setuptools import Extension +from Cython.Build import cythonize +cy_opts = {'compiler_directives': {'language_level': '3'}} + +ext_mods = [Extension( + 'wrapper_module_%(num)s', ['wrapper_module_%(num)s.pyx', 'wrapped_code_%(num)s.c'], + include_dirs=[], + library_dirs=[], + libraries=[], + extra_compile_args=['-std=c99'], + extra_link_args=[] +)] +setup(ext_modules=cythonize(ext_mods, **cy_opts)) +""" % {'num': CodeWrapper._module_counter} + + temp_dir = tempfile.mkdtemp() + TmpFileManager.tmp_folder(temp_dir) + setup_file_path = os.path.join(temp_dir, 'setup.py') + + code_gen._prepare_files(routine, build_dir=temp_dir) + setup_text = Path(setup_file_path).read_text() + assert setup_text == expected + + code_gen = CythonCodeWrapper(CCodeGen(), + include_dirs=['/usr/local/include', '/opt/booger/include'], + library_dirs=['/user/local/lib'], + libraries=['thelib', 'nilib'], + extra_compile_args=['-slow-math'], + extra_link_args=['-lswamp', '-ltrident'], + cythonize_options={'compiler_directives': {'boundscheck': False}} + ) + expected = """\ +from setuptools import setup +from setuptools import Extension +from Cython.Build import cythonize +cy_opts = {'compiler_directives': {'boundscheck': False}} + +ext_mods = [Extension( + 'wrapper_module_%(num)s', ['wrapper_module_%(num)s.pyx', 'wrapped_code_%(num)s.c'], + include_dirs=['/usr/local/include', '/opt/booger/include'], + library_dirs=['/user/local/lib'], + libraries=['thelib', 'nilib'], + extra_compile_args=['-slow-math', '-std=c99'], + extra_link_args=['-lswamp', '-ltrident'] +)] +setup(ext_modules=cythonize(ext_mods, **cy_opts)) +""" % {'num': CodeWrapper._module_counter} + + code_gen._prepare_files(routine, build_dir=temp_dir) + setup_text = Path(setup_file_path).read_text() + assert setup_text == expected + + expected = """\ +from setuptools import setup +from setuptools import Extension +from Cython.Build import cythonize +cy_opts = {'compiler_directives': {'boundscheck': False}} +import numpy as np + +ext_mods = [Extension( + 'wrapper_module_%(num)s', ['wrapper_module_%(num)s.pyx', 'wrapped_code_%(num)s.c'], + include_dirs=['/usr/local/include', '/opt/booger/include', np.get_include()], + library_dirs=['/user/local/lib'], + libraries=['thelib', 'nilib'], + extra_compile_args=['-slow-math', '-std=c99'], + extra_link_args=['-lswamp', '-ltrident'] +)] +setup(ext_modules=cythonize(ext_mods, **cy_opts)) +""" % {'num': CodeWrapper._module_counter} + + code_gen._need_numpy = True + code_gen._prepare_files(routine, build_dir=temp_dir) + setup_text = Path(setup_file_path).read_text() + assert setup_text == expected + + TmpFileManager.cleanup() + +def test_cython_wrapper_unique_dummyvars(): + from sympy.core.relational import Equality + from sympy.core.symbol import Dummy + x, y, z = Dummy('x'), Dummy('y'), Dummy('z') + x_id, y_id, z_id = [str(d.dummy_index) for d in [x, y, z]] + expr = Equality(z, x + y) + routine = make_routine("test", expr) + code_gen = CythonCodeWrapper(CCodeGen()) + source = get_string(code_gen.dump_pyx, [routine]) + expected_template = ( + "cdef extern from 'file.h':\n" + " void test(double x_{x_id}, double y_{y_id}, double *z_{z_id})\n" + "\n" + "def test_c(double x_{x_id}, double y_{y_id}):\n" + "\n" + " cdef double z_{z_id} = 0\n" + " test(x_{x_id}, y_{y_id}, &z_{z_id})\n" + " return z_{z_id}") + expected = expected_template.format(x_id=x_id, y_id=y_id, z_id=z_id) + assert source == expected + +def test_autowrap_dummy(): + x, y, z = symbols('x y z') + + # Uses DummyWrapper to test that codegen works as expected + + f = autowrap(x + y, backend='dummy') + assert f() == str(x + y) + assert f.args == "x, y" + assert f.returns == "nameless" + f = autowrap(Eq(z, x + y), backend='dummy') + assert f() == str(x + y) + assert f.args == "x, y" + assert f.returns == "z" + f = autowrap(Eq(z, x + y + z), backend='dummy') + assert f() == str(x + y + z) + assert f.args == "x, y, z" + assert f.returns == "z" + + +def test_autowrap_args(): + x, y, z = symbols('x y z') + + raises(CodeGenArgumentListError, lambda: autowrap(Eq(z, x + y), + backend='dummy', args=[x])) + f = autowrap(Eq(z, x + y), backend='dummy', args=[y, x]) + assert f() == str(x + y) + assert f.args == "y, x" + assert f.returns == "z" + + raises(CodeGenArgumentListError, lambda: autowrap(Eq(z, x + y + z), + backend='dummy', args=[x, y])) + f = autowrap(Eq(z, x + y + z), backend='dummy', args=[y, x, z]) + assert f() == str(x + y + z) + assert f.args == "y, x, z" + assert f.returns == "z" + + f = autowrap(Eq(z, x + y + z), backend='dummy', args=(y, x, z)) + assert f() == str(x + y + z) + assert f.args == "y, x, z" + assert f.returns == "z" + +def test_autowrap_store_files(): + x, y = symbols('x y') + tmp = tempfile.mkdtemp() + TmpFileManager.tmp_folder(tmp) + + f = autowrap(x + y, backend='dummy', tempdir=tmp) + assert f() == str(x + y) + assert os.access(tmp, os.F_OK) + + TmpFileManager.cleanup() + +def test_autowrap_store_files_issue_gh12939(): + x, y = symbols('x y') + tmp = './tmp' + saved_cwd = os.getcwd() + temp_cwd = tempfile.mkdtemp() + try: + os.chdir(temp_cwd) + f = autowrap(x + y, backend='dummy', tempdir=tmp) + assert f() == str(x + y) + assert os.access(tmp, os.F_OK) + finally: + os.chdir(saved_cwd) + shutil.rmtree(temp_cwd) + + +def test_binary_function(): + x, y = symbols('x y') + f = binary_function('f', x + y, backend='dummy') + assert f._imp_() == str(x + y) + + +def test_ufuncify_source(): + x, y, z = symbols('x,y,z') + code_wrapper = UfuncifyCodeWrapper(C99CodeGen("ufuncify")) + routine = make_routine("test", x + y + z) + source = get_string(code_wrapper.dump_c, [routine]) + expected = """\ +#include "Python.h" +#include "math.h" +#include "numpy/ndarraytypes.h" +#include "numpy/ufuncobject.h" +#include "numpy/halffloat.h" +#include "file.h" + +static PyMethodDef wrapper_module_%(num)sMethods[] = { + {NULL, NULL, 0, NULL} +}; + +#ifdef NPY_1_19_API_VERSION +static void test_ufunc(char **args, const npy_intp *dimensions, const npy_intp* steps, void* data) +#else +static void test_ufunc(char **args, npy_intp *dimensions, npy_intp* steps, void* data) +#endif +{ + npy_intp i; + npy_intp n = dimensions[0]; + char *in0 = args[0]; + char *in1 = args[1]; + char *in2 = args[2]; + char *out0 = args[3]; + npy_intp in0_step = steps[0]; + npy_intp in1_step = steps[1]; + npy_intp in2_step = steps[2]; + npy_intp out0_step = steps[3]; + for (i = 0; i < n; i++) { + *((double *)out0) = test(*(double *)in0, *(double *)in1, *(double *)in2); + in0 += in0_step; + in1 += in1_step; + in2 += in2_step; + out0 += out0_step; + } +} +PyUFuncGenericFunction test_funcs[1] = {&test_ufunc}; +static char test_types[4] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; +static void *test_data[1] = {NULL}; + +#if PY_VERSION_HEX >= 0x03000000 +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "wrapper_module_%(num)s", + NULL, + -1, + wrapper_module_%(num)sMethods, + NULL, + NULL, + NULL, + NULL +}; + +PyMODINIT_FUNC PyInit_wrapper_module_%(num)s(void) +{ + PyObject *m, *d; + PyObject *ufunc0; + m = PyModule_Create(&moduledef); + if (!m) { + return NULL; + } + import_array(); + import_umath(); + d = PyModule_GetDict(m); + ufunc0 = PyUFunc_FromFuncAndData(test_funcs, test_data, test_types, 1, 3, 1, + PyUFunc_None, "wrapper_module_%(num)s", "Created in SymPy with Ufuncify", 0); + PyDict_SetItemString(d, "test", ufunc0); + Py_DECREF(ufunc0); + return m; +} +#else +PyMODINIT_FUNC initwrapper_module_%(num)s(void) +{ + PyObject *m, *d; + PyObject *ufunc0; + m = Py_InitModule("wrapper_module_%(num)s", wrapper_module_%(num)sMethods); + if (m == NULL) { + return; + } + import_array(); + import_umath(); + d = PyModule_GetDict(m); + ufunc0 = PyUFunc_FromFuncAndData(test_funcs, test_data, test_types, 1, 3, 1, + PyUFunc_None, "wrapper_module_%(num)s", "Created in SymPy with Ufuncify", 0); + PyDict_SetItemString(d, "test", ufunc0); + Py_DECREF(ufunc0); +} +#endif""" % {'num': CodeWrapper._module_counter} + assert source == expected + + +def test_ufuncify_source_multioutput(): + x, y, z = symbols('x,y,z') + var_symbols = (x, y, z) + expr = x + y**3 + 10*z**2 + code_wrapper = UfuncifyCodeWrapper(C99CodeGen("ufuncify")) + routines = [make_routine("func{}".format(i), expr.diff(var_symbols[i]), var_symbols) for i in range(len(var_symbols))] + source = get_string(code_wrapper.dump_c, routines, funcname='multitest') + expected = """\ +#include "Python.h" +#include "math.h" +#include "numpy/ndarraytypes.h" +#include "numpy/ufuncobject.h" +#include "numpy/halffloat.h" +#include "file.h" + +static PyMethodDef wrapper_module_%(num)sMethods[] = { + {NULL, NULL, 0, NULL} +}; + +#ifdef NPY_1_19_API_VERSION +static void multitest_ufunc(char **args, const npy_intp *dimensions, const npy_intp* steps, void* data) +#else +static void multitest_ufunc(char **args, npy_intp *dimensions, npy_intp* steps, void* data) +#endif +{ + npy_intp i; + npy_intp n = dimensions[0]; + char *in0 = args[0]; + char *in1 = args[1]; + char *in2 = args[2]; + char *out0 = args[3]; + char *out1 = args[4]; + char *out2 = args[5]; + npy_intp in0_step = steps[0]; + npy_intp in1_step = steps[1]; + npy_intp in2_step = steps[2]; + npy_intp out0_step = steps[3]; + npy_intp out1_step = steps[4]; + npy_intp out2_step = steps[5]; + for (i = 0; i < n; i++) { + *((double *)out0) = func0(*(double *)in0, *(double *)in1, *(double *)in2); + *((double *)out1) = func1(*(double *)in0, *(double *)in1, *(double *)in2); + *((double *)out2) = func2(*(double *)in0, *(double *)in1, *(double *)in2); + in0 += in0_step; + in1 += in1_step; + in2 += in2_step; + out0 += out0_step; + out1 += out1_step; + out2 += out2_step; + } +} +PyUFuncGenericFunction multitest_funcs[1] = {&multitest_ufunc}; +static char multitest_types[6] = {NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE}; +static void *multitest_data[1] = {NULL}; + +#if PY_VERSION_HEX >= 0x03000000 +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "wrapper_module_%(num)s", + NULL, + -1, + wrapper_module_%(num)sMethods, + NULL, + NULL, + NULL, + NULL +}; + +PyMODINIT_FUNC PyInit_wrapper_module_%(num)s(void) +{ + PyObject *m, *d; + PyObject *ufunc0; + m = PyModule_Create(&moduledef); + if (!m) { + return NULL; + } + import_array(); + import_umath(); + d = PyModule_GetDict(m); + ufunc0 = PyUFunc_FromFuncAndData(multitest_funcs, multitest_data, multitest_types, 1, 3, 3, + PyUFunc_None, "wrapper_module_%(num)s", "Created in SymPy with Ufuncify", 0); + PyDict_SetItemString(d, "multitest", ufunc0); + Py_DECREF(ufunc0); + return m; +} +#else +PyMODINIT_FUNC initwrapper_module_%(num)s(void) +{ + PyObject *m, *d; + PyObject *ufunc0; + m = Py_InitModule("wrapper_module_%(num)s", wrapper_module_%(num)sMethods); + if (m == NULL) { + return; + } + import_array(); + import_umath(); + d = PyModule_GetDict(m); + ufunc0 = PyUFunc_FromFuncAndData(multitest_funcs, multitest_data, multitest_types, 1, 3, 3, + PyUFunc_None, "wrapper_module_%(num)s", "Created in SymPy with Ufuncify", 0); + PyDict_SetItemString(d, "multitest", ufunc0); + Py_DECREF(ufunc0); +} +#endif""" % {'num': CodeWrapper._module_counter} + assert source == expected diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_codegen.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_codegen.py new file mode 100644 index 0000000000000000000000000000000000000000..4ccc6f9a90fb0a0bec39cea22420da8091ede740 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_codegen.py @@ -0,0 +1,1632 @@ +from io import StringIO + +from sympy.core import symbols, Eq, pi, Catalan, Lambda, Dummy +from sympy.core.relational import Equality +from sympy.core.symbol import Symbol +from sympy.functions.special.error_functions import erf +from sympy.integrals.integrals import Integral +from sympy.matrices import Matrix, MatrixSymbol +from sympy.utilities.codegen import ( + codegen, make_routine, CCodeGen, C89CodeGen, C99CodeGen, InputArgument, + CodeGenError, FCodeGen, CodeGenArgumentListError, OutputArgument, + InOutArgument) +from sympy.testing.pytest import raises +from sympy.utilities.lambdify import implemented_function + +#FIXME: Fails due to circular import in with core +# from sympy import codegen + + +def get_string(dump_fn, routines, prefix="file", header=False, empty=False): + """Wrapper for dump_fn. dump_fn writes its results to a stream object and + this wrapper returns the contents of that stream as a string. This + auxiliary function is used by many tests below. + + The header and the empty lines are not generated to facilitate the + testing of the output. + """ + output = StringIO() + dump_fn(routines, output, prefix, header, empty) + source = output.getvalue() + output.close() + return source + + +def test_Routine_argument_order(): + a, x, y, z = symbols('a x y z') + expr = (x + y)*z + raises(CodeGenArgumentListError, lambda: make_routine("test", expr, + argument_sequence=[z, x])) + raises(CodeGenArgumentListError, lambda: make_routine("test", Eq(a, + expr), argument_sequence=[z, x, y])) + r = make_routine('test', Eq(a, expr), argument_sequence=[z, x, a, y]) + assert [ arg.name for arg in r.arguments ] == [z, x, a, y] + assert [ type(arg) for arg in r.arguments ] == [ + InputArgument, InputArgument, OutputArgument, InputArgument ] + r = make_routine('test', Eq(z, expr), argument_sequence=[z, x, y]) + assert [ type(arg) for arg in r.arguments ] == [ + InOutArgument, InputArgument, InputArgument ] + + from sympy.tensor import IndexedBase, Idx + A, B = map(IndexedBase, ['A', 'B']) + m = symbols('m', integer=True) + i = Idx('i', m) + r = make_routine('test', Eq(A[i], B[i]), argument_sequence=[B, A, m]) + assert [ arg.name for arg in r.arguments ] == [B.label, A.label, m] + + expr = Integral(x*y*z, (x, 1, 2), (y, 1, 3)) + r = make_routine('test', Eq(a, expr), argument_sequence=[z, x, a, y]) + assert [ arg.name for arg in r.arguments ] == [z, x, a, y] + + +def test_empty_c_code(): + code_gen = C89CodeGen() + source = get_string(code_gen.dump_c, []) + assert source == "#include \"file.h\"\n#include \n" + + +def test_empty_c_code_with_comment(): + code_gen = C89CodeGen() + source = get_string(code_gen.dump_c, [], header=True) + assert source[:82] == ( + "/******************************************************************************\n *" + ) + # " Code generated with SymPy 0.7.2-git " + assert source[158:] == ( "*\n" + " * *\n" + " * See http://www.sympy.org/ for more information. *\n" + " * *\n" + " * This file is part of 'project' *\n" + " ******************************************************************************/\n" + "#include \"file.h\"\n" + "#include \n" + ) + + +def test_empty_c_header(): + code_gen = C99CodeGen() + source = get_string(code_gen.dump_h, []) + assert source == "#ifndef PROJECT__FILE__H\n#define PROJECT__FILE__H\n#endif\n" + + +def test_simple_c_code(): + x, y, z = symbols('x,y,z') + expr = (x + y)*z + routine = make_routine("test", expr) + code_gen = C89CodeGen() + source = get_string(code_gen.dump_c, [routine]) + expected = ( + "#include \"file.h\"\n" + "#include \n" + "double test(double x, double y, double z) {\n" + " double test_result;\n" + " test_result = z*(x + y);\n" + " return test_result;\n" + "}\n" + ) + assert source == expected + + +def test_c_code_reserved_words(): + x, y, z = symbols('if, typedef, while') + expr = (x + y) * z + routine = make_routine("test", expr) + code_gen = C99CodeGen() + source = get_string(code_gen.dump_c, [routine]) + expected = ( + "#include \"file.h\"\n" + "#include \n" + "double test(double if_, double typedef_, double while_) {\n" + " double test_result;\n" + " test_result = while_*(if_ + typedef_);\n" + " return test_result;\n" + "}\n" + ) + assert source == expected + + +def test_numbersymbol_c_code(): + routine = make_routine("test", pi**Catalan) + code_gen = C89CodeGen() + source = get_string(code_gen.dump_c, [routine]) + expected = ( + "#include \"file.h\"\n" + "#include \n" + "double test() {\n" + " double test_result;\n" + " double const Catalan = %s;\n" + " test_result = pow(M_PI, Catalan);\n" + " return test_result;\n" + "}\n" + ) % Catalan.evalf(17) + assert source == expected + + +def test_c_code_argument_order(): + x, y, z = symbols('x,y,z') + expr = x + y + routine = make_routine("test", expr, argument_sequence=[z, x, y]) + code_gen = C89CodeGen() + source = get_string(code_gen.dump_c, [routine]) + expected = ( + "#include \"file.h\"\n" + "#include \n" + "double test(double z, double x, double y) {\n" + " double test_result;\n" + " test_result = x + y;\n" + " return test_result;\n" + "}\n" + ) + assert source == expected + + +def test_simple_c_header(): + x, y, z = symbols('x,y,z') + expr = (x + y)*z + routine = make_routine("test", expr) + code_gen = C89CodeGen() + source = get_string(code_gen.dump_h, [routine]) + expected = ( + "#ifndef PROJECT__FILE__H\n" + "#define PROJECT__FILE__H\n" + "double test(double x, double y, double z);\n" + "#endif\n" + ) + assert source == expected + + +def test_simple_c_codegen(): + x, y, z = symbols('x,y,z') + expr = (x + y)*z + expected = [ + ("file.c", + "#include \"file.h\"\n" + "#include \n" + "double test(double x, double y, double z) {\n" + " double test_result;\n" + " test_result = z*(x + y);\n" + " return test_result;\n" + "}\n"), + ("file.h", + "#ifndef PROJECT__FILE__H\n" + "#define PROJECT__FILE__H\n" + "double test(double x, double y, double z);\n" + "#endif\n") + ] + result = codegen(("test", expr), "C", "file", header=False, empty=False) + assert result == expected + + +def test_multiple_results_c(): + x, y, z = symbols('x,y,z') + expr1 = (x + y)*z + expr2 = (x - y)*z + routine = make_routine( + "test", + [expr1, expr2] + ) + code_gen = C99CodeGen() + raises(CodeGenError, lambda: get_string(code_gen.dump_h, [routine])) + + +def test_no_results_c(): + raises(ValueError, lambda: make_routine("test", [])) + + +def test_ansi_math1_codegen(): + # not included: log10 + from sympy.functions.elementary.complexes import Abs + from sympy.functions.elementary.exponential import log + from sympy.functions.elementary.hyperbolic import (cosh, sinh, tanh) + from sympy.functions.elementary.integers import (ceiling, floor) + from sympy.functions.elementary.miscellaneous import sqrt + from sympy.functions.elementary.trigonometric import (acos, asin, atan, cos, sin, tan) + x = symbols('x') + name_expr = [ + ("test_fabs", Abs(x)), + ("test_acos", acos(x)), + ("test_asin", asin(x)), + ("test_atan", atan(x)), + ("test_ceil", ceiling(x)), + ("test_cos", cos(x)), + ("test_cosh", cosh(x)), + ("test_floor", floor(x)), + ("test_log", log(x)), + ("test_ln", log(x)), + ("test_sin", sin(x)), + ("test_sinh", sinh(x)), + ("test_sqrt", sqrt(x)), + ("test_tan", tan(x)), + ("test_tanh", tanh(x)), + ] + result = codegen(name_expr, "C89", "file", header=False, empty=False) + assert result[0][0] == "file.c" + assert result[0][1] == ( + '#include "file.h"\n#include \n' + 'double test_fabs(double x) {\n double test_fabs_result;\n test_fabs_result = fabs(x);\n return test_fabs_result;\n}\n' + 'double test_acos(double x) {\n double test_acos_result;\n test_acos_result = acos(x);\n return test_acos_result;\n}\n' + 'double test_asin(double x) {\n double test_asin_result;\n test_asin_result = asin(x);\n return test_asin_result;\n}\n' + 'double test_atan(double x) {\n double test_atan_result;\n test_atan_result = atan(x);\n return test_atan_result;\n}\n' + 'double test_ceil(double x) {\n double test_ceil_result;\n test_ceil_result = ceil(x);\n return test_ceil_result;\n}\n' + 'double test_cos(double x) {\n double test_cos_result;\n test_cos_result = cos(x);\n return test_cos_result;\n}\n' + 'double test_cosh(double x) {\n double test_cosh_result;\n test_cosh_result = cosh(x);\n return test_cosh_result;\n}\n' + 'double test_floor(double x) {\n double test_floor_result;\n test_floor_result = floor(x);\n return test_floor_result;\n}\n' + 'double test_log(double x) {\n double test_log_result;\n test_log_result = log(x);\n return test_log_result;\n}\n' + 'double test_ln(double x) {\n double test_ln_result;\n test_ln_result = log(x);\n return test_ln_result;\n}\n' + 'double test_sin(double x) {\n double test_sin_result;\n test_sin_result = sin(x);\n return test_sin_result;\n}\n' + 'double test_sinh(double x) {\n double test_sinh_result;\n test_sinh_result = sinh(x);\n return test_sinh_result;\n}\n' + 'double test_sqrt(double x) {\n double test_sqrt_result;\n test_sqrt_result = sqrt(x);\n return test_sqrt_result;\n}\n' + 'double test_tan(double x) {\n double test_tan_result;\n test_tan_result = tan(x);\n return test_tan_result;\n}\n' + 'double test_tanh(double x) {\n double test_tanh_result;\n test_tanh_result = tanh(x);\n return test_tanh_result;\n}\n' + ) + assert result[1][0] == "file.h" + assert result[1][1] == ( + '#ifndef PROJECT__FILE__H\n#define PROJECT__FILE__H\n' + 'double test_fabs(double x);\ndouble test_acos(double x);\n' + 'double test_asin(double x);\ndouble test_atan(double x);\n' + 'double test_ceil(double x);\ndouble test_cos(double x);\n' + 'double test_cosh(double x);\ndouble test_floor(double x);\n' + 'double test_log(double x);\ndouble test_ln(double x);\n' + 'double test_sin(double x);\ndouble test_sinh(double x);\n' + 'double test_sqrt(double x);\ndouble test_tan(double x);\n' + 'double test_tanh(double x);\n#endif\n' + ) + + +def test_ansi_math2_codegen(): + # not included: frexp, ldexp, modf, fmod + from sympy.functions.elementary.trigonometric import atan2 + x, y = symbols('x,y') + name_expr = [ + ("test_atan2", atan2(x, y)), + ("test_pow", x**y), + ] + result = codegen(name_expr, "C89", "file", header=False, empty=False) + assert result[0][0] == "file.c" + assert result[0][1] == ( + '#include "file.h"\n#include \n' + 'double test_atan2(double x, double y) {\n double test_atan2_result;\n test_atan2_result = atan2(x, y);\n return test_atan2_result;\n}\n' + 'double test_pow(double x, double y) {\n double test_pow_result;\n test_pow_result = pow(x, y);\n return test_pow_result;\n}\n' + ) + assert result[1][0] == "file.h" + assert result[1][1] == ( + '#ifndef PROJECT__FILE__H\n#define PROJECT__FILE__H\n' + 'double test_atan2(double x, double y);\n' + 'double test_pow(double x, double y);\n' + '#endif\n' + ) + + +def test_complicated_codegen(): + from sympy.functions.elementary.trigonometric import (cos, sin, tan) + x, y, z = symbols('x,y,z') + name_expr = [ + ("test1", ((sin(x) + cos(y) + tan(z))**7).expand()), + ("test2", cos(cos(cos(cos(cos(cos(cos(cos(x + y + z))))))))), + ] + result = codegen(name_expr, "C89", "file", header=False, empty=False) + assert result[0][0] == "file.c" + assert result[0][1] == ( + '#include "file.h"\n#include \n' + 'double test1(double x, double y, double z) {\n' + ' double test1_result;\n' + ' test1_result = ' + 'pow(sin(x), 7) + ' + '7*pow(sin(x), 6)*cos(y) + ' + '7*pow(sin(x), 6)*tan(z) + ' + '21*pow(sin(x), 5)*pow(cos(y), 2) + ' + '42*pow(sin(x), 5)*cos(y)*tan(z) + ' + '21*pow(sin(x), 5)*pow(tan(z), 2) + ' + '35*pow(sin(x), 4)*pow(cos(y), 3) + ' + '105*pow(sin(x), 4)*pow(cos(y), 2)*tan(z) + ' + '105*pow(sin(x), 4)*cos(y)*pow(tan(z), 2) + ' + '35*pow(sin(x), 4)*pow(tan(z), 3) + ' + '35*pow(sin(x), 3)*pow(cos(y), 4) + ' + '140*pow(sin(x), 3)*pow(cos(y), 3)*tan(z) + ' + '210*pow(sin(x), 3)*pow(cos(y), 2)*pow(tan(z), 2) + ' + '140*pow(sin(x), 3)*cos(y)*pow(tan(z), 3) + ' + '35*pow(sin(x), 3)*pow(tan(z), 4) + ' + '21*pow(sin(x), 2)*pow(cos(y), 5) + ' + '105*pow(sin(x), 2)*pow(cos(y), 4)*tan(z) + ' + '210*pow(sin(x), 2)*pow(cos(y), 3)*pow(tan(z), 2) + ' + '210*pow(sin(x), 2)*pow(cos(y), 2)*pow(tan(z), 3) + ' + '105*pow(sin(x), 2)*cos(y)*pow(tan(z), 4) + ' + '21*pow(sin(x), 2)*pow(tan(z), 5) + ' + '7*sin(x)*pow(cos(y), 6) + ' + '42*sin(x)*pow(cos(y), 5)*tan(z) + ' + '105*sin(x)*pow(cos(y), 4)*pow(tan(z), 2) + ' + '140*sin(x)*pow(cos(y), 3)*pow(tan(z), 3) + ' + '105*sin(x)*pow(cos(y), 2)*pow(tan(z), 4) + ' + '42*sin(x)*cos(y)*pow(tan(z), 5) + ' + '7*sin(x)*pow(tan(z), 6) + ' + 'pow(cos(y), 7) + ' + '7*pow(cos(y), 6)*tan(z) + ' + '21*pow(cos(y), 5)*pow(tan(z), 2) + ' + '35*pow(cos(y), 4)*pow(tan(z), 3) + ' + '35*pow(cos(y), 3)*pow(tan(z), 4) + ' + '21*pow(cos(y), 2)*pow(tan(z), 5) + ' + '7*cos(y)*pow(tan(z), 6) + ' + 'pow(tan(z), 7);\n' + ' return test1_result;\n' + '}\n' + 'double test2(double x, double y, double z) {\n' + ' double test2_result;\n' + ' test2_result = cos(cos(cos(cos(cos(cos(cos(cos(x + y + z))))))));\n' + ' return test2_result;\n' + '}\n' + ) + assert result[1][0] == "file.h" + assert result[1][1] == ( + '#ifndef PROJECT__FILE__H\n' + '#define PROJECT__FILE__H\n' + 'double test1(double x, double y, double z);\n' + 'double test2(double x, double y, double z);\n' + '#endif\n' + ) + + +def test_loops_c(): + from sympy.tensor import IndexedBase, Idx + from sympy.core.symbol import symbols + n, m = symbols('n m', integer=True) + A = IndexedBase('A') + x = IndexedBase('x') + y = IndexedBase('y') + i = Idx('i', m) + j = Idx('j', n) + + (f1, code), (f2, interface) = codegen( + ('matrix_vector', Eq(y[i], A[i, j]*x[j])), "C99", "file", header=False, empty=False) + + assert f1 == 'file.c' + expected = ( + '#include "file.h"\n' + '#include \n' + 'void matrix_vector(double *A, int m, int n, double *x, double *y) {\n' + ' for (int i=0; i\n' + 'void test_dummies(int m_%(mno)i, double *x, double *y) {\n' + ' for (int i_%(ino)i=0; i_%(ino)i\n' + 'void matrix_vector(double *A, int m, int n, int o, int p, double *x, double *y) {\n' + ' for (int i=o; i<%(upperi)s; i++){\n' + ' y[i] = 0;\n' + ' }\n' + ' for (int i=o; i<%(upperi)s; i++){\n' + ' for (int j=0; j\n' + 'double foo(double x, double *y) {\n' + ' (*y) = sin(x);\n' + ' double foo_result;\n' + ' foo_result = cos(x);\n' + ' return foo_result;\n' + '}\n' + ) + assert result[0][1] == expected + + +def test_output_arg_c_reserved_words(): + from sympy.core.relational import Equality + from sympy.functions.elementary.trigonometric import (cos, sin) + x, y, z = symbols("if, while, z") + r = make_routine("foo", [Equality(y, sin(x)), cos(x)]) + c = C89CodeGen() + result = c.write([r], "test", header=False, empty=False) + assert result[0][0] == "test.c" + expected = ( + '#include "test.h"\n' + '#include \n' + 'double foo(double if_, double *while_) {\n' + ' (*while_) = sin(if_);\n' + ' double foo_result;\n' + ' foo_result = cos(if_);\n' + ' return foo_result;\n' + '}\n' + ) + assert result[0][1] == expected + + +def test_multidim_c_argument_cse(): + A_sym = MatrixSymbol('A', 3, 3) + b_sym = MatrixSymbol('b', 3, 1) + A = Matrix(A_sym) + b = Matrix(b_sym) + c = A*b + cgen = CCodeGen(project="test", cse=True) + r = cgen.routine("c", c) + r.arguments[-1].result_var = "out" + r.arguments[-1]._name = "out" + code = get_string(cgen.dump_c, [r], prefix="test") + expected = ( + '#include "test.h"\n' + "#include \n" + "void c(double *A, double *b, double *out) {\n" + " out[0] = A[0]*b[0] + A[1]*b[1] + A[2]*b[2];\n" + " out[1] = A[3]*b[0] + A[4]*b[1] + A[5]*b[2];\n" + " out[2] = A[6]*b[0] + A[7]*b[1] + A[8]*b[2];\n" + "}\n" + ) + assert code == expected + + +def test_ccode_results_named_ordered(): + x, y, z = symbols('x,y,z') + B, C = symbols('B,C') + A = MatrixSymbol('A', 1, 3) + expr1 = Equality(A, Matrix([[1, 2, x]])) + expr2 = Equality(C, (x + y)*z) + expr3 = Equality(B, 2*x) + name_expr = ("test", [expr1, expr2, expr3]) + expected = ( + '#include "test.h"\n' + '#include \n' + 'void test(double x, double *C, double z, double y, double *A, double *B) {\n' + ' (*C) = z*(x + y);\n' + ' A[0] = 1;\n' + ' A[1] = 2;\n' + ' A[2] = x;\n' + ' (*B) = 2*x;\n' + '}\n' + ) + + result = codegen(name_expr, "c", "test", header=False, empty=False, + argument_sequence=(x, C, z, y, A, B)) + source = result[0][1] + assert source == expected + + +def test_ccode_matrixsymbol_slice(): + A = MatrixSymbol('A', 5, 3) + B = MatrixSymbol('B', 1, 3) + C = MatrixSymbol('C', 1, 3) + D = MatrixSymbol('D', 5, 1) + name_expr = ("test", [Equality(B, A[0, :]), + Equality(C, A[1, :]), + Equality(D, A[:, 2])]) + result = codegen(name_expr, "c99", "test", header=False, empty=False) + source = result[0][1] + expected = ( + '#include "test.h"\n' + '#include \n' + 'void test(double *A, double *B, double *C, double *D) {\n' + ' B[0] = A[0];\n' + ' B[1] = A[1];\n' + ' B[2] = A[2];\n' + ' C[0] = A[3];\n' + ' C[1] = A[4];\n' + ' C[2] = A[5];\n' + ' D[0] = A[2];\n' + ' D[1] = A[5];\n' + ' D[2] = A[8];\n' + ' D[3] = A[11];\n' + ' D[4] = A[14];\n' + '}\n' + ) + assert source == expected + +def test_ccode_cse(): + a, b, c, d = symbols('a b c d') + e = MatrixSymbol('e', 3, 1) + name_expr = ("test", [Equality(e, Matrix([[a*b], [a*b + c*d], [a*b*c*d]]))]) + generator = CCodeGen(cse=True) + result = codegen(name_expr, code_gen=generator, header=False, empty=False) + source = result[0][1] + expected = ( + '#include "test.h"\n' + '#include \n' + 'void test(double a, double b, double c, double d, double *e) {\n' + ' const double x0 = a*b;\n' + ' const double x1 = c*d;\n' + ' e[0] = x0;\n' + ' e[1] = x0 + x1;\n' + ' e[2] = x0*x1;\n' + '}\n' + ) + assert source == expected + +def test_ccode_unused_array_arg(): + x = MatrixSymbol('x', 2, 1) + # x does not appear in output + name_expr = ("test", 1.0) + generator = CCodeGen() + result = codegen(name_expr, code_gen=generator, header=False, empty=False, argument_sequence=(x,)) + source = result[0][1] + # note: x should appear as (double *) + expected = ( + '#include "test.h"\n' + '#include \n' + 'double test(double *x) {\n' + ' double test_result;\n' + ' test_result = 1.0;\n' + ' return test_result;\n' + '}\n' + ) + assert source == expected + +def test_ccode_unused_array_arg_func(): + # issue 16689 + X = MatrixSymbol('X',3,1) + Y = MatrixSymbol('Y',3,1) + z = symbols('z',integer = True) + name_expr = ('testBug', X[0] + X[1]) + result = codegen(name_expr, language='C', header=False, empty=False, argument_sequence=(X, Y, z)) + source = result[0][1] + expected = ( + '#include "testBug.h"\n' + '#include \n' + 'double testBug(double *X, double *Y, int z) {\n' + ' double testBug_result;\n' + ' testBug_result = X[0] + X[1];\n' + ' return testBug_result;\n' + '}\n' + ) + assert source == expected + +def test_empty_f_code(): + code_gen = FCodeGen() + source = get_string(code_gen.dump_f95, []) + assert source == "" + + +def test_empty_f_code_with_header(): + code_gen = FCodeGen() + source = get_string(code_gen.dump_f95, [], header=True) + assert source[:82] == ( + "!******************************************************************************\n!*" + ) + # " Code generated with SymPy 0.7.2-git " + assert source[158:] == ( "*\n" + "!* *\n" + "!* See http://www.sympy.org/ for more information. *\n" + "!* *\n" + "!* This file is part of 'project' *\n" + "!******************************************************************************\n" + ) + + +def test_empty_f_header(): + code_gen = FCodeGen() + source = get_string(code_gen.dump_h, []) + assert source == "" + + +def test_simple_f_code(): + x, y, z = symbols('x,y,z') + expr = (x + y)*z + routine = make_routine("test", expr) + code_gen = FCodeGen() + source = get_string(code_gen.dump_f95, [routine]) + expected = ( + "REAL*8 function test(x, y, z)\n" + "implicit none\n" + "REAL*8, intent(in) :: x\n" + "REAL*8, intent(in) :: y\n" + "REAL*8, intent(in) :: z\n" + "test = z*(x + y)\n" + "end function\n" + ) + assert source == expected + + +def test_numbersymbol_f_code(): + routine = make_routine("test", pi**Catalan) + code_gen = FCodeGen() + source = get_string(code_gen.dump_f95, [routine]) + expected = ( + "REAL*8 function test()\n" + "implicit none\n" + "REAL*8, parameter :: Catalan = %sd0\n" + "REAL*8, parameter :: pi = %sd0\n" + "test = pi**Catalan\n" + "end function\n" + ) % (Catalan.evalf(17), pi.evalf(17)) + assert source == expected + +def test_erf_f_code(): + x = symbols('x') + routine = make_routine("test", erf(x) - erf(-2 * x)) + code_gen = FCodeGen() + source = get_string(code_gen.dump_f95, [routine]) + expected = ( + "REAL*8 function test(x)\n" + "implicit none\n" + "REAL*8, intent(in) :: x\n" + "test = erf(x) + erf(2.0d0*x)\n" + "end function\n" + ) + assert source == expected, source + +def test_f_code_argument_order(): + x, y, z = symbols('x,y,z') + expr = x + y + routine = make_routine("test", expr, argument_sequence=[z, x, y]) + code_gen = FCodeGen() + source = get_string(code_gen.dump_f95, [routine]) + expected = ( + "REAL*8 function test(z, x, y)\n" + "implicit none\n" + "REAL*8, intent(in) :: z\n" + "REAL*8, intent(in) :: x\n" + "REAL*8, intent(in) :: y\n" + "test = x + y\n" + "end function\n" + ) + assert source == expected + + +def test_simple_f_header(): + x, y, z = symbols('x,y,z') + expr = (x + y)*z + routine = make_routine("test", expr) + code_gen = FCodeGen() + source = get_string(code_gen.dump_h, [routine]) + expected = ( + "interface\n" + "REAL*8 function test(x, y, z)\n" + "implicit none\n" + "REAL*8, intent(in) :: x\n" + "REAL*8, intent(in) :: y\n" + "REAL*8, intent(in) :: z\n" + "end function\n" + "end interface\n" + ) + assert source == expected + + +def test_simple_f_codegen(): + x, y, z = symbols('x,y,z') + expr = (x + y)*z + result = codegen( + ("test", expr), "F95", "file", header=False, empty=False) + expected = [ + ("file.f90", + "REAL*8 function test(x, y, z)\n" + "implicit none\n" + "REAL*8, intent(in) :: x\n" + "REAL*8, intent(in) :: y\n" + "REAL*8, intent(in) :: z\n" + "test = z*(x + y)\n" + "end function\n"), + ("file.h", + "interface\n" + "REAL*8 function test(x, y, z)\n" + "implicit none\n" + "REAL*8, intent(in) :: x\n" + "REAL*8, intent(in) :: y\n" + "REAL*8, intent(in) :: z\n" + "end function\n" + "end interface\n") + ] + assert result == expected + + +def test_multiple_results_f(): + x, y, z = symbols('x,y,z') + expr1 = (x + y)*z + expr2 = (x - y)*z + routine = make_routine( + "test", + [expr1, expr2] + ) + code_gen = FCodeGen() + raises(CodeGenError, lambda: get_string(code_gen.dump_h, [routine])) + + +def test_no_results_f(): + raises(ValueError, lambda: make_routine("test", [])) + + +def test_intrinsic_math_codegen(): + # not included: log10 + from sympy.functions.elementary.complexes import Abs + from sympy.functions.elementary.exponential import log + from sympy.functions.elementary.hyperbolic import (cosh, sinh, tanh) + from sympy.functions.elementary.miscellaneous import sqrt + from sympy.functions.elementary.trigonometric import (acos, asin, atan, cos, sin, tan) + x = symbols('x') + name_expr = [ + ("test_abs", Abs(x)), + ("test_acos", acos(x)), + ("test_asin", asin(x)), + ("test_atan", atan(x)), + ("test_cos", cos(x)), + ("test_cosh", cosh(x)), + ("test_log", log(x)), + ("test_ln", log(x)), + ("test_sin", sin(x)), + ("test_sinh", sinh(x)), + ("test_sqrt", sqrt(x)), + ("test_tan", tan(x)), + ("test_tanh", tanh(x)), + ] + result = codegen(name_expr, "F95", "file", header=False, empty=False) + assert result[0][0] == "file.f90" + expected = ( + 'REAL*8 function test_abs(x)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'test_abs = abs(x)\n' + 'end function\n' + 'REAL*8 function test_acos(x)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'test_acos = acos(x)\n' + 'end function\n' + 'REAL*8 function test_asin(x)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'test_asin = asin(x)\n' + 'end function\n' + 'REAL*8 function test_atan(x)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'test_atan = atan(x)\n' + 'end function\n' + 'REAL*8 function test_cos(x)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'test_cos = cos(x)\n' + 'end function\n' + 'REAL*8 function test_cosh(x)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'test_cosh = cosh(x)\n' + 'end function\n' + 'REAL*8 function test_log(x)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'test_log = log(x)\n' + 'end function\n' + 'REAL*8 function test_ln(x)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'test_ln = log(x)\n' + 'end function\n' + 'REAL*8 function test_sin(x)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'test_sin = sin(x)\n' + 'end function\n' + 'REAL*8 function test_sinh(x)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'test_sinh = sinh(x)\n' + 'end function\n' + 'REAL*8 function test_sqrt(x)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'test_sqrt = sqrt(x)\n' + 'end function\n' + 'REAL*8 function test_tan(x)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'test_tan = tan(x)\n' + 'end function\n' + 'REAL*8 function test_tanh(x)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'test_tanh = tanh(x)\n' + 'end function\n' + ) + assert result[0][1] == expected + + assert result[1][0] == "file.h" + expected = ( + 'interface\n' + 'REAL*8 function test_abs(x)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'end function\n' + 'end interface\n' + 'interface\n' + 'REAL*8 function test_acos(x)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'end function\n' + 'end interface\n' + 'interface\n' + 'REAL*8 function test_asin(x)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'end function\n' + 'end interface\n' + 'interface\n' + 'REAL*8 function test_atan(x)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'end function\n' + 'end interface\n' + 'interface\n' + 'REAL*8 function test_cos(x)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'end function\n' + 'end interface\n' + 'interface\n' + 'REAL*8 function test_cosh(x)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'end function\n' + 'end interface\n' + 'interface\n' + 'REAL*8 function test_log(x)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'end function\n' + 'end interface\n' + 'interface\n' + 'REAL*8 function test_ln(x)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'end function\n' + 'end interface\n' + 'interface\n' + 'REAL*8 function test_sin(x)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'end function\n' + 'end interface\n' + 'interface\n' + 'REAL*8 function test_sinh(x)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'end function\n' + 'end interface\n' + 'interface\n' + 'REAL*8 function test_sqrt(x)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'end function\n' + 'end interface\n' + 'interface\n' + 'REAL*8 function test_tan(x)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'end function\n' + 'end interface\n' + 'interface\n' + 'REAL*8 function test_tanh(x)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'end function\n' + 'end interface\n' + ) + assert result[1][1] == expected + + +def test_intrinsic_math2_codegen(): + # not included: frexp, ldexp, modf, fmod + from sympy.functions.elementary.trigonometric import atan2 + x, y = symbols('x,y') + name_expr = [ + ("test_atan2", atan2(x, y)), + ("test_pow", x**y), + ] + result = codegen(name_expr, "F95", "file", header=False, empty=False) + assert result[0][0] == "file.f90" + expected = ( + 'REAL*8 function test_atan2(x, y)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'REAL*8, intent(in) :: y\n' + 'test_atan2 = atan2(x, y)\n' + 'end function\n' + 'REAL*8 function test_pow(x, y)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'REAL*8, intent(in) :: y\n' + 'test_pow = x**y\n' + 'end function\n' + ) + assert result[0][1] == expected + + assert result[1][0] == "file.h" + expected = ( + 'interface\n' + 'REAL*8 function test_atan2(x, y)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'REAL*8, intent(in) :: y\n' + 'end function\n' + 'end interface\n' + 'interface\n' + 'REAL*8 function test_pow(x, y)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'REAL*8, intent(in) :: y\n' + 'end function\n' + 'end interface\n' + ) + assert result[1][1] == expected + + +def test_complicated_codegen_f95(): + from sympy.functions.elementary.trigonometric import (cos, sin, tan) + x, y, z = symbols('x,y,z') + name_expr = [ + ("test1", ((sin(x) + cos(y) + tan(z))**7).expand()), + ("test2", cos(cos(cos(cos(cos(cos(cos(cos(x + y + z))))))))), + ] + result = codegen(name_expr, "F95", "file", header=False, empty=False) + assert result[0][0] == "file.f90" + expected = ( + 'REAL*8 function test1(x, y, z)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'REAL*8, intent(in) :: y\n' + 'REAL*8, intent(in) :: z\n' + 'test1 = sin(x)**7 + 7*sin(x)**6*cos(y) + 7*sin(x)**6*tan(z) + 21*sin(x) &\n' + ' **5*cos(y)**2 + 42*sin(x)**5*cos(y)*tan(z) + 21*sin(x)**5*tan(z) &\n' + ' **2 + 35*sin(x)**4*cos(y)**3 + 105*sin(x)**4*cos(y)**2*tan(z) + &\n' + ' 105*sin(x)**4*cos(y)*tan(z)**2 + 35*sin(x)**4*tan(z)**3 + 35*sin( &\n' + ' x)**3*cos(y)**4 + 140*sin(x)**3*cos(y)**3*tan(z) + 210*sin(x)**3* &\n' + ' cos(y)**2*tan(z)**2 + 140*sin(x)**3*cos(y)*tan(z)**3 + 35*sin(x) &\n' + ' **3*tan(z)**4 + 21*sin(x)**2*cos(y)**5 + 105*sin(x)**2*cos(y)**4* &\n' + ' tan(z) + 210*sin(x)**2*cos(y)**3*tan(z)**2 + 210*sin(x)**2*cos(y) &\n' + ' **2*tan(z)**3 + 105*sin(x)**2*cos(y)*tan(z)**4 + 21*sin(x)**2*tan &\n' + ' (z)**5 + 7*sin(x)*cos(y)**6 + 42*sin(x)*cos(y)**5*tan(z) + 105* &\n' + ' sin(x)*cos(y)**4*tan(z)**2 + 140*sin(x)*cos(y)**3*tan(z)**3 + 105 &\n' + ' *sin(x)*cos(y)**2*tan(z)**4 + 42*sin(x)*cos(y)*tan(z)**5 + 7*sin( &\n' + ' x)*tan(z)**6 + cos(y)**7 + 7*cos(y)**6*tan(z) + 21*cos(y)**5*tan( &\n' + ' z)**2 + 35*cos(y)**4*tan(z)**3 + 35*cos(y)**3*tan(z)**4 + 21*cos( &\n' + ' y)**2*tan(z)**5 + 7*cos(y)*tan(z)**6 + tan(z)**7\n' + 'end function\n' + 'REAL*8 function test2(x, y, z)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'REAL*8, intent(in) :: y\n' + 'REAL*8, intent(in) :: z\n' + 'test2 = cos(cos(cos(cos(cos(cos(cos(cos(x + y + z))))))))\n' + 'end function\n' + ) + assert result[0][1] == expected + assert result[1][0] == "file.h" + expected = ( + 'interface\n' + 'REAL*8 function test1(x, y, z)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'REAL*8, intent(in) :: y\n' + 'REAL*8, intent(in) :: z\n' + 'end function\n' + 'end interface\n' + 'interface\n' + 'REAL*8 function test2(x, y, z)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'REAL*8, intent(in) :: y\n' + 'REAL*8, intent(in) :: z\n' + 'end function\n' + 'end interface\n' + ) + assert result[1][1] == expected + + +def test_loops(): + from sympy.tensor import IndexedBase, Idx + from sympy.core.symbol import symbols + + n, m = symbols('n,m', integer=True) + A, x, y = map(IndexedBase, 'Axy') + i = Idx('i', m) + j = Idx('j', n) + + (f1, code), (f2, interface) = codegen( + ('matrix_vector', Eq(y[i], A[i, j]*x[j])), "F95", "file", header=False, empty=False) + + assert f1 == 'file.f90' + expected = ( + 'subroutine matrix_vector(A, m, n, x, y)\n' + 'implicit none\n' + 'INTEGER*4, intent(in) :: m\n' + 'INTEGER*4, intent(in) :: n\n' + 'REAL*8, intent(in), dimension(1:m, 1:n) :: A\n' + 'REAL*8, intent(in), dimension(1:n) :: x\n' + 'REAL*8, intent(out), dimension(1:m) :: y\n' + 'INTEGER*4 :: i\n' + 'INTEGER*4 :: j\n' + 'do i = 1, m\n' + ' y(i) = 0\n' + 'end do\n' + 'do i = 1, m\n' + ' do j = 1, n\n' + ' y(i) = %(rhs)s + y(i)\n' + ' end do\n' + 'end do\n' + 'end subroutine\n' + ) + + assert code == expected % {'rhs': 'A(i, j)*x(j)'} or\ + code == expected % {'rhs': 'x(j)*A(i, j)'} + assert f2 == 'file.h' + assert interface == ( + 'interface\n' + 'subroutine matrix_vector(A, m, n, x, y)\n' + 'implicit none\n' + 'INTEGER*4, intent(in) :: m\n' + 'INTEGER*4, intent(in) :: n\n' + 'REAL*8, intent(in), dimension(1:m, 1:n) :: A\n' + 'REAL*8, intent(in), dimension(1:n) :: x\n' + 'REAL*8, intent(out), dimension(1:m) :: y\n' + 'end subroutine\n' + 'end interface\n' + ) + + +def test_dummy_loops_f95(): + from sympy.tensor import IndexedBase, Idx + i, m = symbols('i m', integer=True, cls=Dummy) + x = IndexedBase('x') + y = IndexedBase('y') + i = Idx(i, m) + expected = ( + 'subroutine test_dummies(m_%(mcount)i, x, y)\n' + 'implicit none\n' + 'INTEGER*4, intent(in) :: m_%(mcount)i\n' + 'REAL*8, intent(in), dimension(1:m_%(mcount)i) :: x\n' + 'REAL*8, intent(out), dimension(1:m_%(mcount)i) :: y\n' + 'INTEGER*4 :: i_%(icount)i\n' + 'do i_%(icount)i = 1, m_%(mcount)i\n' + ' y(i_%(icount)i) = x(i_%(icount)i)\n' + 'end do\n' + 'end subroutine\n' + ) % {'icount': i.label.dummy_index, 'mcount': m.dummy_index} + r = make_routine('test_dummies', Eq(y[i], x[i])) + c = FCodeGen() + code = get_string(c.dump_f95, [r]) + assert code == expected + + +def test_loops_InOut(): + from sympy.tensor import IndexedBase, Idx + from sympy.core.symbol import symbols + + i, j, n, m = symbols('i,j,n,m', integer=True) + A, x, y = symbols('A,x,y') + A = IndexedBase(A)[Idx(i, m), Idx(j, n)] + x = IndexedBase(x)[Idx(j, n)] + y = IndexedBase(y)[Idx(i, m)] + + (f1, code), (f2, interface) = codegen( + ('matrix_vector', Eq(y, y + A*x)), "F95", "file", header=False, empty=False) + + assert f1 == 'file.f90' + expected = ( + 'subroutine matrix_vector(A, m, n, x, y)\n' + 'implicit none\n' + 'INTEGER*4, intent(in) :: m\n' + 'INTEGER*4, intent(in) :: n\n' + 'REAL*8, intent(in), dimension(1:m, 1:n) :: A\n' + 'REAL*8, intent(in), dimension(1:n) :: x\n' + 'REAL*8, intent(inout), dimension(1:m) :: y\n' + 'INTEGER*4 :: i\n' + 'INTEGER*4 :: j\n' + 'do i = 1, m\n' + ' do j = 1, n\n' + ' y(i) = %(rhs)s + y(i)\n' + ' end do\n' + 'end do\n' + 'end subroutine\n' + ) + + assert (code == expected % {'rhs': 'A(i, j)*x(j)'} or + code == expected % {'rhs': 'x(j)*A(i, j)'}) + assert f2 == 'file.h' + assert interface == ( + 'interface\n' + 'subroutine matrix_vector(A, m, n, x, y)\n' + 'implicit none\n' + 'INTEGER*4, intent(in) :: m\n' + 'INTEGER*4, intent(in) :: n\n' + 'REAL*8, intent(in), dimension(1:m, 1:n) :: A\n' + 'REAL*8, intent(in), dimension(1:n) :: x\n' + 'REAL*8, intent(inout), dimension(1:m) :: y\n' + 'end subroutine\n' + 'end interface\n' + ) + + +def test_partial_loops_f(): + # check that loop boundaries are determined by Idx, and array strides + # determined by shape of IndexedBase object. + from sympy.tensor import IndexedBase, Idx + from sympy.core.symbol import symbols + n, m, o, p = symbols('n m o p', integer=True) + A = IndexedBase('A', shape=(m, p)) + x = IndexedBase('x') + y = IndexedBase('y') + i = Idx('i', (o, m - 5)) # Note: bounds are inclusive + j = Idx('j', n) # dimension n corresponds to bounds (0, n - 1) + + (f1, code), (f2, interface) = codegen( + ('matrix_vector', Eq(y[i], A[i, j]*x[j])), "F95", "file", header=False, empty=False) + + expected = ( + 'subroutine matrix_vector(A, m, n, o, p, x, y)\n' + 'implicit none\n' + 'INTEGER*4, intent(in) :: m\n' + 'INTEGER*4, intent(in) :: n\n' + 'INTEGER*4, intent(in) :: o\n' + 'INTEGER*4, intent(in) :: p\n' + 'REAL*8, intent(in), dimension(1:m, 1:p) :: A\n' + 'REAL*8, intent(in), dimension(1:n) :: x\n' + 'REAL*8, intent(out), dimension(1:%(iup-ilow)s) :: y\n' + 'INTEGER*4 :: i\n' + 'INTEGER*4 :: j\n' + 'do i = %(ilow)s, %(iup)s\n' + ' y(i) = 0\n' + 'end do\n' + 'do i = %(ilow)s, %(iup)s\n' + ' do j = 1, n\n' + ' y(i) = %(rhs)s + y(i)\n' + ' end do\n' + 'end do\n' + 'end subroutine\n' + ) % { + 'rhs': '%(rhs)s', + 'iup': str(m - 4), + 'ilow': str(1 + o), + 'iup-ilow': str(m - 4 - o) + } + + assert code == expected % {'rhs': 'A(i, j)*x(j)'} or\ + code == expected % {'rhs': 'x(j)*A(i, j)'} + + +def test_output_arg_f(): + from sympy.core.relational import Equality + from sympy.functions.elementary.trigonometric import (cos, sin) + x, y, z = symbols("x,y,z") + r = make_routine("foo", [Equality(y, sin(x)), cos(x)]) + c = FCodeGen() + result = c.write([r], "test", header=False, empty=False) + assert result[0][0] == "test.f90" + assert result[0][1] == ( + 'REAL*8 function foo(x, y)\n' + 'implicit none\n' + 'REAL*8, intent(in) :: x\n' + 'REAL*8, intent(out) :: y\n' + 'y = sin(x)\n' + 'foo = cos(x)\n' + 'end function\n' + ) + + +def test_inline_function(): + from sympy.tensor import IndexedBase, Idx + from sympy.core.symbol import symbols + n, m = symbols('n m', integer=True) + A, x, y = map(IndexedBase, 'Axy') + i = Idx('i', m) + p = FCodeGen() + func = implemented_function('func', Lambda(n, n*(n + 1))) + routine = make_routine('test_inline', Eq(y[i], func(x[i]))) + code = get_string(p.dump_f95, [routine]) + expected = ( + 'subroutine test_inline(m, x, y)\n' + 'implicit none\n' + 'INTEGER*4, intent(in) :: m\n' + 'REAL*8, intent(in), dimension(1:m) :: x\n' + 'REAL*8, intent(out), dimension(1:m) :: y\n' + 'INTEGER*4 :: i\n' + 'do i = 1, m\n' + ' y(i) = %s*%s\n' + 'end do\n' + 'end subroutine\n' + ) + args = ('x(i)', '(x(i) + 1)') + assert code == expected % args or\ + code == expected % args[::-1] + + +def test_f_code_call_signature_wrap(): + # Issue #7934 + x = symbols('x:20') + expr = 0 + for sym in x: + expr += sym + routine = make_routine("test", expr) + code_gen = FCodeGen() + source = get_string(code_gen.dump_f95, [routine]) + expected = """\ +REAL*8 function test(x0, x1, x10, x11, x12, x13, x14, x15, x16, x17, x18, & + x19, x2, x3, x4, x5, x6, x7, x8, x9) +implicit none +REAL*8, intent(in) :: x0 +REAL*8, intent(in) :: x1 +REAL*8, intent(in) :: x10 +REAL*8, intent(in) :: x11 +REAL*8, intent(in) :: x12 +REAL*8, intent(in) :: x13 +REAL*8, intent(in) :: x14 +REAL*8, intent(in) :: x15 +REAL*8, intent(in) :: x16 +REAL*8, intent(in) :: x17 +REAL*8, intent(in) :: x18 +REAL*8, intent(in) :: x19 +REAL*8, intent(in) :: x2 +REAL*8, intent(in) :: x3 +REAL*8, intent(in) :: x4 +REAL*8, intent(in) :: x5 +REAL*8, intent(in) :: x6 +REAL*8, intent(in) :: x7 +REAL*8, intent(in) :: x8 +REAL*8, intent(in) :: x9 +test = x0 + x1 + x10 + x11 + x12 + x13 + x14 + x15 + x16 + x17 + x18 + & + x19 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 +end function +""" + assert source == expected + + +def test_check_case(): + x, X = symbols('x,X') + raises(CodeGenError, lambda: codegen(('test', x*X), 'f95', 'prefix')) + + +def test_check_case_false_positive(): + # The upper case/lower case exception should not be triggered by SymPy + # objects that differ only because of assumptions. (It may be useful to + # have a check for that as well, but here we only want to test against + # false positives with respect to case checking.) + x1 = symbols('x') + x2 = symbols('x', my_assumption=True) + try: + codegen(('test', x1*x2), 'f95', 'prefix') + except CodeGenError as e: + if e.args[0].startswith("Fortran ignores case."): + raise AssertionError("This exception should not be raised!") + + +def test_c_fortran_omit_routine_name(): + x, y = symbols("x,y") + name_expr = [("foo", 2*x)] + result = codegen(name_expr, "F95", header=False, empty=False) + expresult = codegen(name_expr, "F95", "foo", header=False, empty=False) + assert result[0][1] == expresult[0][1] + + name_expr = ("foo", x*y) + result = codegen(name_expr, "F95", header=False, empty=False) + expresult = codegen(name_expr, "F95", "foo", header=False, empty=False) + assert result[0][1] == expresult[0][1] + + name_expr = ("foo", Matrix([[x, y], [x+y, x-y]])) + result = codegen(name_expr, "C89", header=False, empty=False) + expresult = codegen(name_expr, "C89", "foo", header=False, empty=False) + assert result[0][1] == expresult[0][1] + + +def test_fcode_matrix_output(): + x, y, z = symbols('x,y,z') + e1 = x + y + e2 = Matrix([[x, y], [z, 16]]) + name_expr = ("test", (e1, e2)) + result = codegen(name_expr, "f95", "test", header=False, empty=False) + source = result[0][1] + expected = ( + "REAL*8 function test(x, y, z, out_%(hash)s)\n" + "implicit none\n" + "REAL*8, intent(in) :: x\n" + "REAL*8, intent(in) :: y\n" + "REAL*8, intent(in) :: z\n" + "REAL*8, intent(out), dimension(1:2, 1:2) :: out_%(hash)s\n" + "out_%(hash)s(1, 1) = x\n" + "out_%(hash)s(2, 1) = z\n" + "out_%(hash)s(1, 2) = y\n" + "out_%(hash)s(2, 2) = 16\n" + "test = x + y\n" + "end function\n" + ) + # look for the magic number + a = source.splitlines()[5] + b = a.split('_') + out = b[1] + expected = expected % {'hash': out} + assert source == expected + + +def test_fcode_results_named_ordered(): + x, y, z = symbols('x,y,z') + B, C = symbols('B,C') + A = MatrixSymbol('A', 1, 3) + expr1 = Equality(A, Matrix([[1, 2, x]])) + expr2 = Equality(C, (x + y)*z) + expr3 = Equality(B, 2*x) + name_expr = ("test", [expr1, expr2, expr3]) + result = codegen(name_expr, "f95", "test", header=False, empty=False, + argument_sequence=(x, z, y, C, A, B)) + source = result[0][1] + expected = ( + "subroutine test(x, z, y, C, A, B)\n" + "implicit none\n" + "REAL*8, intent(in) :: x\n" + "REAL*8, intent(in) :: z\n" + "REAL*8, intent(in) :: y\n" + "REAL*8, intent(out) :: C\n" + "REAL*8, intent(out) :: B\n" + "REAL*8, intent(out), dimension(1:1, 1:3) :: A\n" + "C = z*(x + y)\n" + "A(1, 1) = 1\n" + "A(1, 2) = 2\n" + "A(1, 3) = x\n" + "B = 2*x\n" + "end subroutine\n" + ) + assert source == expected + + +def test_fcode_matrixsymbol_slice(): + A = MatrixSymbol('A', 2, 3) + B = MatrixSymbol('B', 1, 3) + C = MatrixSymbol('C', 1, 3) + D = MatrixSymbol('D', 2, 1) + name_expr = ("test", [Equality(B, A[0, :]), + Equality(C, A[1, :]), + Equality(D, A[:, 2])]) + result = codegen(name_expr, "f95", "test", header=False, empty=False) + source = result[0][1] + expected = ( + "subroutine test(A, B, C, D)\n" + "implicit none\n" + "REAL*8, intent(in), dimension(1:2, 1:3) :: A\n" + "REAL*8, intent(out), dimension(1:1, 1:3) :: B\n" + "REAL*8, intent(out), dimension(1:1, 1:3) :: C\n" + "REAL*8, intent(out), dimension(1:2, 1:1) :: D\n" + "B(1, 1) = A(1, 1)\n" + "B(1, 2) = A(1, 2)\n" + "B(1, 3) = A(1, 3)\n" + "C(1, 1) = A(2, 1)\n" + "C(1, 2) = A(2, 2)\n" + "C(1, 3) = A(2, 3)\n" + "D(1, 1) = A(1, 3)\n" + "D(2, 1) = A(2, 3)\n" + "end subroutine\n" + ) + assert source == expected + + +def test_fcode_matrixsymbol_slice_autoname(): + # see issue #8093 + A = MatrixSymbol('A', 2, 3) + name_expr = ("test", A[:, 1]) + result = codegen(name_expr, "f95", "test", header=False, empty=False) + source = result[0][1] + expected = ( + "subroutine test(A, out_%(hash)s)\n" + "implicit none\n" + "REAL*8, intent(in), dimension(1:2, 1:3) :: A\n" + "REAL*8, intent(out), dimension(1:2, 1:1) :: out_%(hash)s\n" + "out_%(hash)s(1, 1) = A(1, 2)\n" + "out_%(hash)s(2, 1) = A(2, 2)\n" + "end subroutine\n" + ) + # look for the magic number + a = source.splitlines()[3] + b = a.split('_') + out = b[1] + expected = expected % {'hash': out} + assert source == expected + + +def test_global_vars(): + x, y, z, t = symbols("x y z t") + result = codegen(('f', x*y), "F95", header=False, empty=False, + global_vars=(y,)) + source = result[0][1] + expected = ( + "REAL*8 function f(x)\n" + "implicit none\n" + "REAL*8, intent(in) :: x\n" + "f = x*y\n" + "end function\n" + ) + assert source == expected + + expected = ( + '#include "f.h"\n' + '#include \n' + 'double f(double x, double y) {\n' + ' double f_result;\n' + ' f_result = x*y + z;\n' + ' return f_result;\n' + '}\n' + ) + result = codegen(('f', x*y+z), "C", header=False, empty=False, + global_vars=(z, t)) + source = result[0][1] + assert source == expected + +def test_custom_codegen(): + from sympy.printing.c import C99CodePrinter + from sympy.functions.elementary.exponential import exp + + printer = C99CodePrinter(settings={'user_functions': {'exp': 'fastexp'}}) + + x, y = symbols('x y') + expr = exp(x + y) + + # replace math.h with a different header + gen = C99CodeGen(printer=printer, + preprocessor_statements=['#include "fastexp.h"']) + + expected = ( + '#include "expr.h"\n' + '#include "fastexp.h"\n' + 'double expr(double x, double y) {\n' + ' double expr_result;\n' + ' expr_result = fastexp(x + y);\n' + ' return expr_result;\n' + '}\n' + ) + + result = codegen(('expr', expr), header=False, empty=False, code_gen=gen) + source = result[0][1] + assert source == expected + + # use both math.h and an external header + gen = C99CodeGen(printer=printer) + gen.preprocessor_statements.append('#include "fastexp.h"') + + expected = ( + '#include "expr.h"\n' + '#include \n' + '#include "fastexp.h"\n' + 'double expr(double x, double y) {\n' + ' double expr_result;\n' + ' expr_result = fastexp(x + y);\n' + ' return expr_result;\n' + '}\n' + ) + + result = codegen(('expr', expr), header=False, empty=False, code_gen=gen) + source = result[0][1] + assert source == expected + +def test_c_with_printer(): + # issue 13586 + from sympy.printing.c import C99CodePrinter + class CustomPrinter(C99CodePrinter): + def _print_Pow(self, expr): + return "fastpow({}, {})".format(self._print(expr.base), + self._print(expr.exp)) + + x = symbols('x') + expr = x**3 + expected =[ + ("file.c", + "#include \"file.h\"\n" + "#include \n" + "double test(double x) {\n" + " double test_result;\n" + " test_result = fastpow(x, 3);\n" + " return test_result;\n" + "}\n"), + ("file.h", + "#ifndef PROJECT__FILE__H\n" + "#define PROJECT__FILE__H\n" + "double test(double x);\n" + "#endif\n") + ] + result = codegen(("test", expr), "C","file", header=False, empty=False, printer = CustomPrinter()) + assert result == expected + + +def test_fcode_complex(): + import sympy.utilities.codegen + sympy.utilities.codegen.COMPLEX_ALLOWED = True + x = Symbol('x', real=True) + y = Symbol('y',real=True) + result = codegen(('test',x+y), 'f95', 'test', header=False, empty=False) + source = (result[0][1]) + expected = ( + "REAL*8 function test(x, y)\n" + "implicit none\n" + "REAL*8, intent(in) :: x\n" + "REAL*8, intent(in) :: y\n" + "test = x + y\n" + "end function\n") + assert source == expected + x = Symbol('x') + y = Symbol('y',real=True) + result = codegen(('test',x+y), 'f95', 'test', header=False, empty=False) + source = (result[0][1]) + expected = ( + "COMPLEX*16 function test(x, y)\n" + "implicit none\n" + "COMPLEX*16, intent(in) :: x\n" + "REAL*8, intent(in) :: y\n" + "test = x + y\n" + "end function\n" + ) + assert source==expected + sympy.utilities.codegen.COMPLEX_ALLOWED = False diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_codegen_julia.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_codegen_julia.py new file mode 100644 index 0000000000000000000000000000000000000000..12841cb7d476107e3866d91b998bed1f997f3901 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_codegen_julia.py @@ -0,0 +1,620 @@ +from io import StringIO + +from sympy.core import S, symbols, Eq, pi, Catalan, EulerGamma, Function +from sympy.core.relational import Equality +from sympy.functions.elementary.piecewise import Piecewise +from sympy.matrices import Matrix, MatrixSymbol +from sympy.utilities.codegen import JuliaCodeGen, codegen, make_routine +from sympy.testing.pytest import XFAIL +import sympy + + +x, y, z = symbols('x,y,z') + + +def test_empty_jl_code(): + code_gen = JuliaCodeGen() + output = StringIO() + code_gen.dump_jl([], output, "file", header=False, empty=False) + source = output.getvalue() + assert source == "" + + +def test_jl_simple_code(): + name_expr = ("test", (x + y)*z) + result, = codegen(name_expr, "Julia", header=False, empty=False) + assert result[0] == "test.jl" + source = result[1] + expected = ( + "function test(x, y, z)\n" + " out1 = z .* (x + y)\n" + " return out1\n" + "end\n" + ) + assert source == expected + + +def test_jl_simple_code_with_header(): + name_expr = ("test", (x + y)*z) + result, = codegen(name_expr, "Julia", header=True, empty=False) + assert result[0] == "test.jl" + source = result[1] + expected = ( + "# Code generated with SymPy " + sympy.__version__ + "\n" + "#\n" + "# See http://www.sympy.org/ for more information.\n" + "#\n" + "# This file is part of 'project'\n" + "function test(x, y, z)\n" + " out1 = z .* (x + y)\n" + " return out1\n" + "end\n" + ) + assert source == expected + + +def test_jl_simple_code_nameout(): + expr = Equality(z, (x + y)) + name_expr = ("test", expr) + result, = codegen(name_expr, "Julia", header=False, empty=False) + source = result[1] + expected = ( + "function test(x, y)\n" + " z = x + y\n" + " return z\n" + "end\n" + ) + assert source == expected + + +def test_jl_numbersymbol(): + name_expr = ("test", pi**Catalan) + result, = codegen(name_expr, "Julia", header=False, empty=False) + source = result[1] + expected = ( + "function test()\n" + " out1 = pi ^ catalan\n" + " return out1\n" + "end\n" + ) + assert source == expected + + +@XFAIL +def test_jl_numbersymbol_no_inline(): + # FIXME: how to pass inline=False to the JuliaCodePrinter? + name_expr = ("test", [pi**Catalan, EulerGamma]) + result, = codegen(name_expr, "Julia", header=False, + empty=False, inline=False) + source = result[1] + expected = ( + "function test()\n" + " Catalan = 0.915965594177219\n" + " EulerGamma = 0.5772156649015329\n" + " out1 = pi ^ Catalan\n" + " out2 = EulerGamma\n" + " return out1, out2\n" + "end\n" + ) + assert source == expected + + +def test_jl_code_argument_order(): + expr = x + y + routine = make_routine("test", expr, argument_sequence=[z, x, y], language="julia") + code_gen = JuliaCodeGen() + output = StringIO() + code_gen.dump_jl([routine], output, "test", header=False, empty=False) + source = output.getvalue() + expected = ( + "function test(z, x, y)\n" + " out1 = x + y\n" + " return out1\n" + "end\n" + ) + assert source == expected + + +def test_multiple_results_m(): + # Here the output order is the input order + expr1 = (x + y)*z + expr2 = (x - y)*z + name_expr = ("test", [expr1, expr2]) + result, = codegen(name_expr, "Julia", header=False, empty=False) + source = result[1] + expected = ( + "function test(x, y, z)\n" + " out1 = z .* (x + y)\n" + " out2 = z .* (x - y)\n" + " return out1, out2\n" + "end\n" + ) + assert source == expected + + +def test_results_named_unordered(): + # Here output order is based on name_expr + A, B, C = symbols('A,B,C') + expr1 = Equality(C, (x + y)*z) + expr2 = Equality(A, (x - y)*z) + expr3 = Equality(B, 2*x) + name_expr = ("test", [expr1, expr2, expr3]) + result, = codegen(name_expr, "Julia", header=False, empty=False) + source = result[1] + expected = ( + "function test(x, y, z)\n" + " C = z .* (x + y)\n" + " A = z .* (x - y)\n" + " B = 2 * x\n" + " return C, A, B\n" + "end\n" + ) + assert source == expected + + +def test_results_named_ordered(): + A, B, C = symbols('A,B,C') + expr1 = Equality(C, (x + y)*z) + expr2 = Equality(A, (x - y)*z) + expr3 = Equality(B, 2*x) + name_expr = ("test", [expr1, expr2, expr3]) + result = codegen(name_expr, "Julia", header=False, empty=False, + argument_sequence=(x, z, y)) + assert result[0][0] == "test.jl" + source = result[0][1] + expected = ( + "function test(x, z, y)\n" + " C = z .* (x + y)\n" + " A = z .* (x - y)\n" + " B = 2 * x\n" + " return C, A, B\n" + "end\n" + ) + assert source == expected + + +def test_complicated_jl_codegen(): + from sympy.functions.elementary.trigonometric import (cos, sin, tan) + name_expr = ("testlong", + [ ((sin(x) + cos(y) + tan(z))**3).expand(), + cos(cos(cos(cos(cos(cos(cos(cos(x + y + z)))))))) + ]) + result = codegen(name_expr, "Julia", header=False, empty=False) + assert result[0][0] == "testlong.jl" + source = result[0][1] + expected = ( + "function testlong(x, y, z)\n" + " out1 = sin(x) .^ 3 + 3 * sin(x) .^ 2 .* cos(y) + 3 * sin(x) .^ 2 .* tan(z)" + " + 3 * sin(x) .* cos(y) .^ 2 + 6 * sin(x) .* cos(y) .* tan(z) + 3 * sin(x) .* tan(z) .^ 2" + " + cos(y) .^ 3 + 3 * cos(y) .^ 2 .* tan(z) + 3 * cos(y) .* tan(z) .^ 2 + tan(z) .^ 3\n" + " out2 = cos(cos(cos(cos(cos(cos(cos(cos(x + y + z))))))))\n" + " return out1, out2\n" + "end\n" + ) + assert source == expected + + +def test_jl_output_arg_mixed_unordered(): + # named outputs are alphabetical, unnamed output appear in the given order + from sympy.functions.elementary.trigonometric import (cos, sin) + a = symbols("a") + name_expr = ("foo", [cos(2*x), Equality(y, sin(x)), cos(x), Equality(a, sin(2*x))]) + result, = codegen(name_expr, "Julia", header=False, empty=False) + assert result[0] == "foo.jl" + source = result[1] + expected = ( + 'function foo(x)\n' + ' out1 = cos(2 * x)\n' + ' y = sin(x)\n' + ' out3 = cos(x)\n' + ' a = sin(2 * x)\n' + ' return out1, y, out3, a\n' + 'end\n' + ) + assert source == expected + + +def test_jl_piecewise_(): + pw = Piecewise((0, x < -1), (x**2, x <= 1), (-x+2, x > 1), (1, True), evaluate=False) + name_expr = ("pwtest", pw) + result, = codegen(name_expr, "Julia", header=False, empty=False) + source = result[1] + expected = ( + "function pwtest(x)\n" + " out1 = ((x < -1) ? (0) :\n" + " (x <= 1) ? (x .^ 2) :\n" + " (x > 1) ? (2 - x) : (1))\n" + " return out1\n" + "end\n" + ) + assert source == expected + + +@XFAIL +def test_jl_piecewise_no_inline(): + # FIXME: how to pass inline=False to the JuliaCodePrinter? + pw = Piecewise((0, x < -1), (x**2, x <= 1), (-x+2, x > 1), (1, True)) + name_expr = ("pwtest", pw) + result, = codegen(name_expr, "Julia", header=False, empty=False, + inline=False) + source = result[1] + expected = ( + "function pwtest(x)\n" + " if (x < -1)\n" + " out1 = 0\n" + " elseif (x <= 1)\n" + " out1 = x .^ 2\n" + " elseif (x > 1)\n" + " out1 = -x + 2\n" + " else\n" + " out1 = 1\n" + " end\n" + " return out1\n" + "end\n" + ) + assert source == expected + + +def test_jl_multifcns_per_file(): + name_expr = [ ("foo", [2*x, 3*y]), ("bar", [y**2, 4*y]) ] + result = codegen(name_expr, "Julia", header=False, empty=False) + assert result[0][0] == "foo.jl" + source = result[0][1] + expected = ( + "function foo(x, y)\n" + " out1 = 2 * x\n" + " out2 = 3 * y\n" + " return out1, out2\n" + "end\n" + "function bar(y)\n" + " out1 = y .^ 2\n" + " out2 = 4 * y\n" + " return out1, out2\n" + "end\n" + ) + assert source == expected + + +def test_jl_multifcns_per_file_w_header(): + name_expr = [ ("foo", [2*x, 3*y]), ("bar", [y**2, 4*y]) ] + result = codegen(name_expr, "Julia", header=True, empty=False) + assert result[0][0] == "foo.jl" + source = result[0][1] + expected = ( + "# Code generated with SymPy " + sympy.__version__ + "\n" + "#\n" + "# See http://www.sympy.org/ for more information.\n" + "#\n" + "# This file is part of 'project'\n" + "function foo(x, y)\n" + " out1 = 2 * x\n" + " out2 = 3 * y\n" + " return out1, out2\n" + "end\n" + "function bar(y)\n" + " out1 = y .^ 2\n" + " out2 = 4 * y\n" + " return out1, out2\n" + "end\n" + ) + assert source == expected + + +def test_jl_filename_match_prefix(): + name_expr = [ ("foo", [2*x, 3*y]), ("bar", [y**2, 4*y]) ] + result, = codegen(name_expr, "Julia", prefix="baz", header=False, + empty=False) + assert result[0] == "baz.jl" + + +def test_jl_matrix_named(): + e2 = Matrix([[x, 2*y, pi*z]]) + name_expr = ("test", Equality(MatrixSymbol('myout1', 1, 3), e2)) + result = codegen(name_expr, "Julia", header=False, empty=False) + assert result[0][0] == "test.jl" + source = result[0][1] + expected = ( + "function test(x, y, z)\n" + " myout1 = [x 2 * y pi * z]\n" + " return myout1\n" + "end\n" + ) + assert source == expected + + +def test_jl_matrix_named_matsym(): + myout1 = MatrixSymbol('myout1', 1, 3) + e2 = Matrix([[x, 2*y, pi*z]]) + name_expr = ("test", Equality(myout1, e2, evaluate=False)) + result, = codegen(name_expr, "Julia", header=False, empty=False) + source = result[1] + expected = ( + "function test(x, y, z)\n" + " myout1 = [x 2 * y pi * z]\n" + " return myout1\n" + "end\n" + ) + assert source == expected + + +def test_jl_matrix_output_autoname(): + expr = Matrix([[x, x+y, 3]]) + name_expr = ("test", expr) + result, = codegen(name_expr, "Julia", header=False, empty=False) + source = result[1] + expected = ( + "function test(x, y)\n" + " out1 = [x x + y 3]\n" + " return out1\n" + "end\n" + ) + assert source == expected + + +def test_jl_matrix_output_autoname_2(): + e1 = (x + y) + e2 = Matrix([[2*x, 2*y, 2*z]]) + e3 = Matrix([[x], [y], [z]]) + e4 = Matrix([[x, y], [z, 16]]) + name_expr = ("test", (e1, e2, e3, e4)) + result, = codegen(name_expr, "Julia", header=False, empty=False) + source = result[1] + expected = ( + "function test(x, y, z)\n" + " out1 = x + y\n" + " out2 = [2 * x 2 * y 2 * z]\n" + " out3 = [x, y, z]\n" + " out4 = [x y;\n" + " z 16]\n" + " return out1, out2, out3, out4\n" + "end\n" + ) + assert source == expected + + +def test_jl_results_matrix_named_ordered(): + B, C = symbols('B,C') + A = MatrixSymbol('A', 1, 3) + expr1 = Equality(C, (x + y)*z) + expr2 = Equality(A, Matrix([[1, 2, x]])) + expr3 = Equality(B, 2*x) + name_expr = ("test", [expr1, expr2, expr3]) + result, = codegen(name_expr, "Julia", header=False, empty=False, + argument_sequence=(x, z, y)) + source = result[1] + expected = ( + "function test(x, z, y)\n" + " C = z .* (x + y)\n" + " A = [1 2 x]\n" + " B = 2 * x\n" + " return C, A, B\n" + "end\n" + ) + assert source == expected + + +def test_jl_matrixsymbol_slice(): + A = MatrixSymbol('A', 2, 3) + B = MatrixSymbol('B', 1, 3) + C = MatrixSymbol('C', 1, 3) + D = MatrixSymbol('D', 2, 1) + name_expr = ("test", [Equality(B, A[0, :]), + Equality(C, A[1, :]), + Equality(D, A[:, 2])]) + result, = codegen(name_expr, "Julia", header=False, empty=False) + source = result[1] + expected = ( + "function test(A)\n" + " B = A[1,:]\n" + " C = A[2,:]\n" + " D = A[:,3]\n" + " return B, C, D\n" + "end\n" + ) + assert source == expected + + +def test_jl_matrixsymbol_slice2(): + A = MatrixSymbol('A', 3, 4) + B = MatrixSymbol('B', 2, 2) + C = MatrixSymbol('C', 2, 2) + name_expr = ("test", [Equality(B, A[0:2, 0:2]), + Equality(C, A[0:2, 1:3])]) + result, = codegen(name_expr, "Julia", header=False, empty=False) + source = result[1] + expected = ( + "function test(A)\n" + " B = A[1:2,1:2]\n" + " C = A[1:2,2:3]\n" + " return B, C\n" + "end\n" + ) + assert source == expected + + +def test_jl_matrixsymbol_slice3(): + A = MatrixSymbol('A', 8, 7) + B = MatrixSymbol('B', 2, 2) + C = MatrixSymbol('C', 4, 2) + name_expr = ("test", [Equality(B, A[6:, 1::3]), + Equality(C, A[::2, ::3])]) + result, = codegen(name_expr, "Julia", header=False, empty=False) + source = result[1] + expected = ( + "function test(A)\n" + " B = A[7:end,2:3:end]\n" + " C = A[1:2:end,1:3:end]\n" + " return B, C\n" + "end\n" + ) + assert source == expected + + +def test_jl_matrixsymbol_slice_autoname(): + A = MatrixSymbol('A', 2, 3) + B = MatrixSymbol('B', 1, 3) + name_expr = ("test", [Equality(B, A[0,:]), A[1,:], A[:,0], A[:,1]]) + result, = codegen(name_expr, "Julia", header=False, empty=False) + source = result[1] + expected = ( + "function test(A)\n" + " B = A[1,:]\n" + " out2 = A[2,:]\n" + " out3 = A[:,1]\n" + " out4 = A[:,2]\n" + " return B, out2, out3, out4\n" + "end\n" + ) + assert source == expected + + +def test_jl_loops(): + # Note: an Julia programmer would probably vectorize this across one or + # more dimensions. Also, size(A) would be used rather than passing in m + # and n. Perhaps users would expect us to vectorize automatically here? + # Or is it possible to represent such things using IndexedBase? + from sympy.tensor import IndexedBase, Idx + from sympy.core.symbol import symbols + n, m = symbols('n m', integer=True) + A = IndexedBase('A') + x = IndexedBase('x') + y = IndexedBase('y') + i = Idx('i', m) + j = Idx('j', n) + result, = codegen(('mat_vec_mult', Eq(y[i], A[i, j]*x[j])), "Julia", + header=False, empty=False) + source = result[1] + expected = ( + 'function mat_vec_mult(y, A, m, n, x)\n' + ' for i = 1:m\n' + ' y[i] = 0\n' + ' end\n' + ' for i = 1:m\n' + ' for j = 1:n\n' + ' y[i] = %(rhs)s + y[i]\n' + ' end\n' + ' end\n' + ' return y\n' + 'end\n' + ) + assert (source == expected % {'rhs': 'A[%s,%s] .* x[j]' % (i, j)} or + source == expected % {'rhs': 'x[j] .* A[%s,%s]' % (i, j)}) + + +def test_jl_tensor_loops_multiple_contractions(): + # see comments in previous test about vectorizing + from sympy.tensor import IndexedBase, Idx + from sympy.core.symbol import symbols + n, m, o, p = symbols('n m o p', integer=True) + A = IndexedBase('A') + B = IndexedBase('B') + y = IndexedBase('y') + i = Idx('i', m) + j = Idx('j', n) + k = Idx('k', o) + l = Idx('l', p) + result, = codegen(('tensorthing', Eq(y[i], B[j, k, l]*A[i, j, k, l])), + "Julia", header=False, empty=False) + source = result[1] + expected = ( + 'function tensorthing(y, A, B, m, n, o, p)\n' + ' for i = 1:m\n' + ' y[i] = 0\n' + ' end\n' + ' for i = 1:m\n' + ' for j = 1:n\n' + ' for k = 1:o\n' + ' for l = 1:p\n' + ' y[i] = A[i,j,k,l] .* B[j,k,l] + y[i]\n' + ' end\n' + ' end\n' + ' end\n' + ' end\n' + ' return y\n' + 'end\n' + ) + assert source == expected + + +def test_jl_InOutArgument(): + expr = Equality(x, x**2) + name_expr = ("mysqr", expr) + result, = codegen(name_expr, "Julia", header=False, empty=False) + source = result[1] + expected = ( + "function mysqr(x)\n" + " x = x .^ 2\n" + " return x\n" + "end\n" + ) + assert source == expected + + +def test_jl_InOutArgument_order(): + # can specify the order as (x, y) + expr = Equality(x, x**2 + y) + name_expr = ("test", expr) + result, = codegen(name_expr, "Julia", header=False, + empty=False, argument_sequence=(x,y)) + source = result[1] + expected = ( + "function test(x, y)\n" + " x = x .^ 2 + y\n" + " return x\n" + "end\n" + ) + assert source == expected + # make sure it gives (x, y) not (y, x) + expr = Equality(x, x**2 + y) + name_expr = ("test", expr) + result, = codegen(name_expr, "Julia", header=False, empty=False) + source = result[1] + expected = ( + "function test(x, y)\n" + " x = x .^ 2 + y\n" + " return x\n" + "end\n" + ) + assert source == expected + + +def test_jl_not_supported(): + f = Function('f') + name_expr = ("test", [f(x).diff(x), S.ComplexInfinity]) + result, = codegen(name_expr, "Julia", header=False, empty=False) + source = result[1] + expected = ( + "function test(x)\n" + " # unsupported: Derivative(f(x), x)\n" + " # unsupported: zoo\n" + " out1 = Derivative(f(x), x)\n" + " out2 = zoo\n" + " return out1, out2\n" + "end\n" + ) + assert source == expected + + +def test_global_vars_octave(): + x, y, z, t = symbols("x y z t") + result = codegen(('f', x*y), "Julia", header=False, empty=False, + global_vars=(y,)) + source = result[0][1] + expected = ( + "function f(x)\n" + " out1 = x .* y\n" + " return out1\n" + "end\n" + ) + assert source == expected + + result = codegen(('f', x*y+z), "Julia", header=False, empty=False, + argument_sequence=(x, y), global_vars=(z, t)) + source = result[0][1] + expected = ( + "function f(x, y)\n" + " out1 = x .* y + z\n" + " return out1\n" + "end\n" + ) + assert source == expected diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_codegen_octave.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_codegen_octave.py new file mode 100644 index 0000000000000000000000000000000000000000..77aaef7dd0d81d6855024e49fbb3d6d4c09f3384 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_codegen_octave.py @@ -0,0 +1,589 @@ +from io import StringIO + +from sympy.core import S, symbols, Eq, pi, Catalan, EulerGamma, Function +from sympy.core.relational import Equality +from sympy.functions.elementary.piecewise import Piecewise +from sympy.matrices import Matrix, MatrixSymbol +from sympy.utilities.codegen import OctaveCodeGen, codegen, make_routine +from sympy.testing.pytest import raises +from sympy.testing.pytest import XFAIL +import sympy + + +x, y, z = symbols('x,y,z') + + +def test_empty_m_code(): + code_gen = OctaveCodeGen() + output = StringIO() + code_gen.dump_m([], output, "file", header=False, empty=False) + source = output.getvalue() + assert source == "" + + +def test_m_simple_code(): + name_expr = ("test", (x + y)*z) + result, = codegen(name_expr, "Octave", header=False, empty=False) + assert result[0] == "test.m" + source = result[1] + expected = ( + "function out1 = test(x, y, z)\n" + " out1 = z.*(x + y);\n" + "end\n" + ) + assert source == expected + + +def test_m_simple_code_with_header(): + name_expr = ("test", (x + y)*z) + result, = codegen(name_expr, "Octave", header=True, empty=False) + assert result[0] == "test.m" + source = result[1] + expected = ( + "function out1 = test(x, y, z)\n" + " %TEST Autogenerated by SymPy\n" + " % Code generated with SymPy " + sympy.__version__ + "\n" + " %\n" + " % See http://www.sympy.org/ for more information.\n" + " %\n" + " % This file is part of 'project'\n" + " out1 = z.*(x + y);\n" + "end\n" + ) + assert source == expected + + +def test_m_simple_code_nameout(): + expr = Equality(z, (x + y)) + name_expr = ("test", expr) + result, = codegen(name_expr, "Octave", header=False, empty=False) + source = result[1] + expected = ( + "function z = test(x, y)\n" + " z = x + y;\n" + "end\n" + ) + assert source == expected + + +def test_m_numbersymbol(): + name_expr = ("test", pi**Catalan) + result, = codegen(name_expr, "Octave", header=False, empty=False) + source = result[1] + expected = ( + "function out1 = test()\n" + " out1 = pi^%s;\n" + "end\n" + ) % Catalan.evalf(17) + assert source == expected + + +@XFAIL +def test_m_numbersymbol_no_inline(): + # FIXME: how to pass inline=False to the OctaveCodePrinter? + name_expr = ("test", [pi**Catalan, EulerGamma]) + result, = codegen(name_expr, "Octave", header=False, + empty=False, inline=False) + source = result[1] + expected = ( + "function [out1, out2] = test()\n" + " Catalan = 0.915965594177219; % constant\n" + " EulerGamma = 0.5772156649015329; % constant\n" + " out1 = pi^Catalan;\n" + " out2 = EulerGamma;\n" + "end\n" + ) + assert source == expected + + +def test_m_code_argument_order(): + expr = x + y + routine = make_routine("test", expr, argument_sequence=[z, x, y], language="octave") + code_gen = OctaveCodeGen() + output = StringIO() + code_gen.dump_m([routine], output, "test", header=False, empty=False) + source = output.getvalue() + expected = ( + "function out1 = test(z, x, y)\n" + " out1 = x + y;\n" + "end\n" + ) + assert source == expected + + +def test_multiple_results_m(): + # Here the output order is the input order + expr1 = (x + y)*z + expr2 = (x - y)*z + name_expr = ("test", [expr1, expr2]) + result, = codegen(name_expr, "Octave", header=False, empty=False) + source = result[1] + expected = ( + "function [out1, out2] = test(x, y, z)\n" + " out1 = z.*(x + y);\n" + " out2 = z.*(x - y);\n" + "end\n" + ) + assert source == expected + + +def test_results_named_unordered(): + # Here output order is based on name_expr + A, B, C = symbols('A,B,C') + expr1 = Equality(C, (x + y)*z) + expr2 = Equality(A, (x - y)*z) + expr3 = Equality(B, 2*x) + name_expr = ("test", [expr1, expr2, expr3]) + result, = codegen(name_expr, "Octave", header=False, empty=False) + source = result[1] + expected = ( + "function [C, A, B] = test(x, y, z)\n" + " C = z.*(x + y);\n" + " A = z.*(x - y);\n" + " B = 2*x;\n" + "end\n" + ) + assert source == expected + + +def test_results_named_ordered(): + A, B, C = symbols('A,B,C') + expr1 = Equality(C, (x + y)*z) + expr2 = Equality(A, (x - y)*z) + expr3 = Equality(B, 2*x) + name_expr = ("test", [expr1, expr2, expr3]) + result = codegen(name_expr, "Octave", header=False, empty=False, + argument_sequence=(x, z, y)) + assert result[0][0] == "test.m" + source = result[0][1] + expected = ( + "function [C, A, B] = test(x, z, y)\n" + " C = z.*(x + y);\n" + " A = z.*(x - y);\n" + " B = 2*x;\n" + "end\n" + ) + assert source == expected + + +def test_complicated_m_codegen(): + from sympy.functions.elementary.trigonometric import (cos, sin, tan) + name_expr = ("testlong", + [ ((sin(x) + cos(y) + tan(z))**3).expand(), + cos(cos(cos(cos(cos(cos(cos(cos(x + y + z)))))))) + ]) + result = codegen(name_expr, "Octave", header=False, empty=False) + assert result[0][0] == "testlong.m" + source = result[0][1] + expected = ( + "function [out1, out2] = testlong(x, y, z)\n" + " out1 = sin(x).^3 + 3*sin(x).^2.*cos(y) + 3*sin(x).^2.*tan(z)" + " + 3*sin(x).*cos(y).^2 + 6*sin(x).*cos(y).*tan(z) + 3*sin(x).*tan(z).^2" + " + cos(y).^3 + 3*cos(y).^2.*tan(z) + 3*cos(y).*tan(z).^2 + tan(z).^3;\n" + " out2 = cos(cos(cos(cos(cos(cos(cos(cos(x + y + z))))))));\n" + "end\n" + ) + assert source == expected + + +def test_m_output_arg_mixed_unordered(): + # named outputs are alphabetical, unnamed output appear in the given order + from sympy.functions.elementary.trigonometric import (cos, sin) + a = symbols("a") + name_expr = ("foo", [cos(2*x), Equality(y, sin(x)), cos(x), Equality(a, sin(2*x))]) + result, = codegen(name_expr, "Octave", header=False, empty=False) + assert result[0] == "foo.m" + source = result[1] + expected = ( + 'function [out1, y, out3, a] = foo(x)\n' + ' out1 = cos(2*x);\n' + ' y = sin(x);\n' + ' out3 = cos(x);\n' + ' a = sin(2*x);\n' + 'end\n' + ) + assert source == expected + + +def test_m_piecewise_(): + pw = Piecewise((0, x < -1), (x**2, x <= 1), (-x+2, x > 1), (1, True), evaluate=False) + name_expr = ("pwtest", pw) + result, = codegen(name_expr, "Octave", header=False, empty=False) + source = result[1] + expected = ( + "function out1 = pwtest(x)\n" + " out1 = ((x < -1).*(0) + (~(x < -1)).*( ...\n" + " (x <= 1).*(x.^2) + (~(x <= 1)).*( ...\n" + " (x > 1).*(2 - x) + (~(x > 1)).*(1))));\n" + "end\n" + ) + assert source == expected + + +@XFAIL +def test_m_piecewise_no_inline(): + # FIXME: how to pass inline=False to the OctaveCodePrinter? + pw = Piecewise((0, x < -1), (x**2, x <= 1), (-x+2, x > 1), (1, True)) + name_expr = ("pwtest", pw) + result, = codegen(name_expr, "Octave", header=False, empty=False, + inline=False) + source = result[1] + expected = ( + "function out1 = pwtest(x)\n" + " if (x < -1)\n" + " out1 = 0;\n" + " elseif (x <= 1)\n" + " out1 = x.^2;\n" + " elseif (x > 1)\n" + " out1 = -x + 2;\n" + " else\n" + " out1 = 1;\n" + " end\n" + "end\n" + ) + assert source == expected + + +def test_m_multifcns_per_file(): + name_expr = [ ("foo", [2*x, 3*y]), ("bar", [y**2, 4*y]) ] + result = codegen(name_expr, "Octave", header=False, empty=False) + assert result[0][0] == "foo.m" + source = result[0][1] + expected = ( + "function [out1, out2] = foo(x, y)\n" + " out1 = 2*x;\n" + " out2 = 3*y;\n" + "end\n" + "function [out1, out2] = bar(y)\n" + " out1 = y.^2;\n" + " out2 = 4*y;\n" + "end\n" + ) + assert source == expected + + +def test_m_multifcns_per_file_w_header(): + name_expr = [ ("foo", [2*x, 3*y]), ("bar", [y**2, 4*y]) ] + result = codegen(name_expr, "Octave", header=True, empty=False) + assert result[0][0] == "foo.m" + source = result[0][1] + expected = ( + "function [out1, out2] = foo(x, y)\n" + " %FOO Autogenerated by SymPy\n" + " % Code generated with SymPy " + sympy.__version__ + "\n" + " %\n" + " % See http://www.sympy.org/ for more information.\n" + " %\n" + " % This file is part of 'project'\n" + " out1 = 2*x;\n" + " out2 = 3*y;\n" + "end\n" + "function [out1, out2] = bar(y)\n" + " out1 = y.^2;\n" + " out2 = 4*y;\n" + "end\n" + ) + assert source == expected + + +def test_m_filename_match_first_fcn(): + name_expr = [ ("foo", [2*x, 3*y]), ("bar", [y**2, 4*y]) ] + raises(ValueError, lambda: codegen(name_expr, + "Octave", prefix="bar", header=False, empty=False)) + + +def test_m_matrix_named(): + e2 = Matrix([[x, 2*y, pi*z]]) + name_expr = ("test", Equality(MatrixSymbol('myout1', 1, 3), e2)) + result = codegen(name_expr, "Octave", header=False, empty=False) + assert result[0][0] == "test.m" + source = result[0][1] + expected = ( + "function myout1 = test(x, y, z)\n" + " myout1 = [x 2*y pi*z];\n" + "end\n" + ) + assert source == expected + + +def test_m_matrix_named_matsym(): + myout1 = MatrixSymbol('myout1', 1, 3) + e2 = Matrix([[x, 2*y, pi*z]]) + name_expr = ("test", Equality(myout1, e2, evaluate=False)) + result, = codegen(name_expr, "Octave", header=False, empty=False) + source = result[1] + expected = ( + "function myout1 = test(x, y, z)\n" + " myout1 = [x 2*y pi*z];\n" + "end\n" + ) + assert source == expected + + +def test_m_matrix_output_autoname(): + expr = Matrix([[x, x+y, 3]]) + name_expr = ("test", expr) + result, = codegen(name_expr, "Octave", header=False, empty=False) + source = result[1] + expected = ( + "function out1 = test(x, y)\n" + " out1 = [x x + y 3];\n" + "end\n" + ) + assert source == expected + + +def test_m_matrix_output_autoname_2(): + e1 = (x + y) + e2 = Matrix([[2*x, 2*y, 2*z]]) + e3 = Matrix([[x], [y], [z]]) + e4 = Matrix([[x, y], [z, 16]]) + name_expr = ("test", (e1, e2, e3, e4)) + result, = codegen(name_expr, "Octave", header=False, empty=False) + source = result[1] + expected = ( + "function [out1, out2, out3, out4] = test(x, y, z)\n" + " out1 = x + y;\n" + " out2 = [2*x 2*y 2*z];\n" + " out3 = [x; y; z];\n" + " out4 = [x y; z 16];\n" + "end\n" + ) + assert source == expected + + +def test_m_results_matrix_named_ordered(): + B, C = symbols('B,C') + A = MatrixSymbol('A', 1, 3) + expr1 = Equality(C, (x + y)*z) + expr2 = Equality(A, Matrix([[1, 2, x]])) + expr3 = Equality(B, 2*x) + name_expr = ("test", [expr1, expr2, expr3]) + result, = codegen(name_expr, "Octave", header=False, empty=False, + argument_sequence=(x, z, y)) + source = result[1] + expected = ( + "function [C, A, B] = test(x, z, y)\n" + " C = z.*(x + y);\n" + " A = [1 2 x];\n" + " B = 2*x;\n" + "end\n" + ) + assert source == expected + + +def test_m_matrixsymbol_slice(): + A = MatrixSymbol('A', 2, 3) + B = MatrixSymbol('B', 1, 3) + C = MatrixSymbol('C', 1, 3) + D = MatrixSymbol('D', 2, 1) + name_expr = ("test", [Equality(B, A[0, :]), + Equality(C, A[1, :]), + Equality(D, A[:, 2])]) + result, = codegen(name_expr, "Octave", header=False, empty=False) + source = result[1] + expected = ( + "function [B, C, D] = test(A)\n" + " B = A(1, :);\n" + " C = A(2, :);\n" + " D = A(:, 3);\n" + "end\n" + ) + assert source == expected + + +def test_m_matrixsymbol_slice2(): + A = MatrixSymbol('A', 3, 4) + B = MatrixSymbol('B', 2, 2) + C = MatrixSymbol('C', 2, 2) + name_expr = ("test", [Equality(B, A[0:2, 0:2]), + Equality(C, A[0:2, 1:3])]) + result, = codegen(name_expr, "Octave", header=False, empty=False) + source = result[1] + expected = ( + "function [B, C] = test(A)\n" + " B = A(1:2, 1:2);\n" + " C = A(1:2, 2:3);\n" + "end\n" + ) + assert source == expected + + +def test_m_matrixsymbol_slice3(): + A = MatrixSymbol('A', 8, 7) + B = MatrixSymbol('B', 2, 2) + C = MatrixSymbol('C', 4, 2) + name_expr = ("test", [Equality(B, A[6:, 1::3]), + Equality(C, A[::2, ::3])]) + result, = codegen(name_expr, "Octave", header=False, empty=False) + source = result[1] + expected = ( + "function [B, C] = test(A)\n" + " B = A(7:end, 2:3:end);\n" + " C = A(1:2:end, 1:3:end);\n" + "end\n" + ) + assert source == expected + + +def test_m_matrixsymbol_slice_autoname(): + A = MatrixSymbol('A', 2, 3) + B = MatrixSymbol('B', 1, 3) + name_expr = ("test", [Equality(B, A[0,:]), A[1,:], A[:,0], A[:,1]]) + result, = codegen(name_expr, "Octave", header=False, empty=False) + source = result[1] + expected = ( + "function [B, out2, out3, out4] = test(A)\n" + " B = A(1, :);\n" + " out2 = A(2, :);\n" + " out3 = A(:, 1);\n" + " out4 = A(:, 2);\n" + "end\n" + ) + assert source == expected + + +def test_m_loops(): + # Note: an Octave programmer would probably vectorize this across one or + # more dimensions. Also, size(A) would be used rather than passing in m + # and n. Perhaps users would expect us to vectorize automatically here? + # Or is it possible to represent such things using IndexedBase? + from sympy.tensor import IndexedBase, Idx + from sympy.core.symbol import symbols + n, m = symbols('n m', integer=True) + A = IndexedBase('A') + x = IndexedBase('x') + y = IndexedBase('y') + i = Idx('i', m) + j = Idx('j', n) + result, = codegen(('mat_vec_mult', Eq(y[i], A[i, j]*x[j])), "Octave", + header=False, empty=False) + source = result[1] + expected = ( + 'function y = mat_vec_mult(A, m, n, x)\n' + ' for i = 1:m\n' + ' y(i) = 0;\n' + ' end\n' + ' for i = 1:m\n' + ' for j = 1:n\n' + ' y(i) = %(rhs)s + y(i);\n' + ' end\n' + ' end\n' + 'end\n' + ) + assert (source == expected % {'rhs': 'A(%s, %s).*x(j)' % (i, j)} or + source == expected % {'rhs': 'x(j).*A(%s, %s)' % (i, j)}) + + +def test_m_tensor_loops_multiple_contractions(): + # see comments in previous test about vectorizing + from sympy.tensor import IndexedBase, Idx + from sympy.core.symbol import symbols + n, m, o, p = symbols('n m o p', integer=True) + A = IndexedBase('A') + B = IndexedBase('B') + y = IndexedBase('y') + i = Idx('i', m) + j = Idx('j', n) + k = Idx('k', o) + l = Idx('l', p) + result, = codegen(('tensorthing', Eq(y[i], B[j, k, l]*A[i, j, k, l])), + "Octave", header=False, empty=False) + source = result[1] + expected = ( + 'function y = tensorthing(A, B, m, n, o, p)\n' + ' for i = 1:m\n' + ' y(i) = 0;\n' + ' end\n' + ' for i = 1:m\n' + ' for j = 1:n\n' + ' for k = 1:o\n' + ' for l = 1:p\n' + ' y(i) = A(i, j, k, l).*B(j, k, l) + y(i);\n' + ' end\n' + ' end\n' + ' end\n' + ' end\n' + 'end\n' + ) + assert source == expected + + +def test_m_InOutArgument(): + expr = Equality(x, x**2) + name_expr = ("mysqr", expr) + result, = codegen(name_expr, "Octave", header=False, empty=False) + source = result[1] + expected = ( + "function x = mysqr(x)\n" + " x = x.^2;\n" + "end\n" + ) + assert source == expected + + +def test_m_InOutArgument_order(): + # can specify the order as (x, y) + expr = Equality(x, x**2 + y) + name_expr = ("test", expr) + result, = codegen(name_expr, "Octave", header=False, + empty=False, argument_sequence=(x,y)) + source = result[1] + expected = ( + "function x = test(x, y)\n" + " x = x.^2 + y;\n" + "end\n" + ) + assert source == expected + # make sure it gives (x, y) not (y, x) + expr = Equality(x, x**2 + y) + name_expr = ("test", expr) + result, = codegen(name_expr, "Octave", header=False, empty=False) + source = result[1] + expected = ( + "function x = test(x, y)\n" + " x = x.^2 + y;\n" + "end\n" + ) + assert source == expected + + +def test_m_not_supported(): + f = Function('f') + name_expr = ("test", [f(x).diff(x), S.ComplexInfinity]) + result, = codegen(name_expr, "Octave", header=False, empty=False) + source = result[1] + expected = ( + "function [out1, out2] = test(x)\n" + " % unsupported: Derivative(f(x), x)\n" + " % unsupported: zoo\n" + " out1 = Derivative(f(x), x);\n" + " out2 = zoo;\n" + "end\n" + ) + assert source == expected + + +def test_global_vars_octave(): + x, y, z, t = symbols("x y z t") + result = codegen(('f', x*y), "Octave", header=False, empty=False, + global_vars=(y,)) + source = result[0][1] + expected = ( + "function out1 = f(x)\n" + " global y\n" + " out1 = x.*y;\n" + "end\n" + ) + assert source == expected + + result = codegen(('f', x*y+z), "Octave", header=False, empty=False, + argument_sequence=(x, y), global_vars=(z, t)) + source = result[0][1] + expected = ( + "function out1 = f(x, y)\n" + " global t z\n" + " out1 = x.*y + z;\n" + "end\n" + ) + assert source == expected diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_codegen_rust.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_codegen_rust.py new file mode 100644 index 0000000000000000000000000000000000000000..bc7f82158ae8fa7dfe34bf909aa695b119fb9526 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_codegen_rust.py @@ -0,0 +1,401 @@ +from io import StringIO + +from sympy.core import S, symbols, pi, Catalan, EulerGamma, Function +from sympy.core.relational import Equality +from sympy.functions.elementary.piecewise import Piecewise +from sympy.utilities.codegen import RustCodeGen, codegen, make_routine +from sympy.testing.pytest import XFAIL +import sympy + + +x, y, z = symbols('x,y,z') + + +def test_empty_rust_code(): + code_gen = RustCodeGen() + output = StringIO() + code_gen.dump_rs([], output, "file", header=False, empty=False) + source = output.getvalue() + assert source == "" + + +def test_simple_rust_code(): + name_expr = ("test", (x + y)*z) + result, = codegen(name_expr, "Rust", header=False, empty=False) + assert result[0] == "test.rs" + source = result[1] + expected = ( + "fn test(x: f64, y: f64, z: f64) -> f64 {\n" + " let out1 = z*(x + y);\n" + " out1\n" + "}\n" + ) + assert source == expected + + +def test_simple_code_with_header(): + name_expr = ("test", (x + y)*z) + result, = codegen(name_expr, "Rust", header=True, empty=False) + assert result[0] == "test.rs" + source = result[1] + version_str = "Code generated with SymPy %s" % sympy.__version__ + version_line = version_str.center(76).rstrip() + expected = ( + "/*\n" + " *%(version_line)s\n" + " *\n" + " * See http://www.sympy.org/ for more information.\n" + " *\n" + " * This file is part of 'project'\n" + " */\n" + "fn test(x: f64, y: f64, z: f64) -> f64 {\n" + " let out1 = z*(x + y);\n" + " out1\n" + "}\n" + ) % {'version_line': version_line} + assert source == expected + + +def test_simple_code_nameout(): + expr = Equality(z, (x + y)) + name_expr = ("test", expr) + result, = codegen(name_expr, "Rust", header=False, empty=False) + source = result[1] + expected = ( + "fn test(x: f64, y: f64) -> f64 {\n" + " let z = x + y;\n" + " z\n" + "}\n" + ) + assert source == expected + + +def test_numbersymbol(): + name_expr = ("test", pi**Catalan) + result, = codegen(name_expr, "Rust", header=False, empty=False) + source = result[1] + expected = ( + "fn test() -> f64 {\n" + " const Catalan: f64 = %s;\n" + " let out1 = PI.powf(Catalan);\n" + " out1\n" + "}\n" + ) % Catalan.evalf(17) + assert source == expected + + +@XFAIL +def test_numbersymbol_inline(): + # FIXME: how to pass inline to the RustCodePrinter? + name_expr = ("test", [pi**Catalan, EulerGamma]) + result, = codegen(name_expr, "Rust", header=False, + empty=False, inline=True) + source = result[1] + expected = ( + "fn test() -> (f64, f64) {\n" + " const Catalan: f64 = %s;\n" + " const EulerGamma: f64 = %s;\n" + " let out1 = PI.powf(Catalan);\n" + " let out2 = EulerGamma);\n" + " (out1, out2)\n" + "}\n" + ) % (Catalan.evalf(17), EulerGamma.evalf(17)) + assert source == expected + + +def test_argument_order(): + expr = x + y + routine = make_routine("test", expr, argument_sequence=[z, x, y], language="rust") + code_gen = RustCodeGen() + output = StringIO() + code_gen.dump_rs([routine], output, "test", header=False, empty=False) + source = output.getvalue() + expected = ( + "fn test(z: f64, x: f64, y: f64) -> f64 {\n" + " let out1 = x + y;\n" + " out1\n" + "}\n" + ) + assert source == expected + + +def test_multiple_results_rust(): + # Here the output order is the input order + expr1 = (x + y)*z + expr2 = (x - y)*z + name_expr = ("test", [expr1, expr2]) + result, = codegen(name_expr, "Rust", header=False, empty=False) + source = result[1] + expected = ( + "fn test(x: f64, y: f64, z: f64) -> (f64, f64) {\n" + " let out1 = z*(x + y);\n" + " let out2 = z*(x - y);\n" + " (out1, out2)\n" + "}\n" + ) + assert source == expected + + +def test_results_named_unordered(): + # Here output order is based on name_expr + A, B, C = symbols('A,B,C') + expr1 = Equality(C, (x + y)*z) + expr2 = Equality(A, (x - y)*z) + expr3 = Equality(B, 2*x) + name_expr = ("test", [expr1, expr2, expr3]) + result, = codegen(name_expr, "Rust", header=False, empty=False) + source = result[1] + expected = ( + "fn test(x: f64, y: f64, z: f64) -> (f64, f64, f64) {\n" + " let C = z*(x + y);\n" + " let A = z*(x - y);\n" + " let B = 2*x;\n" + " (C, A, B)\n" + "}\n" + ) + assert source == expected + + +def test_results_named_ordered(): + A, B, C = symbols('A,B,C') + expr1 = Equality(C, (x + y)*z) + expr2 = Equality(A, (x - y)*z) + expr3 = Equality(B, 2*x) + name_expr = ("test", [expr1, expr2, expr3]) + result = codegen(name_expr, "Rust", header=False, empty=False, + argument_sequence=(x, z, y)) + assert result[0][0] == "test.rs" + source = result[0][1] + expected = ( + "fn test(x: f64, z: f64, y: f64) -> (f64, f64, f64) {\n" + " let C = z*(x + y);\n" + " let A = z*(x - y);\n" + " let B = 2*x;\n" + " (C, A, B)\n" + "}\n" + ) + assert source == expected + + +def test_complicated_rs_codegen(): + from sympy.functions.elementary.trigonometric import (cos, sin, tan) + name_expr = ("testlong", + [ ((sin(x) + cos(y) + tan(z))**3).expand(), + cos(cos(cos(cos(cos(cos(cos(cos(x + y + z)))))))) + ]) + result = codegen(name_expr, "Rust", header=False, empty=False) + assert result[0][0] == "testlong.rs" + source = result[0][1] + expected = ( + "fn testlong(x: f64, y: f64, z: f64) -> (f64, f64) {\n" + " let out1 = x.sin().powi(3) + 3*x.sin().powi(2)*y.cos()" + " + 3*x.sin().powi(2)*z.tan() + 3*x.sin()*y.cos().powi(2)" + " + 6*x.sin()*y.cos()*z.tan() + 3*x.sin()*z.tan().powi(2)" + " + y.cos().powi(3) + 3*y.cos().powi(2)*z.tan()" + " + 3*y.cos()*z.tan().powi(2) + z.tan().powi(3);\n" + " let out2 = (x + y + z).cos().cos().cos().cos()" + ".cos().cos().cos().cos();\n" + " (out1, out2)\n" + "}\n" + ) + assert source == expected + + +def test_output_arg_mixed_unordered(): + # named outputs are alphabetical, unnamed output appear in the given order + from sympy.functions.elementary.trigonometric import (cos, sin) + a = symbols("a") + name_expr = ("foo", [cos(2*x), Equality(y, sin(x)), cos(x), Equality(a, sin(2*x))]) + result, = codegen(name_expr, "Rust", header=False, empty=False) + assert result[0] == "foo.rs" + source = result[1] + expected = ( + "fn foo(x: f64) -> (f64, f64, f64, f64) {\n" + " let out1 = (2*x).cos();\n" + " let y = x.sin();\n" + " let out3 = x.cos();\n" + " let a = (2*x).sin();\n" + " (out1, y, out3, a)\n" + "}\n" + ) + assert source == expected + + +def test_piecewise_(): + pw = Piecewise((0, x < -1), (x**2, x <= 1), (-x+2, x > 1), (1, True), evaluate=False) + name_expr = ("pwtest", pw) + result, = codegen(name_expr, "Rust", header=False, empty=False) + source = result[1] + expected = ( + "fn pwtest(x: f64) -> f64 {\n" + " let out1 = if (x < -1.0) {\n" + " 0\n" + " } else if (x <= 1.0) {\n" + " x.powi(2)\n" + " } else if (x > 1.0) {\n" + " 2 - x\n" + " } else {\n" + " 1\n" + " };\n" + " out1\n" + "}\n" + ) + assert source == expected + + +@XFAIL +def test_piecewise_inline(): + # FIXME: how to pass inline to the RustCodePrinter? + pw = Piecewise((0, x < -1), (x**2, x <= 1), (-x+2, x > 1), (1, True)) + name_expr = ("pwtest", pw) + result, = codegen(name_expr, "Rust", header=False, empty=False, + inline=True) + source = result[1] + expected = ( + "fn pwtest(x: f64) -> f64 {\n" + " let out1 = if (x < -1) { 0 } else if (x <= 1) { x.powi(2) }" + " else if (x > 1) { -x + 2 } else { 1 };\n" + " out1\n" + "}\n" + ) + assert source == expected + + +def test_multifcns_per_file(): + name_expr = [ ("foo", [2*x, 3*y]), ("bar", [y**2, 4*y]) ] + result = codegen(name_expr, "Rust", header=False, empty=False) + assert result[0][0] == "foo.rs" + source = result[0][1] + expected = ( + "fn foo(x: f64, y: f64) -> (f64, f64) {\n" + " let out1 = 2*x;\n" + " let out2 = 3*y;\n" + " (out1, out2)\n" + "}\n" + "fn bar(y: f64) -> (f64, f64) {\n" + " let out1 = y.powi(2);\n" + " let out2 = 4*y;\n" + " (out1, out2)\n" + "}\n" + ) + assert source == expected + + +def test_multifcns_per_file_w_header(): + name_expr = [ ("foo", [2*x, 3*y]), ("bar", [y**2, 4*y]) ] + result = codegen(name_expr, "Rust", header=True, empty=False) + assert result[0][0] == "foo.rs" + source = result[0][1] + version_str = "Code generated with SymPy %s" % sympy.__version__ + version_line = version_str.center(76).rstrip() + expected = ( + "/*\n" + " *%(version_line)s\n" + " *\n" + " * See http://www.sympy.org/ for more information.\n" + " *\n" + " * This file is part of 'project'\n" + " */\n" + "fn foo(x: f64, y: f64) -> (f64, f64) {\n" + " let out1 = 2*x;\n" + " let out2 = 3*y;\n" + " (out1, out2)\n" + "}\n" + "fn bar(y: f64) -> (f64, f64) {\n" + " let out1 = y.powi(2);\n" + " let out2 = 4*y;\n" + " (out1, out2)\n" + "}\n" + ) % {'version_line': version_line} + assert source == expected + + +def test_filename_match_prefix(): + name_expr = [ ("foo", [2*x, 3*y]), ("bar", [y**2, 4*y]) ] + result, = codegen(name_expr, "Rust", prefix="baz", header=False, + empty=False) + assert result[0] == "baz.rs" + + +def test_InOutArgument(): + expr = Equality(x, x**2) + name_expr = ("mysqr", expr) + result, = codegen(name_expr, "Rust", header=False, empty=False) + source = result[1] + expected = ( + "fn mysqr(x: f64) -> f64 {\n" + " let x = x.powi(2);\n" + " x\n" + "}\n" + ) + assert source == expected + + +def test_InOutArgument_order(): + # can specify the order as (x, y) + expr = Equality(x, x**2 + y) + name_expr = ("test", expr) + result, = codegen(name_expr, "Rust", header=False, + empty=False, argument_sequence=(x,y)) + source = result[1] + expected = ( + "fn test(x: f64, y: f64) -> f64 {\n" + " let x = x.powi(2) + y;\n" + " x\n" + "}\n" + ) + assert source == expected + # make sure it gives (x, y) not (y, x) + expr = Equality(x, x**2 + y) + name_expr = ("test", expr) + result, = codegen(name_expr, "Rust", header=False, empty=False) + source = result[1] + expected = ( + "fn test(x: f64, y: f64) -> f64 {\n" + " let x = x.powi(2) + y;\n" + " x\n" + "}\n" + ) + assert source == expected + + +def test_not_supported(): + f = Function('f') + name_expr = ("test", [f(x).diff(x), S.ComplexInfinity]) + result, = codegen(name_expr, "Rust", header=False, empty=False) + source = result[1] + expected = ( + "fn test(x: f64) -> (f64, f64) {\n" + " // unsupported: Derivative(f(x), x)\n" + " // unsupported: zoo\n" + " let out1 = Derivative(f(x), x);\n" + " let out2 = zoo;\n" + " (out1, out2)\n" + "}\n" + ) + assert source == expected + + +def test_global_vars_rust(): + x, y, z, t = symbols("x y z t") + result = codegen(('f', x*y), "Rust", header=False, empty=False, + global_vars=(y,)) + source = result[0][1] + expected = ( + "fn f(x: f64) -> f64 {\n" + " let out1 = x*y;\n" + " out1\n" + "}\n" + ) + assert source == expected + + result = codegen(('f', x*y+z), "Rust", header=False, empty=False, + argument_sequence=(x, y), global_vars=(z, t)) + source = result[0][1] + expected = ( + "fn f(x: f64, y: f64) -> f64 {\n" + " let out1 = x*y + z;\n" + " out1\n" + "}\n" + ) + assert source == expected diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_decorator.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_decorator.py new file mode 100644 index 0000000000000000000000000000000000000000..b1870d4db8f719fdabfeab14120bfb3ce10131a9 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_decorator.py @@ -0,0 +1,129 @@ +from functools import wraps + +from sympy.utilities.decorator import threaded, xthreaded, memoize_property, deprecated +from sympy.testing.pytest import warns_deprecated_sympy + +from sympy.core.basic import Basic +from sympy.core.relational import Eq +from sympy.matrices.dense import Matrix + +from sympy.abc import x, y + + +def test_threaded(): + @threaded + def function(expr, *args): + return 2*expr + sum(args) + + assert function(Matrix([[x, y], [1, x]]), 1, 2) == \ + Matrix([[2*x + 3, 2*y + 3], [5, 2*x + 3]]) + + assert function(Eq(x, y), 1, 2) == Eq(2*x + 3, 2*y + 3) + + assert function([x, y], 1, 2) == [2*x + 3, 2*y + 3] + assert function((x, y), 1, 2) == (2*x + 3, 2*y + 3) + + assert function({x, y}, 1, 2) == {2*x + 3, 2*y + 3} + + @threaded + def function(expr, n): + return expr**n + + assert function(x + y, 2) == x**2 + y**2 + assert function(x, 2) == x**2 + + +def test_xthreaded(): + @xthreaded + def function(expr, n): + return expr**n + + assert function(x + y, 2) == (x + y)**2 + + +def test_wraps(): + def my_func(x): + """My function. """ + + my_func.is_my_func = True + + new_my_func = threaded(my_func) + new_my_func = wraps(my_func)(new_my_func) + + assert new_my_func.__name__ == 'my_func' + assert new_my_func.__doc__ == 'My function. ' + assert hasattr(new_my_func, 'is_my_func') + assert new_my_func.is_my_func is True + + +def test_memoize_property(): + class TestMemoize(Basic): + @memoize_property + def prop(self): + return Basic() + + member = TestMemoize() + obj1 = member.prop + obj2 = member.prop + assert obj1 is obj2 + +def test_deprecated(): + @deprecated('deprecated_function is deprecated', + deprecated_since_version='1.10', + # This is the target at the top of the file, which will never + # go away. + active_deprecations_target='active-deprecations') + def deprecated_function(x): + return x + + with warns_deprecated_sympy(): + assert deprecated_function(1) == 1 + + @deprecated('deprecated_class is deprecated', + deprecated_since_version='1.10', + active_deprecations_target='active-deprecations') + class deprecated_class: + pass + + with warns_deprecated_sympy(): + assert isinstance(deprecated_class(), deprecated_class) + + # Ensure the class decorator works even when the class never returns + # itself + @deprecated('deprecated_class_new is deprecated', + deprecated_since_version='1.10', + active_deprecations_target='active-deprecations') + class deprecated_class_new: + def __new__(cls, arg): + return arg + + with warns_deprecated_sympy(): + assert deprecated_class_new(1) == 1 + + @deprecated('deprecated_class_init is deprecated', + deprecated_since_version='1.10', + active_deprecations_target='active-deprecations') + class deprecated_class_init: + def __init__(self, arg): + self.arg = 1 + + with warns_deprecated_sympy(): + assert deprecated_class_init(1).arg == 1 + + @deprecated('deprecated_class_new_init is deprecated', + deprecated_since_version='1.10', + active_deprecations_target='active-deprecations') + class deprecated_class_new_init: + def __new__(cls, arg): + if arg == 0: + return arg + return object.__new__(cls) + + def __init__(self, arg): + self.arg = 1 + + with warns_deprecated_sympy(): + assert deprecated_class_new_init(0) == 0 + + with warns_deprecated_sympy(): + assert deprecated_class_new_init(1).arg == 1 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_deprecated.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_deprecated.py new file mode 100644 index 0000000000000000000000000000000000000000..dd4534ef1abc38ff368011b3ef9d11c497f3675b --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_deprecated.py @@ -0,0 +1,13 @@ +from sympy.testing.pytest import warns_deprecated_sympy + +# See https://github.com/sympy/sympy/pull/18095 + +def test_deprecated_utilities(): + with warns_deprecated_sympy(): + import sympy.utilities.pytest # noqa:F401 + with warns_deprecated_sympy(): + import sympy.utilities.runtests # noqa:F401 + with warns_deprecated_sympy(): + import sympy.utilities.randtest # noqa:F401 + with warns_deprecated_sympy(): + import sympy.utilities.tmpfiles # noqa:F401 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_enumerative.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_enumerative.py new file mode 100644 index 0000000000000000000000000000000000000000..357499d5fd400b14e2bcad067f3015b74b0e9003 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_enumerative.py @@ -0,0 +1,179 @@ +import string +from itertools import zip_longest + +from sympy.utilities.enumerative import ( + list_visitor, + MultisetPartitionTraverser, + multiset_partitions_taocp + ) +from sympy.utilities.iterables import _set_partitions + +# first some functions only useful as test scaffolding - these provide +# straightforward, but slow reference implementations against which to +# compare the real versions, and also a comparison to verify that +# different versions are giving identical results. + +def part_range_filter(partition_iterator, lb, ub): + """ + Filters (on the number of parts) a multiset partition enumeration + + Arguments + ========= + + lb, and ub are a range (in the Python slice sense) on the lpart + variable returned from a multiset partition enumeration. Recall + that lpart is 0-based (it points to the topmost part on the part + stack), so if you want to return parts of sizes 2,3,4,5 you would + use lb=1 and ub=5. + """ + for state in partition_iterator: + f, lpart, pstack = state + if lpart >= lb and lpart < ub: + yield state + +def multiset_partitions_baseline(multiplicities, components): + """Enumerates partitions of a multiset + + Parameters + ========== + + multiplicities + list of integer multiplicities of the components of the multiset. + + components + the components (elements) themselves + + Returns + ======= + + Set of partitions. Each partition is tuple of parts, and each + part is a tuple of components (with repeats to indicate + multiplicity) + + Notes + ===== + + Multiset partitions can be created as equivalence classes of set + partitions, and this function does just that. This approach is + slow and memory intensive compared to the more advanced algorithms + available, but the code is simple and easy to understand. Hence + this routine is strictly for testing -- to provide a + straightforward baseline against which to regress the production + versions. (This code is a simplified version of an earlier + production implementation.) + """ + + canon = [] # list of components with repeats + for ct, elem in zip(multiplicities, components): + canon.extend([elem]*ct) + + # accumulate the multiset partitions in a set to eliminate dups + cache = set() + n = len(canon) + for nc, q in _set_partitions(n): + rv = [[] for i in range(nc)] + for i in range(n): + rv[q[i]].append(canon[i]) + canonical = tuple( + sorted([tuple(p) for p in rv])) + cache.add(canonical) + return cache + + +def compare_multiset_w_baseline(multiplicities): + """ + Enumerates the partitions of multiset with AOCP algorithm and + baseline implementation, and compare the results. + + """ + letters = string.ascii_lowercase + bl_partitions = multiset_partitions_baseline(multiplicities, letters) + + # The partitions returned by the different algorithms may have + # their parts in different orders. Also, they generate partitions + # in different orders. Hence the sorting, and set comparison. + + aocp_partitions = set() + for state in multiset_partitions_taocp(multiplicities): + p1 = tuple(sorted( + [tuple(p) for p in list_visitor(state, letters)])) + aocp_partitions.add(p1) + + assert bl_partitions == aocp_partitions + +def compare_multiset_states(s1, s2): + """compare for equality two instances of multiset partition states + + This is useful for comparing different versions of the algorithm + to verify correctness.""" + # Comparison is physical, the only use of semantics is to ignore + # trash off the top of the stack. + f1, lpart1, pstack1 = s1 + f2, lpart2, pstack2 = s2 + + if (lpart1 == lpart2) and (f1[0:lpart1+1] == f2[0:lpart2+1]): + if pstack1[0:f1[lpart1+1]] == pstack2[0:f2[lpart2+1]]: + return True + return False + +def test_multiset_partitions_taocp(): + """Compares the output of multiset_partitions_taocp with a baseline + (set partition based) implementation.""" + + # Test cases should not be too large, since the baseline + # implementation is fairly slow. + multiplicities = [2,2] + compare_multiset_w_baseline(multiplicities) + + multiplicities = [4,3,1] + compare_multiset_w_baseline(multiplicities) + +def test_multiset_partitions_versions(): + """Compares Knuth-based versions of multiset_partitions""" + multiplicities = [5,2,2,1] + m = MultisetPartitionTraverser() + for s1, s2 in zip_longest(m.enum_all(multiplicities), + multiset_partitions_taocp(multiplicities)): + assert compare_multiset_states(s1, s2) + +def subrange_exercise(mult, lb, ub): + """Compare filter-based and more optimized subrange implementations + + Helper for tests, called with both small and larger multisets. + """ + m = MultisetPartitionTraverser() + assert m.count_partitions(mult) == \ + m.count_partitions_slow(mult) + + # Note - multiple traversals from the same + # MultisetPartitionTraverser object cannot execute at the same + # time, hence make several instances here. + ma = MultisetPartitionTraverser() + mc = MultisetPartitionTraverser() + md = MultisetPartitionTraverser() + + # Several paths to compute just the size two partitions + a_it = ma.enum_range(mult, lb, ub) + b_it = part_range_filter(multiset_partitions_taocp(mult), lb, ub) + c_it = part_range_filter(mc.enum_small(mult, ub), lb, sum(mult)) + d_it = part_range_filter(md.enum_large(mult, lb), 0, ub) + + for sa, sb, sc, sd in zip_longest(a_it, b_it, c_it, d_it): + assert compare_multiset_states(sa, sb) + assert compare_multiset_states(sa, sc) + assert compare_multiset_states(sa, sd) + +def test_subrange(): + # Quick, but doesn't hit some of the corner cases + mult = [4,4,2,1] # mississippi + lb = 1 + ub = 2 + subrange_exercise(mult, lb, ub) + + +def test_subrange_large(): + # takes a second or so, depending on cpu, Python version, etc. + mult = [6,3,2,1] + lb = 4 + ub = 7 + subrange_exercise(mult, lb, ub) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_exceptions.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_exceptions.py new file mode 100644 index 0000000000000000000000000000000000000000..d91e55e95d0ae4ac57cdd1989e0b3d39a55cd07d --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_exceptions.py @@ -0,0 +1,12 @@ +from sympy.testing.pytest import raises +from sympy.utilities.exceptions import sympy_deprecation_warning + +# Only test exceptions here because the other cases are tested in the +# warns_deprecated_sympy tests +def test_sympy_deprecation_warning(): + raises(TypeError, lambda: sympy_deprecation_warning('test', + deprecated_since_version=1.10, + active_deprecations_target='active-deprecations')) + + raises(ValueError, lambda: sympy_deprecation_warning('test', + deprecated_since_version="1.10", active_deprecations_target='(active-deprecations)=')) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_iterables.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_iterables.py new file mode 100644 index 0000000000000000000000000000000000000000..1003522bcd556c6f63e04de7da57b43498575fee --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_iterables.py @@ -0,0 +1,945 @@ +from textwrap import dedent +from itertools import islice, product + +from sympy.core.basic import Basic +from sympy.core.numbers import Integer +from sympy.core.sorting import ordered +from sympy.core.symbol import (Dummy, symbols) +from sympy.functions.combinatorial.factorials import factorial +from sympy.matrices.dense import Matrix +from sympy.combinatorics import RGS_enum, RGS_unrank, Permutation +from sympy.utilities.iterables import ( + _partition, _set_partitions, binary_partitions, bracelets, capture, + cartes, common_prefix, common_suffix, connected_components, dict_merge, + filter_symbols, flatten, generate_bell, generate_derangements, + generate_involutions, generate_oriented_forest, group, has_dups, ibin, + iproduct, kbins, minlex, multiset, multiset_combinations, + multiset_partitions, multiset_permutations, necklaces, numbered_symbols, + partitions, permutations, postfixes, + prefixes, reshape, rotate_left, rotate_right, runs, sift, + strongly_connected_components, subsets, take, topological_sort, unflatten, + uniq, variations, ordered_partitions, rotations, is_palindromic, iterable, + NotIterable, multiset_derangements, signed_permutations, + sequence_partitions, sequence_partitions_empty) +from sympy.utilities.enumerative import ( + factoring_visitor, multiset_partitions_taocp ) + +from sympy.core.singleton import S +from sympy.testing.pytest import raises, warns_deprecated_sympy + +w, x, y, z = symbols('w,x,y,z') + + +def test_deprecated_iterables(): + from sympy.utilities.iterables import default_sort_key, ordered + with warns_deprecated_sympy(): + assert list(ordered([y, x])) == [x, y] + with warns_deprecated_sympy(): + assert sorted([y, x], key=default_sort_key) == [x, y] + + +def test_is_palindromic(): + assert is_palindromic('') + assert is_palindromic('x') + assert is_palindromic('xx') + assert is_palindromic('xyx') + assert not is_palindromic('xy') + assert not is_palindromic('xyzx') + assert is_palindromic('xxyzzyx', 1) + assert not is_palindromic('xxyzzyx', 2) + assert is_palindromic('xxyzzyx', 2, -1) + assert is_palindromic('xxyzzyx', 2, 6) + assert is_palindromic('xxyzyx', 1) + assert not is_palindromic('xxyzyx', 2) + assert is_palindromic('xxyzyx', 2, 2 + 3) + + +def test_flatten(): + assert flatten((1, (1,))) == [1, 1] + assert flatten((x, (x,))) == [x, x] + + ls = [[(-2, -1), (1, 2)], [(0, 0)]] + + assert flatten(ls, levels=0) == ls + assert flatten(ls, levels=1) == [(-2, -1), (1, 2), (0, 0)] + assert flatten(ls, levels=2) == [-2, -1, 1, 2, 0, 0] + assert flatten(ls, levels=3) == [-2, -1, 1, 2, 0, 0] + + raises(ValueError, lambda: flatten(ls, levels=-1)) + + class MyOp(Basic): + pass + + assert flatten([MyOp(x, y), z]) == [MyOp(x, y), z] + assert flatten([MyOp(x, y), z], cls=MyOp) == [x, y, z] + + assert flatten({1, 11, 2}) == list({1, 11, 2}) + + +def test_iproduct(): + assert list(iproduct()) == [()] + assert list(iproduct([])) == [] + assert list(iproduct([1,2,3])) == [(1,),(2,),(3,)] + assert sorted(iproduct([1, 2], [3, 4, 5])) == [ + (1,3),(1,4),(1,5),(2,3),(2,4),(2,5)] + assert sorted(iproduct([0,1],[0,1],[0,1])) == [ + (0,0,0),(0,0,1),(0,1,0),(0,1,1),(1,0,0),(1,0,1),(1,1,0),(1,1,1)] + assert iterable(iproduct(S.Integers)) is True + assert iterable(iproduct(S.Integers, S.Integers)) is True + assert (3,) in iproduct(S.Integers) + assert (4, 5) in iproduct(S.Integers, S.Integers) + assert (1, 2, 3) in iproduct(S.Integers, S.Integers, S.Integers) + triples = set(islice(iproduct(S.Integers, S.Integers, S.Integers), 1000)) + for n1, n2, n3 in triples: + assert isinstance(n1, Integer) + assert isinstance(n2, Integer) + assert isinstance(n3, Integer) + for t in set(product(*([range(-2, 3)]*3))): + assert t in iproduct(S.Integers, S.Integers, S.Integers) + + +def test_group(): + assert group([]) == [] + assert group([], multiple=False) == [] + + assert group([1]) == [[1]] + assert group([1], multiple=False) == [(1, 1)] + + assert group([1, 1]) == [[1, 1]] + assert group([1, 1], multiple=False) == [(1, 2)] + + assert group([1, 1, 1]) == [[1, 1, 1]] + assert group([1, 1, 1], multiple=False) == [(1, 3)] + + assert group([1, 2, 1]) == [[1], [2], [1]] + assert group([1, 2, 1], multiple=False) == [(1, 1), (2, 1), (1, 1)] + + assert group([1, 1, 2, 2, 2, 1, 3, 3]) == [[1, 1], [2, 2, 2], [1], [3, 3]] + assert group([1, 1, 2, 2, 2, 1, 3, 3], multiple=False) == [(1, 2), + (2, 3), (1, 1), (3, 2)] + + +def test_subsets(): + # combinations + assert list(subsets([1, 2, 3], 0)) == [()] + assert list(subsets([1, 2, 3], 1)) == [(1,), (2,), (3,)] + assert list(subsets([1, 2, 3], 2)) == [(1, 2), (1, 3), (2, 3)] + assert list(subsets([1, 2, 3], 3)) == [(1, 2, 3)] + l = list(range(4)) + assert list(subsets(l, 0, repetition=True)) == [()] + assert list(subsets(l, 1, repetition=True)) == [(0,), (1,), (2,), (3,)] + assert list(subsets(l, 2, repetition=True)) == [(0, 0), (0, 1), (0, 2), + (0, 3), (1, 1), (1, 2), + (1, 3), (2, 2), (2, 3), + (3, 3)] + assert list(subsets(l, 3, repetition=True)) == [(0, 0, 0), (0, 0, 1), + (0, 0, 2), (0, 0, 3), + (0, 1, 1), (0, 1, 2), + (0, 1, 3), (0, 2, 2), + (0, 2, 3), (0, 3, 3), + (1, 1, 1), (1, 1, 2), + (1, 1, 3), (1, 2, 2), + (1, 2, 3), (1, 3, 3), + (2, 2, 2), (2, 2, 3), + (2, 3, 3), (3, 3, 3)] + assert len(list(subsets(l, 4, repetition=True))) == 35 + + assert list(subsets(l[:2], 3, repetition=False)) == [] + assert list(subsets(l[:2], 3, repetition=True)) == [(0, 0, 0), + (0, 0, 1), + (0, 1, 1), + (1, 1, 1)] + assert list(subsets([1, 2], repetition=True)) == \ + [(), (1,), (2,), (1, 1), (1, 2), (2, 2)] + assert list(subsets([1, 2], repetition=False)) == \ + [(), (1,), (2,), (1, 2)] + assert list(subsets([1, 2, 3], 2)) == \ + [(1, 2), (1, 3), (2, 3)] + assert list(subsets([1, 2, 3], 2, repetition=True)) == \ + [(1, 1), (1, 2), (1, 3), (2, 2), (2, 3), (3, 3)] + + +def test_variations(): + # permutations + l = list(range(4)) + assert list(variations(l, 0, repetition=False)) == [()] + assert list(variations(l, 1, repetition=False)) == [(0,), (1,), (2,), (3,)] + assert list(variations(l, 2, repetition=False)) == [(0, 1), (0, 2), (0, 3), (1, 0), (1, 2), (1, 3), (2, 0), (2, 1), (2, 3), (3, 0), (3, 1), (3, 2)] + assert list(variations(l, 3, repetition=False)) == [(0, 1, 2), (0, 1, 3), (0, 2, 1), (0, 2, 3), (0, 3, 1), (0, 3, 2), (1, 0, 2), (1, 0, 3), (1, 2, 0), (1, 2, 3), (1, 3, 0), (1, 3, 2), (2, 0, 1), (2, 0, 3), (2, 1, 0), (2, 1, 3), (2, 3, 0), (2, 3, 1), (3, 0, 1), (3, 0, 2), (3, 1, 0), (3, 1, 2), (3, 2, 0), (3, 2, 1)] + assert list(variations(l, 0, repetition=True)) == [()] + assert list(variations(l, 1, repetition=True)) == [(0,), (1,), (2,), (3,)] + assert list(variations(l, 2, repetition=True)) == [(0, 0), (0, 1), (0, 2), + (0, 3), (1, 0), (1, 1), + (1, 2), (1, 3), (2, 0), + (2, 1), (2, 2), (2, 3), + (3, 0), (3, 1), (3, 2), + (3, 3)] + assert len(list(variations(l, 3, repetition=True))) == 64 + assert len(list(variations(l, 4, repetition=True))) == 256 + assert list(variations(l[:2], 3, repetition=False)) == [] + assert list(variations(l[:2], 3, repetition=True)) == [ + (0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1), + (1, 0, 0), (1, 0, 1), (1, 1, 0), (1, 1, 1) + ] + + +def test_cartes(): + assert list(cartes([1, 2], [3, 4, 5])) == \ + [(1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5)] + assert list(cartes()) == [()] + assert list(cartes('a')) == [('a',)] + assert list(cartes('a', repeat=2)) == [('a', 'a')] + assert list(cartes(list(range(2)))) == [(0,), (1,)] + + +def test_filter_symbols(): + s = numbered_symbols() + filtered = filter_symbols(s, symbols("x0 x2 x3")) + assert take(filtered, 3) == list(symbols("x1 x4 x5")) + + +def test_numbered_symbols(): + s = numbered_symbols(cls=Dummy) + assert isinstance(next(s), Dummy) + assert next(numbered_symbols('C', start=1, exclude=[symbols('C1')])) == \ + symbols('C2') + + +def test_sift(): + assert sift(list(range(5)), lambda _: _ % 2) == {1: [1, 3], 0: [0, 2, 4]} + assert sift([x, y], lambda _: _.has(x)) == {False: [y], True: [x]} + assert sift([S.One], lambda _: _.has(x)) == {False: [1]} + assert sift([0, 1, 2, 3], lambda x: x % 2, binary=True) == ( + [1, 3], [0, 2]) + assert sift([0, 1, 2, 3], lambda x: x % 3 == 1, binary=True) == ( + [1], [0, 2, 3]) + raises(ValueError, lambda: + sift([0, 1, 2, 3], lambda x: x % 3, binary=True)) + + +def test_take(): + X = numbered_symbols() + + assert take(X, 5) == list(symbols('x0:5')) + assert take(X, 5) == list(symbols('x5:10')) + + assert take([1, 2, 3, 4, 5], 5) == [1, 2, 3, 4, 5] + + +def test_dict_merge(): + assert dict_merge({}, {1: x, y: z}) == {1: x, y: z} + assert dict_merge({1: x, y: z}, {}) == {1: x, y: z} + + assert dict_merge({2: z}, {1: x, y: z}) == {1: x, 2: z, y: z} + assert dict_merge({1: x, y: z}, {2: z}) == {1: x, 2: z, y: z} + + assert dict_merge({1: y, 2: z}, {1: x, y: z}) == {1: x, 2: z, y: z} + assert dict_merge({1: x, y: z}, {1: y, 2: z}) == {1: y, 2: z, y: z} + + +def test_prefixes(): + assert list(prefixes([])) == [] + assert list(prefixes([1])) == [[1]] + assert list(prefixes([1, 2])) == [[1], [1, 2]] + + assert list(prefixes([1, 2, 3, 4, 5])) == \ + [[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5]] + + +def test_postfixes(): + assert list(postfixes([])) == [] + assert list(postfixes([1])) == [[1]] + assert list(postfixes([1, 2])) == [[2], [1, 2]] + + assert list(postfixes([1, 2, 3, 4, 5])) == \ + [[5], [4, 5], [3, 4, 5], [2, 3, 4, 5], [1, 2, 3, 4, 5]] + + +def test_topological_sort(): + V = [2, 3, 5, 7, 8, 9, 10, 11] + E = [(7, 11), (7, 8), (5, 11), + (3, 8), (3, 10), (11, 2), + (11, 9), (11, 10), (8, 9)] + + assert topological_sort((V, E)) == [3, 5, 7, 8, 11, 2, 9, 10] + assert topological_sort((V, E), key=lambda v: -v) == \ + [7, 5, 11, 3, 10, 8, 9, 2] + + raises(ValueError, lambda: topological_sort((V, E + [(10, 7)]))) + + +def test_strongly_connected_components(): + assert strongly_connected_components(([], [])) == [] + assert strongly_connected_components(([1, 2, 3], [])) == [[1], [2], [3]] + + V = [1, 2, 3] + E = [(1, 2), (1, 3), (2, 1), (2, 3), (3, 1)] + assert strongly_connected_components((V, E)) == [[1, 2, 3]] + + V = [1, 2, 3, 4] + E = [(1, 2), (2, 3), (3, 2), (3, 4)] + assert strongly_connected_components((V, E)) == [[4], [2, 3], [1]] + + V = [1, 2, 3, 4] + E = [(1, 2), (2, 1), (3, 4), (4, 3)] + assert strongly_connected_components((V, E)) == [[1, 2], [3, 4]] + + +def test_connected_components(): + assert connected_components(([], [])) == [] + assert connected_components(([1, 2, 3], [])) == [[1], [2], [3]] + + V = [1, 2, 3] + E = [(1, 2), (1, 3), (2, 1), (2, 3), (3, 1)] + assert connected_components((V, E)) == [[1, 2, 3]] + + V = [1, 2, 3, 4] + E = [(1, 2), (2, 3), (3, 2), (3, 4)] + assert connected_components((V, E)) == [[1, 2, 3, 4]] + + V = [1, 2, 3, 4] + E = [(1, 2), (3, 4)] + assert connected_components((V, E)) == [[1, 2], [3, 4]] + + +def test_rotate(): + A = [0, 1, 2, 3, 4] + + assert rotate_left(A, 2) == [2, 3, 4, 0, 1] + assert rotate_right(A, 1) == [4, 0, 1, 2, 3] + A = [] + B = rotate_right(A, 1) + assert B == [] + B.append(1) + assert A == [] + B = rotate_left(A, 1) + assert B == [] + B.append(1) + assert A == [] + + +def test_multiset_partitions(): + A = [0, 1, 2, 3, 4] + + assert list(multiset_partitions(A, 5)) == [[[0], [1], [2], [3], [4]]] + assert len(list(multiset_partitions(A, 4))) == 10 + assert len(list(multiset_partitions(A, 3))) == 25 + + assert list(multiset_partitions([1, 1, 1, 2, 2], 2)) == [ + [[1, 1, 1, 2], [2]], [[1, 1, 1], [2, 2]], [[1, 1, 2, 2], [1]], + [[1, 1, 2], [1, 2]], [[1, 1], [1, 2, 2]]] + + assert list(multiset_partitions([1, 1, 2, 2], 2)) == [ + [[1, 1, 2], [2]], [[1, 1], [2, 2]], [[1, 2, 2], [1]], + [[1, 2], [1, 2]]] + + assert list(multiset_partitions([1, 2, 3, 4], 2)) == [ + [[1, 2, 3], [4]], [[1, 2, 4], [3]], [[1, 2], [3, 4]], + [[1, 3, 4], [2]], [[1, 3], [2, 4]], [[1, 4], [2, 3]], + [[1], [2, 3, 4]]] + + assert list(multiset_partitions([1, 2, 2], 2)) == [ + [[1, 2], [2]], [[1], [2, 2]]] + + assert list(multiset_partitions(3)) == [ + [[0, 1, 2]], [[0, 1], [2]], [[0, 2], [1]], [[0], [1, 2]], + [[0], [1], [2]]] + assert list(multiset_partitions(3, 2)) == [ + [[0, 1], [2]], [[0, 2], [1]], [[0], [1, 2]]] + assert list(multiset_partitions([1] * 3, 2)) == [[[1], [1, 1]]] + assert list(multiset_partitions([1] * 3)) == [ + [[1, 1, 1]], [[1], [1, 1]], [[1], [1], [1]]] + a = [3, 2, 1] + assert list(multiset_partitions(a)) == \ + list(multiset_partitions(sorted(a))) + assert list(multiset_partitions(a, 5)) == [] + assert list(multiset_partitions(a, 1)) == [[[1, 2, 3]]] + assert list(multiset_partitions(a + [4], 5)) == [] + assert list(multiset_partitions(a + [4], 1)) == [[[1, 2, 3, 4]]] + assert list(multiset_partitions(2, 5)) == [] + assert list(multiset_partitions(2, 1)) == [[[0, 1]]] + assert list(multiset_partitions('a')) == [[['a']]] + assert list(multiset_partitions('a', 2)) == [] + assert list(multiset_partitions('ab')) == [[['a', 'b']], [['a'], ['b']]] + assert list(multiset_partitions('ab', 1)) == [[['a', 'b']]] + assert list(multiset_partitions('aaa', 1)) == [['aaa']] + assert list(multiset_partitions([1, 1], 1)) == [[[1, 1]]] + ans = [('mpsyy',), ('mpsy', 'y'), ('mps', 'yy'), ('mps', 'y', 'y'), + ('mpyy', 's'), ('mpy', 'sy'), ('mpy', 's', 'y'), ('mp', 'syy'), + ('mp', 'sy', 'y'), ('mp', 's', 'yy'), ('mp', 's', 'y', 'y'), + ('msyy', 'p'), ('msy', 'py'), ('msy', 'p', 'y'), ('ms', 'pyy'), + ('ms', 'py', 'y'), ('ms', 'p', 'yy'), ('ms', 'p', 'y', 'y'), + ('myy', 'ps'), ('myy', 'p', 's'), ('my', 'psy'), ('my', 'ps', 'y'), + ('my', 'py', 's'), ('my', 'p', 'sy'), ('my', 'p', 's', 'y'), + ('m', 'psyy'), ('m', 'psy', 'y'), ('m', 'ps', 'yy'), + ('m', 'ps', 'y', 'y'), ('m', 'pyy', 's'), ('m', 'py', 'sy'), + ('m', 'py', 's', 'y'), ('m', 'p', 'syy'), + ('m', 'p', 'sy', 'y'), ('m', 'p', 's', 'yy'), + ('m', 'p', 's', 'y', 'y')] + assert [tuple("".join(part) for part in p) + for p in multiset_partitions('sympy')] == ans + factorings = [[24], [8, 3], [12, 2], [4, 6], [4, 2, 3], + [6, 2, 2], [2, 2, 2, 3]] + assert [factoring_visitor(p, [2,3]) for + p in multiset_partitions_taocp([3, 1])] == factorings + + +def test_multiset_combinations(): + ans = ['iii', 'iim', 'iip', 'iis', 'imp', 'ims', 'ipp', 'ips', + 'iss', 'mpp', 'mps', 'mss', 'pps', 'pss', 'sss'] + assert [''.join(i) for i in + list(multiset_combinations('mississippi', 3))] == ans + M = multiset('mississippi') + assert [''.join(i) for i in + list(multiset_combinations(M, 3))] == ans + assert [''.join(i) for i in multiset_combinations(M, 30)] == [] + assert list(multiset_combinations([[1], [2, 3]], 2)) == [[[1], [2, 3]]] + assert len(list(multiset_combinations('a', 3))) == 0 + assert len(list(multiset_combinations('a', 0))) == 1 + assert list(multiset_combinations('abc', 1)) == [['a'], ['b'], ['c']] + raises(ValueError, lambda: list(multiset_combinations({0: 3, 1: -1}, 2))) + + +def test_multiset_permutations(): + ans = ['abby', 'abyb', 'aybb', 'baby', 'bayb', 'bbay', 'bbya', 'byab', + 'byba', 'yabb', 'ybab', 'ybba'] + assert [''.join(i) for i in multiset_permutations('baby')] == ans + assert [''.join(i) for i in multiset_permutations(multiset('baby'))] == ans + assert list(multiset_permutations([0, 0, 0], 2)) == [[0, 0]] + assert list(multiset_permutations([0, 2, 1], 2)) == [ + [0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1]] + assert len(list(multiset_permutations('a', 0))) == 1 + assert len(list(multiset_permutations('a', 3))) == 0 + for nul in ([], {}, ''): + assert list(multiset_permutations(nul)) == [[]] + assert list(multiset_permutations(nul, 0)) == [[]] + # impossible requests give no result + assert list(multiset_permutations(nul, 1)) == [] + assert list(multiset_permutations(nul, -1)) == [] + + def test(): + for i in range(1, 7): + print(i) + for p in multiset_permutations([0, 0, 1, 0, 1], i): + print(p) + assert capture(lambda: test()) == dedent('''\ + 1 + [0] + [1] + 2 + [0, 0] + [0, 1] + [1, 0] + [1, 1] + 3 + [0, 0, 0] + [0, 0, 1] + [0, 1, 0] + [0, 1, 1] + [1, 0, 0] + [1, 0, 1] + [1, 1, 0] + 4 + [0, 0, 0, 1] + [0, 0, 1, 0] + [0, 0, 1, 1] + [0, 1, 0, 0] + [0, 1, 0, 1] + [0, 1, 1, 0] + [1, 0, 0, 0] + [1, 0, 0, 1] + [1, 0, 1, 0] + [1, 1, 0, 0] + 5 + [0, 0, 0, 1, 1] + [0, 0, 1, 0, 1] + [0, 0, 1, 1, 0] + [0, 1, 0, 0, 1] + [0, 1, 0, 1, 0] + [0, 1, 1, 0, 0] + [1, 0, 0, 0, 1] + [1, 0, 0, 1, 0] + [1, 0, 1, 0, 0] + [1, 1, 0, 0, 0] + 6\n''') + raises(ValueError, lambda: list(multiset_permutations({0: 3, 1: -1}))) + + +def test_partitions(): + ans = [[{}], [(0, {})]] + for i in range(2): + assert list(partitions(0, size=i)) == ans[i] + assert list(partitions(1, 0, size=i)) == ans[i] + assert list(partitions(6, 2, 2, size=i)) == ans[i] + assert list(partitions(6, 2, None, size=i)) != ans[i] + assert list(partitions(6, None, 2, size=i)) != ans[i] + assert list(partitions(6, 2, 0, size=i)) == ans[i] + + assert list(partitions(6, k=2)) == [ + {2: 3}, {1: 2, 2: 2}, {1: 4, 2: 1}, {1: 6}] + + assert list(partitions(6, k=3)) == [ + {3: 2}, {1: 1, 2: 1, 3: 1}, {1: 3, 3: 1}, {2: 3}, {1: 2, 2: 2}, + {1: 4, 2: 1}, {1: 6}] + + assert list(partitions(8, k=4, m=3)) == [ + {4: 2}, {1: 1, 3: 1, 4: 1}, {2: 2, 4: 1}, {2: 1, 3: 2}] == [ + i for i in partitions(8, k=4, m=3) if all(k <= 4 for k in i) + and sum(i.values()) <=3] + + assert list(partitions(S(3), m=2)) == [ + {3: 1}, {1: 1, 2: 1}] + + assert list(partitions(4, k=3)) == [ + {1: 1, 3: 1}, {2: 2}, {1: 2, 2: 1}, {1: 4}] == [ + i for i in partitions(4) if all(k <= 3 for k in i)] + + + # Consistency check on output of _partitions and RGS_unrank. + # This provides a sanity test on both routines. Also verifies that + # the total number of partitions is the same in each case. + # (from pkrathmann2) + + for n in range(2, 6): + i = 0 + for m, q in _set_partitions(n): + assert q == RGS_unrank(i, n) + i += 1 + assert i == RGS_enum(n) + + +def test_binary_partitions(): + assert [i[:] for i in binary_partitions(10)] == [[8, 2], [8, 1, 1], + [4, 4, 2], [4, 4, 1, 1], [4, 2, 2, 2], [4, 2, 2, 1, 1], + [4, 2, 1, 1, 1, 1], [4, 1, 1, 1, 1, 1, 1], [2, 2, 2, 2, 2], + [2, 2, 2, 2, 1, 1], [2, 2, 2, 1, 1, 1, 1], [2, 2, 1, 1, 1, 1, 1, 1], + [2, 1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]] + + assert len([j[:] for j in binary_partitions(16)]) == 36 + + +def test_bell_perm(): + assert [len(set(generate_bell(i))) for i in range(1, 7)] == [ + factorial(i) for i in range(1, 7)] + assert list(generate_bell(3)) == [ + (0, 1, 2), (0, 2, 1), (2, 0, 1), (2, 1, 0), (1, 2, 0), (1, 0, 2)] + # generate_bell and trotterjohnson are advertised to return the same + # permutations; this is not technically necessary so this test could + # be removed + for n in range(1, 5): + p = Permutation(range(n)) + b = generate_bell(n) + for bi in b: + assert bi == tuple(p.array_form) + p = p.next_trotterjohnson() + raises(ValueError, lambda: list(generate_bell(0))) # XXX is this consistent with other permutation algorithms? + + +def test_involutions(): + lengths = [1, 2, 4, 10, 26, 76] + for n, N in enumerate(lengths): + i = list(generate_involutions(n + 1)) + assert len(i) == N + assert len({Permutation(j)**2 for j in i}) == 1 + + +def test_derangements(): + assert len(list(generate_derangements(list(range(6))))) == 265 + assert ''.join(''.join(i) for i in generate_derangements('abcde')) == ( + 'badecbaecdbcaedbcdeabceadbdaecbdeacbdecabeacdbedacbedcacabedcadebcaebd' + 'cdaebcdbeacdeabcdebaceabdcebadcedabcedbadabecdaebcdaecbdcaebdcbeadceab' + 'dcebadeabcdeacbdebacdebcaeabcdeadbceadcbecabdecbadecdabecdbaedabcedacb' + 'edbacedbca') + assert list(generate_derangements([0, 1, 2, 3])) == [ + [1, 0, 3, 2], [1, 2, 3, 0], [1, 3, 0, 2], [2, 0, 3, 1], + [2, 3, 0, 1], [2, 3, 1, 0], [3, 0, 1, 2], [3, 2, 0, 1], [3, 2, 1, 0]] + assert list(generate_derangements([0, 1, 2, 2])) == [ + [2, 2, 0, 1], [2, 2, 1, 0]] + assert list(generate_derangements('ba')) == [list('ab')] + # multiset_derangements + D = multiset_derangements + assert list(D('abb')) == [] + assert [''.join(i) for i in D('ab')] == ['ba'] + assert [''.join(i) for i in D('abc')] == ['bca', 'cab'] + assert [''.join(i) for i in D('aabb')] == ['bbaa'] + assert [''.join(i) for i in D('aabbcccc')] == [ + 'ccccaabb', 'ccccabab', 'ccccabba', 'ccccbaab', 'ccccbaba', + 'ccccbbaa'] + assert [''.join(i) for i in D('aabbccc')] == [ + 'cccabba', 'cccabab', 'cccaabb', 'ccacbba', 'ccacbab', + 'ccacabb', 'cbccbaa', 'cbccaba', 'cbccaab', 'bcccbaa', + 'bcccaba', 'bcccaab'] + assert [''.join(i) for i in D('books')] == ['kbsoo', 'ksboo', + 'sbkoo', 'skboo', 'oksbo', 'oskbo', 'okbso', 'obkso', 'oskob', + 'oksob', 'osbok', 'obsok'] + assert list(generate_derangements([[3], [2], [2], [1]])) == [ + [[2], [1], [3], [2]], [[2], [3], [1], [2]]] + + +def test_necklaces(): + def count(n, k, f): + return len(list(necklaces(n, k, f))) + m = [] + for i in range(1, 8): + m.append(( + i, count(i, 2, 0), count(i, 2, 1), count(i, 3, 1))) + assert Matrix(m) == Matrix([ + [1, 2, 2, 3], + [2, 3, 3, 6], + [3, 4, 4, 10], + [4, 6, 6, 21], + [5, 8, 8, 39], + [6, 14, 13, 92], + [7, 20, 18, 198]]) + + +def test_bracelets(): + bc = list(bracelets(2, 4)) + assert Matrix(bc) == Matrix([ + [0, 0], + [0, 1], + [0, 2], + [0, 3], + [1, 1], + [1, 2], + [1, 3], + [2, 2], + [2, 3], + [3, 3] + ]) + bc = list(bracelets(4, 2)) + assert Matrix(bc) == Matrix([ + [0, 0, 0, 0], + [0, 0, 0, 1], + [0, 0, 1, 1], + [0, 1, 0, 1], + [0, 1, 1, 1], + [1, 1, 1, 1] + ]) + + +def test_generate_oriented_forest(): + assert list(generate_oriented_forest(5)) == [[0, 1, 2, 3, 4], + [0, 1, 2, 3, 3], [0, 1, 2, 3, 2], [0, 1, 2, 3, 1], [0, 1, 2, 3, 0], + [0, 1, 2, 2, 2], [0, 1, 2, 2, 1], [0, 1, 2, 2, 0], [0, 1, 2, 1, 2], + [0, 1, 2, 1, 1], [0, 1, 2, 1, 0], [0, 1, 2, 0, 1], [0, 1, 2, 0, 0], + [0, 1, 1, 1, 1], [0, 1, 1, 1, 0], [0, 1, 1, 0, 1], [0, 1, 1, 0, 0], + [0, 1, 0, 1, 0], [0, 1, 0, 0, 0], [0, 0, 0, 0, 0]] + assert len(list(generate_oriented_forest(10))) == 1842 + + +def test_unflatten(): + r = list(range(10)) + assert unflatten(r) == list(zip(r[::2], r[1::2])) + assert unflatten(r, 5) == [tuple(r[:5]), tuple(r[5:])] + raises(ValueError, lambda: unflatten(list(range(10)), 3)) + raises(ValueError, lambda: unflatten(list(range(10)), -2)) + + +def test_common_prefix_suffix(): + assert common_prefix([], [1]) == [] + assert common_prefix(list(range(3))) == [0, 1, 2] + assert common_prefix(list(range(3)), list(range(4))) == [0, 1, 2] + assert common_prefix([1, 2, 3], [1, 2, 5]) == [1, 2] + assert common_prefix([1, 2, 3], [1, 3, 5]) == [1] + + assert common_suffix([], [1]) == [] + assert common_suffix(list(range(3))) == [0, 1, 2] + assert common_suffix(list(range(3)), list(range(3))) == [0, 1, 2] + assert common_suffix(list(range(3)), list(range(4))) == [] + assert common_suffix([1, 2, 3], [9, 2, 3]) == [2, 3] + assert common_suffix([1, 2, 3], [9, 7, 3]) == [3] + + +def test_minlex(): + assert minlex([1, 2, 0]) == (0, 1, 2) + assert minlex((1, 2, 0)) == (0, 1, 2) + assert minlex((1, 0, 2)) == (0, 2, 1) + assert minlex((1, 0, 2), directed=False) == (0, 1, 2) + assert minlex('aba') == 'aab' + assert minlex(('bb', 'aaa', 'c', 'a'), key=len) == ('c', 'a', 'bb', 'aaa') + + +def test_ordered(): + assert list(ordered((x, y), hash, default=False)) in [[x, y], [y, x]] + assert list(ordered((x, y), hash, default=False)) == \ + list(ordered((y, x), hash, default=False)) + assert list(ordered((x, y))) == [x, y] + + seq, keys = [[[1, 2, 1], [0, 3, 1], [1, 1, 3], [2], [1]], + (lambda x: len(x), lambda x: sum(x))] + assert list(ordered(seq, keys, default=False, warn=False)) == \ + [[1], [2], [1, 2, 1], [0, 3, 1], [1, 1, 3]] + raises(ValueError, lambda: + list(ordered(seq, keys, default=False, warn=True))) + + +def test_runs(): + assert runs([]) == [] + assert runs([1]) == [[1]] + assert runs([1, 1]) == [[1], [1]] + assert runs([1, 1, 2]) == [[1], [1, 2]] + assert runs([1, 2, 1]) == [[1, 2], [1]] + assert runs([2, 1, 1]) == [[2], [1], [1]] + from operator import lt + assert runs([2, 1, 1], lt) == [[2, 1], [1]] + + +def test_reshape(): + seq = list(range(1, 9)) + assert reshape(seq, [4]) == \ + [[1, 2, 3, 4], [5, 6, 7, 8]] + assert reshape(seq, (4,)) == \ + [(1, 2, 3, 4), (5, 6, 7, 8)] + assert reshape(seq, (2, 2)) == \ + [(1, 2, 3, 4), (5, 6, 7, 8)] + assert reshape(seq, (2, [2])) == \ + [(1, 2, [3, 4]), (5, 6, [7, 8])] + assert reshape(seq, ((2,), [2])) == \ + [((1, 2), [3, 4]), ((5, 6), [7, 8])] + assert reshape(seq, (1, [2], 1)) == \ + [(1, [2, 3], 4), (5, [6, 7], 8)] + assert reshape(tuple(seq), ([[1], 1, (2,)],)) == \ + (([[1], 2, (3, 4)],), ([[5], 6, (7, 8)],)) + assert reshape(tuple(seq), ([1], 1, (2,))) == \ + (([1], 2, (3, 4)), ([5], 6, (7, 8))) + assert reshape(list(range(12)), [2, [3], {2}, (1, (3,), 1)]) == \ + [[0, 1, [2, 3, 4], {5, 6}, (7, (8, 9, 10), 11)]] + raises(ValueError, lambda: reshape([0, 1], [-1])) + raises(ValueError, lambda: reshape([0, 1], [3])) + + +def test_uniq(): + assert list(uniq(p for p in partitions(4))) == \ + [{4: 1}, {1: 1, 3: 1}, {2: 2}, {1: 2, 2: 1}, {1: 4}] + assert list(uniq(x % 2 for x in range(5))) == [0, 1] + assert list(uniq('a')) == ['a'] + assert list(uniq('ababc')) == list('abc') + assert list(uniq([[1], [2, 1], [1]])) == [[1], [2, 1]] + assert list(uniq(permutations(i for i in [[1], 2, 2]))) == \ + [([1], 2, 2), (2, [1], 2), (2, 2, [1])] + assert list(uniq([2, 3, 2, 4, [2], [1], [2], [3], [1]])) == \ + [2, 3, 4, [2], [1], [3]] + f = [1] + raises(RuntimeError, lambda: [f.remove(i) for i in uniq(f)]) + f = [[1]] + raises(RuntimeError, lambda: [f.remove(i) for i in uniq(f)]) + + +def test_kbins(): + assert len(list(kbins('1123', 2, ordered=1))) == 24 + assert len(list(kbins('1123', 2, ordered=11))) == 36 + assert len(list(kbins('1123', 2, ordered=10))) == 10 + assert len(list(kbins('1123', 2, ordered=0))) == 5 + assert len(list(kbins('1123', 2, ordered=None))) == 3 + + def test1(): + for orderedval in [None, 0, 1, 10, 11]: + print('ordered =', orderedval) + for p in kbins([0, 0, 1], 2, ordered=orderedval): + print(' ', p) + assert capture(lambda : test1()) == dedent('''\ + ordered = None + [[0], [0, 1]] + [[0, 0], [1]] + ordered = 0 + [[0, 0], [1]] + [[0, 1], [0]] + ordered = 1 + [[0], [0, 1]] + [[0], [1, 0]] + [[1], [0, 0]] + ordered = 10 + [[0, 0], [1]] + [[1], [0, 0]] + [[0, 1], [0]] + [[0], [0, 1]] + ordered = 11 + [[0], [0, 1]] + [[0, 0], [1]] + [[0], [1, 0]] + [[0, 1], [0]] + [[1], [0, 0]] + [[1, 0], [0]]\n''') + + def test2(): + for orderedval in [None, 0, 1, 10, 11]: + print('ordered =', orderedval) + for p in kbins(list(range(3)), 2, ordered=orderedval): + print(' ', p) + assert capture(lambda : test2()) == dedent('''\ + ordered = None + [[0], [1, 2]] + [[0, 1], [2]] + ordered = 0 + [[0, 1], [2]] + [[0, 2], [1]] + [[0], [1, 2]] + ordered = 1 + [[0], [1, 2]] + [[0], [2, 1]] + [[1], [0, 2]] + [[1], [2, 0]] + [[2], [0, 1]] + [[2], [1, 0]] + ordered = 10 + [[0, 1], [2]] + [[2], [0, 1]] + [[0, 2], [1]] + [[1], [0, 2]] + [[0], [1, 2]] + [[1, 2], [0]] + ordered = 11 + [[0], [1, 2]] + [[0, 1], [2]] + [[0], [2, 1]] + [[0, 2], [1]] + [[1], [0, 2]] + [[1, 0], [2]] + [[1], [2, 0]] + [[1, 2], [0]] + [[2], [0, 1]] + [[2, 0], [1]] + [[2], [1, 0]] + [[2, 1], [0]]\n''') + + +def test_has_dups(): + assert has_dups(set()) is False + assert has_dups(list(range(3))) is False + assert has_dups([1, 2, 1]) is True + assert has_dups([[1], [1]]) is True + assert has_dups([[1], [2]]) is False + + +def test__partition(): + assert _partition('abcde', [1, 0, 1, 2, 0]) == [ + ['b', 'e'], ['a', 'c'], ['d']] + assert _partition('abcde', [1, 0, 1, 2, 0], 3) == [ + ['b', 'e'], ['a', 'c'], ['d']] + output = (3, [1, 0, 1, 2, 0]) + assert _partition('abcde', *output) == [['b', 'e'], ['a', 'c'], ['d']] + + +def test_ordered_partitions(): + from sympy.functions.combinatorial.numbers import nT + f = ordered_partitions + assert list(f(0, 1)) == [[]] + assert list(f(1, 0)) == [[]] + for i in range(1, 7): + for j in [None] + list(range(1, i)): + assert ( + sum(1 for p in f(i, j, 1)) == + sum(1 for p in f(i, j, 0)) == + nT(i, j)) + + +def test_rotations(): + assert list(rotations('ab')) == [['a', 'b'], ['b', 'a']] + assert list(rotations(range(3))) == [[0, 1, 2], [1, 2, 0], [2, 0, 1]] + assert list(rotations(range(3), dir=-1)) == [[0, 1, 2], [2, 0, 1], [1, 2, 0]] + + +def test_ibin(): + assert ibin(3) == [1, 1] + assert ibin(3, 3) == [0, 1, 1] + assert ibin(3, str=True) == '11' + assert ibin(3, 3, str=True) == '011' + assert list(ibin(2, 'all')) == [(0, 0), (0, 1), (1, 0), (1, 1)] + assert list(ibin(2, '', str=True)) == ['00', '01', '10', '11'] + raises(ValueError, lambda: ibin(-.5)) + raises(ValueError, lambda: ibin(2, 1)) + + +def test_iterable(): + assert iterable(0) is False + assert iterable(1) is False + assert iterable(None) is False + + class Test1(NotIterable): + pass + + assert iterable(Test1()) is False + + class Test2(NotIterable): + _iterable = True + + assert iterable(Test2()) is True + + class Test3: + pass + + assert iterable(Test3()) is False + + class Test4: + _iterable = True + + assert iterable(Test4()) is True + + class Test5: + def __iter__(self): + yield 1 + + assert iterable(Test5()) is True + + class Test6(Test5): + _iterable = False + + assert iterable(Test6()) is False + + +def test_sequence_partitions(): + assert list(sequence_partitions([1], 1)) == [[[1]]] + assert list(sequence_partitions([1, 2], 1)) == [[[1, 2]]] + assert list(sequence_partitions([1, 2], 2)) == [[[1], [2]]] + assert list(sequence_partitions([1, 2, 3], 1)) == [[[1, 2, 3]]] + assert list(sequence_partitions([1, 2, 3], 2)) == \ + [[[1], [2, 3]], [[1, 2], [3]]] + assert list(sequence_partitions([1, 2, 3], 3)) == [[[1], [2], [3]]] + + # Exceptional cases + assert list(sequence_partitions([], 0)) == [] + assert list(sequence_partitions([], 1)) == [] + assert list(sequence_partitions([1, 2], 0)) == [] + assert list(sequence_partitions([1, 2], 3)) == [] + + +def test_sequence_partitions_empty(): + assert list(sequence_partitions_empty([], 1)) == [[[]]] + assert list(sequence_partitions_empty([], 2)) == [[[], []]] + assert list(sequence_partitions_empty([], 3)) == [[[], [], []]] + assert list(sequence_partitions_empty([1], 1)) == [[[1]]] + assert list(sequence_partitions_empty([1], 2)) == [[[], [1]], [[1], []]] + assert list(sequence_partitions_empty([1], 3)) == \ + [[[], [], [1]], [[], [1], []], [[1], [], []]] + assert list(sequence_partitions_empty([1, 2], 1)) == [[[1, 2]]] + assert list(sequence_partitions_empty([1, 2], 2)) == \ + [[[], [1, 2]], [[1], [2]], [[1, 2], []]] + assert list(sequence_partitions_empty([1, 2], 3)) == [ + [[], [], [1, 2]], [[], [1], [2]], [[], [1, 2], []], + [[1], [], [2]], [[1], [2], []], [[1, 2], [], []] + ] + assert list(sequence_partitions_empty([1, 2, 3], 1)) == [[[1, 2, 3]]] + assert list(sequence_partitions_empty([1, 2, 3], 2)) == \ + [[[], [1, 2, 3]], [[1], [2, 3]], [[1, 2], [3]], [[1, 2, 3], []]] + assert list(sequence_partitions_empty([1, 2, 3], 3)) == [ + [[], [], [1, 2, 3]], [[], [1], [2, 3]], + [[], [1, 2], [3]], [[], [1, 2, 3], []], + [[1], [], [2, 3]], [[1], [2], [3]], + [[1], [2, 3], []], [[1, 2], [], [3]], + [[1, 2], [3], []], [[1, 2, 3], [], []] + ] + + # Exceptional cases + assert list(sequence_partitions([], 0)) == [] + assert list(sequence_partitions([1], 0)) == [] + assert list(sequence_partitions([1, 2], 0)) == [] + + +def test_signed_permutations(): + ans = [(0, 1, 1), (0, -1, 1), (0, 1, -1), (0, -1, -1), + (1, 0, 1), (-1, 0, 1), (1, 0, -1), (-1, 0, -1), + (1, 1, 0), (-1, 1, 0), (1, -1, 0), (-1, -1, 0)] + assert list(signed_permutations((0, 1, 1))) == ans + assert list(signed_permutations((1, 0, 1))) == ans + assert list(signed_permutations((1, 1, 0))) == ans diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_lambdify.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_lambdify.py new file mode 100644 index 0000000000000000000000000000000000000000..b094c67d39f09c24bcb9abc1e755cb5328e143e7 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_lambdify.py @@ -0,0 +1,2263 @@ +from itertools import product +import math +import inspect +import linecache +import gc + +import mpmath +import cmath + +from sympy.testing.pytest import raises, warns_deprecated_sympy +from sympy.concrete.summations import Sum +from sympy.core.function import (Function, Lambda, diff) +from sympy.core.numbers import (E, Float, I, Rational, all_close, oo, pi) +from sympy.core.relational import Eq +from sympy.core.singleton import S +from sympy.core.symbol import (Dummy, symbols) +from sympy.functions.combinatorial.factorials import (RisingFactorial, factorial) +from sympy.functions.combinatorial.numbers import bernoulli, harmonic +from sympy.functions.elementary.complexes import Abs, sign +from sympy.functions.elementary.exponential import exp, log +from sympy.functions.elementary.hyperbolic import asinh,acosh,atanh +from sympy.functions.elementary.integers import floor +from sympy.functions.elementary.miscellaneous import (Max, Min, sqrt) +from sympy.functions.elementary.piecewise import Piecewise +from sympy.functions.elementary.trigonometric import (asin, acos, atan, cos, cot, sin, + sinc, tan) +from sympy.functions import sinh,cosh,tanh +from sympy.functions.special.bessel import (besseli, besselj, besselk, bessely, jn, yn) +from sympy.functions.special.beta_functions import (beta, betainc, betainc_regularized) +from sympy.functions.special.delta_functions import (Heaviside) +from sympy.functions.special.error_functions import (Ei, erf, erfc, fresnelc, fresnels, Si, Ci) +from sympy.functions.special.gamma_functions import (digamma, gamma, loggamma, polygamma) +from sympy.functions.special.zeta_functions import zeta +from sympy.integrals.integrals import Integral +from sympy.logic.boolalg import (And, false, ITE, Not, Or, true) +from sympy.matrices.expressions.dotproduct import DotProduct +from sympy.simplify.cse_main import cse +from sympy.tensor.array import derive_by_array, Array +from sympy.tensor.array.expressions import ArraySymbol +from sympy.tensor.indexed import IndexedBase, Idx +from sympy.utilities.lambdify import lambdify +from sympy.utilities.iterables import numbered_symbols +from sympy.vector import CoordSys3D +from sympy.core.expr import UnevaluatedExpr +from sympy.codegen.cfunctions import expm1, log1p, exp2, log2, log10, hypot, isnan, isinf +from sympy.codegen.numpy_nodes import logaddexp, logaddexp2, amin, amax, minimum, maximum +from sympy.codegen.scipy_nodes import cosm1, powm1 +from sympy.functions.elementary.complexes import re, im, arg +from sympy.functions.special.polynomials import \ + chebyshevt, chebyshevu, legendre, hermite, laguerre, gegenbauer, \ + assoc_legendre, assoc_laguerre, jacobi +from sympy.matrices import Matrix, MatrixSymbol, SparseMatrix +from sympy.printing.codeprinter import PrintMethodNotImplementedError +from sympy.printing.lambdarepr import LambdaPrinter +from sympy.printing.numpy import NumPyPrinter +from sympy.utilities.lambdify import implemented_function, lambdastr +from sympy.testing.pytest import skip +from sympy.utilities.decorator import conserve_mpmath_dps +from sympy.utilities.exceptions import ignore_warnings +from sympy.external import import_module +from sympy.functions.special.gamma_functions import uppergamma, lowergamma + + +import sympy + + +MutableDenseMatrix = Matrix + +numpy = import_module('numpy') +scipy = import_module('scipy', import_kwargs={'fromlist': ['sparse']}) +numexpr = import_module('numexpr') +tensorflow = import_module('tensorflow') +cupy = import_module('cupy') +jax = import_module('jax') +numba = import_module('numba') + +if tensorflow: + # Hide Tensorflow warnings + import os + os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' + +w, x, y, z = symbols('w,x,y,z') + +#================== Test different arguments ======================= + + +def test_no_args(): + f = lambdify([], 1) + raises(TypeError, lambda: f(-1)) + assert f() == 1 + + +def test_single_arg(): + f = lambdify(x, 2*x) + assert f(1) == 2 + + +def test_list_args(): + f = lambdify([x, y], x + y) + assert f(1, 2) == 3 + + +def test_nested_args(): + f1 = lambdify([[w, x]], [w, x]) + assert f1([91, 2]) == [91, 2] + raises(TypeError, lambda: f1(1, 2)) + + f2 = lambdify([(w, x), (y, z)], [w, x, y, z]) + assert f2((18, 12), (73, 4)) == [18, 12, 73, 4] + raises(TypeError, lambda: f2(3, 4)) + + f3 = lambdify([w, [[[x]], y], z], [w, x, y, z]) + assert f3(10, [[[52]], 31], 44) == [10, 52, 31, 44] + + +def test_str_args(): + f = lambdify('x,y,z', 'z,y,x') + assert f(3, 2, 1) == (1, 2, 3) + assert f(1.0, 2.0, 3.0) == (3.0, 2.0, 1.0) + # make sure correct number of args required + raises(TypeError, lambda: f(0)) + + +def test_own_namespace_1(): + myfunc = lambda x: 1 + f = lambdify(x, sin(x), {"sin": myfunc}) + assert f(0.1) == 1 + assert f(100) == 1 + + +def test_own_namespace_2(): + def myfunc(x): + return 1 + f = lambdify(x, sin(x), {'sin': myfunc}) + assert f(0.1) == 1 + assert f(100) == 1 + + +def test_own_module(): + f = lambdify(x, sin(x), math) + assert f(0) == 0.0 + + p, q, r = symbols("p q r", real=True) + ae = abs(exp(p+UnevaluatedExpr(q+r))) + f = lambdify([p, q, r], [ae, ae], modules=math) + results = f(1.0, 1e18, -1e18) + refvals = [math.exp(1.0)]*2 + for res, ref in zip(results, refvals): + assert abs((res-ref)/ref) < 1e-15 + + +def test_bad_args(): + # no vargs given + raises(TypeError, lambda: lambdify(1)) + # same with vector exprs + raises(TypeError, lambda: lambdify([1, 2])) + + +def test_atoms(): + # Non-Symbol atoms should not be pulled out from the expression namespace + f = lambdify(x, pi + x, {"pi": 3.14}) + assert f(0) == 3.14 + f = lambdify(x, I + x, {"I": 1j}) + assert f(1) == 1 + 1j + +#================== Test different modules ========================= + +# high precision output of sin(0.2*pi) is used to detect if precision is lost unwanted + + +@conserve_mpmath_dps +def test_sympy_lambda(): + mpmath.mp.dps = 50 + sin02 = mpmath.mpf("0.19866933079506121545941262711838975037020672954020") + f = lambdify(x, sin(x), "sympy") + assert f(x) == sin(x) + prec = 1e-15 + assert -prec < f(Rational(1, 5)).evalf() - Float(str(sin02)) < prec + # arctan is in numpy module and should not be available + # The arctan below gives NameError. What is this supposed to test? + # raises(NameError, lambda: lambdify(x, arctan(x), "sympy")) + + +@conserve_mpmath_dps +def test_math_lambda(): + mpmath.mp.dps = 50 + sin02 = mpmath.mpf("0.19866933079506121545941262711838975037020672954020") + f = lambdify(x, sin(x), "math") + prec = 1e-15 + assert -prec < f(0.2) - sin02 < prec + raises(TypeError, lambda: f(x)) + # if this succeeds, it can't be a Python math function + + +@conserve_mpmath_dps +def test_mpmath_lambda(): + mpmath.mp.dps = 50 + sin02 = mpmath.mpf("0.19866933079506121545941262711838975037020672954020") + f = lambdify(x, sin(x), "mpmath") + prec = 1e-49 # mpmath precision is around 50 decimal places + assert -prec < f(mpmath.mpf("0.2")) - sin02 < prec + raises(TypeError, lambda: f(x)) + # if this succeeds, it can't be a mpmath function + + ref2 = (mpmath.mpf("1e-30") + - mpmath.mpf("1e-45")/2 + + 5*mpmath.mpf("1e-60")/6 + - 3*mpmath.mpf("1e-75")/4 + + 33*mpmath.mpf("1e-90")/40 + ) + f2a = lambdify((x, y), x**y - 1, "mpmath") + f2b = lambdify((x, y), powm1(x, y), "mpmath") + f2c = lambdify((x,), expm1(x*log1p(x)), "mpmath") + ans2a = f2a(mpmath.mpf("1")+mpmath.mpf("1e-15"), mpmath.mpf("1e-15")) + ans2b = f2b(mpmath.mpf("1")+mpmath.mpf("1e-15"), mpmath.mpf("1e-15")) + ans2c = f2c(mpmath.mpf("1e-15")) + assert abs(ans2a - ref2) < 1e-51 + assert abs(ans2b - ref2) < 1e-67 + assert abs(ans2c - ref2) < 1e-80 + + +@conserve_mpmath_dps +def test_number_precision(): + mpmath.mp.dps = 50 + sin02 = mpmath.mpf("0.19866933079506121545941262711838975037020672954020") + f = lambdify(x, sin02, "mpmath") + prec = 1e-49 # mpmath precision is around 50 decimal places + assert -prec < f(0) - sin02 < prec + +@conserve_mpmath_dps +def test_mpmath_precision(): + mpmath.mp.dps = 100 + assert str(lambdify((), pi.evalf(100), 'mpmath')()) == str(pi.evalf(100)) + +#================== Test Translations ============================== +# We can only check if all translated functions are valid. It has to be checked +# by hand if they are complete. + + +def test_math_transl(): + from sympy.utilities.lambdify import MATH_TRANSLATIONS + for sym, mat in MATH_TRANSLATIONS.items(): + assert sym in sympy.__dict__ + assert mat in math.__dict__ + + +def test_mpmath_transl(): + from sympy.utilities.lambdify import MPMATH_TRANSLATIONS + for sym, mat in MPMATH_TRANSLATIONS.items(): + assert sym in sympy.__dict__ or sym == 'Matrix' + assert mat in mpmath.__dict__ + + +def test_numpy_transl(): + if not numpy: + skip("numpy not installed.") + + from sympy.utilities.lambdify import NUMPY_TRANSLATIONS + for sym, nump in NUMPY_TRANSLATIONS.items(): + assert sym in sympy.__dict__ + assert nump in numpy.__dict__ + + +def test_scipy_transl(): + if not scipy: + skip("scipy not installed.") + + from sympy.utilities.lambdify import SCIPY_TRANSLATIONS + for sym, scip in SCIPY_TRANSLATIONS.items(): + assert sym in sympy.__dict__ + assert scip in scipy.__dict__ or scip in scipy.special.__dict__ + + +def test_numpy_translation_abs(): + if not numpy: + skip("numpy not installed.") + + f = lambdify(x, Abs(x), "numpy") + assert f(-1) == 1 + assert f(1) == 1 + + +def test_numexpr_printer(): + if not numexpr: + skip("numexpr not installed.") + + # if translation/printing is done incorrectly then evaluating + # a lambdified numexpr expression will throw an exception + from sympy.printing.lambdarepr import NumExprPrinter + + blacklist = ('where', 'complex', 'contains') + arg_tuple = (x, y, z) # some functions take more than one argument + for sym in NumExprPrinter._numexpr_functions.keys(): + if sym in blacklist: + continue + ssym = S(sym) + if hasattr(ssym, '_nargs'): + nargs = ssym._nargs[0] + else: + nargs = 1 + args = arg_tuple[:nargs] + f = lambdify(args, ssym(*args), modules='numexpr') + assert f(*(1, )*nargs) is not None + + +def test_cmath_sqrt(): + f = lambdify(x, sqrt(x), "cmath") + assert f(0) == 0 + assert f(1) == 1 + assert f(4) == 2 + assert abs(f(2) - 1.414) < 0.001 + assert f(-1) == 1j + assert f(-4) == 2j + + +def test_cmath_log(): + f = lambdify(x, log(x), "cmath") + assert abs(f(1) - 0) < 1e-15 + assert abs(f(cmath.e) - 1) < 1e-15 + assert abs(f(-1) - cmath.log(-1)) < 1e-15 + + +def test_cmath_sinh(): + f = lambdify(x, sinh(x), "cmath") + assert abs(f(0) - cmath.sinh(0)) < 1e-15 + assert abs(f(pi) - cmath.sinh(pi)) < 1e-15 + assert abs(f(-pi) - cmath.sinh(-pi)) < 1e-15 + assert abs(f(1j) - cmath.sinh(1j)) < 1e-15 + + +def test_cmath_cosh(): + f = lambdify(x, cosh(x), "cmath") + assert abs(f(0) - cmath.cosh(0)) < 1e-15 + assert abs(f(pi) - cmath.cosh(pi)) < 1e-15 + assert abs(f(-pi) - cmath.cosh(-pi)) < 1e-15 + assert abs(f(1j) - cmath.cosh(1j)) < 1e-15 + + +def test_cmath_tanh(): + f = lambdify(x, tanh(x), "cmath") + assert abs(f(0) - cmath.tanh(0)) < 1e-15 + assert abs(f(pi) - cmath.tanh(pi)) < 1e-15 + assert abs(f(-pi) - cmath.tanh(-pi)) < 1e-15 + assert abs(f(1j) - cmath.tanh(1j)) < 1e-15 + + +def test_cmath_sin(): + f = lambdify(x, sin(x), "cmath") + assert abs(f(0) - cmath.sin(0)) < 1e-15 + assert abs(f(pi) - cmath.sin(pi)) < 1e-15 + assert abs(f(-pi) - cmath.sin(-pi)) < 1e-15 + assert abs(f(1j) - cmath.sin(1j)) < 1e-15 + + +def test_cmath_cos(): + f = lambdify(x, cos(x), "cmath") + assert abs(f(0) - cmath.cos(0)) < 1e-15 + assert abs(f(pi) - cmath.cos(pi)) < 1e-15 + assert abs(f(-pi) - cmath.cos(-pi)) < 1e-15 + assert abs(f(1j) - cmath.cos(1j)) < 1e-15 + + +def test_cmath_tan(): + f = lambdify(x, tan(x), "cmath") + assert abs(f(0) - cmath.tan(0)) < 1e-15 + assert abs(f(1j) - cmath.tan(1j)) < 1e-15 + + +def test_cmath_asin(): + f = lambdify(x, asin(x), "cmath") + assert abs(f(0) - cmath.asin(0)) < 1e-15 + assert abs(f(1) - cmath.asin(1)) < 1e-15 + assert abs(f(-1) - cmath.asin(-1)) < 1e-15 + assert abs(f(2) - cmath.asin(2)) < 1e-15 + assert abs(f(1j) - cmath.asin(1j)) < 1e-15 + + +def test_cmath_acos(): + f = lambdify(x, acos(x), "cmath") + assert abs(f(1) - cmath.acos(1)) < 1e-15 + assert abs(f(-1) - cmath.acos(-1)) < 1e-15 + assert abs(f(2) - cmath.acos(2)) < 1e-15 + assert abs(f(1j) - cmath.acos(1j)) < 1e-15 + + +def test_cmath_atan(): + f = lambdify(x, atan(x), "cmath") + assert abs(f(0) - cmath.atan(0)) < 1e-15 + assert abs(f(1) - cmath.atan(1)) < 1e-15 + assert abs(f(-1) - cmath.atan(-1)) < 1e-15 + assert abs(f(2) - cmath.atan(2)) < 1e-15 + assert abs(f(2j) - cmath.atan(2j)) < 1e-15 + + +def test_cmath_asinh(): + f = lambdify(x, asinh(x), "cmath") + assert abs(f(0) - cmath.asinh(0)) < 1e-15 + assert abs(f(1) - cmath.asinh(1)) < 1e-15 + assert abs(f(-1) - cmath.asinh(-1)) < 1e-15 + assert abs(f(2) - cmath.asinh(2)) < 1e-15 + assert abs(f(2j) - cmath.asinh(2j)) < 1e-15 + + +def test_cmath_acosh(): + f = lambdify(x, acosh(x), "cmath") + assert abs(f(1) - cmath.acosh(1)) < 1e-15 + assert abs(f(2) - cmath.acosh(2)) < 1e-15 + assert abs(f(-1) - cmath.acosh(-1)) < 1e-15 + assert abs(f(2j) - cmath.acosh(2j)) < 1e-15 + + +def test_cmath_atanh(): + f = lambdify(x, atanh(x), "cmath") + assert abs(f(0) - cmath.atanh(0)) < 1e-15 + assert abs(f(0.5) - cmath.atanh(0.5)) < 1e-15 + assert abs(f(-0.5) - cmath.atanh(-0.5)) < 1e-15 + assert abs(f(2) - cmath.atanh(2)) < 1e-15 + assert abs(f(-2) - cmath.atanh(-2)) < 1e-15 + assert abs(f(2j) - cmath.atanh(2j)) < 1e-15 + + +def test_cmath_complex_identities(): + # Define symbol + z = symbols('z') + + # Trigonometric identity using re(z) and im(z) + expr = cos(z) - cos(re(z)) * cosh(im(z)) + I * sin(re(z)) * sinh(im(z)) + func = lambdify([z], expr, modules=["cmath", "math"]) + hpi = math.pi / 2 + assert abs(func(hpi + 1j * hpi)) < 4e-16 + + # Euler's Formula: e^(i*z) = cos(z) + i*sin(z) + func = lambdify([z], exp(I * z) - (cos(z) + I * sin(z)), modules=["cmath", "math"]) + assert abs(func(hpi)) < 4e-16 + + # Exponential Identity: e^z = e^(Re(z)) * (cos(Im(z)) + i*sin(Im(z))) + func_exp = lambdify([z], exp(z) - exp(re(z)) * (cos(im(z)) + I * sin(im(z))), + modules=["cmath", "math"]) + assert abs(func_exp(hpi + 1j * hpi)) < 4e-16 + + # Complex Cosine Identity: cos(z) = cos(Re(z)) * cosh(Im(z)) - i*sin(Re(z)) * sinh(Im(z)) + func_cos = lambdify([z], cos(z) - (cos(re(z)) * cosh(im(z)) - I * sin(re(z)) * sinh(im(z))), + modules=["cmath", "math"]) + assert abs(func_cos(hpi + 1j * hpi)) < 4e-16 + + # Complex Sine Identity: sin(z) = sin(Re(z)) * cosh(Im(z)) + i*cos(Re(z)) * sinh(Im(z)) + func_sin = lambdify([z], sin(z) - (sin(re(z)) * cosh(im(z)) + I * cos(re(z)) * sinh(im(z))), + modules=["cmath", "math"]) + assert abs(func_sin(hpi + 1j * hpi)) < 4e-16 + + # Complex Hyperbolic Cosine Identity: cosh(z) = cosh(Re(z)) * cos(Im(z)) + i*sinh(Re(z)) * sin(Im(z)) + func_cosh_1 = lambdify([z], cosh(z) - (cosh(re(z)) * cos(im(z)) + I * sinh(re(z)) * sin(im(z))), + modules=["cmath", "math"]) + assert abs(func_cosh_1(hpi + 1j * hpi)) < 4e-16 + + # Complex Hyperbolic Sine Identity: sinh(z) = sinh(Re(z)) * cos(Im(z)) + i*cosh(Re(z)) * sin(Im(z)) + func_sinh = lambdify([z], sinh(z) - (sinh(re(z)) * cos(im(z)) + I * cosh(re(z)) * sin(im(z))), + modules=["cmath", "math"]) + assert abs(func_sinh(hpi + 1j * hpi)) < 4e-16 + + # cosh(z) = (e^z + e^(-z)) / 2 + func_cosh_2 = lambdify([z], cosh(z) - (exp(z) + exp(-z)) / 2, modules=["cmath", "math"]) + assert abs(func_cosh_2(hpi)) < 4e-16 + + # Additional expressions testing log and exp with real and imaginary parts + expr1 = log(re(z)) + log(im(z)) - log(re(z) * im(z)) + expr2 = exp(re(z)) * exp(im(z) * I) - exp(z) + expr3 = log(exp(re(z))) - re(z) + expr4 = exp(log(re(z))) - re(z) + expr5 = log(exp(re(z) + im(z))) - (re(z) + im(z)) + expr6 = exp(log(re(z) + im(z))) - (re(z) + im(z)) + func1 = lambdify([z], expr1, modules=["cmath", "math"]) + func2 = lambdify([z], expr2, modules=["cmath", "math"]) + func3 = lambdify([z], expr3, modules=["cmath", "math"]) + func4 = lambdify([z], expr4, modules=["cmath", "math"]) + func5 = lambdify([z], expr5, modules=["cmath", "math"]) + func6 = lambdify([z], expr6, modules=["cmath", "math"]) + test_value = 3 + 4j + assert abs(func1(test_value)) < 4e-16 + assert abs(func2(test_value)) < 4e-16 + assert abs(func3(test_value)) < 4e-16 + assert abs(func4(test_value)) < 4e-16 + assert abs(func5(test_value)) < 4e-16 + assert abs(func6(test_value)) < 4e-16 + + +def test_issue_9334(): + if not numexpr: + skip("numexpr not installed.") + if not numpy: + skip("numpy not installed.") + expr = S('b*a - sqrt(a**2)') + a, b = sorted(expr.free_symbols, key=lambda s: s.name) + func_numexpr = lambdify((a,b), expr, modules=[numexpr], dummify=False) + foo, bar = numpy.random.random((2, 4)) + func_numexpr(foo, bar) + + +def test_issue_12984(): + if not numexpr: + skip("numexpr not installed.") + func_numexpr = lambdify((x,y,z), Piecewise((y, x >= 0), (z, x > -1)), numexpr) + with ignore_warnings(RuntimeWarning): + assert func_numexpr(1, 24, 42) == 24 + assert str(func_numexpr(-1, 24, 42)) == 'nan' + + +def test_empty_modules(): + x, y = symbols('x y') + expr = -(x % y) + + no_modules = lambdify([x, y], expr) + empty_modules = lambdify([x, y], expr, modules=[]) + assert no_modules(3, 7) == empty_modules(3, 7) + assert no_modules(3, 7) == -3 + + +def test_exponentiation(): + f = lambdify(x, x**2) + assert f(-1) == 1 + assert f(0) == 0 + assert f(1) == 1 + assert f(-2) == 4 + assert f(2) == 4 + assert f(2.5) == 6.25 + + +def test_sqrt(): + f = lambdify(x, sqrt(x)) + assert f(0) == 0.0 + assert f(1) == 1.0 + assert f(4) == 2.0 + assert abs(f(2) - 1.414) < 0.001 + assert f(6.25) == 2.5 + + +def test_trig(): + f = lambdify([x], [cos(x), sin(x)], 'math') + d = f(pi) + prec = 1e-11 + assert -prec < d[0] + 1 < prec + assert -prec < d[1] < prec + d = f(3.14159) + prec = 1e-5 + assert -prec < d[0] + 1 < prec + assert -prec < d[1] < prec + + +def test_integral(): + if numpy and not scipy: + skip("scipy not installed.") + f = Lambda(x, exp(-x**2)) + l = lambdify(y, Integral(f(x), (x, y, oo))) + d = l(-oo) + assert 1.77245385 < d < 1.772453851 + + +def test_double_integral(): + if numpy and not scipy: + skip("scipy not installed.") + # example from http://mpmath.org/doc/current/calculus/integration.html + i = Integral(1/(1 - x**2*y**2), (x, 0, 1), (y, 0, z)) + l = lambdify([z], i) + d = l(1) + assert 1.23370055 < d < 1.233700551 + +def test_spherical_bessel(): + if numpy and not scipy: + skip("scipy not installed.") + test_point = 4.2 #randomly selected + x = symbols("x") + jtest = jn(2, x) + assert abs(lambdify(x,jtest)(test_point) - + jtest.subs(x,test_point).evalf()) < 1e-8 + ytest = yn(2, x) + assert abs(lambdify(x,ytest)(test_point) - + ytest.subs(x,test_point).evalf()) < 1e-8 + + +#================== Test vectors =================================== + + +def test_vector_simple(): + f = lambdify((x, y, z), (z, y, x)) + assert f(3, 2, 1) == (1, 2, 3) + assert f(1.0, 2.0, 3.0) == (3.0, 2.0, 1.0) + # make sure correct number of args required + raises(TypeError, lambda: f(0)) + + +def test_vector_discontinuous(): + f = lambdify(x, (-1/x, 1/x)) + raises(ZeroDivisionError, lambda: f(0)) + assert f(1) == (-1.0, 1.0) + assert f(2) == (-0.5, 0.5) + assert f(-2) == (0.5, -0.5) + + +def test_trig_symbolic(): + f = lambdify([x], [cos(x), sin(x)], 'math') + d = f(pi) + assert abs(d[0] + 1) < 0.0001 + assert abs(d[1] - 0) < 0.0001 + + +def test_trig_float(): + f = lambdify([x], [cos(x), sin(x)]) + d = f(3.14159) + assert abs(d[0] + 1) < 0.0001 + assert abs(d[1] - 0) < 0.0001 + + +def test_docs(): + f = lambdify(x, x**2) + assert f(2) == 4 + f = lambdify([x, y, z], [z, y, x]) + assert f(1, 2, 3) == [3, 2, 1] + f = lambdify(x, sqrt(x)) + assert f(4) == 2.0 + f = lambdify((x, y), sin(x*y)**2) + assert f(0, 5) == 0 + + +def test_math(): + f = lambdify((x, y), sin(x), modules="math") + assert f(0, 5) == 0 + + +def test_sin(): + f = lambdify(x, sin(x)**2) + assert isinstance(f(2), float) + f = lambdify(x, sin(x)**2, modules="math") + assert isinstance(f(2), float) + + +def test_matrix(): + A = Matrix([[x, x*y], [sin(z) + 4, x**z]]) + sol = Matrix([[1, 2], [sin(3) + 4, 1]]) + f = lambdify((x, y, z), A, modules="sympy") + assert f(1, 2, 3) == sol + f = lambdify((x, y, z), (A, [A]), modules="sympy") + assert f(1, 2, 3) == (sol, [sol]) + J = Matrix((x, x + y)).jacobian((x, y)) + v = Matrix((x, y)) + sol = Matrix([[1, 0], [1, 1]]) + assert lambdify(v, J, modules='sympy')(1, 2) == sol + assert lambdify(v.T, J, modules='sympy')(1, 2) == sol + + +def test_numpy_matrix(): + if not numpy: + skip("numpy not installed.") + A = Matrix([[x, x*y], [sin(z) + 4, x**z]]) + sol_arr = numpy.array([[1, 2], [numpy.sin(3) + 4, 1]]) + #Lambdify array first, to ensure return to array as default + f = lambdify((x, y, z), A, ['numpy']) + numpy.testing.assert_allclose(f(1, 2, 3), sol_arr) + #Check that the types are arrays and matrices + assert isinstance(f(1, 2, 3), numpy.ndarray) + + # gh-15071 + class dot(Function): + pass + x_dot_mtx = dot(x, Matrix([[2], [1], [0]])) + f_dot1 = lambdify(x, x_dot_mtx) + inp = numpy.zeros((17, 3)) + assert numpy.all(f_dot1(inp) == 0) + + strict_kw = {"allow_unknown_functions": False, "inline": True, "fully_qualified_modules": False} + p2 = NumPyPrinter(dict(user_functions={'dot': 'dot'}, **strict_kw)) + f_dot2 = lambdify(x, x_dot_mtx, printer=p2) + assert numpy.all(f_dot2(inp) == 0) + + p3 = NumPyPrinter(strict_kw) + # The line below should probably fail upon construction (before calling with "(inp)"): + raises(Exception, lambda: lambdify(x, x_dot_mtx, printer=p3)(inp)) + + +def test_numpy_transpose(): + if not numpy: + skip("numpy not installed.") + A = Matrix([[1, x], [0, 1]]) + f = lambdify((x), A.T, modules="numpy") + numpy.testing.assert_array_equal(f(2), numpy.array([[1, 0], [2, 1]])) + + +def test_numpy_dotproduct(): + if not numpy: + skip("numpy not installed") + A = Matrix([x, y, z]) + f1 = lambdify([x, y, z], DotProduct(A, A), modules='numpy') + f2 = lambdify([x, y, z], DotProduct(A, A.T), modules='numpy') + f3 = lambdify([x, y, z], DotProduct(A.T, A), modules='numpy') + f4 = lambdify([x, y, z], DotProduct(A, A.T), modules='numpy') + + assert f1(1, 2, 3) == \ + f2(1, 2, 3) == \ + f3(1, 2, 3) == \ + f4(1, 2, 3) == \ + numpy.array([14]) + + +def test_numpy_inverse(): + if not numpy: + skip("numpy not installed.") + A = Matrix([[1, x], [0, 1]]) + f = lambdify((x), A**-1, modules="numpy") + numpy.testing.assert_array_equal(f(2), numpy.array([[1, -2], [0, 1]])) + + +def test_numpy_old_matrix(): + if not numpy: + skip("numpy not installed.") + A = Matrix([[x, x*y], [sin(z) + 4, x**z]]) + sol_arr = numpy.array([[1, 2], [numpy.sin(3) + 4, 1]]) + f = lambdify((x, y, z), A, [{'ImmutableDenseMatrix': numpy.matrix}, 'numpy']) + with ignore_warnings(PendingDeprecationWarning): + numpy.testing.assert_allclose(f(1, 2, 3), sol_arr) + assert isinstance(f(1, 2, 3), numpy.matrix) + + +def test_scipy_sparse_matrix(): + if not scipy: + skip("scipy not installed.") + A = SparseMatrix([[x, 0], [0, y]]) + f = lambdify((x, y), A, modules="scipy") + B = f(1, 2) + assert isinstance(B, scipy.sparse.coo_matrix) + + +def test_python_div_zero_issue_11306(): + if not numpy: + skip("numpy not installed.") + p = Piecewise((1 / x, y < -1), (x, y < 1), (1 / x, True)) + f = lambdify([x, y], p, modules='numpy') + with numpy.errstate(divide='ignore'): + assert float(f(numpy.array(0), numpy.array(0.5))) == 0 + assert float(f(numpy.array(0), numpy.array(1))) == float('inf') + + +def test_issue9474(): + mods = [None, 'math'] + if numpy: + mods.append('numpy') + if mpmath: + mods.append('mpmath') + for mod in mods: + f = lambdify(x, S.One/x, modules=mod) + assert f(2) == 0.5 + f = lambdify(x, floor(S.One/x), modules=mod) + assert f(2) == 0 + + for absfunc, modules in product([Abs, abs], mods): + f = lambdify(x, absfunc(x), modules=modules) + assert f(-1) == 1 + assert f(1) == 1 + assert f(3+4j) == 5 + + +def test_issue_9871(): + if not numexpr: + skip("numexpr not installed.") + if not numpy: + skip("numpy not installed.") + + r = sqrt(x**2 + y**2) + expr = diff(1/r, x) + + xn = yn = numpy.linspace(1, 10, 16) + # expr(xn, xn) = -xn/(sqrt(2)*xn)^3 + fv_exact = -numpy.sqrt(2.)**-3 * xn**-2 + + fv_numpy = lambdify((x, y), expr, modules='numpy')(xn, yn) + fv_numexpr = lambdify((x, y), expr, modules='numexpr')(xn, yn) + numpy.testing.assert_allclose(fv_numpy, fv_exact, rtol=1e-10) + numpy.testing.assert_allclose(fv_numexpr, fv_exact, rtol=1e-10) + + +def test_numpy_piecewise(): + if not numpy: + skip("numpy not installed.") + pieces = Piecewise((x, x < 3), (x**2, x > 5), (0, True)) + f = lambdify(x, pieces, modules="numpy") + numpy.testing.assert_array_equal(f(numpy.arange(10)), + numpy.array([0, 1, 2, 0, 0, 0, 36, 49, 64, 81])) + # If we evaluate somewhere all conditions are False, we should get back NaN + nodef_func = lambdify(x, Piecewise((x, x > 0), (-x, x < 0))) + numpy.testing.assert_array_equal(nodef_func(numpy.array([-1, 0, 1])), + numpy.array([1, numpy.nan, 1])) + + +def test_numpy_logical_ops(): + if not numpy: + skip("numpy not installed.") + and_func = lambdify((x, y), And(x, y), modules="numpy") + and_func_3 = lambdify((x, y, z), And(x, y, z), modules="numpy") + or_func = lambdify((x, y), Or(x, y), modules="numpy") + or_func_3 = lambdify((x, y, z), Or(x, y, z), modules="numpy") + not_func = lambdify((x), Not(x), modules="numpy") + arr1 = numpy.array([True, True]) + arr2 = numpy.array([False, True]) + arr3 = numpy.array([True, False]) + numpy.testing.assert_array_equal(and_func(arr1, arr2), numpy.array([False, True])) + numpy.testing.assert_array_equal(and_func_3(arr1, arr2, arr3), numpy.array([False, False])) + numpy.testing.assert_array_equal(or_func(arr1, arr2), numpy.array([True, True])) + numpy.testing.assert_array_equal(or_func_3(arr1, arr2, arr3), numpy.array([True, True])) + numpy.testing.assert_array_equal(not_func(arr2), numpy.array([True, False])) + + +def test_numpy_matmul(): + if not numpy: + skip("numpy not installed.") + xmat = Matrix([[x, y], [z, 1+z]]) + ymat = Matrix([[x**2], [Abs(x)]]) + mat_func = lambdify((x, y, z), xmat*ymat, modules="numpy") + numpy.testing.assert_array_equal(mat_func(0.5, 3, 4), numpy.array([[1.625], [3.5]])) + numpy.testing.assert_array_equal(mat_func(-0.5, 3, 4), numpy.array([[1.375], [3.5]])) + # Multiple matrices chained together in multiplication + f = lambdify((x, y, z), xmat*xmat*xmat, modules="numpy") + numpy.testing.assert_array_equal(f(0.5, 3, 4), numpy.array([[72.125, 119.25], + [159, 251]])) + + +def test_numpy_numexpr(): + if not numpy: + skip("numpy not installed.") + if not numexpr: + skip("numexpr not installed.") + a, b, c = numpy.random.randn(3, 128, 128) + # ensure that numpy and numexpr return same value for complicated expression + expr = sin(x) + cos(y) + tan(z)**2 + Abs(z-y)*acos(sin(y*z)) + \ + Abs(y-z)*acosh(2+exp(y-x))- sqrt(x**2+I*y**2) + npfunc = lambdify((x, y, z), expr, modules='numpy') + nefunc = lambdify((x, y, z), expr, modules='numexpr') + assert numpy.allclose(npfunc(a, b, c), nefunc(a, b, c)) + + +def test_numexpr_userfunctions(): + if not numpy: + skip("numpy not installed.") + if not numexpr: + skip("numexpr not installed.") + a, b = numpy.random.randn(2, 10) + uf = type('uf', (Function, ), + {'eval' : classmethod(lambda x, y : y**2+1)}) + func = lambdify(x, 1-uf(x), modules='numexpr') + assert numpy.allclose(func(a), -(a**2)) + + uf = implemented_function(Function('uf'), lambda x, y : 2*x*y+1) + func = lambdify((x, y), uf(x, y), modules='numexpr') + assert numpy.allclose(func(a, b), 2*a*b+1) + + +def test_tensorflow_basic_math(): + if not tensorflow: + skip("tensorflow not installed.") + expr = Max(sin(x), Abs(1/(x+2))) + func = lambdify(x, expr, modules="tensorflow") + + with tensorflow.compat.v1.Session() as s: + a = tensorflow.constant(0, dtype=tensorflow.float32) + assert func(a).eval(session=s) == 0.5 + + +def test_tensorflow_placeholders(): + if not tensorflow: + skip("tensorflow not installed.") + expr = Max(sin(x), Abs(1/(x+2))) + func = lambdify(x, expr, modules="tensorflow") + + with tensorflow.compat.v1.Session() as s: + a = tensorflow.compat.v1.placeholder(dtype=tensorflow.float32) + assert func(a).eval(session=s, feed_dict={a: 0}) == 0.5 + + +def test_tensorflow_variables(): + if not tensorflow: + skip("tensorflow not installed.") + expr = Max(sin(x), Abs(1/(x+2))) + func = lambdify(x, expr, modules="tensorflow") + + with tensorflow.compat.v1.Session() as s: + a = tensorflow.Variable(0, dtype=tensorflow.float32) + s.run(a.initializer) + assert func(a).eval(session=s, feed_dict={a: 0}) == 0.5 + + +def test_tensorflow_logical_operations(): + if not tensorflow: + skip("tensorflow not installed.") + expr = Not(And(Or(x, y), y)) + func = lambdify([x, y], expr, modules="tensorflow") + + with tensorflow.compat.v1.Session() as s: + assert func(False, True).eval(session=s) == False + + +def test_tensorflow_piecewise(): + if not tensorflow: + skip("tensorflow not installed.") + expr = Piecewise((0, Eq(x,0)), (-1, x < 0), (1, x > 0)) + func = lambdify(x, expr, modules="tensorflow") + + with tensorflow.compat.v1.Session() as s: + assert func(-1).eval(session=s) == -1 + assert func(0).eval(session=s) == 0 + assert func(1).eval(session=s) == 1 + + +def test_tensorflow_multi_max(): + if not tensorflow: + skip("tensorflow not installed.") + expr = Max(x, -x, x**2) + func = lambdify(x, expr, modules="tensorflow") + + with tensorflow.compat.v1.Session() as s: + assert func(-2).eval(session=s) == 4 + + +def test_tensorflow_multi_min(): + if not tensorflow: + skip("tensorflow not installed.") + expr = Min(x, -x, x**2) + func = lambdify(x, expr, modules="tensorflow") + + with tensorflow.compat.v1.Session() as s: + assert func(-2).eval(session=s) == -2 + + +def test_tensorflow_relational(): + if not tensorflow: + skip("tensorflow not installed.") + expr = x >= 0 + func = lambdify(x, expr, modules="tensorflow") + + with tensorflow.compat.v1.Session() as s: + assert func(1).eval(session=s) == True + + +def test_tensorflow_complexes(): + if not tensorflow: + skip("tensorflow not installed") + + func1 = lambdify(x, re(x), modules="tensorflow") + func2 = lambdify(x, im(x), modules="tensorflow") + func3 = lambdify(x, Abs(x), modules="tensorflow") + func4 = lambdify(x, arg(x), modules="tensorflow") + + with tensorflow.compat.v1.Session() as s: + # For versions before + # https://github.com/tensorflow/tensorflow/issues/30029 + # resolved, using Python numeric types may not work + a = tensorflow.constant(1+2j) + assert func1(a).eval(session=s) == 1 + assert func2(a).eval(session=s) == 2 + + tensorflow_result = func3(a).eval(session=s) + sympy_result = Abs(1 + 2j).evalf() + assert abs(tensorflow_result-sympy_result) < 10**-6 + + tensorflow_result = func4(a).eval(session=s) + sympy_result = arg(1 + 2j).evalf() + assert abs(tensorflow_result-sympy_result) < 10**-6 + + +def test_tensorflow_array_arg(): + # Test for issue 14655 (tensorflow part) + if not tensorflow: + skip("tensorflow not installed.") + + f = lambdify([[x, y]], x*x + y, 'tensorflow') + + with tensorflow.compat.v1.Session() as s: + fcall = f(tensorflow.constant([2.0, 1.0])) + assert fcall.eval(session=s) == 5.0 + + +#================== Test symbolic ================================== + + +def test_sym_single_arg(): + f = lambdify(x, x * y) + assert f(z) == z * y + + +def test_sym_list_args(): + f = lambdify([x, y], x + y + z) + assert f(1, 2) == 3 + z + + +def test_sym_integral(): + f = Lambda(x, exp(-x**2)) + l = lambdify(x, Integral(f(x), (x, -oo, oo)), modules="sympy") + assert l(y) == Integral(exp(-y**2), (y, -oo, oo)) + assert l(y).doit() == sqrt(pi) + + +def test_namespace_order(): + # lambdify had a bug, such that module dictionaries or cached module + # dictionaries would pull earlier namespaces into themselves. + # Because the module dictionaries form the namespace of the + # generated lambda, this meant that the behavior of a previously + # generated lambda function could change as a result of later calls + # to lambdify. + n1 = {'f': lambda x: 'first f'} + n2 = {'f': lambda x: 'second f', + 'g': lambda x: 'function g'} + f = sympy.Function('f') + g = sympy.Function('g') + if1 = lambdify(x, f(x), modules=(n1, "sympy")) + assert if1(1) == 'first f' + if2 = lambdify(x, g(x), modules=(n2, "sympy")) + # previously gave 'second f' + assert if1(1) == 'first f' + + assert if2(1) == 'function g' + + +def test_imps(): + # Here we check if the default returned functions are anonymous - in + # the sense that we can have more than one function with the same name + f = implemented_function('f', lambda x: 2*x) + g = implemented_function('f', lambda x: math.sqrt(x)) + l1 = lambdify(x, f(x)) + l2 = lambdify(x, g(x)) + assert str(f(x)) == str(g(x)) + assert l1(3) == 6 + assert l2(3) == math.sqrt(3) + # check that we can pass in a Function as input + func = sympy.Function('myfunc') + assert not hasattr(func, '_imp_') + my_f = implemented_function(func, lambda x: 2*x) + assert hasattr(my_f, '_imp_') + # Error for functions with same name and different implementation + f2 = implemented_function("f", lambda x: x + 101) + raises(ValueError, lambda: lambdify(x, f(f2(x)))) + + +def test_imps_errors(): + # Test errors that implemented functions can return, and still be able to + # form expressions. + # See: https://github.com/sympy/sympy/issues/10810 + # + # XXX: Removed AttributeError here. This test was added due to issue 10810 + # but that issue was about ValueError. It doesn't seem reasonable to + # "support" catching AttributeError in the same context... + for val, error_class in product((0, 0., 2, 2.0), (TypeError, ValueError)): + + def myfunc(a): + if a == 0: + raise error_class + return 1 + + f = implemented_function('f', myfunc) + expr = f(val) + assert expr == f(val) + + +def test_imps_wrong_args(): + raises(ValueError, lambda: implemented_function(sin, lambda x: x)) + + +def test_lambdify_imps(): + # Test lambdify with implemented functions + # first test basic (sympy) lambdify + f = sympy.cos + assert lambdify(x, f(x))(0) == 1 + assert lambdify(x, 1 + f(x))(0) == 2 + assert lambdify((x, y), y + f(x))(0, 1) == 2 + # make an implemented function and test + f = implemented_function("f", lambda x: x + 100) + assert lambdify(x, f(x))(0) == 100 + assert lambdify(x, 1 + f(x))(0) == 101 + assert lambdify((x, y), y + f(x))(0, 1) == 101 + # Can also handle tuples, lists, dicts as expressions + lam = lambdify(x, (f(x), x)) + assert lam(3) == (103, 3) + lam = lambdify(x, [f(x), x]) + assert lam(3) == [103, 3] + lam = lambdify(x, [f(x), (f(x), x)]) + assert lam(3) == [103, (103, 3)] + lam = lambdify(x, {f(x): x}) + assert lam(3) == {103: 3} + lam = lambdify(x, {f(x): x}) + assert lam(3) == {103: 3} + lam = lambdify(x, {x: f(x)}) + assert lam(3) == {3: 103} + # Check that imp preferred to other namespaces by default + d = {'f': lambda x: x + 99} + lam = lambdify(x, f(x), d) + assert lam(3) == 103 + # Unless flag passed + lam = lambdify(x, f(x), d, use_imps=False) + assert lam(3) == 102 + + +def test_dummification(): + t = symbols('t') + F = Function('F') + G = Function('G') + #"\alpha" is not a valid Python variable name + #lambdify should sub in a dummy for it, and return + #without a syntax error + alpha = symbols(r'\alpha') + some_expr = 2 * F(t)**2 / G(t) + lam = lambdify((F(t), G(t)), some_expr) + assert lam(3, 9) == 2 + lam = lambdify(sin(t), 2 * sin(t)**2) + assert lam(F(t)) == 2 * F(t)**2 + #Test that \alpha was properly dummified + lam = lambdify((alpha, t), 2*alpha + t) + assert lam(2, 1) == 5 + raises(SyntaxError, lambda: lambdify(F(t) * G(t), F(t) * G(t) + 5)) + raises(SyntaxError, lambda: lambdify(2 * F(t), 2 * F(t) + 5)) + raises(SyntaxError, lambda: lambdify(2 * F(t), 4 * F(t) + 5)) + + +def test_lambdify__arguments_with_invalid_python_identifiers(): + # see sympy/sympy#26690 + N = CoordSys3D('N') + xn, yn, zn = N.base_scalars() + expr = xn + yn + f = lambdify([xn, yn], expr) + res = f(0.2, 0.3) + ref = 0.2 + 0.3 + assert abs(res-ref) < 1e-15 + + +def test_curly_matrix_symbol(): + # Issue #15009 + curlyv = sympy.MatrixSymbol("{v}", 2, 1) + lam = lambdify(curlyv, curlyv) + assert lam(1)==1 + lam = lambdify(curlyv, curlyv, dummify=True) + assert lam(1)==1 + + +def test_python_keywords(): + # Test for issue 7452. The automatic dummification should ensure use of + # Python reserved keywords as symbol names will create valid lambda + # functions. This is an additional regression test. + python_if = symbols('if') + expr = python_if / 2 + f = lambdify(python_if, expr) + assert f(4.0) == 2.0 + + +def test_lambdify_docstring(): + func = lambdify((w, x, y, z), w + x + y + z) + ref = ( + "Created with lambdify. Signature:\n\n" + "func(w, x, y, z)\n\n" + "Expression:\n\n" + "w + x + y + z" + ).splitlines() + assert func.__doc__.splitlines()[:len(ref)] == ref + syms = symbols('a1:26') + func = lambdify(syms, sum(syms)) + ref = ( + "Created with lambdify. Signature:\n\n" + "func(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15,\n" + " a16, a17, a18, a19, a20, a21, a22, a23, a24, a25)\n\n" + "Expression:\n\n" + "a1 + a10 + a11 + a12 + a13 + a14 + a15 + a16 + a17 + a18 + a19 + a2 + a20 +..." + ).splitlines() + assert func.__doc__.splitlines()[:len(ref)] == ref + + +def test_lambdify_linecache(): + func = lambdify(x, x + 1) + source = 'def _lambdifygenerated(x):\n return x + 1\n' + assert inspect.getsource(func) == source + filename = inspect.getsourcefile(func) + assert filename.startswith('= (1, 10) + + if have_scipy_1_10plus: + cm2 = lambdify((x, y), powm1(x, y), modules='scipy') + assert abs(cm2(1.2, 1e-9) - 1.82321557e-10) < 1e-17 + + +def test_scipy_bernoulli(): + if not scipy: + skip("scipy not installed") + + bern = lambdify((x,), bernoulli(x), modules='scipy') + assert bern(1) == 0.5 + + +def test_scipy_harmonic(): + if not scipy: + skip("scipy not installed") + + hn = lambdify((x,), harmonic(x), modules='scipy') + assert hn(2) == 1.5 + hnm = lambdify((x, y), harmonic(x, y), modules='scipy') + assert hnm(2, 2) == 1.25 + + +def test_cupy_array_arg(): + if not cupy: + skip("CuPy not installed") + + f = lambdify([[x, y]], x*x + y, 'cupy') + result = f(cupy.array([2.0, 1.0])) + assert result == 5 + assert "cupy" in str(type(result)) + + +def test_cupy_array_arg_using_numpy(): + # numpy functions can be run on cupy arrays + # unclear if we can "officially" support this, + # depends on numpy __array_function__ support + if not cupy: + skip("CuPy not installed") + + f = lambdify([[x, y]], x*x + y, 'numpy') + result = f(cupy.array([2.0, 1.0])) + assert result == 5 + assert "cupy" in str(type(result)) + +def test_cupy_dotproduct(): + if not cupy: + skip("CuPy not installed") + + A = Matrix([x, y, z]) + f1 = lambdify([x, y, z], DotProduct(A, A), modules='cupy') + f2 = lambdify([x, y, z], DotProduct(A, A.T), modules='cupy') + f3 = lambdify([x, y, z], DotProduct(A.T, A), modules='cupy') + f4 = lambdify([x, y, z], DotProduct(A, A.T), modules='cupy') + + assert f1(1, 2, 3) == \ + f2(1, 2, 3) == \ + f3(1, 2, 3) == \ + f4(1, 2, 3) == \ + cupy.array([14]) + + +def test_jax_array_arg(): + if not jax: + skip("JAX not installed") + + f = lambdify([[x, y]], x*x + y, 'jax') + result = f(jax.numpy.array([2.0, 1.0])) + assert result == 5 + assert "jax" in str(type(result)) + + +def test_jax_array_arg_using_numpy(): + if not jax: + skip("JAX not installed") + + f = lambdify([[x, y]], x*x + y, 'numpy') + result = f(jax.numpy.array([2.0, 1.0])) + assert result == 5 + assert "jax" in str(type(result)) + + +def test_jax_dotproduct(): + if not jax: + skip("JAX not installed") + + A = Matrix([x, y, z]) + f1 = lambdify([x, y, z], DotProduct(A, A), modules='jax') + f2 = lambdify([x, y, z], DotProduct(A, A.T), modules='jax') + f3 = lambdify([x, y, z], DotProduct(A.T, A), modules='jax') + f4 = lambdify([x, y, z], DotProduct(A, A.T), modules='jax') + + assert f1(1, 2, 3) == \ + f2(1, 2, 3) == \ + f3(1, 2, 3) == \ + f4(1, 2, 3) == \ + jax.numpy.array([14]) + + +def test_lambdify_cse(): + def no_op_cse(exprs): + return (), exprs + + def dummy_cse(exprs): + from sympy.simplify.cse_main import cse + return cse(exprs, symbols=numbered_symbols(cls=Dummy)) + + def minmem(exprs): + from sympy.simplify.cse_main import cse_release_variables, cse + return cse(exprs, postprocess=cse_release_variables) + + class Case: + def __init__(self, *, args, exprs, num_args, requires_numpy=False): + self.args = args + self.exprs = exprs + self.num_args = num_args + subs_dict = dict(zip(self.args, self.num_args)) + self.ref = [e.subs(subs_dict).evalf() for e in exprs] + self.requires_numpy = requires_numpy + + def lambdify(self, *, cse): + return lambdify(self.args, self.exprs, cse=cse) + + def assertAllClose(self, result, *, abstol=1e-15, reltol=1e-15): + if self.requires_numpy: + assert all(numpy.allclose(result[i], numpy.asarray(r, dtype=float), + rtol=reltol, atol=abstol) + for i, r in enumerate(self.ref)) + return + + for i, r in enumerate(self.ref): + abs_err = abs(result[i] - r) + if r == 0: + assert abs_err < abstol + else: + assert abs_err/abs(r) < reltol + + cases = [ + Case( + args=(x, y, z), + exprs=[ + x + y + z, + x + y - z, + 2*x + 2*y - z, + (x+y)**2 + (y+z)**2, + ], + num_args=(2., 3., 4.) + ), + Case( + args=(x, y, z), + exprs=[ + x + sympy.Heaviside(x), + y + sympy.Heaviside(x), + z + sympy.Heaviside(x, 1), + z/sympy.Heaviside(x, 1) + ], + num_args=(0., 3., 4.) + ), + Case( + args=(x, y, z), + exprs=[ + x + sinc(y), + y + sinc(y), + z - sinc(y) + ], + num_args=(0.1, 0.2, 0.3) + ), + Case( + args=(x, y, z), + exprs=[ + Matrix([[x, x*y], [sin(z) + 4, x**z]]), + x*y+sin(z)-x**z, + Matrix([x*x, sin(z), x**z]) + ], + num_args=(1.,2.,3.), + requires_numpy=True + ), + Case( + args=(x, y), + exprs=[(x + y - 1)**2, x, x + y, + (x + y)/(2*x + 1) + (x + y - 1)**2, (2*x + 1)**(x + y)], + num_args=(1,2) + ) + ] + for case in cases: + if not numpy and case.requires_numpy: + continue + for _cse in [False, True, minmem, no_op_cse, dummy_cse]: + f = case.lambdify(cse=_cse) + result = f(*case.num_args) + case.assertAllClose(result) + +def test_issue_25288(): + syms = numbered_symbols(cls=Dummy) + ok = lambdify(x, [x**2, sin(x**2)], cse=lambda e: cse(e, symbols=syms))(2) + assert ok + + +def test_deprecated_set(): + with warns_deprecated_sympy(): + lambdify({x, y}, x + y) + +def test_issue_13881(): + if not numpy: + skip("numpy not installed.") + + X = MatrixSymbol('X', 3, 1) + + f = lambdify(X, X.T*X, 'numpy') + assert f(numpy.array([1, 2, 3])) == 14 + assert f(numpy.array([3, 2, 1])) == 14 + + f = lambdify(X, X*X.T, 'numpy') + assert f(numpy.array([1, 2, 3])) == 14 + assert f(numpy.array([3, 2, 1])) == 14 + + f = lambdify(X, (X*X.T)*X, 'numpy') + arr1 = numpy.array([[1], [2], [3]]) + arr2 = numpy.array([[14],[28],[42]]) + + assert numpy.array_equal(f(arr1), arr2) + + +def test_23536_lambdify_cse_dummy(): + + f = Function('x')(y) + g = Function('w')(y) + expr = z + (f**4 + g**5)*(f**3 + (g*f)**3) + expr = expr.expand() + eval_expr = lambdify(((f, g), z), expr, cse=True) + ans = eval_expr((1.0, 2.0), 3.0) # shouldn't raise NameError + assert ans == 300.0 # not a list and value is 300 + + +class LambdifyDocstringTestCase: + SIGNATURE = None + EXPR = None + SRC = None + + def __init__(self, docstring_limit, expected_redacted): + self.docstring_limit = docstring_limit + self.expected_redacted = expected_redacted + + @property + def expected_expr(self): + expr_redacted_msg = "EXPRESSION REDACTED DUE TO LENGTH, (see lambdify's `docstring_limit`)" + return self.EXPR if not self.expected_redacted else expr_redacted_msg + + @property + def expected_src(self): + src_redacted_msg = "SOURCE CODE REDACTED DUE TO LENGTH, (see lambdify's `docstring_limit`)" + return self.SRC if not self.expected_redacted else src_redacted_msg + + @property + def expected_docstring(self): + expected_docstring = ( + f'Created with lambdify. Signature:\n\n' + f'func({self.SIGNATURE})\n\n' + f'Expression:\n\n' + f'{self.expected_expr}\n\n' + f'Source code:\n\n' + f'{self.expected_src}\n\n' + f'Imported modules:\n\n' + ) + return expected_docstring + + def __len__(self): + return len(self.expected_docstring) + + def __repr__(self): + return ( + f'{self.__class__.__name__}(' + f'docstring_limit={self.docstring_limit}, ' + f'expected_redacted={self.expected_redacted})' + ) + + +def test_lambdify_docstring_size_limit_simple_symbol(): + + class SimpleSymbolTestCase(LambdifyDocstringTestCase): + SIGNATURE = 'x' + EXPR = 'x' + SRC = ( + 'def _lambdifygenerated(x):\n' + ' return x\n' + ) + + x = symbols('x') + + test_cases = ( + SimpleSymbolTestCase(docstring_limit=None, expected_redacted=False), + SimpleSymbolTestCase(docstring_limit=100, expected_redacted=False), + SimpleSymbolTestCase(docstring_limit=1, expected_redacted=False), + SimpleSymbolTestCase(docstring_limit=0, expected_redacted=True), + SimpleSymbolTestCase(docstring_limit=-1, expected_redacted=True), + ) + for test_case in test_cases: + lambdified_expr = lambdify( + [x], + x, + 'sympy', + docstring_limit=test_case.docstring_limit, + ) + assert lambdified_expr.__doc__ == test_case.expected_docstring + + +def test_lambdify_docstring_size_limit_nested_expr(): + + class ExprListTestCase(LambdifyDocstringTestCase): + SIGNATURE = 'x, y, z' + EXPR = ( + '[x, [y], z, x**3 + 3*x**2*y + 3*x**2*z + 3*x*y**2 + 6*x*y*z ' + '+ 3*x*z**2 +...' + ) + SRC = ( + 'def _lambdifygenerated(x, y, z):\n' + ' return [x, [y], z, x**3 + 3*x**2*y + 3*x**2*z + 3*x*y**2 ' + '+ 6*x*y*z + 3*x*z**2 + y**3 + 3*y**2*z + 3*y*z**2 + z**3]\n' + ) + + x, y, z = symbols('x, y, z') + expr = [x, [y], z, ((x + y + z)**3).expand()] + + test_cases = ( + ExprListTestCase(docstring_limit=None, expected_redacted=False), + ExprListTestCase(docstring_limit=200, expected_redacted=False), + ExprListTestCase(docstring_limit=50, expected_redacted=True), + ExprListTestCase(docstring_limit=0, expected_redacted=True), + ExprListTestCase(docstring_limit=-1, expected_redacted=True), + ) + for test_case in test_cases: + lambdified_expr = lambdify( + [x, y, z], + expr, + 'sympy', + docstring_limit=test_case.docstring_limit, + ) + assert lambdified_expr.__doc__ == test_case.expected_docstring + + +def test_lambdify_docstring_size_limit_matrix(): + + class MatrixTestCase(LambdifyDocstringTestCase): + SIGNATURE = 'x, y, z' + EXPR = ( + 'Matrix([[0, x], [x + y + z, x**3 + 3*x**2*y + 3*x**2*z + 3*x*y**2 ' + '+ 6*x*y*z...' + ) + SRC = ( + 'def _lambdifygenerated(x, y, z):\n' + ' return ImmutableDenseMatrix([[0, x], [x + y + z, x**3 ' + '+ 3*x**2*y + 3*x**2*z + 3*x*y**2 + 6*x*y*z + 3*x*z**2 + y**3 ' + '+ 3*y**2*z + 3*y*z**2 + z**3]])\n' + ) + + x, y, z = symbols('x, y, z') + expr = Matrix([[S.Zero, x], [x + y + z, ((x + y + z)**3).expand()]]) + + test_cases = ( + MatrixTestCase(docstring_limit=None, expected_redacted=False), + MatrixTestCase(docstring_limit=200, expected_redacted=False), + MatrixTestCase(docstring_limit=50, expected_redacted=True), + MatrixTestCase(docstring_limit=0, expected_redacted=True), + MatrixTestCase(docstring_limit=-1, expected_redacted=True), + ) + for test_case in test_cases: + lambdified_expr = lambdify( + [x, y, z], + expr, + 'sympy', + docstring_limit=test_case.docstring_limit, + ) + assert lambdified_expr.__doc__ == test_case.expected_docstring + + +def test_lambdify_empty_tuple(): + a = symbols("a") + expr = ((), (a,)) + f = lambdify(a, expr) + result = f(1) + assert result == ((), (1,)), "Lambdify did not handle the empty tuple correctly." + + +def test_assoc_legendre_numerical_evaluation(): + + tol = 1e-10 + + sympy_result_integer = assoc_legendre(1, 1/2, 0.1).evalf() + sympy_result_complex = assoc_legendre(2, 1, 3).evalf() + mpmath_result_integer = -0.474572528387641 + mpmath_result_complex = -25.45584412271571*I + + assert all_close(sympy_result_integer, mpmath_result_integer, tol) + assert all_close(sympy_result_complex, mpmath_result_complex, tol) + + +def test_Piecewise(): + + modules = [math] + if numpy: + modules.append('numpy') + + for mod in modules: + # test isinf + f = lambdify(x, Piecewise((7.0, isinf(x)), (3.0, True)), mod) + assert f(+float('inf')) == +7.0 + assert f(-float('inf')) == +7.0 + assert f(42.) == 3.0 + + f2 = lambdify(x, Piecewise((7.0*sign(x), isinf(x)), (3.0, True)), mod) + assert f2(+float('inf')) == +7.0 + assert f2(-float('inf')) == -7.0 + assert f2(42.) == 3.0 + + # test isnan (gh-26784) + g = lambdify(x, Piecewise((7.0, isnan(x)), (3.0, True)), mod) + assert g(float('nan')) == 7.0 + assert g(42.) == 3.0 + + +def test_array_symbol(): + if not numpy: + skip("numpy not installed.") + a = ArraySymbol('a', (3,)) + f = lambdify((a), a) + assert numpy.all(f(numpy.array([1,2,3])) == numpy.array([1,2,3])) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_matchpy_connector.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_matchpy_connector.py new file mode 100644 index 0000000000000000000000000000000000000000..3648bd49f9e56ca20fbf428ed46c01429dbe8b15 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_matchpy_connector.py @@ -0,0 +1,164 @@ +import pickle + +from sympy.core.relational import (Eq, Ne) +from sympy.core.singleton import S +from sympy.core.symbol import symbols +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.external import import_module +from sympy.testing.pytest import skip +from sympy.utilities.matchpy_connector import WildDot, WildPlus, WildStar, Replacer + +matchpy = import_module("matchpy") + +x, y, z = symbols("x y z") + + +def _get_first_match(expr, pattern): + from matchpy import ManyToOneMatcher, Pattern + + matcher = ManyToOneMatcher() + matcher.add(Pattern(pattern)) + return next(iter(matcher.match(expr))) + + +def test_matchpy_connector(): + if matchpy is None: + skip("matchpy not installed") + + from multiset import Multiset + from matchpy import Pattern, Substitution + + w_ = WildDot("w_") + w__ = WildPlus("w__") + w___ = WildStar("w___") + + expr = x + y + pattern = x + w_ + p, subst = _get_first_match(expr, pattern) + assert p == Pattern(pattern) + assert subst == Substitution({'w_': y}) + + expr = x + y + z + pattern = x + w__ + p, subst = _get_first_match(expr, pattern) + assert p == Pattern(pattern) + assert subst == Substitution({'w__': Multiset([y, z])}) + + expr = x + y + z + pattern = x + y + z + w___ + p, subst = _get_first_match(expr, pattern) + assert p == Pattern(pattern) + assert subst == Substitution({'w___': Multiset()}) + + +def test_matchpy_optional(): + if matchpy is None: + skip("matchpy not installed") + + from matchpy import Pattern, Substitution + from matchpy import ManyToOneReplacer, ReplacementRule + + p = WildDot("p", optional=1) + q = WildDot("q", optional=0) + + pattern = p*x + q + + expr1 = 2*x + pa, subst = _get_first_match(expr1, pattern) + assert pa == Pattern(pattern) + assert subst == Substitution({'p': 2, 'q': 0}) + + expr2 = x + 3 + pa, subst = _get_first_match(expr2, pattern) + assert pa == Pattern(pattern) + assert subst == Substitution({'p': 1, 'q': 3}) + + expr3 = x + pa, subst = _get_first_match(expr3, pattern) + assert pa == Pattern(pattern) + assert subst == Substitution({'p': 1, 'q': 0}) + + expr4 = x*y + z + pa, subst = _get_first_match(expr4, pattern) + assert pa == Pattern(pattern) + assert subst == Substitution({'p': y, 'q': z}) + + replacer = ManyToOneReplacer() + replacer.add(ReplacementRule(Pattern(pattern), lambda p, q: sin(p)*cos(q))) + assert replacer.replace(expr1) == sin(2)*cos(0) + assert replacer.replace(expr2) == sin(1)*cos(3) + assert replacer.replace(expr3) == sin(1)*cos(0) + assert replacer.replace(expr4) == sin(y)*cos(z) + + +def test_replacer(): + if matchpy is None: + skip("matchpy not installed") + + for info in [True, False]: + for lambdify in [True, False]: + _perform_test_replacer(info, lambdify) + + +def _perform_test_replacer(info, lambdify): + + x1_ = WildDot("x1_") + x2_ = WildDot("x2_") + + a_ = WildDot("a_", optional=S.One) + b_ = WildDot("b_", optional=S.One) + c_ = WildDot("c_", optional=S.Zero) + + replacer = Replacer(common_constraints=[ + matchpy.CustomConstraint(lambda a_: not a_.has(x)), + matchpy.CustomConstraint(lambda b_: not b_.has(x)), + matchpy.CustomConstraint(lambda c_: not c_.has(x)), + ], lambdify=lambdify, info=info) + + # Rewrite the equation into implicit form, unless it's already solved: + replacer.add(Eq(x1_, x2_), Eq(x1_ - x2_, 0), conditions_nonfalse=[Ne(x2_, 0), Ne(x1_, 0), Ne(x1_, x), Ne(x2_, x)], info=1) + + # Simple equation solver for real numbers: + replacer.add(Eq(a_*x + b_, 0), Eq(x, -b_/a_), info=2) + disc = b_**2 - 4*a_*c_ + replacer.add( + Eq(a_*x**2 + b_*x + c_, 0), + Eq(x, (-b_ - sqrt(disc))/(2*a_)) | Eq(x, (-b_ + sqrt(disc))/(2*a_)), + conditions_nonfalse=[disc >= 0], + info=3 + ) + replacer.add( + Eq(a_*x**2 + c_, 0), + Eq(x, sqrt(-c_/a_)) | Eq(x, -sqrt(-c_/a_)), + conditions_nonfalse=[-c_*a_ > 0], + info=4 + ) + + g = lambda expr, infos: (expr, infos) if info else expr + + assert replacer.replace(Eq(3*x, y)) == g(Eq(x, y/3), [1, 2]) + assert replacer.replace(Eq(x**2 + 1, 0)) == g(Eq(x**2 + 1, 0), []) + assert replacer.replace(Eq(x**2, 4)) == g((Eq(x, 2) | Eq(x, -2)), [1, 4]) + assert replacer.replace(Eq(x**2 + 4*y*x + 4*y**2, 0)) == g(Eq(x, -2*y), [3]) + + +def test_matchpy_object_pickle(): + if matchpy is None: + return + + a1 = WildDot("a") + a2 = pickle.loads(pickle.dumps(a1)) + assert a1 == a2 + + a1 = WildDot("a", S(1)) + a2 = pickle.loads(pickle.dumps(a1)) + assert a1 == a2 + + a1 = WildPlus("a", S(1)) + a2 = pickle.loads(pickle.dumps(a1)) + assert a1 == a2 + + a1 = WildStar("a", S(1)) + a2 = pickle.loads(pickle.dumps(a1)) + assert a1 == a2 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_mathml.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_mathml.py new file mode 100644 index 0000000000000000000000000000000000000000..e4a7598f175be34f8bb34c0bd9c003d1c0238c7b --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_mathml.py @@ -0,0 +1,33 @@ +import os +from textwrap import dedent +from sympy.external import import_module +from sympy.testing.pytest import skip +from sympy.utilities.mathml import apply_xsl + + + +lxml = import_module('lxml') + +path = os.path.abspath(os.path.join(os.path.dirname(__file__), "test_xxe.py")) + + +def test_xxe(): + assert os.path.isfile(path) + if not lxml: + skip("lxml not installed.") + + mml = dedent( + rf""" + + ]> + + John + &ent; + + """ + ) + xsl = 'mathml/data/simple_mmlctop.xsl' + + res = apply_xsl(mml, xsl) + assert res == \ + '\n\nJohn\n\n\n' diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_misc.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_misc.py new file mode 100644 index 0000000000000000000000000000000000000000..0a3e059419303c33cbd7b770679b5efc1b03486d --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_misc.py @@ -0,0 +1,148 @@ +from textwrap import dedent +import sys +from subprocess import Popen, PIPE +import os + +from sympy.core.singleton import S +from sympy.testing.pytest import (raises, warns_deprecated_sympy, + skip_under_pyodide) +from sympy.utilities.misc import (translate, replace, ordinal, rawlines, + strlines, as_int, find_executable) + + +def test_translate(): + abc = 'abc' + assert translate(abc, None, 'a') == 'bc' + assert translate(abc, None, '') == 'abc' + assert translate(abc, {'a': 'x'}, 'c') == 'xb' + assert translate(abc, {'a': 'bc'}, 'c') == 'bcb' + assert translate(abc, {'ab': 'x'}, 'c') == 'x' + assert translate(abc, {'ab': ''}, 'c') == '' + assert translate(abc, {'bc': 'x'}, 'c') == 'ab' + assert translate(abc, {'abc': 'x', 'a': 'y'}) == 'x' + u = chr(4096) + assert translate(abc, 'a', 'x', u) == 'xbc' + assert (u in translate(abc, 'a', u, u)) is True + + +def test_replace(): + assert replace('abc', ('a', 'b')) == 'bbc' + assert replace('abc', {'a': 'Aa'}) == 'Aabc' + assert replace('abc', ('a', 'b'), ('c', 'C')) == 'bbC' + + +def test_ordinal(): + assert ordinal(-1) == '-1st' + assert ordinal(0) == '0th' + assert ordinal(1) == '1st' + assert ordinal(2) == '2nd' + assert ordinal(3) == '3rd' + assert all(ordinal(i).endswith('th') for i in range(4, 21)) + assert ordinal(100) == '100th' + assert ordinal(101) == '101st' + assert ordinal(102) == '102nd' + assert ordinal(103) == '103rd' + assert ordinal(104) == '104th' + assert ordinal(200) == '200th' + assert all(ordinal(i) == str(i) + 'th' for i in range(-220, -203)) + + +def test_rawlines(): + assert rawlines('a a\na') == "dedent('''\\\n a a\n a''')" + assert rawlines('a a') == "'a a'" + assert rawlines(strlines('\\le"ft')) == ( + '(\n' + " '(\\n'\n" + ' \'r\\\'\\\\le"ft\\\'\\n\'\n' + " ')'\n" + ')') + + +def test_strlines(): + q = 'this quote (") is in the middle' + # the following assert rhs was prepared with + # print(rawlines(strlines(q, 10))) + assert strlines(q, 10) == dedent('''\ + ( + 'this quo' + 'te (") i' + 's in the' + ' middle' + )''') + assert q == ( + 'this quo' + 'te (") i' + 's in the' + ' middle' + ) + q = "this quote (') is in the middle" + assert strlines(q, 20) == dedent('''\ + ( + "this quote (') is " + "in the middle" + )''') + assert strlines('\\left') == ( + '(\n' + "r'\\left'\n" + ')') + assert strlines('\\left', short=True) == r"r'\left'" + assert strlines('\\le"ft') == ( + '(\n' + 'r\'\\le"ft\'\n' + ')') + q = 'this\nother line' + assert strlines(q) == rawlines(q) + + +def test_translate_args(): + try: + translate(None, None, None, 'not_none') + except ValueError: + pass # Exception raised successfully + else: + assert False + + assert translate('s', None, None, None) == 's' + + try: + translate('s', 'a', 'bc') + except ValueError: + pass # Exception raised successfully + else: + assert False + + +@skip_under_pyodide("Cannot create subprocess under pyodide.") +def test_debug_output(): + env = os.environ.copy() + env['SYMPY_DEBUG'] = 'True' + cmd = 'from sympy import *; x = Symbol("x"); print(integrate((1-cos(x))/x, x))' + cmdline = [sys.executable, '-c', cmd] + proc = Popen(cmdline, env=env, stdout=PIPE, stderr=PIPE) + out, err = proc.communicate() + out = out.decode('ascii') # utf-8? + err = err.decode('ascii') + expected = 'substituted: -x*(1 - cos(x)), u: 1/x, u_var: _u' + assert expected in err, err + + +def test_as_int(): + raises(ValueError, lambda : as_int(True)) + raises(ValueError, lambda : as_int(1.1)) + raises(ValueError, lambda : as_int([])) + raises(ValueError, lambda : as_int(S.NaN)) + raises(ValueError, lambda : as_int(S.Infinity)) + raises(ValueError, lambda : as_int(S.NegativeInfinity)) + raises(ValueError, lambda : as_int(S.ComplexInfinity)) + # for the following, limited precision makes int(arg) == arg + # but the int value is not necessarily what a user might have + # expected; Q.prime is more nuanced in its response for + # expressions which might be complex representations of an + # integer. This is not -- by design -- as_ints role. + raises(ValueError, lambda : as_int(1e23)) + raises(ValueError, lambda : as_int(S('1.'+'0'*20+'1'))) + assert as_int(True, strict=False) == 1 + +def test_deprecated_find_executable(): + with warns_deprecated_sympy(): + find_executable('python') diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_pickling.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_pickling.py new file mode 100644 index 0000000000000000000000000000000000000000..7ea2d062286cbcf802eb0f42f2d7d130123599af --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_pickling.py @@ -0,0 +1,723 @@ +import inspect +import copy +import pickle + +from sympy.physics.units import meter + +from sympy.testing.pytest import XFAIL, raises, ignore_warnings + +from sympy.core.basic import Atom, Basic +from sympy.core.singleton import SingletonRegistry +from sympy.core.symbol import Str, Dummy, Symbol, Wild +from sympy.core.numbers import (E, I, pi, oo, zoo, nan, Integer, + Rational, Float, AlgebraicNumber) +from sympy.core.relational import (Equality, GreaterThan, LessThan, Relational, + StrictGreaterThan, StrictLessThan, Unequality) +from sympy.core.add import Add +from sympy.core.mul import Mul +from sympy.core.power import Pow +from sympy.core.function import Derivative, Function, FunctionClass, Lambda, \ + WildFunction +from sympy.sets.sets import Interval +from sympy.core.multidimensional import vectorize + +from sympy.external.gmpy import gmpy as _gmpy +from sympy.utilities.exceptions import SymPyDeprecationWarning + +from sympy.core.singleton import S +from sympy.core.symbol import symbols + +from sympy.external import import_module +cloudpickle = import_module('cloudpickle') + + +not_equal_attrs = { + '_assumptions', # This is a local cache that isn't automatically filled on creation + '_mhash', # Cached after __hash__ is called but set to None after creation +} + + +deprecated_attrs = { + 'is_EmptySet', # Deprecated from SymPy 1.5. This can be removed when is_EmptySet is removed. + 'expr_free_symbols', # Deprecated from SymPy 1.9. This can be removed when exr_free_symbols is removed. +} + +dont_check_attrs = { + '_sage_', # Fails because Sage is not installed +} + + +def check(a, exclude=[], check_attr=True, deprecated=()): + """ Check that pickling and copying round-trips. + """ + # Pickling with protocols 0 and 1 is disabled for Basic instances: + if isinstance(a, Basic): + for protocol in [0, 1]: + raises(NotImplementedError, lambda: pickle.dumps(a, protocol)) + + protocols = [2, copy.copy, copy.deepcopy, 3, 4] + if cloudpickle: + protocols.extend([cloudpickle]) + + for protocol in protocols: + if protocol in exclude: + continue + + if callable(protocol): + if isinstance(a, type): + # Classes can't be copied, but that's okay. + continue + b = protocol(a) + elif inspect.ismodule(protocol): + b = protocol.loads(protocol.dumps(a)) + else: + b = pickle.loads(pickle.dumps(a, protocol)) + + d1 = dir(a) + d2 = dir(b) + assert set(d1) == set(d2) + + if not check_attr: + continue + + def c(a, b, d): + for i in d: + if i in dont_check_attrs: + continue + elif i in not_equal_attrs: + if hasattr(a, i): + assert hasattr(b, i), i + elif i in deprecated_attrs or i in deprecated: + with ignore_warnings(SymPyDeprecationWarning): + assert getattr(a, i) == getattr(b, i), i + elif not hasattr(a, i): + continue + else: + attr = getattr(a, i) + if not hasattr(attr, "__call__"): + assert hasattr(b, i), i + assert getattr(b, i) == attr, "%s != %s, protocol: %s" % (getattr(b, i), attr, protocol) + + c(a, b, d1) + c(b, a, d2) + + + +#================== core ========================= + + +def test_core_basic(): + for c in (Atom, Atom(), Basic, Basic(), SingletonRegistry, S): + check(c) + +def test_core_Str(): + check(Str('x')) + +def test_core_symbol(): + # make the Symbol a unique name that doesn't class with any other + # testing variable in this file since after this test the symbol + # having the same name will be cached as noncommutative + for c in (Dummy, Dummy("x", commutative=False), Symbol, + Symbol("_issue_3130", commutative=False), Wild, Wild("x")): + check(c) + + +def test_core_numbers(): + for c in (Integer(2), Rational(2, 3), Float("1.2")): + check(c) + for c in (AlgebraicNumber, AlgebraicNumber(sqrt(3))): + check(c, check_attr=False) + + +def test_core_float_copy(): + # See gh-7457 + y = Symbol("x") + 1.0 + check(y) # does not raise TypeError ("argument is not an mpz") + + +def test_core_relational(): + x = Symbol("x") + y = Symbol("y") + for c in (Equality, Equality(x, y), GreaterThan, GreaterThan(x, y), + LessThan, LessThan(x, y), Relational, Relational(x, y), + StrictGreaterThan, StrictGreaterThan(x, y), StrictLessThan, + StrictLessThan(x, y), Unequality, Unequality(x, y)): + check(c) + + +def test_core_add(): + x = Symbol("x") + for c in (Add, Add(x, 4)): + check(c) + + +def test_core_mul(): + x = Symbol("x") + for c in (Mul, Mul(x, 4)): + check(c) + + +def test_core_power(): + x = Symbol("x") + for c in (Pow, Pow(x, 4)): + check(c) + + +def test_core_function(): + x = Symbol("x") + for f in (Derivative, Derivative(x), Function, FunctionClass, Lambda, + WildFunction): + check(f) + + +def test_core_undefinedfunctions(): + f = Function("f") + check(f) + + +def test_core_appliedundef(): + x = Symbol("_long_unique_name_1") + f = Function("_long_unique_name_2") + check(f(x)) + + +def test_core_interval(): + for c in (Interval, Interval(0, 2)): + check(c) + + +def test_core_multidimensional(): + for c in (vectorize, vectorize(0)): + check(c) + + +def test_Singletons(): + protocols = [0, 1, 2, 3, 4] + copiers = [copy.copy, copy.deepcopy] + copiers += [lambda x: pickle.loads(pickle.dumps(x, proto)) + for proto in protocols] + if cloudpickle: + copiers += [lambda x: cloudpickle.loads(cloudpickle.dumps(x))] + + for obj in (Integer(-1), Integer(0), Integer(1), Rational(1, 2), pi, E, I, + oo, -oo, zoo, nan, S.GoldenRatio, S.TribonacciConstant, + S.EulerGamma, S.Catalan, S.EmptySet, S.IdentityFunction): + for func in copiers: + assert func(obj) is obj + +#================== combinatorics =================== +from sympy.combinatorics.free_groups import FreeGroup + +def test_free_group(): + check(FreeGroup("x, y, z"), check_attr=False) + +#================== functions =================== +from sympy.functions import (Piecewise, lowergamma, acosh, chebyshevu, + chebyshevt, ln, chebyshevt_root, legendre, Heaviside, bernoulli, coth, + tanh, assoc_legendre, sign, arg, asin, DiracDelta, re, rf, Abs, + uppergamma, binomial, sinh, cos, cot, acos, acot, gamma, bell, + hermite, harmonic, LambertW, zeta, log, factorial, asinh, acoth, cosh, + dirichlet_eta, Eijk, loggamma, erf, ceiling, im, fibonacci, + tribonacci, conjugate, tan, chebyshevu_root, floor, atanh, sqrt, sin, + atan, ff, lucas, atan2, polygamma, exp) + + +def test_functions(): + one_var = (acosh, ln, Heaviside, factorial, bernoulli, coth, tanh, + sign, arg, asin, DiracDelta, re, Abs, sinh, cos, cot, acos, acot, + gamma, bell, harmonic, LambertW, zeta, log, factorial, asinh, + acoth, cosh, dirichlet_eta, loggamma, erf, ceiling, im, fibonacci, + tribonacci, conjugate, tan, floor, atanh, sin, atan, lucas, exp) + two_var = (rf, ff, lowergamma, chebyshevu, chebyshevt, binomial, + atan2, polygamma, hermite, legendre, uppergamma) + x, y, z = symbols("x,y,z") + others = (chebyshevt_root, chebyshevu_root, Eijk(x, y, z), + Piecewise( (0, x < -1), (x**2, x <= 1), (x**3, True)), + assoc_legendre) + for cls in one_var: + check(cls) + c = cls(x) + check(c) + for cls in two_var: + check(cls) + c = cls(x, y) + check(c) + for cls in others: + check(cls) + +#================== geometry ==================== +from sympy.geometry.entity import GeometryEntity +from sympy.geometry.point import Point +from sympy.geometry.ellipse import Circle, Ellipse +from sympy.geometry.line import Line, LinearEntity, Ray, Segment +from sympy.geometry.polygon import Polygon, RegularPolygon, Triangle + + +def test_geometry(): + p1 = Point(1, 2) + p2 = Point(2, 3) + p3 = Point(0, 0) + p4 = Point(0, 1) + for c in ( + GeometryEntity, GeometryEntity(), Point, p1, Circle, Circle(p1, 2), + Ellipse, Ellipse(p1, 3, 4), Line, Line(p1, p2), LinearEntity, + LinearEntity(p1, p2), Ray, Ray(p1, p2), Segment, Segment(p1, p2), + Polygon, Polygon(p1, p2, p3, p4), RegularPolygon, + RegularPolygon(p1, 4, 5), Triangle, Triangle(p1, p2, p3)): + check(c, check_attr=False) + +#================== integrals ==================== +from sympy.integrals.integrals import Integral + + +def test_integrals(): + x = Symbol("x") + for c in (Integral, Integral(x)): + check(c) + +#==================== logic ===================== +from sympy.core.logic import Logic + + +def test_logic(): + for c in (Logic, Logic(1)): + check(c) + +#================== matrices ==================== +from sympy.matrices import Matrix, SparseMatrix + + +def test_matrices(): + for c in (Matrix, Matrix([1, 2, 3]), SparseMatrix, SparseMatrix([[1, 2], [3, 4]])): + check(c, deprecated=['_smat', '_mat']) + +#================== ntheory ===================== +from sympy.ntheory.generate import Sieve + + +def test_ntheory(): + for c in (Sieve, Sieve()): + check(c) + +#================== physics ===================== +from sympy.physics.paulialgebra import Pauli +from sympy.physics.units import Unit + + +def test_physics(): + for c in (Unit, meter, Pauli, Pauli(1)): + check(c) + +#================== plotting ==================== +# XXX: These tests are not complete, so XFAIL them + + +@XFAIL +def test_plotting(): + from sympy.plotting.pygletplot.color_scheme import ColorGradient, ColorScheme + from sympy.plotting.pygletplot.managed_window import ManagedWindow + from sympy.plotting.plot import Plot, ScreenShot + from sympy.plotting.pygletplot.plot_axes import PlotAxes, PlotAxesBase, PlotAxesFrame, PlotAxesOrdinate + from sympy.plotting.pygletplot.plot_camera import PlotCamera + from sympy.plotting.pygletplot.plot_controller import PlotController + from sympy.plotting.pygletplot.plot_curve import PlotCurve + from sympy.plotting.pygletplot.plot_interval import PlotInterval + from sympy.plotting.pygletplot.plot_mode import PlotMode + from sympy.plotting.pygletplot.plot_modes import Cartesian2D, Cartesian3D, Cylindrical, \ + ParametricCurve2D, ParametricCurve3D, ParametricSurface, Polar, Spherical + from sympy.plotting.pygletplot.plot_object import PlotObject + from sympy.plotting.pygletplot.plot_surface import PlotSurface + from sympy.plotting.pygletplot.plot_window import PlotWindow + for c in ( + ColorGradient, ColorGradient(0.2, 0.4), ColorScheme, ManagedWindow, + ManagedWindow, Plot, ScreenShot, PlotAxes, PlotAxesBase, + PlotAxesFrame, PlotAxesOrdinate, PlotCamera, PlotController, + PlotCurve, PlotInterval, PlotMode, Cartesian2D, Cartesian3D, + Cylindrical, ParametricCurve2D, ParametricCurve3D, + ParametricSurface, Polar, Spherical, PlotObject, PlotSurface, + PlotWindow): + check(c) + + +@XFAIL +def test_plotting2(): + #from sympy.plotting.color_scheme import ColorGradient + from sympy.plotting.pygletplot.color_scheme import ColorScheme + #from sympy.plotting.managed_window import ManagedWindow + from sympy.plotting.plot import Plot + #from sympy.plotting.plot import ScreenShot + from sympy.plotting.pygletplot.plot_axes import PlotAxes + #from sympy.plotting.plot_axes import PlotAxesBase, PlotAxesFrame, PlotAxesOrdinate + #from sympy.plotting.plot_camera import PlotCamera + #from sympy.plotting.plot_controller import PlotController + #from sympy.plotting.plot_curve import PlotCurve + #from sympy.plotting.plot_interval import PlotInterval + #from sympy.plotting.plot_mode import PlotMode + #from sympy.plotting.plot_modes import Cartesian2D, Cartesian3D, Cylindrical, \ + # ParametricCurve2D, ParametricCurve3D, ParametricSurface, Polar, Spherical + #from sympy.plotting.plot_object import PlotObject + #from sympy.plotting.plot_surface import PlotSurface + # from sympy.plotting.plot_window import PlotWindow + check(ColorScheme("rainbow")) + check(Plot(1, visible=False)) + check(PlotAxes()) + +#================== polys ======================= +from sympy.polys.domains.integerring import ZZ +from sympy.polys.domains.rationalfield import QQ +from sympy.polys.orderings import lex +from sympy.polys.polytools import Poly + +def test_pickling_polys_polytools(): + from sympy.polys.polytools import PurePoly + # from sympy.polys.polytools import GroebnerBasis + x = Symbol('x') + + for c in (Poly, Poly(x, x)): + check(c) + + for c in (PurePoly, PurePoly(x)): + check(c) + + # TODO: fix pickling of Options class (see GroebnerBasis._options) + # for c in (GroebnerBasis, GroebnerBasis([x**2 - 1], x, order=lex)): + # check(c) + +def test_pickling_polys_polyclasses(): + from sympy.polys.polyclasses import DMP, DMF, ANP + + for c in (DMP, DMP([[ZZ(1)], [ZZ(2)], [ZZ(3)]], ZZ)): + check(c, deprecated=['rep']) + for c in (DMF, DMF(([ZZ(1), ZZ(2)], [ZZ(1), ZZ(3)]), ZZ)): + check(c) + for c in (ANP, ANP([QQ(1), QQ(2)], [QQ(1), QQ(2), QQ(3)], QQ)): + check(c) + +@XFAIL +def test_pickling_polys_rings(): + # NOTE: can't use protocols < 2 because we have to execute __new__ to + # make sure caching of rings works properly. + + from sympy.polys.rings import PolyRing + + ring = PolyRing("x,y,z", ZZ, lex) + + for c in (PolyRing, ring): + check(c, exclude=[0, 1]) + + for c in (ring.dtype, ring.one): + check(c, exclude=[0, 1], check_attr=False) # TODO: Py3k + +def test_pickling_polys_fields(): + pass + # NOTE: can't use protocols < 2 because we have to execute __new__ to + # make sure caching of fields works properly. + + # from sympy.polys.fields import FracField + + # field = FracField("x,y,z", ZZ, lex) + + # TODO: AssertionError: assert id(obj) not in self.memo + # for c in (FracField, field): + # check(c, exclude=[0, 1]) + + # TODO: AssertionError: assert id(obj) not in self.memo + # for c in (field.dtype, field.one): + # check(c, exclude=[0, 1]) + +def test_pickling_polys_elements(): + from sympy.polys.domains.pythonrational import PythonRational + #from sympy.polys.domains.pythonfinitefield import PythonFiniteField + #from sympy.polys.domains.mpelements import MPContext + + for c in (PythonRational, PythonRational(1, 7)): + check(c) + + #gf = PythonFiniteField(17) + + # TODO: fix pickling of ModularInteger + # for c in (gf.dtype, gf(5)): + # check(c) + + #mp = MPContext() + + # TODO: fix pickling of RealElement + # for c in (mp.mpf, mp.mpf(1.0)): + # check(c) + + # TODO: fix pickling of ComplexElement + # for c in (mp.mpc, mp.mpc(1.0, -1.5)): + # check(c) + +def test_pickling_polys_domains(): + # from sympy.polys.domains.pythonfinitefield import PythonFiniteField + from sympy.polys.domains.pythonintegerring import PythonIntegerRing + from sympy.polys.domains.pythonrationalfield import PythonRationalField + + # TODO: fix pickling of ModularInteger + # for c in (PythonFiniteField, PythonFiniteField(17)): + # check(c) + + for c in (PythonIntegerRing, PythonIntegerRing()): + check(c, check_attr=False) + + for c in (PythonRationalField, PythonRationalField()): + check(c, check_attr=False) + + if _gmpy is not None: + # from sympy.polys.domains.gmpyfinitefield import GMPYFiniteField + from sympy.polys.domains.gmpyintegerring import GMPYIntegerRing + from sympy.polys.domains.gmpyrationalfield import GMPYRationalField + + # TODO: fix pickling of ModularInteger + # for c in (GMPYFiniteField, GMPYFiniteField(17)): + # check(c) + + for c in (GMPYIntegerRing, GMPYIntegerRing()): + check(c, check_attr=False) + + for c in (GMPYRationalField, GMPYRationalField()): + check(c, check_attr=False) + + #from sympy.polys.domains.realfield import RealField + #from sympy.polys.domains.complexfield import ComplexField + from sympy.polys.domains.algebraicfield import AlgebraicField + #from sympy.polys.domains.polynomialring import PolynomialRing + #from sympy.polys.domains.fractionfield import FractionField + from sympy.polys.domains.expressiondomain import ExpressionDomain + + # TODO: fix pickling of RealElement + # for c in (RealField, RealField(100)): + # check(c) + + # TODO: fix pickling of ComplexElement + # for c in (ComplexField, ComplexField(100)): + # check(c) + + for c in (AlgebraicField, AlgebraicField(QQ, sqrt(3))): + check(c, check_attr=False) + + # TODO: AssertionError + # for c in (PolynomialRing, PolynomialRing(ZZ, "x,y,z")): + # check(c) + + # TODO: AttributeError: 'PolyElement' object has no attribute 'ring' + # for c in (FractionField, FractionField(ZZ, "x,y,z")): + # check(c) + + for c in (ExpressionDomain, ExpressionDomain()): + check(c, check_attr=False) + + +def test_pickling_polys_orderings(): + from sympy.polys.orderings import (LexOrder, GradedLexOrder, + ReversedGradedLexOrder, InverseOrder) + # from sympy.polys.orderings import ProductOrder + + for c in (LexOrder, LexOrder()): + check(c) + + for c in (GradedLexOrder, GradedLexOrder()): + check(c) + + for c in (ReversedGradedLexOrder, ReversedGradedLexOrder()): + check(c) + + # TODO: Argh, Python is so naive. No lambdas nor inner function support in + # pickling module. Maybe someone could figure out what to do with this. + # + # for c in (ProductOrder, ProductOrder((LexOrder(), lambda m: m[:2]), + # (GradedLexOrder(), lambda m: m[2:]))): + # check(c) + + for c in (InverseOrder, InverseOrder(LexOrder())): + check(c) + +def test_pickling_polys_monomials(): + from sympy.polys.monomials import MonomialOps, Monomial + x, y, z = symbols("x,y,z") + + for c in (MonomialOps, MonomialOps(3)): + check(c) + + for c in (Monomial, Monomial((1, 2, 3), (x, y, z))): + check(c) + +def test_pickling_polys_errors(): + from sympy.polys.polyerrors import (HeuristicGCDFailed, + HomomorphismFailed, IsomorphismFailed, ExtraneousFactors, + EvaluationFailed, RefinementFailed, CoercionFailed, NotInvertible, + NotReversible, NotAlgebraic, DomainError, PolynomialError, + UnificationFailed, GeneratorsError, GeneratorsNeeded, + UnivariatePolynomialError, MultivariatePolynomialError, OptionError, + FlagError) + # from sympy.polys.polyerrors import (ExactQuotientFailed, + # OperationNotSupported, ComputationFailed, PolificationFailed) + + # x = Symbol('x') + + # TODO: TypeError: __init__() takes at least 3 arguments (1 given) + # for c in (ExactQuotientFailed, ExactQuotientFailed(x, 3*x, ZZ)): + # check(c) + + # TODO: TypeError: can't pickle instancemethod objects + # for c in (OperationNotSupported, OperationNotSupported(Poly(x), Poly.gcd)): + # check(c) + + for c in (HeuristicGCDFailed, HeuristicGCDFailed()): + check(c) + + for c in (HomomorphismFailed, HomomorphismFailed()): + check(c) + + for c in (IsomorphismFailed, IsomorphismFailed()): + check(c) + + for c in (ExtraneousFactors, ExtraneousFactors()): + check(c) + + for c in (EvaluationFailed, EvaluationFailed()): + check(c) + + for c in (RefinementFailed, RefinementFailed()): + check(c) + + for c in (CoercionFailed, CoercionFailed()): + check(c) + + for c in (NotInvertible, NotInvertible()): + check(c) + + for c in (NotReversible, NotReversible()): + check(c) + + for c in (NotAlgebraic, NotAlgebraic()): + check(c) + + for c in (DomainError, DomainError()): + check(c) + + for c in (PolynomialError, PolynomialError()): + check(c) + + for c in (UnificationFailed, UnificationFailed()): + check(c) + + for c in (GeneratorsError, GeneratorsError()): + check(c) + + for c in (GeneratorsNeeded, GeneratorsNeeded()): + check(c) + + # TODO: PicklingError: Can't pickle at 0x38578c0>: it's not found as __main__. + # for c in (ComputationFailed, ComputationFailed(lambda t: t, 3, None)): + # check(c) + + for c in (UnivariatePolynomialError, UnivariatePolynomialError()): + check(c) + + for c in (MultivariatePolynomialError, MultivariatePolynomialError()): + check(c) + + # TODO: TypeError: __init__() takes at least 3 arguments (1 given) + # for c in (PolificationFailed, PolificationFailed({}, x, x, False)): + # check(c) + + for c in (OptionError, OptionError()): + check(c) + + for c in (FlagError, FlagError()): + check(c) + +#def test_pickling_polys_options(): + #from sympy.polys.polyoptions import Options + + # TODO: fix pickling of `symbols' flag + # for c in (Options, Options((), dict(domain='ZZ', polys=False))): + # check(c) + +# TODO: def test_pickling_polys_rootisolation(): +# RealInterval +# ComplexInterval + +def test_pickling_polys_rootoftools(): + from sympy.polys.rootoftools import CRootOf, RootSum + + x = Symbol('x') + f = x**3 + x + 3 + + for c in (CRootOf, CRootOf(f, 0)): + check(c) + + for c in (RootSum, RootSum(f, exp)): + check(c) + +#================== printing ==================== +from sympy.printing.latex import LatexPrinter +from sympy.printing.mathml import MathMLContentPrinter, MathMLPresentationPrinter +from sympy.printing.pretty.pretty import PrettyPrinter +from sympy.printing.pretty.stringpict import prettyForm, stringPict +from sympy.printing.printer import Printer +from sympy.printing.python import PythonPrinter + + +def test_printing(): + for c in (LatexPrinter, LatexPrinter(), MathMLContentPrinter, + MathMLPresentationPrinter, PrettyPrinter, prettyForm, stringPict, + stringPict("a"), Printer, Printer(), PythonPrinter, + PythonPrinter()): + check(c) + + +@XFAIL +def test_printing1(): + check(MathMLContentPrinter()) + + +@XFAIL +def test_printing2(): + check(MathMLPresentationPrinter()) + + +@XFAIL +def test_printing3(): + check(PrettyPrinter()) + +#================== series ====================== +from sympy.series.limits import Limit +from sympy.series.order import Order + + +def test_series(): + e = Symbol("e") + x = Symbol("x") + for c in (Limit, Limit(e, x, 1), Order, Order(e)): + check(c) + +#================== concrete ================== +from sympy.concrete.products import Product +from sympy.concrete.summations import Sum + + +def test_concrete(): + x = Symbol("x") + for c in (Product, Product(x, (x, 2, 4)), Sum, Sum(x, (x, 2, 4))): + check(c) + +def test_deprecation_warning(): + w = SymPyDeprecationWarning("message", deprecated_since_version='1.0', active_deprecations_target="active-deprecations") + check(w) + +def test_issue_18438(): + assert pickle.loads(pickle.dumps(S.Half)) == S.Half + + +#================= old pickles ================= +def test_unpickle_from_older_versions(): + data = ( + b'\x80\x04\x95^\x00\x00\x00\x00\x00\x00\x00\x8c\x10sympy.core.power' + b'\x94\x8c\x03Pow\x94\x93\x94\x8c\x12sympy.core.numbers\x94\x8c' + b'\x07Integer\x94\x93\x94K\x02\x85\x94R\x94}\x94bh\x03\x8c\x04Half' + b'\x94\x93\x94)R\x94}\x94b\x86\x94R\x94}\x94b.' + ) + assert pickle.loads(data) == sqrt(2) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_source.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_source.py new file mode 100644 index 0000000000000000000000000000000000000000..468185bc579fc325aee21024dfa15ebf14287b5f --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_source.py @@ -0,0 +1,11 @@ +from sympy.utilities.source import get_mod_func, get_class + + +def test_get_mod_func(): + assert get_mod_func( + 'sympy.core.basic.Basic') == ('sympy.core.basic', 'Basic') + + +def test_get_class(): + _basic = get_class('sympy.core.basic.Basic') + assert _basic.__name__ == 'Basic' diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_timeutils.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_timeutils.py new file mode 100644 index 0000000000000000000000000000000000000000..14edfd089c7315ee9f39a4298af0289f8919da6b --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_timeutils.py @@ -0,0 +1,10 @@ +"""Tests for simple tools for timing functions' execution. """ + +from sympy.utilities.timeutils import timed + +def test_timed(): + result = timed(lambda: 1 + 1, limit=100000) + assert result[0] == 100000 and result[3] == "ns", str(result) + + result = timed("1 + 1", limit=100000) + assert result[0] == 100000 and result[3] == "ns" diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_wester.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_wester.py new file mode 100644 index 0000000000000000000000000000000000000000..c5699a4eb0824e507967ecd4ff8f7a5f32cc9a54 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_wester.py @@ -0,0 +1,3104 @@ +""" Tests from Michael Wester's 1999 paper "Review of CAS mathematical +capabilities". + +http://www.math.unm.edu/~wester/cas/book/Wester.pdf +See also http://math.unm.edu/~wester/cas_review.html for detailed output of +each tested system. +""" + +from sympy.assumptions.ask import Q, ask +from sympy.assumptions.refine import refine +from sympy.concrete.products import product +from sympy.core import EulerGamma +from sympy.core.evalf import N +from sympy.core.function import (Derivative, Function, Lambda, Subs, + diff, expand, expand_func) +from sympy.core.mul import Mul +from sympy.core.intfunc import igcd +from sympy.core.numbers import (AlgebraicNumber, E, I, Rational, + nan, oo, pi, zoo) +from sympy.core.relational import Eq, Lt +from sympy.core.singleton import S +from sympy.core.symbol import Dummy, Symbol, symbols +from sympy.functions.combinatorial.factorials import (rf, binomial, + factorial, factorial2) +from sympy.functions.combinatorial.numbers import bernoulli, fibonacci, totient, partition +from sympy.functions.elementary.complexes import (conjugate, im, re, + sign) +from sympy.functions.elementary.exponential import LambertW, exp, log +from sympy.functions.elementary.hyperbolic import (asinh, cosh, sinh, + tanh) +from sympy.functions.elementary.integers import ceiling, floor +from sympy.functions.elementary.miscellaneous import Max, Min, sqrt +from sympy.functions.elementary.piecewise import Piecewise +from sympy.functions.elementary.trigonometric import (acos, acot, asin, + atan, cos, cot, csc, sec, sin, tan) +from sympy.functions.special.bessel import besselj +from sympy.functions.special.delta_functions import DiracDelta +from sympy.functions.special.elliptic_integrals import (elliptic_e, + elliptic_f) +from sympy.functions.special.gamma_functions import gamma, polygamma +from sympy.functions.special.hyper import hyper +from sympy.functions.special.polynomials import (assoc_legendre, + chebyshevt) +from sympy.functions.special.zeta_functions import polylog +from sympy.geometry.util import idiff +from sympy.logic.boolalg import And +from sympy.matrices.dense import hessian, wronskian +from sympy.matrices.expressions.matmul import MatMul +from sympy.ntheory.continued_fraction import ( + continued_fraction_convergents as cf_c, + continued_fraction_iterator as cf_i, continued_fraction_periodic as + cf_p, continued_fraction_reduce as cf_r) +from sympy.ntheory.factor_ import factorint +from sympy.ntheory.generate import primerange +from sympy.polys.domains.integerring import ZZ +from sympy.polys.orthopolys import legendre_poly +from sympy.polys.partfrac import apart +from sympy.polys.polytools import Poly, factor, gcd, resultant +from sympy.series.limits import limit +from sympy.series.order import O +from sympy.series.residues import residue +from sympy.series.series import series +from sympy.sets.fancysets import ImageSet +from sympy.sets.sets import FiniteSet, Intersection, Interval, Union +from sympy.simplify.combsimp import combsimp +from sympy.simplify.hyperexpand import hyperexpand +from sympy.simplify.powsimp import powdenest, powsimp +from sympy.simplify.radsimp import radsimp +from sympy.simplify.simplify import logcombine, simplify +from sympy.simplify.sqrtdenest import sqrtdenest +from sympy.simplify.trigsimp import trigsimp +from sympy.solvers.solvers import solve + +import mpmath +from sympy.functions.combinatorial.numbers import stirling +from sympy.functions.special.delta_functions import Heaviside +from sympy.functions.special.error_functions import Ci, Si, erf +from sympy.functions.special.zeta_functions import zeta +from sympy.testing.pytest import (XFAIL, slow, SKIP, tooslow, raises) +from sympy.utilities.iterables import partitions +from mpmath import mpi, mpc +from sympy.matrices import Matrix, GramSchmidt, eye +from sympy.matrices.expressions.blockmatrix import BlockMatrix, block_collapse +from sympy.matrices.expressions import MatrixSymbol, ZeroMatrix +from sympy.physics.quantum import Commutator +from sympy.polys.rings import PolyRing +from sympy.polys.fields import FracField +from sympy.polys.solvers import solve_lin_sys +from sympy.concrete import Sum +from sympy.concrete.products import Product +from sympy.integrals import integrate +from sympy.integrals.transforms import laplace_transform,\ + inverse_laplace_transform, LaplaceTransform, fourier_transform,\ + mellin_transform, laplace_correspondence, laplace_initial_conds +from sympy.solvers.recurr import rsolve +from sympy.solvers.solveset import solveset, solveset_real, linsolve +from sympy.solvers.ode import dsolve +from sympy.core.relational import Equality +from itertools import islice, takewhile +from sympy.series.formal import fps +from sympy.series.fourier import fourier_series +from sympy.calculus.util import minimum + + +EmptySet = S.EmptySet +R = Rational +x, y, z = symbols('x y z') +i, j, k, l, m, n = symbols('i j k l m n', integer=True) +f = Function('f') +g = Function('g') + +# A. Boolean Logic and Quantifier Elimination +# Not implemented. + +# B. Set Theory + + +def test_B1(): + assert (FiniteSet(i, j, j, k, k, k) | FiniteSet(l, k, j) | + FiniteSet(j, m, j)) == FiniteSet(i, j, k, l, m) + + +def test_B2(): + assert (FiniteSet(i, j, j, k, k, k) & FiniteSet(l, k, j) & + FiniteSet(j, m, j)) == Intersection({j, m}, {i, j, k}, {j, k, l}) + # Previous output below. Not sure why that should be the expected output. + # There should probably be a way to rewrite Intersections that way but I + # don't see why an Intersection should evaluate like that: + # + # == Union({j}, Intersection({m}, Union({j, k}, Intersection({i}, {l})))) + + +def test_B3(): + assert (FiniteSet(i, j, k, l, m) - FiniteSet(j) == + FiniteSet(i, k, l, m)) + + +def test_B4(): + assert (FiniteSet(*(FiniteSet(i, j)*FiniteSet(k, l))) == + FiniteSet((i, k), (i, l), (j, k), (j, l))) + + +# C. Numbers + + +def test_C1(): + assert (factorial(50) == + 30414093201713378043612608166064768844377641568960512000000000000) + + +def test_C2(): + assert (factorint(factorial(50)) == {2: 47, 3: 22, 5: 12, 7: 8, + 11: 4, 13: 3, 17: 2, 19: 2, 23: 2, 29: 1, 31: 1, 37: 1, + 41: 1, 43: 1, 47: 1}) + + +def test_C3(): + assert (factorial2(10), factorial2(9)) == (3840, 945) + + +# Base conversions; not really implemented by SymPy +# Whatever. Take credit! +def test_C4(): + assert 0xABC == 2748 + + +def test_C5(): + assert 123 == int('234', 7) + + +def test_C6(): + assert int('677', 8) == int('1BF', 16) == 447 + + +def test_C7(): + assert log(32768, 8) == 5 + + +def test_C8(): + # Modular multiplicative inverse. Would be nice if divmod could do this. + assert ZZ.invert(5, 7) == 3 + assert ZZ.invert(5, 6) == 5 + + +def test_C9(): + assert igcd(igcd(1776, 1554), 5698) == 74 + + +def test_C10(): + x = 0 + for n in range(2, 11): + x += R(1, n) + assert x == R(4861, 2520) + + +def test_C11(): + assert R(1, 7) == S('0.[142857]') + + +def test_C12(): + assert R(7, 11) * R(22, 7) == 2 + + +def test_C13(): + test = R(10, 7) * (1 + R(29, 1000)) ** R(1, 3) + good = 3 ** R(1, 3) + assert test == good + + +def test_C14(): + assert sqrtdenest(sqrt(2*sqrt(3) + 4)) == 1 + sqrt(3) + + +def test_C15(): + test = sqrtdenest(sqrt(14 + 3*sqrt(3 + 2*sqrt(5 - 12*sqrt(3 - 2*sqrt(2)))))) + good = sqrt(2) + 3 + assert test == good + + +def test_C16(): + test = sqrtdenest(sqrt(10 + 2*sqrt(6) + 2*sqrt(10) + 2*sqrt(15))) + good = sqrt(2) + sqrt(3) + sqrt(5) + assert test == good + + +def test_C17(): + test = radsimp((sqrt(3) + sqrt(2)) / (sqrt(3) - sqrt(2))) + good = 5 + 2*sqrt(6) + assert test == good + + +def test_C18(): + assert simplify((sqrt(-2 + sqrt(-5)) * sqrt(-2 - sqrt(-5))).expand(complex=True)) == 3 + + +@XFAIL +def test_C19(): + assert radsimp(simplify((90 + 34*sqrt(7)) ** R(1, 3))) == 3 + sqrt(7) + + +def test_C20(): + inside = (135 + 78*sqrt(3)) + test = AlgebraicNumber((inside**R(2, 3) + 3) * sqrt(3) / inside**R(1, 3)) + assert simplify(test) == AlgebraicNumber(12) + + +def test_C21(): + assert simplify(AlgebraicNumber((41 + 29*sqrt(2)) ** R(1, 5))) == \ + AlgebraicNumber(1 + sqrt(2)) + + +@XFAIL +def test_C22(): + test = simplify(((6 - 4*sqrt(2))*log(3 - 2*sqrt(2)) + (3 - 2*sqrt(2))*log(17 + - 12*sqrt(2)) + 32 - 24*sqrt(2)) / (48*sqrt(2) - 72)) + good = sqrt(2)/3 - log(sqrt(2) - 1)/3 + assert test == good + + +def test_C23(): + assert 2 * oo - 3 is oo + + +@XFAIL +def test_C24(): + raise NotImplementedError("2**aleph_null == aleph_1") + +# D. Numerical Analysis + + +def test_D1(): + assert 0.0 / sqrt(2) == 0 + + +def test_D2(): + assert str(exp(-1000000).evalf()) == '3.29683147808856e-434295' + + +def test_D3(): + assert exp(pi*sqrt(163)).evalf(50).num.ae(262537412640768744) + + +def test_D4(): + assert floor(R(-5, 3)) == -2 + assert ceiling(R(-5, 3)) == -1 + + +@XFAIL +def test_D5(): + raise NotImplementedError("cubic_spline([1, 2, 4, 5], [1, 4, 2, 3], x)(3) == 27/8") + + +@XFAIL +def test_D6(): + raise NotImplementedError("translate sum(a[i]*x**i, (i,1,n)) to FORTRAN") + + +@XFAIL +def test_D7(): + raise NotImplementedError("translate sum(a[i]*x**i, (i,1,n)) to C") + + +@XFAIL +def test_D8(): + # One way is to cheat by converting the sum to a string, + # and replacing the '[' and ']' with ''. + # E.g., horner(S(str(_).replace('[','').replace(']',''))) + raise NotImplementedError("apply Horner's rule to sum(a[i]*x**i, (i,1,5))") + + +@XFAIL +def test_D9(): + raise NotImplementedError("translate D8 to FORTRAN") + + +@XFAIL +def test_D10(): + raise NotImplementedError("translate D8 to C") + + +@XFAIL +def test_D11(): + #Is there a way to use count_ops? + raise NotImplementedError("flops(sum(product(f[i][k], (i,1,k)), (k,1,n)))") + + +@XFAIL +def test_D12(): + assert (mpi(-4, 2) * x + mpi(1, 3)) ** 2 == mpi(-8, 16)*x**2 + mpi(-24, 12)*x + mpi(1, 9) + + +@XFAIL +def test_D13(): + raise NotImplementedError("discretize a PDE: diff(f(x,t),t) == diff(diff(f(x,t),x),x)") + +# E. Statistics +# See scipy; all of this is numerical. + +# F. Combinatorial Theory. + + +def test_F1(): + assert rf(x, 3) == x*(1 + x)*(2 + x) + + +def test_F2(): + assert expand_func(binomial(n, 3)) == n*(n - 1)*(n - 2)/6 + + +@XFAIL +def test_F3(): + assert combsimp(2**n * factorial(n) * factorial2(2*n - 1)) == factorial(2*n) + + +@XFAIL +def test_F4(): + assert combsimp(2**n * factorial(n) * product(2*k - 1, (k, 1, n))) == factorial(2*n) + + +@XFAIL +def test_F5(): + assert gamma(n + R(1, 2)) / sqrt(pi) / factorial(n) == factorial(2*n)/2**(2*n)/factorial(n)**2 + + +def test_F6(): + partTest = [p.copy() for p in partitions(4)] + partDesired = [{4: 1}, {1: 1, 3: 1}, {2: 2}, {1: 2, 2:1}, {1: 4}] + assert partTest == partDesired + + +def test_F7(): + assert partition(4) == 5 + + +def test_F8(): + assert stirling(5, 2, signed=True) == -50 # if signed, then kind=1 + + +def test_F9(): + assert totient(1776) == 576 + +# G. Number Theory + + +def test_G1(): + assert list(primerange(999983, 1000004)) == [999983, 1000003] + + +@XFAIL +def test_G2(): + raise NotImplementedError("find the primitive root of 191 == 19") + + +@XFAIL +def test_G3(): + raise NotImplementedError("(a+b)**p mod p == a**p + b**p mod p; p prime") + +# ... G14 Modular equations are not implemented. + +def test_G15(): + assert Rational(sqrt(3).evalf()).limit_denominator(15) == R(26, 15) + assert list(takewhile(lambda x: x.q <= 15, cf_c(cf_i(sqrt(3)))))[-1] == \ + R(26, 15) + + +def test_G16(): + assert list(islice(cf_i(pi),10)) == [3, 7, 15, 1, 292, 1, 1, 1, 2, 1] + + +def test_G17(): + assert cf_p(0, 1, 23) == [4, [1, 3, 1, 8]] + + +def test_G18(): + assert cf_p(1, 2, 5) == [[1]] + assert cf_r([[1]]).expand() == S.Half + sqrt(5)/2 + + +@XFAIL +def test_G19(): + s = symbols('s', integer=True, positive=True) + it = cf_i((exp(1/s) - 1)/(exp(1/s) + 1)) + assert list(islice(it, 5)) == [0, 2*s, 6*s, 10*s, 14*s] + + +def test_G20(): + s = symbols('s', integer=True, positive=True) + # Wester erroneously has this as -s + sqrt(s**2 + 1) + assert cf_r([[2*s]]) == s + sqrt(s**2 + 1) + + +@XFAIL +def test_G20b(): + s = symbols('s', integer=True, positive=True) + assert cf_p(s, 1, s**2 + 1) == [[2*s]] + + +# H. Algebra + + +def test_H1(): + assert simplify(2*2**n) == simplify(2**(n + 1)) + assert powdenest(2*2**n) == simplify(2**(n + 1)) + + +def test_H2(): + assert powsimp(4 * 2**n) == 2**(n + 2) + + +def test_H3(): + assert (-1)**(n*(n + 1)) == 1 + + +def test_H4(): + expr = factor(6*x - 10) + assert type(expr) is Mul + assert expr.args[0] == 2 + assert expr.args[1] == 3*x - 5 + +p1 = 64*x**34 - 21*x**47 - 126*x**8 - 46*x**5 - 16*x**60 - 81 +p2 = 72*x**60 - 25*x**25 - 19*x**23 - 22*x**39 - 83*x**52 + 54*x**10 + 81 +q = 34*x**19 - 25*x**16 + 70*x**7 + 20*x**3 - 91*x - 86 + + +def test_H5(): + assert gcd(p1, p2, x) == 1 + + +def test_H6(): + assert gcd(expand(p1 * q), expand(p2 * q)) == q + + +def test_H7(): + p1 = 24*x*y**19*z**8 - 47*x**17*y**5*z**8 + 6*x**15*y**9*z**2 - 3*x**22 + 5 + p2 = 34*x**5*y**8*z**13 + 20*x**7*y**7*z**7 + 12*x**9*y**16*z**4 + 80*y**14*z + assert gcd(p1, p2, x, y, z) == 1 + + +def test_H8(): + p1 = 24*x*y**19*z**8 - 47*x**17*y**5*z**8 + 6*x**15*y**9*z**2 - 3*x**22 + 5 + p2 = 34*x**5*y**8*z**13 + 20*x**7*y**7*z**7 + 12*x**9*y**16*z**4 + 80*y**14*z + q = 11*x**12*y**7*z**13 - 23*x**2*y**8*z**10 + 47*x**17*y**5*z**8 + assert gcd(p1 * q, p2 * q, x, y, z) == q + + +def test_H9(): + x = Symbol('x', zero=False) + p1 = 2*x**(n + 4) - x**(n + 2) + p2 = 4*x**(n + 1) + 3*x**n + assert gcd(p1, p2) == x**n + + +def test_H10(): + p1 = 3*x**4 + 3*x**3 + x**2 - x - 2 + p2 = x**3 - 3*x**2 + x + 5 + assert resultant(p1, p2, x) == 0 + + +def test_H11(): + assert resultant(p1 * q, p2 * q, x) == 0 + + +def test_H12(): + num = x**2 - 4 + den = x**2 + 4*x + 4 + assert simplify(num/den) == (x - 2)/(x + 2) + + +@XFAIL +def test_H13(): + assert simplify((exp(x) - 1) / (exp(x/2) + 1)) == exp(x/2) - 1 + + +def test_H14(): + p = (x + 1) ** 20 + ep = expand(p) + assert ep == (1 + 20*x + 190*x**2 + 1140*x**3 + 4845*x**4 + 15504*x**5 + + 38760*x**6 + 77520*x**7 + 125970*x**8 + 167960*x**9 + 184756*x**10 + + 167960*x**11 + 125970*x**12 + 77520*x**13 + 38760*x**14 + 15504*x**15 + + 4845*x**16 + 1140*x**17 + 190*x**18 + 20*x**19 + x**20) + dep = diff(ep, x) + assert dep == (20 + 380*x + 3420*x**2 + 19380*x**3 + 77520*x**4 + + 232560*x**5 + 542640*x**6 + 1007760*x**7 + 1511640*x**8 + 1847560*x**9 + + 1847560*x**10 + 1511640*x**11 + 1007760*x**12 + 542640*x**13 + + 232560*x**14 + 77520*x**15 + 19380*x**16 + 3420*x**17 + 380*x**18 + + 20*x**19) + assert factor(dep) == 20*(1 + x)**19 + + +def test_H15(): + assert simplify(Mul(*[x - r for r in solveset(x**3 + x**2 - 7)])) == x**3 + x**2 - 7 + + +def test_H16(): + assert factor(x**100 - 1) == ((x - 1)*(x + 1)*(x**2 + 1)*(x**4 - x**3 + + x**2 - x + 1)*(x**4 + x**3 + x**2 + x + 1)*(x**8 - x**6 + x**4 + - x**2 + 1)*(x**20 - x**15 + x**10 - x**5 + 1)*(x**20 + x**15 + x**10 + + x**5 + 1)*(x**40 - x**30 + x**20 - x**10 + 1)) + + +def test_H17(): + assert simplify(factor(expand(p1 * p2)) - p1*p2) == 0 + + +@XFAIL +def test_H18(): + # Factor over complex rationals. + test = factor(4*x**4 + 8*x**3 + 77*x**2 + 18*x + 153) + good = (2*x + 3*I)*(2*x - 3*I)*(x + 1 - 4*I)*(x + 1 + 4*I) + assert test == good + + +def test_H19(): + a = symbols('a') + # The idea is to let a**2 == 2, then solve 1/(a-1). Answer is a+1") + assert Poly(a - 1).invert(Poly(a**2 - 2)) == a + 1 + + +@XFAIL +def test_H20(): + raise NotImplementedError("let a**2==2; (x**3 + (a-2)*x**2 - " + + "(2*a+3)*x - 3*a) / (x**2-2) = (x**2 - 2*x - 3) / (x-a)") + + +@XFAIL +def test_H21(): + raise NotImplementedError("evaluate (b+c)**4 assuming b**3==2, c**2==3. \ + Answer is 2*b + 8*c + 18*b**2 + 12*b*c + 9") + + +def test_H22(): + assert factor(x**4 - 3*x**2 + 1, modulus=5) == (x - 2)**2 * (x + 2)**2 + + +def test_H23(): + f = x**11 + x + 1 + g = (x**2 + x + 1) * (x**9 - x**8 + x**6 - x**5 + x**3 - x**2 + 1) + assert factor(f, modulus=65537) == g + + +def test_H24(): + phi = AlgebraicNumber(S.GoldenRatio.expand(func=True), alias='phi') + assert factor(x**4 - 3*x**2 + 1, extension=phi) == \ + (x - phi)*(x + 1 - phi)*(x - 1 + phi)*(x + phi) + + +def test_H25(): + e = (x - 2*y**2 + 3*z**3) ** 20 + assert factor(expand(e)) == e + + +def test_H26(): + g = expand((sin(x) - 2*cos(y)**2 + 3*tan(z)**3)**20) + assert factor(g, expand=False) == (-sin(x) + 2*cos(y)**2 - 3*tan(z)**3)**20 + + +def test_H27(): + f = 24*x*y**19*z**8 - 47*x**17*y**5*z**8 + 6*x**15*y**9*z**2 - 3*x**22 + 5 + g = 34*x**5*y**8*z**13 + 20*x**7*y**7*z**7 + 12*x**9*y**16*z**4 + 80*y**14*z + h = -2*z*y**7 \ + *(6*x**9*y**9*z**3 + 10*x**7*z**6 + 17*y*x**5*z**12 + 40*y**7) \ + *(3*x**22 + 47*x**17*y**5*z**8 - 6*x**15*y**9*z**2 - 24*x*y**19*z**8 - 5) + assert factor(expand(f*g)) == h + + +@XFAIL +def test_H28(): + raise NotImplementedError("expand ((1 - c**2)**5 * (1 - s**2)**5 * " + + "(c**2 + s**2)**10) with c**2 + s**2 = 1. Answer is c**10*s**10.") + + +@XFAIL +def test_H29(): + assert factor(4*x**2 - 21*x*y + 20*y**2, modulus=3) == (x + y)*(x - y) + + +def test_H30(): + test = factor(x**3 + y**3, extension=sqrt(-3)) + answer = (x + y)*(x + y*(-R(1, 2) - sqrt(3)/2*I))*(x + y*(-R(1, 2) + sqrt(3)/2*I)) + assert answer == test + + +def test_H31(): + f = (x**2 + 2*x + 3)/(x**3 + 4*x**2 + 5*x + 2) + g = 2 / (x + 1)**2 - 2 / (x + 1) + 3 / (x + 2) + assert apart(f) == g + + +@XFAIL +def test_H32(): # issue 6558 + raise NotImplementedError("[A*B*C - (A*B*C)**(-1)]*A*C*B (product \ + of a non-commuting product and its inverse)") + + +def test_H33(): + A, B, C = symbols('A, B, C', commutative=False) + assert (Commutator(A, Commutator(B, C)) + + Commutator(B, Commutator(C, A)) + + Commutator(C, Commutator(A, B))).doit().expand() == 0 + + +# I. Trigonometry + +def test_I1(): + assert tan(pi*R(7, 10)) == -sqrt(1 + 2/sqrt(5)) + + +@XFAIL +def test_I2(): + assert sqrt((1 + cos(6))/2) == -cos(3) + + +def test_I3(): + assert cos(n*pi) + sin((4*n - 1)*pi/2) == (-1)**n - 1 + + +def test_I4(): + assert refine(cos(pi*cos(n*pi)) + sin(pi/2*cos(n*pi)), Q.integer(n)) == (-1)**n - 1 + + +@XFAIL +def test_I5(): + assert sin((n**5/5 + n**4/2 + n**3/3 - n/30) * pi) == 0 + + +@XFAIL +def test_I6(): + raise NotImplementedError("assuming -3*pi pi**E) + + +@XFAIL +def test_N2(): + x = symbols('x', real=True) + assert ask(x**4 - x + 1 > 0) is True + assert ask(x**4 - x + 1 > 1) is False + + +@XFAIL +def test_N3(): + x = symbols('x', real=True) + assert ask(And(Lt(-1, x), Lt(x, 1)), abs(x) < 1 ) + +@XFAIL +def test_N4(): + x, y = symbols('x y', real=True) + assert ask(2*x**2 > 2*y**2, (x > y) & (y > 0)) is True + + +@XFAIL +def test_N5(): + x, y, k = symbols('x y k', real=True) + assert ask(k*x**2 > k*y**2, (x > y) & (y > 0) & (k > 0)) is True + + +@slow +@XFAIL +def test_N6(): + x, y, k, n = symbols('x y k n', real=True) + assert ask(k*x**n > k*y**n, (x > y) & (y > 0) & (k > 0) & (n > 0)) is True + + +@XFAIL +def test_N7(): + x, y = symbols('x y', real=True) + assert ask(y > 0, (x > 1) & (y >= x - 1)) is True + + +@XFAIL +@slow +def test_N8(): + x, y, z = symbols('x y z', real=True) + assert ask(Eq(x, y) & Eq(y, z), + (x >= y) & (y >= z) & (z >= x)) + + +def test_N9(): + x = Symbol('x') + assert solveset(abs(x - 1) > 2, domain=S.Reals) == Union(Interval(-oo, -1, False, True), + Interval(3, oo, True)) + + +def test_N10(): + x = Symbol('x') + p = (x - 1)*(x - 2)*(x - 3)*(x - 4)*(x - 5) + assert solveset(expand(p) < 0, domain=S.Reals) == Union(Interval(-oo, 1, True, True), + Interval(2, 3, True, True), + Interval(4, 5, True, True)) + + +def test_N11(): + x = Symbol('x') + assert solveset(6/(x - 3) <= 3, domain=S.Reals) == Union(Interval(-oo, 3, True, True), Interval(5, oo)) + + +def test_N12(): + x = Symbol('x') + assert solveset(sqrt(x) < 2, domain=S.Reals) == Interval(0, 4, False, True) + + +def test_N13(): + x = Symbol('x') + assert solveset(sin(x) < 2, domain=S.Reals) == S.Reals + + +@XFAIL +def test_N14(): + x = Symbol('x') + # Gives 'Union(Interval(Integer(0), Mul(Rational(1, 2), pi), false, true), + # Interval(Mul(Rational(1, 2), pi), Mul(Integer(2), pi), true, false))' + # which is not the correct answer, but the provided also seems wrong. + assert solveset(sin(x) < 1, x, domain=S.Reals) == Union(Interval(-oo, pi/2, True, True), + Interval(pi/2, oo, True, True)) + + +def test_N15(): + r, t = symbols('r t') + # raises NotImplementedError: only univariate inequalities are supported + solveset(abs(2*r*(cos(t) - 1) + 1) <= 1, r, S.Reals) + + +def test_N16(): + r, t = symbols('r t') + solveset((r**2)*((cos(t) - 4)**2)*sin(t)**2 < 9, r, S.Reals) + + +@XFAIL +def test_N17(): + # currently only univariate inequalities are supported + assert solveset((x + y > 0, x - y < 0), (x, y)) == (abs(x) < y) + + +def test_O1(): + M = Matrix((1 + I, -2, 3*I)) + assert sqrt(expand(M.dot(M.H))) == sqrt(15) + + +def test_O2(): + assert Matrix((2, 2, -3)).cross(Matrix((1, 3, 1))) == Matrix([[11], + [-5], + [4]]) + +# The vector module has no way of representing vectors symbolically (without +# respect to a basis) +@XFAIL +def test_O3(): + # assert (va ^ vb) | (vc ^ vd) == -(va | vc)*(vb | vd) + (va | vd)*(vb | vc) + raise NotImplementedError("""The vector module has no way of representing + vectors symbolically (without respect to a basis)""") + +def test_O4(): + from sympy.vector import CoordSys3D, Del + N = CoordSys3D("N") + delop = Del() + i, j, k = N.base_vectors() + x, y, z = N.base_scalars() + F = i*(x*y*z) + j*((x*y*z)**2) + k*((y**2)*(z**3)) + assert delop.cross(F).doit() == (-2*x**2*y**2*z + 2*y*z**3)*i + x*y*j + (2*x*y**2*z**2 - x*z)*k + +@XFAIL +def test_O5(): + #assert grad|(f^g)-g|(grad^f)+f|(grad^g) == 0 + raise NotImplementedError("""The vector module has no way of representing + vectors symbolically (without respect to a basis)""") + +#testO8-O9 MISSING!! + + +def test_O10(): + L = [Matrix([2, 3, 5]), Matrix([3, 6, 2]), Matrix([8, 3, 6])] + assert GramSchmidt(L) == [Matrix([ + [2], + [3], + [5]]), + Matrix([ + [R(23, 19)], + [R(63, 19)], + [R(-47, 19)]]), + Matrix([ + [R(1692, 353)], + [R(-1551, 706)], + [R(-423, 706)]])] + + +def test_P1(): + assert Matrix(3, 3, lambda i, j: j - i).diagonal(-1) == Matrix( + 1, 2, [-1, -1]) + + +def test_P2(): + M = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + M.row_del(1) + M.col_del(2) + assert M == Matrix([[1, 2], + [7, 8]]) + + +def test_P3(): + A = Matrix([ + [11, 12, 13, 14], + [21, 22, 23, 24], + [31, 32, 33, 34], + [41, 42, 43, 44]]) + + A11 = A[0:3, 1:4] + A12 = A[(0, 1, 3), (2, 0, 3)] + A21 = A + A221 = -A[0:2, 2:4] + A222 = -A[(3, 0), (2, 1)] + A22 = BlockMatrix([[A221, A222]]).T + rows = [[-A11, A12], [A21, A22]] + raises(ValueError, lambda: BlockMatrix(rows)) + B = Matrix(rows) + assert B == Matrix([ + [-12, -13, -14, 13, 11, 14], + [-22, -23, -24, 23, 21, 24], + [-32, -33, -34, 43, 41, 44], + [11, 12, 13, 14, -13, -23], + [21, 22, 23, 24, -14, -24], + [31, 32, 33, 34, -43, -13], + [41, 42, 43, 44, -42, -12]]) + + +@XFAIL +def test_P4(): + raise NotImplementedError("Block matrix diagonalization not supported") + + +def test_P5(): + M = Matrix([[7, 11], + [3, 8]]) + assert M % 2 == Matrix([[1, 1], + [1, 0]]) + + +def test_P6(): + M = Matrix([[cos(x), sin(x)], + [-sin(x), cos(x)]]) + assert M.diff(x, 2) == Matrix([[-cos(x), -sin(x)], + [sin(x), -cos(x)]]) + + +def test_P7(): + M = Matrix([[x, y]])*( + z*Matrix([[1, 3, 5], + [2, 4, 6]]) + Matrix([[7, -9, 11], + [-8, 10, -12]])) + assert M == Matrix([[x*(z + 7) + y*(2*z - 8), x*(3*z - 9) + y*(4*z + 10), + x*(5*z + 11) + y*(6*z - 12)]]) + + +def test_P8(): + M = Matrix([[1, -2*I], + [-3*I, 4]]) + assert M.norm(ord=S.Infinity) == 7 + + +def test_P9(): + a, b, c = symbols('a b c', nonzero=True) + M = Matrix([[a/(b*c), 1/c, 1/b], + [1/c, b/(a*c), 1/a], + [1/b, 1/a, c/(a*b)]]) + assert factor(M.norm('fro')) == (a**2 + b**2 + c**2)/(abs(a)*abs(b)*abs(c)) + + +@XFAIL +def test_P10(): + M = Matrix([[1, 2 + 3*I], + [f(4 - 5*I), 6]]) + # conjugate(f(4 - 5*i)) is not simplified to f(4+5*I) + assert M.H == Matrix([[1, f(4 + 5*I)], + [2 + 3*I, 6]]) + + +@XFAIL +def test_P11(): + # raises NotImplementedError("Matrix([[x,y],[1,x*y]]).inv() + # not simplifying to extract common factor") + assert Matrix([[x, y], + [1, x*y]]).inv() == (1/(x**2 - 1))*Matrix([[x, -1], + [-1/y, x/y]]) + + +def test_P11_workaround(): + # This test was changed to inverse method ADJ because it depended on the + # specific form of inverse returned from the 'GE' method which has changed. + M = Matrix([[x, y], [1, x*y]]).inv('ADJ') + c = gcd(tuple(M)) + assert MatMul(c, M/c, evaluate=False) == MatMul(c, Matrix([ + [x*y, -y], + [ -1, x]]), evaluate=False) + + +def test_P12(): + A11 = MatrixSymbol('A11', n, n) + A12 = MatrixSymbol('A12', n, n) + A22 = MatrixSymbol('A22', n, n) + B = BlockMatrix([[A11, A12], + [ZeroMatrix(n, n), A22]]) + assert block_collapse(B.I) == BlockMatrix([[A11.I, (-1)*A11.I*A12*A22.I], + [ZeroMatrix(n, n), A22.I]]) + + +def test_P13(): + M = Matrix([[1, x - 2, x - 3], + [x - 1, x**2 - 3*x + 6, x**2 - 3*x - 2], + [x - 2, x**2 - 8, 2*(x**2) - 12*x + 14]]) + L, U, _ = M.LUdecomposition() + assert simplify(L) == Matrix([[1, 0, 0], + [x - 1, 1, 0], + [x - 2, x - 3, 1]]) + assert simplify(U) == Matrix([[1, x - 2, x - 3], + [0, 4, x - 5], + [0, 0, x - 7]]) + + +def test_P14(): + M = Matrix([[1, 2, 3, 1, 3], + [3, 2, 1, 1, 7], + [0, 2, 4, 1, 1], + [1, 1, 1, 1, 4]]) + R, _ = M.rref() + assert R == Matrix([[1, 0, -1, 0, 2], + [0, 1, 2, 0, -1], + [0, 0, 0, 1, 3], + [0, 0, 0, 0, 0]]) + + +def test_P15(): + M = Matrix([[-1, 3, 7, -5], + [4, -2, 1, 3], + [2, 4, 15, -7]]) + assert M.rank() == 2 + + +def test_P16(): + M = Matrix([[2*sqrt(2), 8], + [6*sqrt(6), 24*sqrt(3)]]) + assert M.rank() == 1 + + +def test_P17(): + t = symbols('t', real=True) + M=Matrix([ + [sin(2*t), cos(2*t)], + [2*(1 - (cos(t)**2))*cos(t), (1 - 2*(sin(t)**2))*sin(t)]]) + assert M.rank() == 1 + + +def test_P18(): + M = Matrix([[1, 0, -2, 0], + [-2, 1, 0, 3], + [-1, 2, -6, 6]]) + assert M.nullspace() == [Matrix([[2], + [4], + [1], + [0]]), + Matrix([[0], + [-3], + [0], + [1]])] + + +def test_P19(): + w = symbols('w') + M = Matrix([[1, 1, 1, 1], + [w, x, y, z], + [w**2, x**2, y**2, z**2], + [w**3, x**3, y**3, z**3]]) + assert M.det() == (w**3*x**2*y - w**3*x**2*z - w**3*x*y**2 + w**3*x*z**2 + + w**3*y**2*z - w**3*y*z**2 - w**2*x**3*y + w**2*x**3*z + + w**2*x*y**3 - w**2*x*z**3 - w**2*y**3*z + w**2*y*z**3 + + w*x**3*y**2 - w*x**3*z**2 - w*x**2*y**3 + w*x**2*z**3 + + w*y**3*z**2 - w*y**2*z**3 - x**3*y**2*z + x**3*y*z**2 + + x**2*y**3*z - x**2*y*z**3 - x*y**3*z**2 + x*y**2*z**3 + ) + + +@XFAIL +def test_P20(): + raise NotImplementedError("Matrix minimal polynomial not supported") + + +def test_P21(): + M = Matrix([[5, -3, -7], + [-2, 1, 2], + [2, -3, -4]]) + assert M.charpoly(x).as_expr() == x**3 - 2*x**2 - 5*x + 6 + + +def test_P22(): + d = 100 + M = (2 - x)*eye(d) + assert M.eigenvals() == {-x + 2: d} + + +def test_P23(): + M = Matrix([ + [2, 1, 0, 0, 0], + [1, 2, 1, 0, 0], + [0, 1, 2, 1, 0], + [0, 0, 1, 2, 1], + [0, 0, 0, 1, 2]]) + assert M.eigenvals() == { + S('1'): 1, + S('2'): 1, + S('3'): 1, + S('sqrt(3) + 2'): 1, + S('-sqrt(3) + 2'): 1} + + +def test_P24(): + M = Matrix([[611, 196, -192, 407, -8, -52, -49, 29], + [196, 899, 113, -192, -71, -43, -8, -44], + [-192, 113, 899, 196, 61, 49, 8, 52], + [ 407, -192, 196, 611, 8, 44, 59, -23], + [ -8, -71, 61, 8, 411, -599, 208, 208], + [ -52, -43, 49, 44, -599, 411, 208, 208], + [ -49, -8, 8, 59, 208, 208, 99, -911], + [ 29, -44, 52, -23, 208, 208, -911, 99]]) + assert M.eigenvals() == { + S('0'): 1, + S('10*sqrt(10405)'): 1, + S('100*sqrt(26) + 510'): 1, + S('1000'): 2, + S('-100*sqrt(26) + 510'): 1, + S('-10*sqrt(10405)'): 1, + S('1020'): 1} + + +def test_P25(): + MF = N(Matrix([[ 611, 196, -192, 407, -8, -52, -49, 29], + [ 196, 899, 113, -192, -71, -43, -8, -44], + [-192, 113, 899, 196, 61, 49, 8, 52], + [ 407, -192, 196, 611, 8, 44, 59, -23], + [ -8, -71, 61, 8, 411, -599, 208, 208], + [ -52, -43, 49, 44, -599, 411, 208, 208], + [ -49, -8, 8, 59, 208, 208, 99, -911], + [ 29, -44, 52, -23, 208, 208, -911, 99]])) + + ev_1 = sorted(MF.eigenvals(multiple=True)) + ev_2 = sorted( + [-1020.0490184299969, 0.0, 0.09804864072151699, 1000.0, 1000.0, + 1019.9019513592784, 1020.0, 1020.0490184299969]) + + for x, y in zip(ev_1, ev_2): + assert abs(x - y) < 1e-12 + + +def test_P26(): + a0, a1, a2, a3, a4 = symbols('a0 a1 a2 a3 a4') + M = Matrix([[-a4, -a3, -a2, -a1, -a0, 0, 0, 0, 0], + [ 1, 0, 0, 0, 0, 0, 0, 0, 0], + [ 0, 1, 0, 0, 0, 0, 0, 0, 0], + [ 0, 0, 1, 0, 0, 0, 0, 0, 0], + [ 0, 0, 0, 1, 0, 0, 0, 0, 0], + [ 0, 0, 0, 0, 0, -1, -1, 0, 0], + [ 0, 0, 0, 0, 0, 1, 0, 0, 0], + [ 0, 0, 0, 0, 0, 0, 1, -1, -1], + [ 0, 0, 0, 0, 0, 0, 0, 1, 0]]) + assert M.eigenvals(error_when_incomplete=False) == { + S('-1/2 - sqrt(3)*I/2'): 2, + S('-1/2 + sqrt(3)*I/2'): 2} + + +def test_P27(): + a = symbols('a') + M = Matrix([[a, 0, 0, 0, 0], + [0, 0, 0, 0, 1], + [0, 0, a, 0, 0], + [0, 0, 0, a, 0], + [0, -2, 0, 0, 2]]) + + assert M.eigenvects() == [ + (a, 3, [ + Matrix([1, 0, 0, 0, 0]), + Matrix([0, 0, 1, 0, 0]), + Matrix([0, 0, 0, 1, 0]) + ]), + (1 - I, 1, [ + Matrix([0, (1 + I)/2, 0, 0, 1]) + ]), + (1 + I, 1, [ + Matrix([0, (1 - I)/2, 0, 0, 1]) + ]), + ] + + +@XFAIL +def test_P28(): + raise NotImplementedError("Generalized eigenvectors not supported \ +https://github.com/sympy/sympy/issues/5293") + + +@XFAIL +def test_P29(): + raise NotImplementedError("Generalized eigenvectors not supported \ +https://github.com/sympy/sympy/issues/5293") + + +def test_P30(): + M = Matrix([[1, 0, 0, 1, -1], + [0, 1, -2, 3, -3], + [0, 0, -1, 2, -2], + [1, -1, 1, 0, 1], + [1, -1, 1, -1, 2]]) + _, J = M.jordan_form() + assert J == Matrix([[-1, 0, 0, 0, 0], + [0, 1, 1, 0, 0], + [0, 0, 1, 0, 0], + [0, 0, 0, 1, 1], + [0, 0, 0, 0, 1]]) + + +@XFAIL +def test_P31(): + raise NotImplementedError("Smith normal form not implemented") + + +def test_P32(): + M = Matrix([[1, -2], + [2, 1]]) + assert exp(M).rewrite(cos).simplify() == Matrix([[E*cos(2), -E*sin(2)], + [E*sin(2), E*cos(2)]]) + + +def test_P33(): + w, t = symbols('w t') + M = Matrix([[0, 1, 0, 0], + [0, 0, 0, 2*w], + [0, 0, 0, 1], + [0, -2*w, 3*w**2, 0]]) + assert exp(M*t).rewrite(cos).expand() == Matrix([ + [1, -3*t + 4*sin(t*w)/w, 6*t*w - 6*sin(t*w), -2*cos(t*w)/w + 2/w], + [0, 4*cos(t*w) - 3, -6*w*cos(t*w) + 6*w, 2*sin(t*w)], + [0, 2*cos(t*w)/w - 2/w, -3*cos(t*w) + 4, sin(t*w)/w], + [0, -2*sin(t*w), 3*w*sin(t*w), cos(t*w)]]) + + +@XFAIL +def test_P34(): + a, b, c = symbols('a b c', real=True) + M = Matrix([[a, 1, 0, 0, 0, 0], + [0, a, 0, 0, 0, 0], + [0, 0, b, 0, 0, 0], + [0, 0, 0, c, 1, 0], + [0, 0, 0, 0, c, 1], + [0, 0, 0, 0, 0, c]]) + # raises exception, sin(M) not supported. exp(M*I) also not supported + # https://github.com/sympy/sympy/issues/6218 + assert sin(M) == Matrix([[sin(a), cos(a), 0, 0, 0, 0], + [0, sin(a), 0, 0, 0, 0], + [0, 0, sin(b), 0, 0, 0], + [0, 0, 0, sin(c), cos(c), -sin(c)/2], + [0, 0, 0, 0, sin(c), cos(c)], + [0, 0, 0, 0, 0, sin(c)]]) + + +@XFAIL +def test_P35(): + M = pi/2*Matrix([[2, 1, 1], + [2, 3, 2], + [1, 1, 2]]) + # raises exception, sin(M) not supported. exp(M*I) also not supported + # https://github.com/sympy/sympy/issues/6218 + assert sin(M) == eye(3) + + +@XFAIL +def test_P36(): + M = Matrix([[10, 7], + [7, 17]]) + assert sqrt(M) == Matrix([[3, 1], + [1, 4]]) + + +def test_P37(): + M = Matrix([[1, 1, 0], + [0, 1, 0], + [0, 0, 1]]) + assert M**S.Half == Matrix([[1, R(1, 2), 0], + [0, 1, 0], + [0, 0, 1]]) + + +@XFAIL +def test_P38(): + M=Matrix([[0, 1, 0], + [0, 0, 0], + [0, 0, 0]]) + + with raises(AssertionError): + # raises ValueError: Matrix det == 0; not invertible + M**S.Half + # if it doesn't raise then this assertion will be + # raised and the test will be flagged as not XFAILing + assert None + +@XFAIL +def test_P39(): + """ + M=Matrix([ + [1, 1], + [2, 2], + [3, 3]]) + M.SVD() + """ + raise NotImplementedError("Singular value decomposition not implemented") + + +def test_P40(): + r, t = symbols('r t', real=True) + M = Matrix([r*cos(t), r*sin(t)]) + assert M.jacobian(Matrix([r, t])) == Matrix([[cos(t), -r*sin(t)], + [sin(t), r*cos(t)]]) + + +def test_P41(): + r, t = symbols('r t', real=True) + assert hessian(r**2*sin(t),(r,t)) == Matrix([[ 2*sin(t), 2*r*cos(t)], + [2*r*cos(t), -r**2*sin(t)]]) + + +def test_P42(): + assert wronskian([cos(x), sin(x)], x).simplify() == 1 + + +def test_P43(): + def __my_jacobian(M, Y): + return Matrix([M.diff(v).T for v in Y]).T + r, t = symbols('r t', real=True) + M = Matrix([r*cos(t), r*sin(t)]) + assert __my_jacobian(M,[r,t]) == Matrix([[cos(t), -r*sin(t)], + [sin(t), r*cos(t)]]) + + +def test_P44(): + def __my_hessian(f, Y): + V = Matrix([diff(f, v) for v in Y]) + return Matrix([V.T.diff(v) for v in Y]) + r, t = symbols('r t', real=True) + assert __my_hessian(r**2*sin(t), (r, t)) == Matrix([ + [ 2*sin(t), 2*r*cos(t)], + [2*r*cos(t), -r**2*sin(t)]]) + + +def test_P45(): + def __my_wronskian(Y, v): + M = Matrix([Matrix(Y).T.diff(x, n) for n in range(0, len(Y))]) + return M.det() + assert __my_wronskian([cos(x), sin(x)], x).simplify() == 1 + +# Q1-Q6 Tensor tests missing + + +@XFAIL +def test_R1(): + i, j, n = symbols('i j n', integer=True, positive=True) + xn = MatrixSymbol('xn', n, 1) + Sm = Sum((xn[i, 0] - Sum(xn[j, 0], (j, 0, n - 1))/n)**2, (i, 0, n - 1)) + # sum does not calculate + # Unknown result + Sm.doit() + raise NotImplementedError('Unknown result') + +@XFAIL +def test_R2(): + m, b = symbols('m b') + i, n = symbols('i n', integer=True, positive=True) + xn = MatrixSymbol('xn', n, 1) + yn = MatrixSymbol('yn', n, 1) + f = Sum((yn[i, 0] - m*xn[i, 0] - b)**2, (i, 0, n - 1)) + f1 = diff(f, m) + f2 = diff(f, b) + # raises TypeError: solveset() takes at most 2 arguments (3 given) + solveset((f1, f2), (m, b), domain=S.Reals) + + +@XFAIL +def test_R3(): + n, k = symbols('n k', integer=True, positive=True) + sk = ((-1)**k) * (binomial(2*n, k))**2 + Sm = Sum(sk, (k, 1, oo)) + T = Sm.doit() + T2 = T.combsimp() + # returns -((-1)**n*factorial(2*n) + # - (factorial(n))**2)*exp_polar(-I*pi)/(factorial(n))**2 + assert T2 == (-1)**n*binomial(2*n, n) + + +@XFAIL +def test_R4(): +# Macsyma indefinite sum test case: +#(c15) /* Check whether the full Gosper algorithm is implemented +# => 1/2^(n + 1) binomial(n, k - 1) */ +#closedform(indefsum(binomial(n, k)/2^n - binomial(n + 1, k)/2^(n + 1), k)); +#Time= 2690 msecs +# (- n + k - 1) binomial(n + 1, k) +#(d15) - -------------------------------- +# n +# 2 2 (n + 1) +# +#(c16) factcomb(makefact(%)); +#Time= 220 msecs +# n! +#(d16) ---------------- +# n +# 2 k! 2 (n - k)! +# Might be possible after fixing https://github.com/sympy/sympy/pull/1879 + raise NotImplementedError("Indefinite sum not supported") + + +@XFAIL +def test_R5(): + a, b, c, n, k = symbols('a b c n k', integer=True, positive=True) + sk = ((-1)**k)*(binomial(a + b, a + k) + *binomial(b + c, b + k)*binomial(c + a, c + k)) + Sm = Sum(sk, (k, 1, oo)) + T = Sm.doit() # hypergeometric series not calculated + assert T == factorial(a+b+c)/(factorial(a)*factorial(b)*factorial(c)) + + +def test_R6(): + n, k = symbols('n k', integer=True, positive=True) + gn = MatrixSymbol('gn', n + 2, 1) + Sm = Sum(gn[k, 0] - gn[k - 1, 0], (k, 1, n + 1)) + assert Sm.doit() == -gn[0, 0] + gn[n + 1, 0] + + +def test_R7(): + n, k = symbols('n k', integer=True, positive=True) + T = Sum(k**3,(k,1,n)).doit() + assert T.factor() == n**2*(n + 1)**2/4 + +@XFAIL +def test_R8(): + n, k = symbols('n k', integer=True, positive=True) + Sm = Sum(k**2*binomial(n, k), (k, 1, n)) + T = Sm.doit() #returns Piecewise function + assert T.combsimp() == n*(n + 1)*2**(n - 2) + + +def test_R9(): + n, k = symbols('n k', integer=True, positive=True) + Sm = Sum(binomial(n, k - 1)/k, (k, 1, n + 1)) + assert Sm.doit().simplify() == (2**(n + 1) - 1)/(n + 1) + + +@XFAIL +def test_R10(): + n, m, r, k = symbols('n m r k', integer=True, positive=True) + Sm = Sum(binomial(n, k)*binomial(m, r - k), (k, 0, r)) + T = Sm.doit() + T2 = T.combsimp().rewrite(factorial) + assert T2 == factorial(m + n)/(factorial(r)*factorial(m + n - r)) + assert T2 == binomial(m + n, r).rewrite(factorial) + # rewrite(binomial) is not working. + # https://github.com/sympy/sympy/issues/7135 + T3 = T2.rewrite(binomial) + assert T3 == binomial(m + n, r) + + +@XFAIL +def test_R11(): + n, k = symbols('n k', integer=True, positive=True) + sk = binomial(n, k)*fibonacci(k) + Sm = Sum(sk, (k, 0, n)) + T = Sm.doit() + # Fibonacci simplification not implemented + # https://github.com/sympy/sympy/issues/7134 + assert T == fibonacci(2*n) + + +@XFAIL +def test_R12(): + n, k = symbols('n k', integer=True, positive=True) + Sm = Sum(fibonacci(k)**2, (k, 0, n)) + T = Sm.doit() + assert T == fibonacci(n)*fibonacci(n + 1) + + +@XFAIL +def test_R13(): + n, k = symbols('n k', integer=True, positive=True) + Sm = Sum(sin(k*x), (k, 1, n)) + T = Sm.doit() # Sum is not calculated + assert T.simplify() == cot(x/2)/2 - cos(x*(2*n + 1)/2)/(2*sin(x/2)) + + +@XFAIL +def test_R14(): + n, k = symbols('n k', integer=True, positive=True) + Sm = Sum(sin((2*k - 1)*x), (k, 1, n)) + T = Sm.doit() # Sum is not calculated + assert T.simplify() == sin(n*x)**2/sin(x) + + +@XFAIL +def test_R15(): + n, k = symbols('n k', integer=True, positive=True) + Sm = Sum(binomial(n - k, k), (k, 0, floor(n/2))) + T = Sm.doit() # Sum is not calculated + assert T.simplify() == fibonacci(n + 1) + + +def test_R16(): + k = symbols('k', integer=True, positive=True) + Sm = Sum(1/k**2 + 1/k**3, (k, 1, oo)) + assert Sm.doit() == zeta(3) + pi**2/6 + + +def test_R17(): + k = symbols('k', integer=True, positive=True) + assert abs(float(Sum(1/k**2 + 1/k**3, (k, 1, oo))) + - 2.8469909700078206) < 1e-15 + + +def test_R18(): + k = symbols('k', integer=True, positive=True) + Sm = Sum(1/(2**k*k**2), (k, 1, oo)) + T = Sm.doit() + assert T.simplify() == -log(2)**2/2 + pi**2/12 + + +@slow +@XFAIL +def test_R19(): + k = symbols('k', integer=True, positive=True) + Sm = Sum(1/((3*k + 1)*(3*k + 2)*(3*k + 3)), (k, 0, oo)) + T = Sm.doit() + # assert fails, T not simplified + assert T.simplify() == -log(3)/4 + sqrt(3)*pi/12 + + +@XFAIL +def test_R20(): + n, k = symbols('n k', integer=True, positive=True) + Sm = Sum(binomial(n, 4*k), (k, 0, oo)) + T = Sm.doit() + # assert fails, T not simplified + assert T.simplify() == 2**(n/2)*cos(pi*n/4)/2 + 2**(n - 1)/2 + + +@XFAIL +def test_R21(): + k = symbols('k', integer=True, positive=True) + Sm = Sum(1/(sqrt(k*(k + 1)) * (sqrt(k) + sqrt(k + 1))), (k, 1, oo)) + T = Sm.doit() # Sum not calculated + assert T.simplify() == 1 + + +# test_R22 answer not available in Wester samples +# Sum(Sum(binomial(n, k)*binomial(n - k, n - 2*k)*x**n*y**(n - 2*k), +# (k, 0, floor(n/2))), (n, 0, oo)) with abs(x*y)<1? + + +@XFAIL +def test_R23(): + n, k = symbols('n k', integer=True, positive=True) + Sm = Sum(Sum((factorial(n)/(factorial(k)**2*factorial(n - 2*k)))* + (x/y)**k*(x*y)**(n - k), (n, 2*k, oo)), (k, 0, oo)) + # Missing how to express constraint abs(x*y)<1? + T = Sm.doit() # Sum not calculated + assert T == -1/sqrt(x**2*y**2 - 4*x**2 - 2*x*y + 1) + + +def test_R24(): + m, k = symbols('m k', integer=True, positive=True) + Sm = Sum(Product(k/(2*k - 1), (k, 1, m)), (m, 2, oo)) + assert Sm.doit() == pi/2 + + +def test_S1(): + k = symbols('k', integer=True, positive=True) + Pr = Product(gamma(k/3), (k, 1, 8)) + assert Pr.doit().simplify() == 640*sqrt(3)*pi**3/6561 + + +def test_S2(): + n, k = symbols('n k', integer=True, positive=True) + assert Product(k, (k, 1, n)).doit() == factorial(n) + + +def test_S3(): + n, k = symbols('n k', integer=True, positive=True) + assert Product(x**k, (k, 1, n)).doit().simplify() == x**(n*(n + 1)/2) + + +def test_S4(): + n, k = symbols('n k', integer=True, positive=True) + assert Product(1 + 1/k, (k, 1, n -1)).doit().simplify() == n + + +def test_S5(): + n, k = symbols('n k', integer=True, positive=True) + assert (Product((2*k - 1)/(2*k), (k, 1, n)).doit().gammasimp() == + gamma(n + S.Half)/(sqrt(pi)*gamma(n + 1))) + + +@XFAIL +def test_S6(): + n, k = symbols('n k', integer=True, positive=True) + # Product does not evaluate + assert (Product(x**2 -2*x*cos(k*pi/n) + 1, (k, 1, n - 1)).doit().simplify() + == (x**(2*n) - 1)/(x**2 - 1)) + + +@XFAIL +def test_S7(): + k = symbols('k', integer=True, positive=True) + Pr = Product((k**3 - 1)/(k**3 + 1), (k, 2, oo)) + T = Pr.doit() # Product does not evaluate + assert T.simplify() == R(2, 3) + + +@XFAIL +def test_S8(): + k = symbols('k', integer=True, positive=True) + Pr = Product(1 - 1/(2*k)**2, (k, 1, oo)) + T = Pr.doit() + # Product does not evaluate + assert T.simplify() == 2/pi + + +@XFAIL +def test_S9(): + k = symbols('k', integer=True, positive=True) + Pr = Product(1 + (-1)**(k + 1)/(2*k - 1), (k, 1, oo)) + T = Pr.doit() + # Product produces 0 + # https://github.com/sympy/sympy/issues/7133 + assert T.simplify() == sqrt(2) + + +@XFAIL +def test_S10(): + k = symbols('k', integer=True, positive=True) + Pr = Product((k*(k + 1) + 1 + I)/(k*(k + 1) + 1 - I), (k, 0, oo)) + T = Pr.doit() + # Product does not evaluate + assert T.simplify() == -1 + + +def test_T1(): + assert limit((1 + 1/n)**n, n, oo) == E + assert limit((1 - cos(x))/x**2, x, 0) == S.Half + + +def test_T2(): + assert limit((3**x + 5**x)**(1/x), x, oo) == 5 + + +def test_T3(): + assert limit(log(x)/(log(x) + sin(x)), x, oo) == 1 + + +def test_T4(): + assert limit((exp(x*exp(-x)/(exp(-x) + exp(-2*x**2/(x + 1)))) + - exp(x))/x, x, oo) == -exp(2) + + +def test_T5(): + assert limit(x*log(x)*log(x*exp(x) - x**2)**2/log(log(x**2 + + 2*exp(exp(3*x**3*log(x))))), x, oo) == R(1, 3) + + +def test_T6(): + assert limit(1/n * factorial(n)**(1/n), n, oo) == exp(-1) + + +def test_T7(): + limit(1/n * gamma(n + 1)**(1/n), n, oo) + + +def test_T8(): + a, z = symbols('a z', positive=True) + assert limit(gamma(z + a)/gamma(z)*exp(-a*log(z)), z, oo) == 1 + + +@XFAIL +def test_T9(): + z, k = symbols('z k', positive=True) + # raises NotImplementedError: + # Don't know how to calculate the mrv of '(1, k)' + assert limit(hyper((1, k), (1,), z/k), k, oo) == exp(z) + + +@XFAIL +def test_T10(): + # No longer raises PoleError, but should return euler-mascheroni constant + assert limit(zeta(x) - 1/(x - 1), x, 1) == integrate(-1/x + 1/floor(x), (x, 1, oo)) + +@XFAIL +def test_T11(): + n, k = symbols('n k', integer=True, positive=True) + # evaluates to 0 + assert limit(n**x/(x*product((1 + x/k), (k, 1, n))), n, oo) == gamma(x) + + +def test_T12(): + x, t = symbols('x t', real=True) + # Does not evaluate the limit but returns an expression with erf + assert limit(x * integrate(exp(-t**2), (t, 0, x))/(1 - exp(-x**2)), + x, 0) == 1 + + +def test_T13(): + x = symbols('x', real=True) + assert [limit(x/abs(x), x, 0, dir='-'), + limit(x/abs(x), x, 0, dir='+')] == [-1, 1] + + +def test_T14(): + x = symbols('x', real=True) + assert limit(atan(-log(x)), x, 0, dir='+') == pi/2 + + +def test_U1(): + x = symbols('x', real=True) + assert diff(abs(x), x) == sign(x) + + +def test_U2(): + f = Lambda(x, Piecewise((-x, x < 0), (x, x >= 0))) + assert diff(f(x), x) == Piecewise((-1, x < 0), (1, x >= 0)) + + +def test_U3(): + f = Lambda(x, Piecewise((x**2 - 1, x == 1), (x**3, x != 1))) + f1 = Lambda(x, diff(f(x), x)) + assert f1(x) == 3*x**2 + assert f1(1) == 3 + + +@XFAIL +def test_U4(): + n = symbols('n', integer=True, positive=True) + x = symbols('x', real=True) + d = diff(x**n, x, n) + assert d.rewrite(factorial) == factorial(n) + + +def test_U5(): + # issue 6681 + t = symbols('t') + ans = ( + Derivative(f(g(t)), g(t))*Derivative(g(t), (t, 2)) + + Derivative(f(g(t)), (g(t), 2))*Derivative(g(t), t)**2) + assert f(g(t)).diff(t, 2) == ans + assert ans.doit() == ans + + +def test_U6(): + h = Function('h') + T = integrate(f(y), (y, h(x), g(x))) + assert T.diff(x) == ( + f(g(x))*Derivative(g(x), x) - f(h(x))*Derivative(h(x), x)) + + +@XFAIL +def test_U7(): + p, t = symbols('p t', real=True) + # Exact differential => d(V(P, T)) => dV/dP DP + dV/dT DT + # raises ValueError: Since there is more than one variable in the + # expression, the variable(s) of differentiation must be supplied to + # differentiate f(p,t) + diff(f(p, t)) + + +def test_U8(): + x, y = symbols('x y', real=True) + eq = cos(x*y) + x + # If SymPy had implicit_diff() function this hack could be avoided + # TODO: Replace solve with solveset, current test fails for solveset + assert idiff(y - eq, y, x) == (-y*sin(x*y) + 1)/(x*sin(x*y) + 1) + + +def test_U9(): + # Wester sample case for Maple: + # O29 := diff(f(x, y), x) + diff(f(x, y), y); + # /d \ /d \ + # |-- f(x, y)| + |-- f(x, y)| + # \dx / \dy / + # + # O30 := factor(subs(f(x, y) = g(x^2 + y^2), %)); + # 2 2 + # 2 D(g)(x + y ) (x + y) + x, y = symbols('x y', real=True) + su = diff(f(x, y), x) + diff(f(x, y), y) + s2 = su.subs(f(x, y), g(x**2 + y**2)) + s3 = s2.doit().factor() + # Subs not performed, s3 = 2*(x + y)*Subs(Derivative( + # g(_xi_1), _xi_1), _xi_1, x**2 + y**2) + # Derivative(g(x*2 + y**2), x**2 + y**2) is not valid in SymPy, + # and probably will remain that way. You can take derivatives with respect + # to other expressions only if they are atomic, like a symbol or a + # function. + # D operator should be added to SymPy + # See https://github.com/sympy/sympy/issues/4719. + assert s3 == (x + y)*Subs(Derivative(g(x), x), x, x**2 + y**2)*2 + + +def test_U10(): + # see issue 2519: + assert residue((z**3 + 5)/((z**4 - 1)*(z + 1)), z, -1) == R(-9, 4) + +@XFAIL +def test_U11(): + # assert (2*dx + dz) ^ (3*dx + dy + dz) ^ (dx + dy + 4*dz) == 8*dx ^ dy ^dz + raise NotImplementedError + + +@XFAIL +def test_U12(): + # Wester sample case: + # (c41) /* d(3 x^5 dy /\ dz + 5 x y^2 dz /\ dx + 8 z dx /\ dy) + # => (15 x^4 + 10 x y + 8) dx /\ dy /\ dz */ + # factor(ext_diff(3*x^5 * dy ~ dz + 5*x*y^2 * dz ~ dx + 8*z * dx ~ dy)); + # 4 + # (d41) (10 x y + 15 x + 8) dx dy dz + raise NotImplementedError( + "External diff of differential form not supported") + + +def test_U13(): + assert minimum(x**4 - x + 1, x) == -3*2**R(1,3)/8 + 1 + + +@XFAIL +def test_U14(): + #f = 1/(x**2 + y**2 + 1) + #assert [minimize(f), maximize(f)] == [0,1] + raise NotImplementedError("minimize(), maximize() not supported") + + +@XFAIL +def test_U15(): + raise NotImplementedError("minimize() not supported and also solve does \ +not support multivariate inequalities") + + +@XFAIL +def test_U16(): + raise NotImplementedError("minimize() not supported in SymPy and also \ +solve does not support multivariate inequalities") + + +@XFAIL +def test_U17(): + raise NotImplementedError("Linear programming, symbolic simplex not \ +supported in SymPy") + + +def test_V1(): + x = symbols('x', real=True) + assert integrate(abs(x), x) == Piecewise((-x**2/2, x <= 0), (x**2/2, True)) + + +def test_V2(): + assert integrate(Piecewise((-x, x < 0), (x, x >= 0)), x + ) == Piecewise((-x**2/2, x < 0), (x**2/2, True)) + + +def test_V3(): + assert integrate(1/(x**3 + 2),x).diff().simplify() == 1/(x**3 + 2) + + +def test_V4(): + assert integrate(2**x/sqrt(1 + 4**x), x) == asinh(2**x)/log(2) + + +@XFAIL +def test_V5(): + # Returns (-45*x**2 + 80*x - 41)/(5*sqrt(2*x - 1)*(4*x**2 - 4*x + 1)) + assert (integrate((3*x - 5)**2/(2*x - 1)**R(7, 2), x).simplify() == + (-41 + 80*x - 45*x**2)/(5*(2*x - 1)**R(5, 2))) + + +@XFAIL +def test_V6(): + # returns RootSum(40*_z**2 - 1, Lambda(_i, _i*log(-4*_i + exp(-m*x))))/m + assert (integrate(1/(2*exp(m*x) - 5*exp(-m*x)), x) == sqrt(10)*( + log(2*exp(m*x) - sqrt(10)) - log(2*exp(m*x) + sqrt(10)))/(20*m)) + + +def test_V7(): + r1 = integrate(sinh(x)**4/cosh(x)**2) + assert r1.simplify() == x*R(-3, 2) + sinh(x)**3/(2*cosh(x)) + 3*tanh(x)/2 + + +@XFAIL +def test_V8_V9(): +#Macsyma test case: +#(c27) /* This example involves several symbolic parameters +# => 1/sqrt(b^2 - a^2) log([sqrt(b^2 - a^2) tan(x/2) + a + b]/ +# [sqrt(b^2 - a^2) tan(x/2) - a - b]) (a^2 < b^2) +# [Gradshteyn and Ryzhik 2.553(3)] */ +#assume(b^2 > a^2)$ +#(c28) integrate(1/(a + b*cos(x)), x); +#(c29) trigsimp(ratsimp(diff(%, x))); +# 1 +#(d29) ------------ +# b cos(x) + a + raise NotImplementedError( + "Integrate with assumption not supported") + + +def test_V10(): + assert integrate(1/(3 + 3*cos(x) + 4*sin(x)), x) == log(4*tan(x/2) + 3)/4 + + +def test_V11(): + r1 = integrate(1/(4 + 3*cos(x) + 4*sin(x)), x) + r2 = factor(r1) + assert (logcombine(r2, force=True) == + log(((tan(x/2) + 1)/(tan(x/2) + 7))**R(1, 3))) + + +def test_V12(): + r1 = integrate(1/(5 + 3*cos(x) + 4*sin(x)), x) + assert r1 == -1/(tan(x/2) + 2) + + +@XFAIL +def test_V13(): + r1 = integrate(1/(6 + 3*cos(x) + 4*sin(x)), x) + # expression not simplified, returns: -sqrt(11)*I*log(tan(x/2) + 4/3 + # - sqrt(11)*I/3)/11 + sqrt(11)*I*log(tan(x/2) + 4/3 + sqrt(11)*I/3)/11 + assert r1.simplify() == 2*sqrt(11)*atan(sqrt(11)*(3*tan(x/2) + 4)/11)/11 + + +@slow +@XFAIL +def test_V14(): + r1 = integrate(log(abs(x**2 - y**2)), x) + # Piecewise result does not simplify to the desired result. + assert (r1.simplify() == x*log(abs(x**2 - y**2)) + + y*log(x + y) - y*log(x - y) - 2*x) + + +def test_V15(): + r1 = integrate(x*acot(x/y), x) + assert simplify(r1 - (x*y + (x**2 + y**2)*acot(x/y))/2) == 0 + + +@XFAIL +def test_V16(): + # Integral not calculated + assert integrate(cos(5*x)*Ci(2*x), x) == Ci(2*x)*sin(5*x)/5 - (Si(3*x) + Si(7*x))/10 + +@XFAIL +def test_V17(): + r1 = integrate((diff(f(x), x)*g(x) + - f(x)*diff(g(x), x))/(f(x)**2 - g(x)**2), x) + # integral not calculated + assert simplify(r1 - (f(x) - g(x))/(f(x) + g(x))/2) == 0 + + +@XFAIL +def test_W1(): + # The function has a pole at y. + # The integral has a Cauchy principal value of zero but SymPy returns -I*pi + # https://github.com/sympy/sympy/issues/7159 + assert integrate(1/(x - y), (x, y - 1, y + 1)) == 0 + + +@XFAIL +def test_W2(): + # The function has a pole at y. + # The integral is divergent but SymPy returns -2 + # https://github.com/sympy/sympy/issues/7160 + # Test case in Macsyma: + # (c6) errcatch(integrate(1/(x - a)^2, x, a - 1, a + 1)); + # Integral is divergent + assert integrate(1/(x - y)**2, (x, y - 1, y + 1)) is zoo + + +@XFAIL +@slow +def test_W3(): + # integral is not calculated + # https://github.com/sympy/sympy/issues/7161 + assert integrate(sqrt(x + 1/x - 2), (x, 0, 1)) == R(4, 3) + + +@XFAIL +@slow +def test_W4(): + # integral is not calculated + assert integrate(sqrt(x + 1/x - 2), (x, 1, 2)) == -2*sqrt(2)/3 + R(4, 3) + + +@XFAIL +@slow +def test_W5(): + # integral is not calculated + assert integrate(sqrt(x + 1/x - 2), (x, 0, 2)) == -2*sqrt(2)/3 + R(8, 3) + + +@XFAIL +@slow +def test_W6(): + # integral is not calculated + assert integrate(sqrt(2 - 2*cos(2*x))/2, (x, pi*R(-3, 4), -pi/4)) == sqrt(2) + + +def test_W7(): + a = symbols('a', positive=True) + r1 = integrate(cos(x)/(x**2 + a**2), (x, -oo, oo)) + assert r1.simplify() == pi*exp(-a)/a + + +@XFAIL +def test_W8(): + # Test case in Mathematica: + # In[19]:= Integrate[t^(a - 1)/(1 + t), {t, 0, Infinity}, + # Assumptions -> 0 < a < 1] + # Out[19]= Pi Csc[a Pi] + raise NotImplementedError( + "Integrate with assumption 0 < a < 1 not supported") + + +@XFAIL +@slow +def test_W9(): + # Integrand with a residue at infinity => -2 pi [sin(pi/5) + sin(2pi/5)] + # (principal value) [Levinson and Redheffer, p. 234] *) + r1 = integrate(5*x**3/(1 + x + x**2 + x**3 + x**4), (x, -oo, oo)) + r2 = r1.doit() + assert r2 == -2*pi*(sqrt(-sqrt(5)/8 + 5/8) + sqrt(sqrt(5)/8 + 5/8)) + + +@XFAIL +def test_W10(): + # integrate(1/[1 + x + x^2 + ... + x^(2 n)], x = -infinity..infinity) = + # 2 pi/(2 n + 1) [1 + cos(pi/[2 n + 1])] csc(2 pi/[2 n + 1]) + # [Levinson and Redheffer, p. 255] => 2 pi/5 [1 + cos(pi/5)] csc(2 pi/5) */ + r1 = integrate(x/(1 + x + x**2 + x**4), (x, -oo, oo)) + r2 = r1.doit() + assert r2 == 2*pi*(sqrt(5)/4 + 5/4)*csc(pi*R(2, 5))/5 + + +@XFAIL +def test_W11(): + # integral not calculated + assert (integrate(sqrt(1 - x**2)/(1 + x**2), (x, -1, 1)) == + pi*(-1 + sqrt(2))) + + +def test_W12(): + p = symbols('p', positive=True) + q = symbols('q', real=True) + r1 = integrate(x*exp(-p*x**2 + 2*q*x), (x, -oo, oo)) + assert r1.simplify() == sqrt(pi)*q*exp(q**2/p)/p**R(3, 2) + + +@XFAIL +def test_W13(): + # Integral not calculated. Expected result is 2*(Euler_mascheroni_constant) + r1 = integrate(1/log(x) + 1/(1 - x) - log(log(1/x)), (x, 0, 1)) + assert r1 == 2*EulerGamma + + +def test_W14(): + assert integrate(sin(x)/x*exp(2*I*x), (x, -oo, oo)) == 0 + + +@XFAIL +def test_W15(): + # integral not calculated + assert integrate(log(gamma(x))*cos(6*pi*x), (x, 0, 1)) == R(1, 12) + + +def test_W16(): + assert integrate((1 + x)**3*legendre_poly(1, x)*legendre_poly(2, x), + (x, -1, 1)) == R(36, 35) + + +def test_W17(): + a, b = symbols('a b', positive=True) + assert integrate(exp(-a*x)*besselj(0, b*x), + (x, 0, oo)) == 1/(b*sqrt(a**2/b**2 + 1)) + + +def test_W18(): + assert integrate((besselj(1, x)/x)**2, (x, 0, oo)) == 4/(3*pi) + + +@XFAIL +def test_W19(): + # Integral not calculated + # Expected result is (cos 7 - 1)/7 [Gradshteyn and Ryzhik 6.782(3)] + assert integrate(Ci(x)*besselj(0, 2*sqrt(7*x)), (x, 0, oo)) == (cos(7) - 1)/7 + + +@XFAIL +def test_W20(): + # integral not calculated + assert (integrate(x**2*polylog(3, 1/(x + 1)), (x, 0, 1)) == + -pi**2/36 - R(17, 108) + zeta(3)/4 + + (-pi**2/2 - 4*log(2) + log(2)**2 + 35/3)*log(2)/9) + + +def test_W21(): + assert abs(N(integrate(x**2*polylog(3, 1/(x + 1)), (x, 0, 1))) + - 0.210882859565594) < 1e-15 + + +def test_W22(): + t, u = symbols('t u', real=True) + s = Lambda(x, Piecewise((1, And(x >= 1, x <= 2)), (0, True))) + assert integrate(s(t)*cos(t), (t, 0, u)) == Piecewise( + (0, u < 0), + (-sin(Min(1, u)) + sin(Min(2, u)), True)) + + +@slow +def test_W23(): + a, b = symbols('a b', positive=True) + r1 = integrate(integrate(x/(x**2 + y**2), (x, a, b)), (y, -oo, oo)) + assert r1.collect(pi).cancel() == -pi*a + pi*b + + +def test_W23b(): + # like W23 but limits are reversed + a, b = symbols('a b', positive=True) + r2 = integrate(integrate(x/(x**2 + y**2), (y, -oo, oo)), (x, a, b)) + assert r2.collect(pi) == pi*(-a + b) + + +@XFAIL +@tooslow +def test_W24(): + # Not that slow, but does not fully evaluate so simplify is slow. + # Maybe also require doit() + x, y = symbols('x y', real=True) + r1 = integrate(integrate(sqrt(x**2 + y**2), (x, 0, 1)), (y, 0, 1)) + assert (r1 - (sqrt(2) + asinh(1))/3).simplify() == 0 + + +@XFAIL +@tooslow +def test_W25(): + a, x, y = symbols('a x y', real=True) + i1 = integrate( + sin(a)*sin(y)/sqrt(1 - sin(a)**2*sin(x)**2*sin(y)**2), + (x, 0, pi/2)) + i2 = integrate(i1, (y, 0, pi/2)) + assert (i2 - pi*a/2).simplify() == 0 + + +def test_W26(): + x, y = symbols('x y', real=True) + assert integrate(integrate(abs(y - x**2), (y, 0, 2)), + (x, -1, 1)) == R(46, 15) + + +def test_W27(): + a, b, c = symbols('a b c') + assert integrate(integrate(integrate(1, (z, 0, c*(1 - x/a - y/b))), + (y, 0, b*(1 - x/a))), + (x, 0, a)) == a*b*c/6 + + +def test_X1(): + v, c = symbols('v c', real=True) + assert (series(1/sqrt(1 - (v/c)**2), v, x0=0, n=8) == + 5*v**6/(16*c**6) + 3*v**4/(8*c**4) + v**2/(2*c**2) + 1 + O(v**8)) + + +def test_X2(): + v, c = symbols('v c', real=True) + s1 = series(1/sqrt(1 - (v/c)**2), v, x0=0, n=8) + assert (1/s1**2).series(v, x0=0, n=8) == -v**2/c**2 + 1 + O(v**8) + + +def test_X3(): + s1 = (sin(x).series()/cos(x).series()).series() + s2 = tan(x).series() + assert s2 == x + x**3/3 + 2*x**5/15 + O(x**6) + assert s1 == s2 + + +def test_X4(): + s1 = log(sin(x)/x).series() + assert s1 == -x**2/6 - x**4/180 + O(x**6) + assert log(series(sin(x)/x)).series() == s1 + + +@XFAIL +def test_X5(): + # test case in Mathematica syntax: + # In[21]:= (* => [a f'(a d) + g(b d) + integrate(h(c y), y = 0..d)] + # + [a^2 f''(a d) + b g'(b d) + h(c d)] (x - d) *) + # In[22]:= D[f[a*x], x] + g[b*x] + Integrate[h[c*y], {y, 0, x}] + # Out[22]= g[b x] + Integrate[h[c y], {y, 0, x}] + a f'[a x] + # In[23]:= Series[%, {x, d, 1}] + # Out[23]= (g[b d] + Integrate[h[c y], {y, 0, d}] + a f'[a d]) + + # 2 2 + # (h[c d] + b g'[b d] + a f''[a d]) (-d + x) + O[-d + x] + h = Function('h') + a, b, c, d = symbols('a b c d', real=True) + # series() raises NotImplementedError: + # The _eval_nseries method should be added to to give terms up to O(x**n) at x=0 + series(diff(f(a*x), x) + g(b*x) + integrate(h(c*y), (y, 0, x)), + x, x0=d, n=2) + # assert missing, until exception is removed + + +def test_X6(): + # Taylor series of nonscalar objects (noncommutative multiplication) + # expected result => (B A - A B) t^2/2 + O(t^3) [Stanly Steinberg] + a, b = symbols('a b', commutative=False, scalar=False) + assert (series(exp((a + b)*x) - exp(a*x) * exp(b*x), x, x0=0, n=3) == + x**2*(-a*b/2 + b*a/2) + O(x**3)) + + +def test_X7(): + # => sum( Bernoulli[k]/k! x^(k - 2), k = 1..infinity ) + # = 1/x^2 - 1/(2 x) + 1/12 - x^2/720 + x^4/30240 + O(x^6) + # [Levinson and Redheffer, p. 173] + assert (series(1/(x*(exp(x) - 1)), x, 0, 7) == x**(-2) - 1/(2*x) + + R(1, 12) - x**2/720 + x**4/30240 - x**6/1209600 + O(x**7)) + + +def test_X8(): + # Puiseux series (terms with fractional degree): + # => 1/sqrt(x - 3/2 pi) + (x - 3/2 pi)^(3/2) / 12 + O([x - 3/2 pi]^(7/2)) + + # see issue 7167: + x = symbols('x', real=True) + assert (series(sqrt(sec(x)), x, x0=pi*3/2, n=4) == + 1/sqrt(x - pi*R(3, 2)) + (x - pi*R(3, 2))**R(3, 2)/12 + + (x - pi*R(3, 2))**R(7, 2)/160 + O((x - pi*R(3, 2))**4, (x, pi*R(3, 2)))) + + +def test_X9(): + assert (series(x**x, x, x0=0, n=4) == 1 + x*log(x) + x**2*log(x)**2/2 + + x**3*log(x)**3/6 + O(x**4*log(x)**4)) + + +def test_X10(): + z, w = symbols('z w') + assert (series(log(sinh(z)) + log(cosh(z + w)), z, x0=0, n=2) == + log(cosh(w)) + log(z) + z*sinh(w)/cosh(w) + O(z**2)) + + +def test_X11(): + z, w = symbols('z w') + assert (series(log(sinh(z) * cosh(z + w)), z, x0=0, n=2) == + log(cosh(w)) + log(z) + z*sinh(w)/cosh(w) + O(z**2)) + + +@XFAIL +def test_X12(): + # Look at the generalized Taylor series around x = 1 + # Result => (x - 1)^a/e^b [1 - (a + 2 b) (x - 1) / 2 + O((x - 1)^2)] + a, b, x = symbols('a b x', real=True) + # series returns O(log(x-1)**2) + # https://github.com/sympy/sympy/issues/7168 + assert (series(log(x)**a*exp(-b*x), x, x0=1, n=2) == + (x - 1)**a/exp(b)*(1 - (a + 2*b)*(x - 1)/2 + O((x - 1)**2))) + + +def test_X13(): + assert series(sqrt(2*x**2 + 1), x, x0=oo, n=1) == sqrt(2)*x + O(1/x, (x, oo)) + + +@XFAIL +def test_X14(): + # Wallis' product => 1/sqrt(pi n) + ... [Knopp, p. 385] + assert series(1/2**(2*n)*binomial(2*n, n), + n, x==oo, n=1) == 1/(sqrt(pi)*sqrt(n)) + O(1/x, (x, oo)) + + +@SKIP("https://github.com/sympy/sympy/issues/7164") +def test_X15(): + # => 0!/x - 1!/x^2 + 2!/x^3 - 3!/x^4 + O(1/x^5) [Knopp, p. 544] + x, t = symbols('x t', real=True) + # raises RuntimeError: maximum recursion depth exceeded + # https://github.com/sympy/sympy/issues/7164 + # 2019-02-17: Raises + # PoleError: + # Asymptotic expansion of Ei around [-oo] is not implemented. + e1 = integrate(exp(-t)/t, (t, x, oo)) + assert (series(e1, x, x0=oo, n=5) == + 6/x**4 + 2/x**3 - 1/x**2 + 1/x + O(x**(-5), (x, oo))) + + +def test_X16(): + # Multivariate Taylor series expansion => 1 - (x^2 + 2 x y + y^2)/2 + O(x^4) + assert (series(cos(x + y), x + y, x0=0, n=4) == 1 - (x + y)**2/2 + + O(x**4 + x**3*y + x**2*y**2 + x*y**3 + y**4, x, y)) + + +@XFAIL +def test_X17(): + # Power series (compute the general formula) + # (c41) powerseries(log(sin(x)/x), x, 0); + # /aquarius/data2/opt/local/macsyma_422/library1/trgred.so being loaded. + # inf + # ==== i1 2 i1 2 i1 + # \ (- 1) 2 bern(2 i1) x + # (d41) > ------------------------------ + # / 2 i1 (2 i1)! + # ==== + # i1 = 1 + # fps does not calculate + assert fps(log(sin(x)/x)) == \ + Sum((-1)**k*2**(2*k - 1)*bernoulli(2*k)*x**(2*k)/(k*factorial(2*k)), (k, 1, oo)) + + +@XFAIL +def test_X18(): + # Power series (compute the general formula). Maple FPS: + # > FormalPowerSeries(exp(-x)*sin(x), x = 0); + # infinity + # ----- (1/2 k) k + # \ 2 sin(3/4 k Pi) x + # ) ------------------------- + # / k! + # ----- + # + # Now, SymPy returns + # oo + # _____ + # \ ` + # \ / k k\ + # \ k |I*(-1 - I) I*(-1 + I) | + # \ x *|----------- - -----------| + # / \ 2 2 / + # / ------------------------------ + # / k! + # /____, + # k = 0 + k = Dummy('k') + assert fps(exp(-x)*sin(x)) == \ + Sum(2**(S.Half*k)*sin(R(3, 4)*k*pi)*x**k/factorial(k), (k, 0, oo)) + + +@XFAIL +def test_X19(): + # (c45) /* Derive an explicit Taylor series solution of y as a function of + # x from the following implicit relation: + # y = x - 1 + (x - 1)^2/2 + 2/3 (x - 1)^3 + (x - 1)^4 + + # 17/10 (x - 1)^5 + ... + # */ + # x = sin(y) + cos(y); + # Time= 0 msecs + # (d45) x = sin(y) + cos(y) + # + # (c46) taylor_revert(%, y, 7); + raise NotImplementedError("Solve using series not supported. \ +Inverse Taylor series expansion also not supported") + + +@XFAIL +def test_X20(): + # Pade (rational function) approximation => (2 - x)/(2 + x) + # > numapprox[pade](exp(-x), x = 0, [1, 1]); + # bytes used=9019816, alloc=3669344, time=13.12 + # 1 - 1/2 x + # --------- + # 1 + 1/2 x + # mpmath support numeric Pade approximant but there is + # no symbolic implementation in SymPy + # https://en.wikipedia.org/wiki/Pad%C3%A9_approximant + raise NotImplementedError("Symbolic Pade approximant not supported") + + +def test_X21(): + """ + Test whether `fourier_series` of x periodical on the [-p, p] interval equals + `- (2 p / pi) sum( (-1)^n / n sin(n pi x / p), n = 1..infinity )`. + """ + p = symbols('p', positive=True) + n = symbols('n', positive=True, integer=True) + s = fourier_series(x, (x, -p, p)) + + # All cosine coefficients are equal to 0 + assert s.an.formula == 0 + + # Check for sine coefficients + assert s.bn.formula.subs(s.bn.variables[0], 0) == 0 + assert s.bn.formula.subs(s.bn.variables[0], n) == \ + -2*p/pi * (-1)**n / n * sin(n*pi*x/p) + + +@XFAIL +def test_X22(): + # (c52) /* => p / 2 + # - (2 p / pi^2) sum( [1 - (-1)^n] cos(n pi x / p) / n^2, + # n = 1..infinity ) */ + # fourier_series(abs(x), x, p); + # p + # (e52) a = - + # 0 2 + # + # %nn + # (2 (- 1) - 2) p + # (e53) a = ------------------ + # %nn 2 2 + # %pi %nn + # + # (e54) b = 0 + # %nn + # + # Time= 5290 msecs + # inf %nn %pi %nn x + # ==== (2 (- 1) - 2) cos(---------) + # \ p + # p > ------------------------------- + # / 2 + # ==== %nn + # %nn = 1 p + # (d54) ----------------------------------------- + - + # 2 2 + # %pi + raise NotImplementedError("Fourier series not supported") + + +def test_Y1(): + t = symbols('t', positive=True) + w = symbols('w', real=True) + s = symbols('s') + F, _, _ = laplace_transform(cos((w - 1)*t), t, s) + assert F == s/(s**2 + (w - 1)**2) + + +def test_Y2(): + t = symbols('t', positive=True) + w = symbols('w', real=True) + s = symbols('s') + f = inverse_laplace_transform(s/(s**2 + (w - 1)**2), s, t, simplify=True) + assert f == cos(t*(w - 1)) + + +def test_Y3(): + t = symbols('t', positive=True) + w = symbols('w', real=True) + s = symbols('s') + F, _, _ = laplace_transform(sinh(w*t)*cosh(w*t), t, s, simplify=True) + assert F == w/(s**2 - 4*w**2) + + +def test_Y4(): + t = symbols('t', positive=True) + s = symbols('s') + F, _, _ = laplace_transform(erf(3/sqrt(t)), t, s, simplify=True) + assert F == 1/s - exp(-6*sqrt(s))/s + + +def test_Y5_Y6(): +# Solve y'' + y = 4 [H(t - 1) - H(t - 2)], y(0) = 1, y'(0) = 0 where H is the +# Heaviside (unit step) function (the RHS describes a pulse of magnitude 4 and +# duration 1). See David A. Sanchez, Richard C. Allen, Jr. and Walter T. +# Kyner, _Differential Equations: An Introduction_, Addison-Wesley Publishing +# Company, 1983, p. 211. First, take the Laplace transform of the ODE +# => s^2 Y(s) - s + Y(s) = 4/s [e^(-s) - e^(-2 s)] +# where Y(s) is the Laplace transform of y(t) + t = symbols('t', real=True) + s = symbols('s') + y = Function('y') + Y = Function('Y') + F = laplace_correspondence(laplace_transform(diff(y(t), t, 2) + y(t) + - 4*(Heaviside(t - 1) - Heaviside(t - 2)), + t, s, noconds=True), {y: Y}) + D = ( + -F + s**2*Y(s) - s*y(0) + Y(s) - Subs(Derivative(y(t), t), t, 0) - + 4*exp(-s)/s + 4*exp(-2*s)/s) + assert D == 0 +# Now, solve for Y(s) and then take the inverse Laplace transform +# => Y(s) = s/(s^2 + 1) + 4 [1/s - s/(s^2 + 1)] [e^(-s) - e^(-2 s)] +# => y(t) = cos t + 4 {[1 - cos(t - 1)] H(t - 1) - [1 - cos(t - 2)] H(t - 2)} + Yf = solve(F, Y(s))[0] + Yf = laplace_initial_conds(Yf, t, {y: [1, 0]}) + assert Yf == (s**2*exp(2*s) + 4*exp(s) - 4)*exp(-2*s)/(s*(s**2 + 1)) + yf = inverse_laplace_transform(Yf, s, t) + yf = yf.collect(Heaviside(t-1)).collect(Heaviside(t-2)) + assert yf == ( + (4 - 4*cos(t - 1))*Heaviside(t - 1) + + (4*cos(t - 2) - 4)*Heaviside(t - 2) + + cos(t)*Heaviside(t)) + + +@XFAIL +def test_Y7(): + # What is the Laplace transform of an infinite square wave? + # => 1/s + 2 sum( (-1)^n e^(- s n a)/s, n = 1..infinity ) + # [Sanchez, Allen and Kyner, p. 213] + t = symbols('t', positive=True) + a = symbols('a', real=True) + s = symbols('s') + F, _, _ = laplace_transform(1 + 2*Sum((-1)**n*Heaviside(t - n*a), + (n, 1, oo)), t, s) + # returns 2*LaplaceTransform(Sum((-1)**n*Heaviside(-a*n + t), + # (n, 1, oo)), t, s) + 1/s + # https://github.com/sympy/sympy/issues/7177 + assert F == 2*Sum((-1)**n*exp(-a*n*s)/s, (n, 1, oo)) + 1/s + + +@XFAIL +def test_Y8(): + assert fourier_transform(1, x, z) == DiracDelta(z) + + +def test_Y9(): + assert (fourier_transform(exp(-9*x**2), x, z) == + sqrt(pi)*exp(-pi**2*z**2/9)/3) + + +def test_Y10(): + assert (fourier_transform(abs(x)*exp(-3*abs(x)), x, z).cancel() == + (-8*pi**2*z**2 + 18)/(16*pi**4*z**4 + 72*pi**2*z**2 + 81)) + + +@SKIP("https://github.com/sympy/sympy/issues/7181") +@slow +def test_Y11(): + # => pi cot(pi s) (0 < Re s < 1) [Gradshteyn and Ryzhik 17.43(5)] + x, s = symbols('x s') + # raises RuntimeError: maximum recursion depth exceeded + # https://github.com/sympy/sympy/issues/7181 + # Update 2019-02-17 raises: + # TypeError: cannot unpack non-iterable MellinTransform object + F, _, _ = mellin_transform(1/(1 - x), x, s) + assert F == pi*cot(pi*s) + + +@XFAIL +def test_Y12(): + # => 2^(s - 4) gamma(s/2)/gamma(4 - s/2) (0 < Re s < 1) + # [Gradshteyn and Ryzhik 17.43(16)] + x, s = symbols('x s') + # returns Wrong value -2**(s - 4)*gamma(s/2 - 3)/gamma(-s/2 + 1) + # https://github.com/sympy/sympy/issues/7182 + F, _, _ = mellin_transform(besselj(3, x)/x**3, x, s) + assert F == -2**(s - 4)*gamma(s/2)/gamma(-s/2 + 4) + + +@XFAIL +def test_Y13(): +# Z[H(t - m T)] => z/[z^m (z - 1)] (H is the Heaviside (unit step) function) z + raise NotImplementedError("z-transform not supported") + + +@XFAIL +def test_Y14(): +# Z[H(t - m T)] => z/[z^m (z - 1)] (H is the Heaviside (unit step) function) + raise NotImplementedError("z-transform not supported") + + +def test_Z1(): + r = Function('r') + assert (rsolve(r(n + 2) - 2*r(n + 1) + r(n) - 2, r(n), + {r(0): 1, r(1): m}).simplify() == n**2 + n*(m - 2) + 1) + + +def test_Z2(): + r = Function('r') + assert (rsolve(r(n) - (5*r(n - 1) - 6*r(n - 2)), r(n), {r(0): 0, r(1): 1}) + == -2**n + 3**n) + + +def test_Z3(): + # => r(n) = Fibonacci[n + 1] [Cohen, p. 83] + r = Function('r') + # recurrence solution is correct, Wester expects it to be simplified to + # fibonacci(n+1), but that is quite hard + expected = ((S(1)/2 - sqrt(5)/2)**n*(S(1)/2 - sqrt(5)/10) + + (S(1)/2 + sqrt(5)/2)**n*(sqrt(5)/10 + S(1)/2)) + sol = rsolve(r(n) - (r(n - 1) + r(n - 2)), r(n), {r(1): 1, r(2): 2}) + assert sol == expected + + +@XFAIL +def test_Z4(): +# => [c^(n+1) [c^(n+1) - 2 c - 2] + (n+1) c^2 + 2 c - n] / [(c-1)^3 (c+1)] +# [Joan Z. Yu and Robert Israel in sci.math.symbolic] + r = Function('r') + c = symbols('c') + # raises ValueError: Polynomial or rational function expected, + # got '(c**2 - c**n)/(c - c**n) + s = rsolve(r(n) - ((1 + c - c**(n-1) - c**(n+1))/(1 - c**n)*r(n - 1) + - c*(1 - c**(n-2))/(1 - c**(n-1))*r(n - 2) + 1), + r(n), {r(1): 1, r(2): (2 + 2*c + c**2)/(1 + c)}) + assert (s - (c*(n + 1)*(c*(n + 1) - 2*c - 2) + + (n + 1)*c**2 + 2*c - n)/((c-1)**3*(c+1)) == 0) + + +@XFAIL +def test_Z5(): + # Second order ODE with initial conditions---solve directly + # transform: f(t) = sin(2 t)/8 - t cos(2 t)/4 + C1, C2 = symbols('C1 C2') + # initial conditions not supported, this is a manual workaround + # https://github.com/sympy/sympy/issues/4720 + eq = Derivative(f(x), x, 2) + 4*f(x) - sin(2*x) + sol = dsolve(eq, f(x)) + f0 = Lambda(x, sol.rhs) + assert f0(x) == C2*sin(2*x) + (C1 - x/4)*cos(2*x) + f1 = Lambda(x, diff(f0(x), x)) + # TODO: Replace solve with solveset, when it works for solveset + const_dict = solve((f0(0), f1(0))) + result = f0(x).subs(C1, const_dict[C1]).subs(C2, const_dict[C2]) + assert result == -x*cos(2*x)/4 + sin(2*x)/8 + # Result is OK, but ODE solving with initial conditions should be + # supported without all this manual work + raise NotImplementedError('ODE solving with initial conditions \ +not supported') + + +@XFAIL +def test_Z6(): + # Second order ODE with initial conditions---solve using Laplace + # transform: f(t) = sin(2 t)/8 - t cos(2 t)/4 + t = symbols('t', positive=True) + s = symbols('s') + eq = Derivative(f(t), t, 2) + 4*f(t) - sin(2*t) + F, _, _ = laplace_transform(eq, t, s) + # Laplace transform for diff() not calculated + # https://github.com/sympy/sympy/issues/7176 + assert (F == s**2*LaplaceTransform(f(t), t, s) + + 4*LaplaceTransform(f(t), t, s) - 2/(s**2 + 4)) + # rest of test case not implemented diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_xxe.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_xxe.py new file mode 100644 index 0000000000000000000000000000000000000000..3936e8aa135dde5f22c71548e2f90ed58ac25cb8 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/utilities/tests/test_xxe.py @@ -0,0 +1,3 @@ +# A test file for XXE injection +# Username: Test +# Password: Test diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d76bc977e0ed74cef21423f031791728bdafb503 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/basisdependent.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/basisdependent.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f7e0fdfd2601eb619df77ed4f84d35c01b3a50d6 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/basisdependent.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/coordsysrect.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/coordsysrect.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..68cad98b2b743f4bd6d3de87e3b15a736fc2e55b Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/coordsysrect.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/deloperator.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/deloperator.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..22ddd7c4be31c282011d78ae58886b1d29e3ffbb Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/deloperator.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/dyadic.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/dyadic.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f569b01c23a2ce6e50b60f8b2f7aa63e7a514a10 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/dyadic.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/functions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/functions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6848efd281fd5ce025c0db86011c027d56ab0016 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/functions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/implicitregion.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/implicitregion.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4eeaa364214d02f03cb6b19b44dc67abacd803a1 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/implicitregion.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/integrals.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/integrals.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cc51d1f3a888b8f90c6bb8a6de7b5508d15b3d21 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/integrals.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/kind.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/kind.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..53062f5e136fde25da19205d8cadf806eb00b5d9 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/kind.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/operators.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/operators.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1044146645f79b787ed3e420398c5b92662a1cdb Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/operators.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/orienters.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/orienters.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..197171971d1fdde5ec2746784482af1506bdc9b5 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/orienters.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/parametricregion.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/parametricregion.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5ebf313a5ea5a595387c0a59e0bf92081687be88 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/parametricregion.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/point.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/point.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4df873004d845a5cbf3e3a957b1464935407e76c Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/point.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/scalar.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/scalar.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f3221be9cbd197f4bf3b87975e2a0e03ffce5f9d Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/scalar.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/vector.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/vector.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4e1002719f9cb526fcef70cb074e84232523aa15 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/__pycache__/vector.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/__init__.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9e4de21a769f4c5a5893241f35fe53e8e962af16 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_coordsysrect.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_coordsysrect.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e8a2a5e227b55d5433fd4537530b4a029a77bc40 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_coordsysrect.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_dyadic.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_dyadic.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f4a41077c6868a3f81bd0f7a405c9624d00adc37 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_dyadic.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_field_functions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_field_functions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eacb0e21dc79eb33adf4b7fae0f46c443d296a39 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_field_functions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_functions.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_functions.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a4cf5da03356efcae435c0c64c47ce66113be207 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_functions.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_implicitregion.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_implicitregion.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7ffedd3eef1c0e49792b22ab2be557118016ef20 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_implicitregion.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_integrals.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_integrals.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7fc21fe0cdc408cf36e9cd1548731ff486a7283f Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_integrals.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_operators.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_operators.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..109c513ce4cdf111221c3a0deacaea278ae437d4 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_operators.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_parametricregion.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_parametricregion.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..40f976f611970ae365bc425437a7a663db94ef81 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_parametricregion.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_printing.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_printing.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8fdf33e86694581a1f67fad2ce3e715407b8e530 Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_printing.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_vector.cpython-312.pyc b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_vector.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..910d480cc8ca07f2ed10f95f34319a8ce57bdaad Binary files /dev/null and b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_vector.cpython-312.pyc differ diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_coordsysrect.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_coordsysrect.py new file mode 100644 index 0000000000000000000000000000000000000000..53eb8c89ec1643a71800efe3e370acff3cb6f9c0 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_coordsysrect.py @@ -0,0 +1,464 @@ +from sympy.testing.pytest import raises +from sympy.vector.coordsysrect import CoordSys3D +from sympy.vector.scalar import BaseScalar +from sympy.core.function import expand +from sympy.core.numbers import pi +from sympy.core.symbol import symbols +from sympy.functions.elementary.hyperbolic import (cosh, sinh) +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (acos, atan2, cos, sin) +from sympy.matrices.dense import zeros +from sympy.matrices.immutable import ImmutableDenseMatrix as Matrix +from sympy.simplify.simplify import simplify +from sympy.vector.functions import express +from sympy.vector.point import Point +from sympy.vector.vector import Vector +from sympy.vector.orienters import (AxisOrienter, BodyOrienter, + SpaceOrienter, QuaternionOrienter) + + +x, y, z = symbols('x y z') +a, b, c, q = symbols('a b c q') +q1, q2, q3, q4 = symbols('q1 q2 q3 q4') + + +def test_func_args(): + A = CoordSys3D('A') + assert A.x.func(*A.x.args) == A.x + expr = 3*A.x + 4*A.y + assert expr.func(*expr.args) == expr + assert A.i.func(*A.i.args) == A.i + v = A.x*A.i + A.y*A.j + A.z*A.k + assert v.func(*v.args) == v + assert A.origin.func(*A.origin.args) == A.origin + + +def test_coordsys3d_equivalence(): + A = CoordSys3D('A') + A1 = CoordSys3D('A') + assert A1 == A + B = CoordSys3D('B') + assert A != B + + +def test_orienters(): + A = CoordSys3D('A') + axis_orienter = AxisOrienter(a, A.k) + body_orienter = BodyOrienter(a, b, c, '123') + space_orienter = SpaceOrienter(a, b, c, '123') + q_orienter = QuaternionOrienter(q1, q2, q3, q4) + assert axis_orienter.rotation_matrix(A) == Matrix([ + [ cos(a), sin(a), 0], + [-sin(a), cos(a), 0], + [ 0, 0, 1]]) + assert body_orienter.rotation_matrix() == Matrix([ + [ cos(b)*cos(c), sin(a)*sin(b)*cos(c) + sin(c)*cos(a), + sin(a)*sin(c) - sin(b)*cos(a)*cos(c)], + [-sin(c)*cos(b), -sin(a)*sin(b)*sin(c) + cos(a)*cos(c), + sin(a)*cos(c) + sin(b)*sin(c)*cos(a)], + [ sin(b), -sin(a)*cos(b), + cos(a)*cos(b)]]) + assert space_orienter.rotation_matrix() == Matrix([ + [cos(b)*cos(c), sin(c)*cos(b), -sin(b)], + [sin(a)*sin(b)*cos(c) - sin(c)*cos(a), + sin(a)*sin(b)*sin(c) + cos(a)*cos(c), sin(a)*cos(b)], + [sin(a)*sin(c) + sin(b)*cos(a)*cos(c), -sin(a)*cos(c) + + sin(b)*sin(c)*cos(a), cos(a)*cos(b)]]) + assert q_orienter.rotation_matrix() == Matrix([ + [q1**2 + q2**2 - q3**2 - q4**2, 2*q1*q4 + 2*q2*q3, + -2*q1*q3 + 2*q2*q4], + [-2*q1*q4 + 2*q2*q3, q1**2 - q2**2 + q3**2 - q4**2, + 2*q1*q2 + 2*q3*q4], + [2*q1*q3 + 2*q2*q4, + -2*q1*q2 + 2*q3*q4, q1**2 - q2**2 - q3**2 + q4**2]]) + + +def test_coordinate_vars(): + """ + Tests the coordinate variables functionality with respect to + reorientation of coordinate systems. + """ + A = CoordSys3D('A') + # Note that the name given on the lhs is different from A.x._name + assert BaseScalar(0, A, 'A_x', r'\mathbf{{x}_{A}}') == A.x + assert BaseScalar(1, A, 'A_y', r'\mathbf{{y}_{A}}') == A.y + assert BaseScalar(2, A, 'A_z', r'\mathbf{{z}_{A}}') == A.z + assert BaseScalar(0, A, 'A_x', r'\mathbf{{x}_{A}}').__hash__() == A.x.__hash__() + assert isinstance(A.x, BaseScalar) and \ + isinstance(A.y, BaseScalar) and \ + isinstance(A.z, BaseScalar) + assert A.x*A.y == A.y*A.x + assert A.scalar_map(A) == {A.x: A.x, A.y: A.y, A.z: A.z} + assert A.x.system == A + assert A.x.diff(A.x) == 1 + B = A.orient_new_axis('B', q, A.k) + assert B.scalar_map(A) == {B.z: A.z, B.y: -A.x*sin(q) + A.y*cos(q), + B.x: A.x*cos(q) + A.y*sin(q)} + assert A.scalar_map(B) == {A.x: B.x*cos(q) - B.y*sin(q), + A.y: B.x*sin(q) + B.y*cos(q), A.z: B.z} + assert express(B.x, A, variables=True) == A.x*cos(q) + A.y*sin(q) + assert express(B.y, A, variables=True) == -A.x*sin(q) + A.y*cos(q) + assert express(B.z, A, variables=True) == A.z + assert expand(express(B.x*B.y*B.z, A, variables=True)) == \ + expand(A.z*(-A.x*sin(q) + A.y*cos(q))*(A.x*cos(q) + A.y*sin(q))) + assert express(B.x*B.i + B.y*B.j + B.z*B.k, A) == \ + (B.x*cos(q) - B.y*sin(q))*A.i + (B.x*sin(q) + \ + B.y*cos(q))*A.j + B.z*A.k + assert simplify(express(B.x*B.i + B.y*B.j + B.z*B.k, A, \ + variables=True)) == \ + A.x*A.i + A.y*A.j + A.z*A.k + assert express(A.x*A.i + A.y*A.j + A.z*A.k, B) == \ + (A.x*cos(q) + A.y*sin(q))*B.i + \ + (-A.x*sin(q) + A.y*cos(q))*B.j + A.z*B.k + assert simplify(express(A.x*A.i + A.y*A.j + A.z*A.k, B, \ + variables=True)) == \ + B.x*B.i + B.y*B.j + B.z*B.k + N = B.orient_new_axis('N', -q, B.k) + assert N.scalar_map(A) == \ + {N.x: A.x, N.z: A.z, N.y: A.y} + C = A.orient_new_axis('C', q, A.i + A.j + A.k) + mapping = A.scalar_map(C) + assert mapping[A.x].equals(C.x*(2*cos(q) + 1)/3 + + C.y*(-2*sin(q + pi/6) + 1)/3 + + C.z*(-2*cos(q + pi/3) + 1)/3) + assert mapping[A.y].equals(C.x*(-2*cos(q + pi/3) + 1)/3 + + C.y*(2*cos(q) + 1)/3 + + C.z*(-2*sin(q + pi/6) + 1)/3) + assert mapping[A.z].equals(C.x*(-2*sin(q + pi/6) + 1)/3 + + C.y*(-2*cos(q + pi/3) + 1)/3 + + C.z*(2*cos(q) + 1)/3) + D = A.locate_new('D', a*A.i + b*A.j + c*A.k) + assert D.scalar_map(A) == {D.z: A.z - c, D.x: A.x - a, D.y: A.y - b} + E = A.orient_new_axis('E', a, A.k, a*A.i + b*A.j + c*A.k) + assert A.scalar_map(E) == {A.z: E.z + c, + A.x: E.x*cos(a) - E.y*sin(a) + a, + A.y: E.x*sin(a) + E.y*cos(a) + b} + assert E.scalar_map(A) == {E.x: (A.x - a)*cos(a) + (A.y - b)*sin(a), + E.y: (-A.x + a)*sin(a) + (A.y - b)*cos(a), + E.z: A.z - c} + F = A.locate_new('F', Vector.zero) + assert A.scalar_map(F) == {A.z: F.z, A.x: F.x, A.y: F.y} + + +def test_rotation_matrix(): + N = CoordSys3D('N') + A = N.orient_new_axis('A', q1, N.k) + B = A.orient_new_axis('B', q2, A.i) + C = B.orient_new_axis('C', q3, B.j) + D = N.orient_new_axis('D', q4, N.j) + E = N.orient_new_space('E', q1, q2, q3, '123') + F = N.orient_new_quaternion('F', q1, q2, q3, q4) + G = N.orient_new_body('G', q1, q2, q3, '123') + assert N.rotation_matrix(C) == Matrix([ + [- sin(q1) * sin(q2) * sin(q3) + cos(q1) * cos(q3), - sin(q1) * + cos(q2), sin(q1) * sin(q2) * cos(q3) + sin(q3) * cos(q1)], \ + [sin(q1) * cos(q3) + sin(q2) * sin(q3) * cos(q1), \ + cos(q1) * cos(q2), sin(q1) * sin(q3) - sin(q2) * cos(q1) * \ + cos(q3)], [- sin(q3) * cos(q2), sin(q2), cos(q2) * cos(q3)]]) + test_mat = D.rotation_matrix(C) - Matrix( + [[cos(q1) * cos(q3) * cos(q4) - sin(q3) * (- sin(q4) * cos(q2) + + sin(q1) * sin(q2) * cos(q4)), - sin(q2) * sin(q4) - sin(q1) * + cos(q2) * cos(q4), sin(q3) * cos(q1) * cos(q4) + cos(q3) * \ + (- sin(q4) * cos(q2) + sin(q1) * sin(q2) * cos(q4))], \ + [sin(q1) * cos(q3) + sin(q2) * sin(q3) * cos(q1), cos(q1) * \ + cos(q2), sin(q1) * sin(q3) - sin(q2) * cos(q1) * cos(q3)], \ + [sin(q4) * cos(q1) * cos(q3) - sin(q3) * (cos(q2) * cos(q4) + \ + sin(q1) * sin(q2) * \ + sin(q4)), sin(q2) * + cos(q4) - sin(q1) * sin(q4) * cos(q2), sin(q3) * \ + sin(q4) * cos(q1) + cos(q3) * (cos(q2) * cos(q4) + \ + sin(q1) * sin(q2) * sin(q4))]]) + assert test_mat.expand() == zeros(3, 3) + assert E.rotation_matrix(N) == Matrix( + [[cos(q2)*cos(q3), sin(q3)*cos(q2), -sin(q2)], + [sin(q1)*sin(q2)*cos(q3) - sin(q3)*cos(q1), \ + sin(q1)*sin(q2)*sin(q3) + cos(q1)*cos(q3), sin(q1)*cos(q2)], \ + [sin(q1)*sin(q3) + sin(q2)*cos(q1)*cos(q3), - \ + sin(q1)*cos(q3) + sin(q2)*sin(q3)*cos(q1), cos(q1)*cos(q2)]]) + assert F.rotation_matrix(N) == Matrix([[ + q1**2 + q2**2 - q3**2 - q4**2, + 2*q1*q4 + 2*q2*q3, -2*q1*q3 + 2*q2*q4],[ -2*q1*q4 + 2*q2*q3, + q1**2 - q2**2 + q3**2 - q4**2, 2*q1*q2 + 2*q3*q4], + [2*q1*q3 + 2*q2*q4, + -2*q1*q2 + 2*q3*q4, + q1**2 - q2**2 - q3**2 + q4**2]]) + assert G.rotation_matrix(N) == Matrix([[ + cos(q2)*cos(q3), sin(q1)*sin(q2)*cos(q3) + sin(q3)*cos(q1), + sin(q1)*sin(q3) - sin(q2)*cos(q1)*cos(q3)], [ + -sin(q3)*cos(q2), -sin(q1)*sin(q2)*sin(q3) + cos(q1)*cos(q3), + sin(q1)*cos(q3) + sin(q2)*sin(q3)*cos(q1)],[ + sin(q2), -sin(q1)*cos(q2), cos(q1)*cos(q2)]]) + + +def test_vector_with_orientation(): + """ + Tests the effects of orientation of coordinate systems on + basic vector operations. + """ + N = CoordSys3D('N') + A = N.orient_new_axis('A', q1, N.k) + B = A.orient_new_axis('B', q2, A.i) + C = B.orient_new_axis('C', q3, B.j) + + # Test to_matrix + v1 = a*N.i + b*N.j + c*N.k + assert v1.to_matrix(A) == Matrix([[ a*cos(q1) + b*sin(q1)], + [-a*sin(q1) + b*cos(q1)], + [ c]]) + + # Test dot + assert N.i.dot(A.i) == cos(q1) + assert N.i.dot(A.j) == -sin(q1) + assert N.i.dot(A.k) == 0 + assert N.j.dot(A.i) == sin(q1) + assert N.j.dot(A.j) == cos(q1) + assert N.j.dot(A.k) == 0 + assert N.k.dot(A.i) == 0 + assert N.k.dot(A.j) == 0 + assert N.k.dot(A.k) == 1 + + assert N.i.dot(A.i + A.j) == -sin(q1) + cos(q1) == \ + (A.i + A.j).dot(N.i) + + assert A.i.dot(C.i) == cos(q3) + assert A.i.dot(C.j) == 0 + assert A.i.dot(C.k) == sin(q3) + assert A.j.dot(C.i) == sin(q2)*sin(q3) + assert A.j.dot(C.j) == cos(q2) + assert A.j.dot(C.k) == -sin(q2)*cos(q3) + assert A.k.dot(C.i) == -cos(q2)*sin(q3) + assert A.k.dot(C.j) == sin(q2) + assert A.k.dot(C.k) == cos(q2)*cos(q3) + + # Test cross + assert N.i.cross(A.i) == sin(q1)*A.k + assert N.i.cross(A.j) == cos(q1)*A.k + assert N.i.cross(A.k) == -sin(q1)*A.i - cos(q1)*A.j + assert N.j.cross(A.i) == -cos(q1)*A.k + assert N.j.cross(A.j) == sin(q1)*A.k + assert N.j.cross(A.k) == cos(q1)*A.i - sin(q1)*A.j + assert N.k.cross(A.i) == A.j + assert N.k.cross(A.j) == -A.i + assert N.k.cross(A.k) == Vector.zero + + assert N.i.cross(A.i) == sin(q1)*A.k + assert N.i.cross(A.j) == cos(q1)*A.k + assert N.i.cross(A.i + A.j) == sin(q1)*A.k + cos(q1)*A.k + assert (A.i + A.j).cross(N.i) == (-sin(q1) - cos(q1))*N.k + + assert A.i.cross(C.i) == sin(q3)*C.j + assert A.i.cross(C.j) == -sin(q3)*C.i + cos(q3)*C.k + assert A.i.cross(C.k) == -cos(q3)*C.j + assert C.i.cross(A.i) == (-sin(q3)*cos(q2))*A.j + \ + (-sin(q2)*sin(q3))*A.k + assert C.j.cross(A.i) == (sin(q2))*A.j + (-cos(q2))*A.k + assert express(C.k.cross(A.i), C).trigsimp() == cos(q3)*C.j + + +def test_orient_new_methods(): + N = CoordSys3D('N') + orienter1 = AxisOrienter(q4, N.j) + orienter2 = SpaceOrienter(q1, q2, q3, '123') + orienter3 = QuaternionOrienter(q1, q2, q3, q4) + orienter4 = BodyOrienter(q1, q2, q3, '123') + D = N.orient_new('D', (orienter1, )) + E = N.orient_new('E', (orienter2, )) + F = N.orient_new('F', (orienter3, )) + G = N.orient_new('G', (orienter4, )) + assert D == N.orient_new_axis('D', q4, N.j) + assert E == N.orient_new_space('E', q1, q2, q3, '123') + assert F == N.orient_new_quaternion('F', q1, q2, q3, q4) + assert G == N.orient_new_body('G', q1, q2, q3, '123') + + +def test_locatenew_point(): + """ + Tests Point class, and locate_new method in CoordSys3D. + """ + A = CoordSys3D('A') + assert isinstance(A.origin, Point) + v = a*A.i + b*A.j + c*A.k + C = A.locate_new('C', v) + assert C.origin.position_wrt(A) == \ + C.position_wrt(A) == \ + C.origin.position_wrt(A.origin) == v + assert A.origin.position_wrt(C) == \ + A.position_wrt(C) == \ + A.origin.position_wrt(C.origin) == -v + assert A.origin.express_coordinates(C) == (-a, -b, -c) + p = A.origin.locate_new('p', -v) + assert p.express_coordinates(A) == (-a, -b, -c) + assert p.position_wrt(C.origin) == p.position_wrt(C) == \ + -2 * v + p1 = p.locate_new('p1', 2*v) + assert p1.position_wrt(C.origin) == Vector.zero + assert p1.express_coordinates(C) == (0, 0, 0) + p2 = p.locate_new('p2', A.i) + assert p1.position_wrt(p2) == 2*v - A.i + assert p2.express_coordinates(C) == (-2*a + 1, -2*b, -2*c) + + +def test_create_new(): + a = CoordSys3D('a') + c = a.create_new('c', transformation='spherical') + assert c._parent == a + assert c.transformation_to_parent() == \ + (c.r*sin(c.theta)*cos(c.phi), c.r*sin(c.theta)*sin(c.phi), c.r*cos(c.theta)) + assert c.transformation_from_parent() == \ + (sqrt(a.x**2 + a.y**2 + a.z**2), acos(a.z/sqrt(a.x**2 + a.y**2 + a.z**2)), atan2(a.y, a.x)) + + +def test_evalf(): + A = CoordSys3D('A') + v = 3*A.i + 4*A.j + a*A.k + assert v.n() == v.evalf() + assert v.evalf(subs={a:1}) == v.subs(a, 1).evalf() + + +def test_lame_coefficients(): + a = CoordSys3D('a', 'spherical') + assert a.lame_coefficients() == (1, a.r, sin(a.theta)*a.r) + a = CoordSys3D('a') + assert a.lame_coefficients() == (1, 1, 1) + a = CoordSys3D('a', 'cartesian') + assert a.lame_coefficients() == (1, 1, 1) + a = CoordSys3D('a', 'cylindrical') + assert a.lame_coefficients() == (1, a.r, 1) + + +def test_transformation_equations(): + + x, y, z = symbols('x y z') + # Str + a = CoordSys3D('a', transformation='spherical', + variable_names=["r", "theta", "phi"]) + r, theta, phi = a.base_scalars() + + assert r == a.r + assert theta == a.theta + assert phi == a.phi + + raises(AttributeError, lambda: a.x) + raises(AttributeError, lambda: a.y) + raises(AttributeError, lambda: a.z) + + assert a.transformation_to_parent() == ( + r*sin(theta)*cos(phi), + r*sin(theta)*sin(phi), + r*cos(theta) + ) + assert a.lame_coefficients() == (1, r, r*sin(theta)) + assert a.transformation_from_parent_function()(x, y, z) == ( + sqrt(x ** 2 + y ** 2 + z ** 2), + acos((z) / sqrt(x**2 + y**2 + z**2)), + atan2(y, x) + ) + a = CoordSys3D('a', transformation='cylindrical', + variable_names=["r", "theta", "z"]) + r, theta, z = a.base_scalars() + assert a.transformation_to_parent() == ( + r*cos(theta), + r*sin(theta), + z + ) + assert a.lame_coefficients() == (1, a.r, 1) + assert a.transformation_from_parent_function()(x, y, z) == (sqrt(x**2 + y**2), + atan2(y, x), z) + + a = CoordSys3D('a', 'cartesian') + assert a.transformation_to_parent() == (a.x, a.y, a.z) + assert a.lame_coefficients() == (1, 1, 1) + assert a.transformation_from_parent_function()(x, y, z) == (x, y, z) + + # Variables and expressions + + # Cartesian with equation tuple: + x, y, z = symbols('x y z') + a = CoordSys3D('a', ((x, y, z), (x, y, z))) + a._calculate_inv_trans_equations() + assert a.transformation_to_parent() == (a.x1, a.x2, a.x3) + assert a.lame_coefficients() == (1, 1, 1) + assert a.transformation_from_parent_function()(x, y, z) == (x, y, z) + r, theta, z = symbols("r theta z") + + # Cylindrical with equation tuple: + a = CoordSys3D('a', [(r, theta, z), (r*cos(theta), r*sin(theta), z)], + variable_names=["r", "theta", "z"]) + r, theta, z = a.base_scalars() + assert a.transformation_to_parent() == ( + r*cos(theta), r*sin(theta), z + ) + assert a.lame_coefficients() == ( + sqrt(sin(theta)**2 + cos(theta)**2), + sqrt(r**2*sin(theta)**2 + r**2*cos(theta)**2), + 1 + ) # ==> this should simplify to (1, r, 1), tests are too slow with `simplify`. + + # Definitions with `lambda`: + + # Cartesian with `lambda` + a = CoordSys3D('a', lambda x, y, z: (x, y, z)) + assert a.transformation_to_parent() == (a.x1, a.x2, a.x3) + assert a.lame_coefficients() == (1, 1, 1) + a._calculate_inv_trans_equations() + assert a.transformation_from_parent_function()(x, y, z) == (x, y, z) + + # Spherical with `lambda` + a = CoordSys3D('a', lambda r, theta, phi: (r*sin(theta)*cos(phi), r*sin(theta)*sin(phi), r*cos(theta)), + variable_names=["r", "theta", "phi"]) + r, theta, phi = a.base_scalars() + assert a.transformation_to_parent() == ( + r*sin(theta)*cos(phi), r*sin(phi)*sin(theta), r*cos(theta) + ) + assert a.lame_coefficients() == ( + sqrt(sin(phi)**2*sin(theta)**2 + sin(theta)**2*cos(phi)**2 + cos(theta)**2), + sqrt(r**2*sin(phi)**2*cos(theta)**2 + r**2*sin(theta)**2 + r**2*cos(phi)**2*cos(theta)**2), + sqrt(r**2*sin(phi)**2*sin(theta)**2 + r**2*sin(theta)**2*cos(phi)**2) + ) # ==> this should simplify to (1, r, sin(theta)*r), `simplify` is too slow. + + # Cylindrical with `lambda` + a = CoordSys3D('a', lambda r, theta, z: + (r*cos(theta), r*sin(theta), z), + variable_names=["r", "theta", "z"] + ) + r, theta, z = a.base_scalars() + assert a.transformation_to_parent() == (r*cos(theta), r*sin(theta), z) + assert a.lame_coefficients() == ( + sqrt(sin(theta)**2 + cos(theta)**2), + sqrt(r**2*sin(theta)**2 + r**2*cos(theta)**2), + 1 + ) # ==> this should simplify to (1, a.x, 1) + + raises(TypeError, lambda: CoordSys3D('a', transformation={ + x: x*sin(y)*cos(z), y:x*sin(y)*sin(z), z: x*cos(y)})) + + +def test_check_orthogonality(): + x, y, z = symbols('x y z') + u,v = symbols('u, v') + a = CoordSys3D('a', transformation=((x, y, z), (x*sin(y)*cos(z), x*sin(y)*sin(z), x*cos(y)))) + assert a._check_orthogonality(a._transformation) is True + a = CoordSys3D('a', transformation=((x, y, z), (x * cos(y), x * sin(y), z))) + assert a._check_orthogonality(a._transformation) is True + a = CoordSys3D('a', transformation=((u, v, z), (cosh(u) * cos(v), sinh(u) * sin(v), z))) + assert a._check_orthogonality(a._transformation) is True + + raises(ValueError, lambda: CoordSys3D('a', transformation=((x, y, z), (x, x, z)))) + raises(ValueError, lambda: CoordSys3D('a', transformation=( + (x, y, z), (x*sin(y/2)*cos(z), x*sin(y)*sin(z), x*cos(y))))) + + +def test_rotation_trans_equations(): + a = CoordSys3D('a') + from sympy.core.symbol import symbols + q0 = symbols('q0') + assert a._rotation_trans_equations(a._parent_rotation_matrix, a.base_scalars()) == (a.x, a.y, a.z) + assert a._rotation_trans_equations(a._inverse_rotation_matrix(), a.base_scalars()) == (a.x, a.y, a.z) + b = a.orient_new_axis('b', 0, -a.k) + assert b._rotation_trans_equations(b._parent_rotation_matrix, b.base_scalars()) == (b.x, b.y, b.z) + assert b._rotation_trans_equations(b._inverse_rotation_matrix(), b.base_scalars()) == (b.x, b.y, b.z) + c = a.orient_new_axis('c', q0, -a.k) + assert c._rotation_trans_equations(c._parent_rotation_matrix, c.base_scalars()) == \ + (-sin(q0) * c.y + cos(q0) * c.x, sin(q0) * c.x + cos(q0) * c.y, c.z) + assert c._rotation_trans_equations(c._inverse_rotation_matrix(), c.base_scalars()) == \ + (sin(q0) * c.y + cos(q0) * c.x, -sin(q0) * c.x + cos(q0) * c.y, c.z) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_dyadic.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_dyadic.py new file mode 100644 index 0000000000000000000000000000000000000000..2e396fcf2a81af897b59c0065f6b15f5c6933222 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_dyadic.py @@ -0,0 +1,134 @@ +from sympy.core.numbers import pi +from sympy.core.symbol import symbols +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.matrices.immutable import ImmutableDenseMatrix as Matrix +from sympy.simplify.simplify import simplify +from sympy.vector import (CoordSys3D, Vector, Dyadic, + DyadicAdd, DyadicMul, DyadicZero, + BaseDyadic, express) + + +A = CoordSys3D('A') + + +def test_dyadic(): + a, b = symbols('a, b') + assert Dyadic.zero != 0 + assert isinstance(Dyadic.zero, DyadicZero) + assert BaseDyadic(A.i, A.j) != BaseDyadic(A.j, A.i) + assert (BaseDyadic(Vector.zero, A.i) == + BaseDyadic(A.i, Vector.zero) == Dyadic.zero) + + d1 = A.i | A.i + d2 = A.j | A.j + d3 = A.i | A.j + + assert isinstance(d1, BaseDyadic) + d_mul = a*d1 + assert isinstance(d_mul, DyadicMul) + assert d_mul.base_dyadic == d1 + assert d_mul.measure_number == a + assert isinstance(a*d1 + b*d3, DyadicAdd) + assert d1 == A.i.outer(A.i) + assert d3 == A.i.outer(A.j) + v1 = a*A.i - A.k + v2 = A.i + b*A.j + assert v1 | v2 == v1.outer(v2) == a * (A.i|A.i) + (a*b) * (A.i|A.j) +\ + - (A.k|A.i) - b * (A.k|A.j) + assert d1 * 0 == Dyadic.zero + assert d1 != Dyadic.zero + assert d1 * 2 == 2 * (A.i | A.i) + assert d1 / 2. == 0.5 * d1 + + assert d1.dot(0 * d1) == Vector.zero + assert d1 & d2 == Dyadic.zero + assert d1.dot(A.i) == A.i == d1 & A.i + + assert d1.cross(Vector.zero) == Dyadic.zero + assert d1.cross(A.i) == Dyadic.zero + assert d1 ^ A.j == d1.cross(A.j) + assert d1.cross(A.k) == - A.i | A.j + assert d2.cross(A.i) == - A.j | A.k == d2 ^ A.i + + assert A.i ^ d1 == Dyadic.zero + assert A.j.cross(d1) == - A.k | A.i == A.j ^ d1 + assert Vector.zero.cross(d1) == Dyadic.zero + assert A.k ^ d1 == A.j | A.i + assert A.i.dot(d1) == A.i & d1 == A.i + assert A.j.dot(d1) == Vector.zero + assert Vector.zero.dot(d1) == Vector.zero + assert A.j & d2 == A.j + + assert d1.dot(d3) == d1 & d3 == A.i | A.j == d3 + assert d3 & d1 == Dyadic.zero + + q = symbols('q') + B = A.orient_new_axis('B', q, A.k) + assert express(d1, B) == express(d1, B, B) + + expr1 = ((cos(q)**2) * (B.i | B.i) + (-sin(q) * cos(q)) * + (B.i | B.j) + (-sin(q) * cos(q)) * (B.j | B.i) + (sin(q)**2) * + (B.j | B.j)) + assert (express(d1, B) - expr1).simplify() == Dyadic.zero + + expr2 = (cos(q)) * (B.i | A.i) + (-sin(q)) * (B.j | A.i) + assert (express(d1, B, A) - expr2).simplify() == Dyadic.zero + + expr3 = (cos(q)) * (A.i | B.i) + (-sin(q)) * (A.i | B.j) + assert (express(d1, A, B) - expr3).simplify() == Dyadic.zero + + assert d1.to_matrix(A) == Matrix([[1, 0, 0], [0, 0, 0], [0, 0, 0]]) + assert d1.to_matrix(A, B) == Matrix([[cos(q), -sin(q), 0], + [0, 0, 0], + [0, 0, 0]]) + assert d3.to_matrix(A) == Matrix([[0, 1, 0], [0, 0, 0], [0, 0, 0]]) + a, b, c, d, e, f = symbols('a, b, c, d, e, f') + v1 = a * A.i + b * A.j + c * A.k + v2 = d * A.i + e * A.j + f * A.k + d4 = v1.outer(v2) + assert d4.to_matrix(A) == Matrix([[a * d, a * e, a * f], + [b * d, b * e, b * f], + [c * d, c * e, c * f]]) + d5 = v1.outer(v1) + C = A.orient_new_axis('C', q, A.i) + for expected, actual in zip(C.rotation_matrix(A) * d5.to_matrix(A) * \ + C.rotation_matrix(A).T, d5.to_matrix(C)): + assert (expected - actual).simplify() == 0 + + +def test_dyadic_simplify(): + x, y, z, k, n, m, w, f, s, A = symbols('x, y, z, k, n, m, w, f, s, A') + N = CoordSys3D('N') + + dy = N.i | N.i + test1 = (1 / x + 1 / y) * dy + assert (N.i & test1 & N.i) != (x + y) / (x * y) + test1 = test1.simplify() + assert test1.simplify() == simplify(test1) + assert (N.i & test1 & N.i) == (x + y) / (x * y) + + test2 = (A**2 * s**4 / (4 * pi * k * m**3)) * dy + test2 = test2.simplify() + assert (N.i & test2 & N.i) == (A**2 * s**4 / (4 * pi * k * m**3)) + + test3 = ((4 + 4 * x - 2 * (2 + 2 * x)) / (2 + 2 * x)) * dy + test3 = test3.simplify() + assert (N.i & test3 & N.i) == 0 + + test4 = ((-4 * x * y**2 - 2 * y**3 - 2 * x**2 * y) / (x + y)**2) * dy + test4 = test4.simplify() + assert (N.i & test4 & N.i) == -2 * y + + +def test_dyadic_srepr(): + from sympy.printing.repr import srepr + N = CoordSys3D('N') + + dy = N.i | N.j + res = "BaseDyadic(CoordSys3D(Str('N'), Tuple(ImmutableDenseMatrix([["\ + "Integer(1), Integer(0), Integer(0)], [Integer(0), Integer(1), "\ + "Integer(0)], [Integer(0), Integer(0), Integer(1)]]), "\ + "VectorZero())).i, CoordSys3D(Str('N'), Tuple(ImmutableDenseMatrix("\ + "[[Integer(1), Integer(0), Integer(0)], [Integer(0), Integer(1), "\ + "Integer(0)], [Integer(0), Integer(0), Integer(1)]]), VectorZero())).j)" + assert srepr(dy) == res diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_field_functions.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_field_functions.py new file mode 100644 index 0000000000000000000000000000000000000000..035c2ce0234b81069c5ad8dcb1c74f4de0164a8f --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_field_functions.py @@ -0,0 +1,321 @@ +from sympy.core.function import Derivative +from sympy.vector.vector import Vector +from sympy.vector.coordsysrect import CoordSys3D +from sympy.simplify import simplify +from sympy.core.symbol import symbols +from sympy.core import S +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.vector.vector import Dot +from sympy.vector.operators import curl, divergence, gradient, Gradient, Divergence, Cross +from sympy.vector.deloperator import Del +from sympy.vector.functions import (is_conservative, is_solenoidal, + scalar_potential, directional_derivative, + laplacian, scalar_potential_difference) +from sympy.testing.pytest import raises + +C = CoordSys3D('C') +i, j, k = C.base_vectors() +x, y, z = C.base_scalars() +delop = Del() +a, b, c, q = symbols('a b c q') + + +def test_del_operator(): + # Tests for curl + + assert delop ^ Vector.zero == Vector.zero + assert ((delop ^ Vector.zero).doit() == Vector.zero == + curl(Vector.zero)) + assert delop.cross(Vector.zero) == delop ^ Vector.zero + assert (delop ^ i).doit() == Vector.zero + assert delop.cross(2*y**2*j, doit=True) == Vector.zero + assert delop.cross(2*y**2*j) == delop ^ 2*y**2*j + v = x*y*z * (i + j + k) + assert ((delop ^ v).doit() == + (-x*y + x*z)*i + (x*y - y*z)*j + (-x*z + y*z)*k == + curl(v)) + assert delop ^ v == delop.cross(v) + assert (delop.cross(2*x**2*j) == + (Derivative(0, C.y) - Derivative(2*C.x**2, C.z))*C.i + + (-Derivative(0, C.x) + Derivative(0, C.z))*C.j + + (-Derivative(0, C.y) + Derivative(2*C.x**2, C.x))*C.k) + assert (delop.cross(2*x**2*j, doit=True) == 4*x*k == + curl(2*x**2*j)) + + #Tests for divergence + assert delop & Vector.zero is S.Zero == divergence(Vector.zero) + assert (delop & Vector.zero).doit() is S.Zero + assert delop.dot(Vector.zero) == delop & Vector.zero + assert (delop & i).doit() is S.Zero + assert (delop & x**2*i).doit() == 2*x == divergence(x**2*i) + assert (delop.dot(v, doit=True) == x*y + y*z + z*x == + divergence(v)) + assert delop & v == delop.dot(v) + assert delop.dot(1/(x*y*z) * (i + j + k), doit=True) == \ + - 1 / (x*y*z**2) - 1 / (x*y**2*z) - 1 / (x**2*y*z) + v = x*i + y*j + z*k + assert (delop & v == Derivative(C.x, C.x) + + Derivative(C.y, C.y) + Derivative(C.z, C.z)) + assert delop.dot(v, doit=True) == 3 == divergence(v) + assert delop & v == delop.dot(v) + assert simplify((delop & v).doit()) == 3 + + #Tests for gradient + assert (delop.gradient(0, doit=True) == Vector.zero == + gradient(0)) + assert delop.gradient(0) == delop(0) + assert (delop(S.Zero)).doit() == Vector.zero + assert (delop(x) == (Derivative(C.x, C.x))*C.i + + (Derivative(C.x, C.y))*C.j + (Derivative(C.x, C.z))*C.k) + assert (delop(x)).doit() == i == gradient(x) + assert (delop(x*y*z) == + (Derivative(C.x*C.y*C.z, C.x))*C.i + + (Derivative(C.x*C.y*C.z, C.y))*C.j + + (Derivative(C.x*C.y*C.z, C.z))*C.k) + assert (delop.gradient(x*y*z, doit=True) == + y*z*i + z*x*j + x*y*k == + gradient(x*y*z)) + assert delop(x*y*z) == delop.gradient(x*y*z) + assert (delop(2*x**2)).doit() == 4*x*i + assert ((delop(a*sin(y) / x)).doit() == + -a*sin(y)/x**2 * i + a*cos(y)/x * j) + + #Tests for directional derivative + assert (Vector.zero & delop)(a) is S.Zero + assert ((Vector.zero & delop)(a)).doit() is S.Zero + assert ((v & delop)(Vector.zero)).doit() == Vector.zero + assert ((v & delop)(S.Zero)).doit() is S.Zero + assert ((i & delop)(x)).doit() == 1 + assert ((j & delop)(y)).doit() == 1 + assert ((k & delop)(z)).doit() == 1 + assert ((i & delop)(x*y*z)).doit() == y*z + assert ((v & delop)(x)).doit() == x + assert ((v & delop)(x*y*z)).doit() == 3*x*y*z + assert (v & delop)(x + y + z) == C.x + C.y + C.z + assert ((v & delop)(x + y + z)).doit() == x + y + z + assert ((v & delop)(v)).doit() == v + assert ((i & delop)(v)).doit() == i + assert ((j & delop)(v)).doit() == j + assert ((k & delop)(v)).doit() == k + assert ((v & delop)(Vector.zero)).doit() == Vector.zero + + # Tests for laplacian on scalar fields + assert laplacian(x*y*z) is S.Zero + assert laplacian(x**2) == S(2) + assert laplacian(x**2*y**2*z**2) == \ + 2*y**2*z**2 + 2*x**2*z**2 + 2*x**2*y**2 + A = CoordSys3D('A', transformation="spherical", variable_names=["r", "theta", "phi"]) + B = CoordSys3D('B', transformation='cylindrical', variable_names=["r", "theta", "z"]) + assert laplacian(A.r + A.theta + A.phi) == 2/A.r + cos(A.theta)/(A.r**2*sin(A.theta)) + assert laplacian(B.r + B.theta + B.z) == 1/B.r + + # Tests for laplacian on vector fields + assert laplacian(x*y*z*(i + j + k)) == Vector.zero + assert laplacian(x*y**2*z*(i + j + k)) == \ + 2*x*z*i + 2*x*z*j + 2*x*z*k + + +def test_product_rules(): + """ + Tests the six product rules defined with respect to the Del + operator + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Del + + """ + + #Define the scalar and vector functions + f = 2*x*y*z + g = x*y + y*z + z*x + u = x**2*i + 4*j - y**2*z*k + v = 4*i + x*y*z*k + + # First product rule + lhs = delop(f * g, doit=True) + rhs = (f * delop(g) + g * delop(f)).doit() + assert simplify(lhs) == simplify(rhs) + + # Second product rule + lhs = delop(u & v).doit() + rhs = ((u ^ (delop ^ v)) + (v ^ (delop ^ u)) + \ + ((u & delop)(v)) + ((v & delop)(u))).doit() + assert simplify(lhs) == simplify(rhs) + + # Third product rule + lhs = (delop & (f*v)).doit() + rhs = ((f * (delop & v)) + (v & (delop(f)))).doit() + assert simplify(lhs) == simplify(rhs) + + # Fourth product rule + lhs = (delop & (u ^ v)).doit() + rhs = ((v & (delop ^ u)) - (u & (delop ^ v))).doit() + assert simplify(lhs) == simplify(rhs) + + # Fifth product rule + lhs = (delop ^ (f * v)).doit() + rhs = (((delop(f)) ^ v) + (f * (delop ^ v))).doit() + assert simplify(lhs) == simplify(rhs) + + # Sixth product rule + lhs = (delop ^ (u ^ v)).doit() + rhs = (u * (delop & v) - v * (delop & u) + + (v & delop)(u) - (u & delop)(v)).doit() + assert simplify(lhs) == simplify(rhs) + + +P = C.orient_new_axis('P', q, C.k) # type: ignore +scalar_field = 2*x**2*y*z +grad_field = gradient(scalar_field) +vector_field = y**2*i + 3*x*j + 5*y*z*k +curl_field = curl(vector_field) + + +def test_conservative(): + assert is_conservative(Vector.zero) is True + assert is_conservative(i) is True + assert is_conservative(2 * i + 3 * j + 4 * k) is True + assert (is_conservative(y*z*i + x*z*j + x*y*k) is + True) + assert is_conservative(x * j) is False + assert is_conservative(grad_field) is True + assert is_conservative(curl_field) is False + assert (is_conservative(4*x*y*z*i + 2*x**2*z*j) is + False) + assert is_conservative(z*P.i + P.x*k) is True + + +def test_solenoidal(): + assert is_solenoidal(Vector.zero) is True + assert is_solenoidal(i) is True + assert is_solenoidal(2 * i + 3 * j + 4 * k) is True + assert (is_solenoidal(y*z*i + x*z*j + x*y*k) is + True) + assert is_solenoidal(y * j) is False + assert is_solenoidal(grad_field) is False + assert is_solenoidal(curl_field) is True + assert is_solenoidal((-2*y + 3)*k) is True + assert is_solenoidal(cos(q)*i + sin(q)*j + cos(q)*P.k) is True + assert is_solenoidal(z*P.i + P.x*k) is True + + +def test_directional_derivative(): + assert directional_derivative(C.x*C.y*C.z, 3*C.i + 4*C.j + C.k) == C.x*C.y + 4*C.x*C.z + 3*C.y*C.z + assert directional_derivative(5*C.x**2*C.z, 3*C.i + 4*C.j + C.k) == 5*C.x**2 + 30*C.x*C.z + assert directional_derivative(5*C.x**2*C.z, 4*C.j) is S.Zero + + D = CoordSys3D("D", "spherical", variable_names=["r", "theta", "phi"], + vector_names=["e_r", "e_theta", "e_phi"]) + r, theta, phi = D.base_scalars() + e_r, e_theta, e_phi = D.base_vectors() + assert directional_derivative(r**2*e_r, e_r) == 2*r*e_r + assert directional_derivative(5*r**2*phi, 3*e_r + 4*e_theta + e_phi) == 5*r**2 + 30*r*phi + + +def test_scalar_potential(): + assert scalar_potential(Vector.zero, C) == 0 + assert scalar_potential(i, C) == x + assert scalar_potential(j, C) == y + assert scalar_potential(k, C) == z + assert scalar_potential(y*z*i + x*z*j + x*y*k, C) == x*y*z + assert scalar_potential(grad_field, C) == scalar_field + assert scalar_potential(z*P.i + P.x*k, C) == x*z*cos(q) + y*z*sin(q) + assert scalar_potential(z*P.i + P.x*k, P) == P.x*P.z + raises(ValueError, lambda: scalar_potential(x*j, C)) + + +def test_scalar_potential_difference(): + point1 = C.origin.locate_new('P1', 1*i + 2*j + 3*k) + point2 = C.origin.locate_new('P2', 4*i + 5*j + 6*k) + genericpointC = C.origin.locate_new('RP', x*i + y*j + z*k) + genericpointP = P.origin.locate_new('PP', P.x*P.i + P.y*P.j + P.z*P.k) + assert scalar_potential_difference(S.Zero, C, point1, point2) == 0 + assert (scalar_potential_difference(scalar_field, C, C.origin, + genericpointC) == + scalar_field) + assert (scalar_potential_difference(grad_field, C, C.origin, + genericpointC) == + scalar_field) + assert scalar_potential_difference(grad_field, C, point1, point2) == 948 + assert (scalar_potential_difference(y*z*i + x*z*j + + x*y*k, C, point1, + genericpointC) == + x*y*z - 6) + potential_diff_P = (2*P.z*(P.x*sin(q) + P.y*cos(q))* + (P.x*cos(q) - P.y*sin(q))**2) + assert (scalar_potential_difference(grad_field, P, P.origin, + genericpointP).simplify() == + potential_diff_P.simplify()) + + +def test_differential_operators_curvilinear_system(): + A = CoordSys3D('A', transformation="spherical", variable_names=["r", "theta", "phi"]) + B = CoordSys3D('B', transformation='cylindrical', variable_names=["r", "theta", "z"]) + # Test for spherical coordinate system and gradient + assert gradient(3*A.r + 4*A.theta) == 3*A.i + 4/A.r*A.j + assert gradient(3*A.r*A.phi + 4*A.theta) == 3*A.phi*A.i + 4/A.r*A.j + (3/sin(A.theta))*A.k + assert gradient(0*A.r + 0*A.theta+0*A.phi) == Vector.zero + assert gradient(A.r*A.theta*A.phi) == A.theta*A.phi*A.i + A.phi*A.j + (A.theta/sin(A.theta))*A.k + # Test for spherical coordinate system and divergence + assert divergence(A.r * A.i + A.theta * A.j + A.phi * A.k) == \ + (sin(A.theta)*A.r + cos(A.theta)*A.r*A.theta)/(sin(A.theta)*A.r**2) + 3 + 1/(sin(A.theta)*A.r) + assert divergence(3*A.r*A.phi*A.i + A.theta*A.j + A.r*A.theta*A.phi*A.k) == \ + (sin(A.theta)*A.r + cos(A.theta)*A.r*A.theta)/(sin(A.theta)*A.r**2) + 9*A.phi + A.theta/sin(A.theta) + assert divergence(Vector.zero) == 0 + assert divergence(0*A.i + 0*A.j + 0*A.k) == 0 + # Test for spherical coordinate system and curl + assert curl(A.r*A.i + A.theta*A.j + A.phi*A.k) == \ + (cos(A.theta)*A.phi/(sin(A.theta)*A.r))*A.i + (-A.phi/A.r)*A.j + A.theta/A.r*A.k + assert curl(A.r*A.j + A.phi*A.k) == (cos(A.theta)*A.phi/(sin(A.theta)*A.r))*A.i + (-A.phi/A.r)*A.j + 2*A.k + + # Test for cylindrical coordinate system and gradient + assert gradient(0*B.r + 0*B.theta+0*B.z) == Vector.zero + assert gradient(B.r*B.theta*B.z) == B.theta*B.z*B.i + B.z*B.j + B.r*B.theta*B.k + assert gradient(3*B.r) == 3*B.i + assert gradient(2*B.theta) == 2/B.r * B.j + assert gradient(4*B.z) == 4*B.k + # Test for cylindrical coordinate system and divergence + assert divergence(B.r*B.i + B.theta*B.j + B.z*B.k) == 3 + 1/B.r + assert divergence(B.r*B.j + B.z*B.k) == 1 + # Test for cylindrical coordinate system and curl + assert curl(B.r*B.j + B.z*B.k) == 2*B.k + assert curl(3*B.i + 2/B.r*B.j + 4*B.k) == Vector.zero + +def test_mixed_coordinates(): + # gradient + a = CoordSys3D('a') + b = CoordSys3D('b') + c = CoordSys3D('c') + assert gradient(a.x*b.y) == b.y*a.i + a.x*b.j + assert gradient(3*cos(q)*a.x*b.x+a.y*(a.x+(cos(q)+b.x))) ==\ + (a.y + 3*b.x*cos(q))*a.i + (a.x + b.x + cos(q))*a.j + (3*a.x*cos(q) + a.y)*b.i + # Some tests need further work: + # assert gradient(a.x*(cos(a.x+b.x))) == (cos(a.x + b.x))*a.i + a.x*Gradient(cos(a.x + b.x)) + # assert gradient(cos(a.x + b.x)*cos(a.x + b.z)) == Gradient(cos(a.x + b.x)*cos(a.x + b.z)) + assert gradient(a.x**b.y) == Gradient(a.x**b.y) + # assert gradient(cos(a.x+b.y)*a.z) == None + assert gradient(cos(a.x*b.y)) == Gradient(cos(a.x*b.y)) + assert gradient(3*cos(q)*a.x*b.x*a.z*a.y+ b.y*b.z + cos(a.x+a.y)*b.z) == \ + (3*a.y*a.z*b.x*cos(q) - b.z*sin(a.x + a.y))*a.i + \ + (3*a.x*a.z*b.x*cos(q) - b.z*sin(a.x + a.y))*a.j + (3*a.x*a.y*b.x*cos(q))*a.k + \ + (3*a.x*a.y*a.z*cos(q))*b.i + b.z*b.j + (b.y + cos(a.x + a.y))*b.k + # divergence + assert divergence(a.i*a.x+a.j*a.y+a.z*a.k + b.i*b.x+b.j*b.y+b.z*b.k + c.i*c.x+c.j*c.y+c.z*c.k) == S(9) + # assert divergence(3*a.i*a.x*cos(a.x+b.z) + a.j*b.x*c.z) == None + assert divergence(3*a.i*a.x*a.z + b.j*b.x*c.z + 3*a.j*a.z*a.y) == \ + 6*a.z + b.x*Dot(b.j, c.k) + assert divergence(3*cos(q)*a.x*b.x*b.i*c.x) == \ + 3*a.x*b.x*cos(q)*Dot(b.i, c.i) + 3*a.x*c.x*cos(q) + 3*b.x*c.x*cos(q)*Dot(b.i, a.i) + assert divergence(a.x*b.x*c.x*Cross(a.x*a.i, a.y*b.j)) ==\ + a.x*b.x*c.x*Divergence(Cross(a.x*a.i, a.y*b.j)) + \ + b.x*c.x*Dot(Cross(a.x*a.i, a.y*b.j), a.i) + \ + a.x*c.x*Dot(Cross(a.x*a.i, a.y*b.j), b.i) + \ + a.x*b.x*Dot(Cross(a.x*a.i, a.y*b.j), c.i) + assert divergence(a.x*b.x*c.x*(a.x*a.i + b.x*b.i)) == \ + 4*a.x*b.x*c.x +\ + a.x**2*c.x*Dot(a.i, b.i) +\ + a.x**2*b.x*Dot(a.i, c.i) +\ + b.x**2*c.x*Dot(b.i, a.i) +\ + a.x*b.x**2*Dot(b.i, c.i) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_functions.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_functions.py new file mode 100644 index 0000000000000000000000000000000000000000..dfdf9821b6c853755ce12d0cbdfa599bd4f312e4 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_functions.py @@ -0,0 +1,184 @@ +from sympy.vector.vector import Vector +from sympy.vector.coordsysrect import CoordSys3D +from sympy.vector.functions import express, matrix_to_vector, orthogonalize +from sympy.core.numbers import Rational +from sympy.core.singleton import S +from sympy.core.symbol import symbols +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.matrices.immutable import ImmutableDenseMatrix as Matrix +from sympy.testing.pytest import raises + +N = CoordSys3D('N') +q1, q2, q3, q4, q5 = symbols('q1 q2 q3 q4 q5') +A = N.orient_new_axis('A', q1, N.k) # type: ignore +B = A.orient_new_axis('B', q2, A.i) +C = B.orient_new_axis('C', q3, B.j) + + +def test_express(): + assert express(Vector.zero, N) == Vector.zero + assert express(S.Zero, N) is S.Zero + assert express(A.i, C) == cos(q3)*C.i + sin(q3)*C.k + assert express(A.j, C) == sin(q2)*sin(q3)*C.i + cos(q2)*C.j - \ + sin(q2)*cos(q3)*C.k + assert express(A.k, C) == -sin(q3)*cos(q2)*C.i + sin(q2)*C.j + \ + cos(q2)*cos(q3)*C.k + assert express(A.i, N) == cos(q1)*N.i + sin(q1)*N.j + assert express(A.j, N) == -sin(q1)*N.i + cos(q1)*N.j + assert express(A.k, N) == N.k + assert express(A.i, A) == A.i + assert express(A.j, A) == A.j + assert express(A.k, A) == A.k + assert express(A.i, B) == B.i + assert express(A.j, B) == cos(q2)*B.j - sin(q2)*B.k + assert express(A.k, B) == sin(q2)*B.j + cos(q2)*B.k + assert express(A.i, C) == cos(q3)*C.i + sin(q3)*C.k + assert express(A.j, C) == sin(q2)*sin(q3)*C.i + cos(q2)*C.j - \ + sin(q2)*cos(q3)*C.k + assert express(A.k, C) == -sin(q3)*cos(q2)*C.i + sin(q2)*C.j + \ + cos(q2)*cos(q3)*C.k + # Check to make sure UnitVectors get converted properly + assert express(N.i, N) == N.i + assert express(N.j, N) == N.j + assert express(N.k, N) == N.k + assert express(N.i, A) == (cos(q1)*A.i - sin(q1)*A.j) + assert express(N.j, A) == (sin(q1)*A.i + cos(q1)*A.j) + assert express(N.k, A) == A.k + assert express(N.i, B) == (cos(q1)*B.i - sin(q1)*cos(q2)*B.j + + sin(q1)*sin(q2)*B.k) + assert express(N.j, B) == (sin(q1)*B.i + cos(q1)*cos(q2)*B.j - + sin(q2)*cos(q1)*B.k) + assert express(N.k, B) == (sin(q2)*B.j + cos(q2)*B.k) + assert express(N.i, C) == ( + (cos(q1)*cos(q3) - sin(q1)*sin(q2)*sin(q3))*C.i - + sin(q1)*cos(q2)*C.j + + (sin(q3)*cos(q1) + sin(q1)*sin(q2)*cos(q3))*C.k) + assert express(N.j, C) == ( + (sin(q1)*cos(q3) + sin(q2)*sin(q3)*cos(q1))*C.i + + cos(q1)*cos(q2)*C.j + + (sin(q1)*sin(q3) - sin(q2)*cos(q1)*cos(q3))*C.k) + assert express(N.k, C) == (-sin(q3)*cos(q2)*C.i + sin(q2)*C.j + + cos(q2)*cos(q3)*C.k) + + assert express(A.i, N) == (cos(q1)*N.i + sin(q1)*N.j) + assert express(A.j, N) == (-sin(q1)*N.i + cos(q1)*N.j) + assert express(A.k, N) == N.k + assert express(A.i, A) == A.i + assert express(A.j, A) == A.j + assert express(A.k, A) == A.k + assert express(A.i, B) == B.i + assert express(A.j, B) == (cos(q2)*B.j - sin(q2)*B.k) + assert express(A.k, B) == (sin(q2)*B.j + cos(q2)*B.k) + assert express(A.i, C) == (cos(q3)*C.i + sin(q3)*C.k) + assert express(A.j, C) == (sin(q2)*sin(q3)*C.i + cos(q2)*C.j - + sin(q2)*cos(q3)*C.k) + assert express(A.k, C) == (-sin(q3)*cos(q2)*C.i + sin(q2)*C.j + + cos(q2)*cos(q3)*C.k) + + assert express(B.i, N) == (cos(q1)*N.i + sin(q1)*N.j) + assert express(B.j, N) == (-sin(q1)*cos(q2)*N.i + + cos(q1)*cos(q2)*N.j + sin(q2)*N.k) + assert express(B.k, N) == (sin(q1)*sin(q2)*N.i - + sin(q2)*cos(q1)*N.j + cos(q2)*N.k) + assert express(B.i, A) == A.i + assert express(B.j, A) == (cos(q2)*A.j + sin(q2)*A.k) + assert express(B.k, A) == (-sin(q2)*A.j + cos(q2)*A.k) + assert express(B.i, B) == B.i + assert express(B.j, B) == B.j + assert express(B.k, B) == B.k + assert express(B.i, C) == (cos(q3)*C.i + sin(q3)*C.k) + assert express(B.j, C) == C.j + assert express(B.k, C) == (-sin(q3)*C.i + cos(q3)*C.k) + + assert express(C.i, N) == ( + (cos(q1)*cos(q3) - sin(q1)*sin(q2)*sin(q3))*N.i + + (sin(q1)*cos(q3) + sin(q2)*sin(q3)*cos(q1))*N.j - + sin(q3)*cos(q2)*N.k) + assert express(C.j, N) == ( + -sin(q1)*cos(q2)*N.i + cos(q1)*cos(q2)*N.j + sin(q2)*N.k) + assert express(C.k, N) == ( + (sin(q3)*cos(q1) + sin(q1)*sin(q2)*cos(q3))*N.i + + (sin(q1)*sin(q3) - sin(q2)*cos(q1)*cos(q3))*N.j + + cos(q2)*cos(q3)*N.k) + assert express(C.i, A) == (cos(q3)*A.i + sin(q2)*sin(q3)*A.j - + sin(q3)*cos(q2)*A.k) + assert express(C.j, A) == (cos(q2)*A.j + sin(q2)*A.k) + assert express(C.k, A) == (sin(q3)*A.i - sin(q2)*cos(q3)*A.j + + cos(q2)*cos(q3)*A.k) + assert express(C.i, B) == (cos(q3)*B.i - sin(q3)*B.k) + assert express(C.j, B) == B.j + assert express(C.k, B) == (sin(q3)*B.i + cos(q3)*B.k) + assert express(C.i, C) == C.i + assert express(C.j, C) == C.j + assert express(C.k, C) == C.k == (C.k) + + # Check to make sure Vectors get converted back to UnitVectors + assert N.i == express((cos(q1)*A.i - sin(q1)*A.j), N).simplify() + assert N.j == express((sin(q1)*A.i + cos(q1)*A.j), N).simplify() + assert N.i == express((cos(q1)*B.i - sin(q1)*cos(q2)*B.j + + sin(q1)*sin(q2)*B.k), N).simplify() + assert N.j == express((sin(q1)*B.i + cos(q1)*cos(q2)*B.j - + sin(q2)*cos(q1)*B.k), N).simplify() + assert N.k == express((sin(q2)*B.j + cos(q2)*B.k), N).simplify() + + + assert A.i == express((cos(q1)*N.i + sin(q1)*N.j), A).simplify() + assert A.j == express((-sin(q1)*N.i + cos(q1)*N.j), A).simplify() + + assert A.j == express((cos(q2)*B.j - sin(q2)*B.k), A).simplify() + assert A.k == express((sin(q2)*B.j + cos(q2)*B.k), A).simplify() + + assert A.i == express((cos(q3)*C.i + sin(q3)*C.k), A).simplify() + assert A.j == express((sin(q2)*sin(q3)*C.i + cos(q2)*C.j - + sin(q2)*cos(q3)*C.k), A).simplify() + + assert A.k == express((-sin(q3)*cos(q2)*C.i + sin(q2)*C.j + + cos(q2)*cos(q3)*C.k), A).simplify() + assert B.i == express((cos(q1)*N.i + sin(q1)*N.j), B).simplify() + assert B.j == express((-sin(q1)*cos(q2)*N.i + + cos(q1)*cos(q2)*N.j + sin(q2)*N.k), B).simplify() + + assert B.k == express((sin(q1)*sin(q2)*N.i - + sin(q2)*cos(q1)*N.j + cos(q2)*N.k), B).simplify() + + assert B.j == express((cos(q2)*A.j + sin(q2)*A.k), B).simplify() + assert B.k == express((-sin(q2)*A.j + cos(q2)*A.k), B).simplify() + assert B.i == express((cos(q3)*C.i + sin(q3)*C.k), B).simplify() + assert B.k == express((-sin(q3)*C.i + cos(q3)*C.k), B).simplify() + assert C.i == express((cos(q3)*A.i + sin(q2)*sin(q3)*A.j - + sin(q3)*cos(q2)*A.k), C).simplify() + assert C.j == express((cos(q2)*A.j + sin(q2)*A.k), C).simplify() + assert C.k == express((sin(q3)*A.i - sin(q2)*cos(q3)*A.j + + cos(q2)*cos(q3)*A.k), C).simplify() + assert C.i == express((cos(q3)*B.i - sin(q3)*B.k), C).simplify() + assert C.k == express((sin(q3)*B.i + cos(q3)*B.k), C).simplify() + + +def test_matrix_to_vector(): + m = Matrix([[1], [2], [3]]) + assert matrix_to_vector(m, C) == C.i + 2*C.j + 3*C.k + m = Matrix([[0], [0], [0]]) + assert matrix_to_vector(m, N) == matrix_to_vector(m, C) == \ + Vector.zero + m = Matrix([[q1], [q2], [q3]]) + assert matrix_to_vector(m, N) == q1*N.i + q2*N.j + q3*N.k + + +def test_orthogonalize(): + C = CoordSys3D('C') + a, b = symbols('a b', integer=True) + i, j, k = C.base_vectors() + v1 = i + 2*j + v2 = 2*i + 3*j + v3 = 3*i + 5*j + v4 = 3*i + j + v5 = 2*i + 2*j + v6 = a*i + b*j + v7 = 4*a*i + 4*b*j + assert orthogonalize(v1, v2) == [C.i + 2*C.j, C.i*Rational(2, 5) + -C.j/5] + # from wikipedia + assert orthogonalize(v4, v5, orthonormal=True) == \ + [(3*sqrt(10))*C.i/10 + (sqrt(10))*C.j/10, (-sqrt(10))*C.i/10 + (3*sqrt(10))*C.j/10] + raises(ValueError, lambda: orthogonalize(v1, v2, v3)) + raises(ValueError, lambda: orthogonalize(v6, v7)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_implicitregion.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_implicitregion.py new file mode 100644 index 0000000000000000000000000000000000000000..3686d847a7f165cb5ba9aeb813e5922aaa17e1e0 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_implicitregion.py @@ -0,0 +1,90 @@ +from sympy.core.relational import Eq +from sympy.core.singleton import S +from sympy.abc import x, y, z, s, t +from sympy.sets import FiniteSet, EmptySet +from sympy.geometry import Point +from sympy.vector import ImplicitRegion +from sympy.testing.pytest import raises + + +def test_ImplicitRegion(): + ellipse = ImplicitRegion((x, y), (x**2/4 + y**2/16 - 1)) + assert ellipse.equation == x**2/4 + y**2/16 - 1 + assert ellipse.variables == (x, y) + assert ellipse.degree == 2 + r = ImplicitRegion((x, y, z), Eq(x**4 + y**2 - x*y, 6)) + assert r.equation == x**4 + y**2 - x*y - 6 + assert r.variables == (x, y, z) + assert r.degree == 4 + + +def test_regular_point(): + r1 = ImplicitRegion((x,), x**2 - 16) + assert r1.regular_point() == (-4,) + c1 = ImplicitRegion((x, y), x**2 + y**2 - 4) + assert c1.regular_point() == (0, -2) + c2 = ImplicitRegion((x, y), (x - S(5)/2)**2 + y**2 - (S(1)/4)**2) + assert c2.regular_point() == (S(5)/2, -S(1)/4) + c3 = ImplicitRegion((x, y), (y - 5)**2 - 16*(x - 5)) + assert c3.regular_point() == (5, 5) + r2 = ImplicitRegion((x, y), x**2 - 4*x*y - 3*y**2 + 4*x + 8*y - 5) + assert r2.regular_point() == (S(4)/7, S(9)/7) + r3 = ImplicitRegion((x, y), x**2 - 2*x*y + 3*y**2 - 2*x - 5*y + 3/2) + raises(ValueError, lambda: r3.regular_point()) + + +def test_singular_points_and_multiplicty(): + r1 = ImplicitRegion((x, y, z), Eq(x + y + z, 0)) + assert r1.singular_points() == EmptySet + r2 = ImplicitRegion((x, y, z), x*y*z + y**4 -x**2*z**2) + assert r2.singular_points() == FiniteSet((0, 0, z), (x, 0, 0)) + assert r2.multiplicity((0, 0, 0)) == 3 + assert r2.multiplicity((0, 0, 6)) == 2 + r3 = ImplicitRegion((x, y, z), z**2 - x**2 - y**2) + assert r3.singular_points() == FiniteSet((0, 0, 0)) + assert r3.multiplicity((0, 0, 0)) == 2 + r4 = ImplicitRegion((x, y), x**2 + y**2 - 2*x) + assert r4.singular_points() == EmptySet + assert r4.multiplicity(Point(1, 3)) == 0 + + +def test_rational_parametrization(): + p = ImplicitRegion((x,), x - 2) + assert p.rational_parametrization() == (x - 2,) + + line = ImplicitRegion((x, y), Eq(y, 3*x + 2)) + assert line.rational_parametrization() == (x, 3*x + 2) + + circle1 = ImplicitRegion((x, y), (x-2)**2 + (y+3)**2 - 4) + assert circle1.rational_parametrization(parameters=t) == (4*t/(t**2 + 1) + 2, 4*t**2/(t**2 + 1) - 5) + circle2 = ImplicitRegion((x, y), (x - S.Half)**2 + y**2 - (S(1)/2)**2) + + assert circle2.rational_parametrization(parameters=t) == (t/(t**2 + 1) + S(1)/2, t**2/(t**2 + 1) - S(1)/2) + circle3 = ImplicitRegion((x, y), Eq(x**2 + y**2, 2*x)) + assert circle3.rational_parametrization(parameters=(t,)) == (2*t/(t**2 + 1) + 1, 2*t**2/(t**2 + 1) - 1) + + parabola = ImplicitRegion((x, y), (y - 3)**2 - 4*(x + 6)) + assert parabola.rational_parametrization(t) == (-6 + 4/t**2, 3 + 4/t) + + rect_hyperbola = ImplicitRegion((x, y), x*y - 1) + assert rect_hyperbola.rational_parametrization(t) == (-1 + (t + 1)/t, t) + + cubic_curve = ImplicitRegion((x, y), x**3 + x**2 - y**2) + assert cubic_curve.rational_parametrization(parameters=(t)) == (t**2 - 1, t*(t**2 - 1)) + cuspidal = ImplicitRegion((x, y), (x**3 - y**2)) + assert cuspidal.rational_parametrization(t) == (t**2, t**3) + + I = ImplicitRegion((x, y), x**3 + x**2 - y**2) + assert I.rational_parametrization(t) == (t**2 - 1, t*(t**2 - 1)) + + sphere = ImplicitRegion((x, y, z), Eq(x**2 + y**2 + z**2, 2*x)) + assert sphere.rational_parametrization(parameters=(s, t)) == (2/(s**2 + t**2 + 1), 2*t/(s**2 + t**2 + 1), 2*s/(s**2 + t**2 + 1)) + + conic = ImplicitRegion((x, y), Eq(x**2 + 4*x*y + 3*y**2 + x - y + 10, 0)) + assert conic.rational_parametrization(t) == ( + S(17)/2 + 4/(3*t**2 + 4*t + 1), 4*t/(3*t**2 + 4*t + 1) - S(11)/2) + + r1 = ImplicitRegion((x, y), y**2 - x**3 + x) + raises(NotImplementedError, lambda: r1.rational_parametrization()) + r2 = ImplicitRegion((x, y), y**2 - x**3 - x**2 + 1) + raises(NotImplementedError, lambda: r2.rational_parametrization()) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_integrals.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_integrals.py new file mode 100644 index 0000000000000000000000000000000000000000..84c900d038e214df1ea59a8cd8fb2929005c3674 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_integrals.py @@ -0,0 +1,106 @@ +from sympy.core.numbers import pi +from sympy.core.singleton import S +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.testing.pytest import raises +from sympy.vector.coordsysrect import CoordSys3D +from sympy.vector.integrals import ParametricIntegral, vector_integrate +from sympy.vector.parametricregion import ParametricRegion +from sympy.vector.implicitregion import ImplicitRegion +from sympy.abc import x, y, z, u, v, r, t, theta, phi +from sympy.geometry import Point, Segment, Curve, Circle, Polygon, Plane + +C = CoordSys3D('C') + +def test_parametric_lineintegrals(): + halfcircle = ParametricRegion((4*cos(theta), 4*sin(theta)), (theta, -pi/2, pi/2)) + assert ParametricIntegral(C.x*C.y**4, halfcircle) == S(8192)/5 + + curve = ParametricRegion((t, t**2, t**3), (t, 0, 1)) + field1 = 8*C.x**2*C.y*C.z*C.i + 5*C.z*C.j - 4*C.x*C.y*C.k + assert ParametricIntegral(field1, curve) == 1 + line = ParametricRegion((4*t - 1, 2 - 2*t, t), (t, 0, 1)) + assert ParametricIntegral(C.x*C.z*C.i - C.y*C.z*C.k, line) == 3 + + assert ParametricIntegral(4*C.x**3, ParametricRegion((1, t), (t, 0, 2))) == 8 + + helix = ParametricRegion((cos(t), sin(t), 3*t), (t, 0, 4*pi)) + assert ParametricIntegral(C.x*C.y*C.z, helix) == -3*sqrt(10)*pi + + field2 = C.y*C.i + C.z*C.j + C.z*C.k + assert ParametricIntegral(field2, ParametricRegion((cos(t), sin(t), t**2), (t, 0, pi))) == -5*pi/2 + pi**4/2 + +def test_parametric_surfaceintegrals(): + + semisphere = ParametricRegion((2*sin(phi)*cos(theta), 2*sin(phi)*sin(theta), 2*cos(phi)),\ + (theta, 0, 2*pi), (phi, 0, pi/2)) + assert ParametricIntegral(C.z, semisphere) == 8*pi + + cylinder = ParametricRegion((sqrt(3)*cos(theta), sqrt(3)*sin(theta), z), (z, 0, 6), (theta, 0, 2*pi)) + assert ParametricIntegral(C.y, cylinder) == 0 + + cone = ParametricRegion((v*cos(u), v*sin(u), v), (u, 0, 2*pi), (v, 0, 1)) + assert ParametricIntegral(C.x*C.i + C.y*C.j + C.z**4*C.k, cone) == pi/3 + + triangle1 = ParametricRegion((x, y), (x, 0, 2), (y, 0, 10 - 5*x)) + triangle2 = ParametricRegion((x, y), (y, 0, 10 - 5*x), (x, 0, 2)) + assert ParametricIntegral(-15.6*C.y*C.k, triangle1) == ParametricIntegral(-15.6*C.y*C.k, triangle2) + assert ParametricIntegral(C.z, triangle1) == 10*C.z + +def test_parametric_volumeintegrals(): + + cube = ParametricRegion((x, y, z), (x, 0, 1), (y, 0, 1), (z, 0, 1)) + assert ParametricIntegral(1, cube) == 1 + + solidsphere1 = ParametricRegion((r*sin(phi)*cos(theta), r*sin(phi)*sin(theta), r*cos(phi)),\ + (r, 0, 2), (theta, 0, 2*pi), (phi, 0, pi)) + solidsphere2 = ParametricRegion((r*sin(phi)*cos(theta), r*sin(phi)*sin(theta), r*cos(phi)),\ + (r, 0, 2), (phi, 0, pi), (theta, 0, 2*pi)) + assert ParametricIntegral(C.x**2 + C.y**2, solidsphere1) == -256*pi/15 + assert ParametricIntegral(C.x**2 + C.y**2, solidsphere2) == 256*pi/15 + + region_under_plane1 = ParametricRegion((x, y, z), (x, 0, 3), (y, 0, -2*x/3 + 2),\ + (z, 0, 6 - 2*x - 3*y)) + region_under_plane2 = ParametricRegion((x, y, z), (x, 0, 3), (z, 0, 6 - 2*x - 3*y),\ + (y, 0, -2*x/3 + 2)) + + assert ParametricIntegral(C.x*C.i + C.j - 100*C.k, region_under_plane1) == \ + ParametricIntegral(C.x*C.i + C.j - 100*C.k, region_under_plane2) + assert ParametricIntegral(2*C.x, region_under_plane2) == -9 + +def test_vector_integrate(): + halfdisc = ParametricRegion((r*cos(theta), r* sin(theta)), (r, -2, 2), (theta, 0, pi)) + assert vector_integrate(C.x**2, halfdisc) == 4*pi + assert vector_integrate(C.x, ParametricRegion((t, t**2), (t, 2, 3))) == -17*sqrt(17)/12 + 37*sqrt(37)/12 + + assert vector_integrate(C.y**3*C.z, (C.x, 0, 3), (C.y, -1, 4)) == 765*C.z/4 + + s1 = Segment(Point(0, 0), Point(0, 1)) + assert vector_integrate(-15*C.y, s1) == S(-15)/2 + s2 = Segment(Point(4, 3, 9), Point(1, 1, 7)) + assert vector_integrate(C.y*C.i, s2) == -6 + + curve = Curve((sin(t), cos(t)), (t, 0, 2)) + assert vector_integrate(5*C.z, curve) == 10*C.z + + c1 = Circle(Point(2, 3), 6) + assert vector_integrate(C.x*C.y, c1) == 72*pi + c2 = Circle(Point(0, 0), Point(1, 1), Point(1, 0)) + assert vector_integrate(1, c2) == c2.circumference + + triangle = Polygon((0, 0), (1, 0), (1, 1)) + assert vector_integrate(C.x*C.i - 14*C.y*C.j, triangle) == 0 + p1, p2, p3, p4 = [(0, 0), (1, 0), (5, 1), (0, 1)] + poly = Polygon(p1, p2, p3, p4) + assert vector_integrate(-23*C.z, poly) == -161*C.z - 23*sqrt(17)*C.z + + point = Point(2, 3) + assert vector_integrate(C.i*C.y, point) == ParametricIntegral(C.y*C.i, ParametricRegion((2, 3))) + + c3 = ImplicitRegion((x, y), x**2 + y**2 - 4) + assert vector_integrate(45, c3) == 180*pi + c4 = ImplicitRegion((x, y), (x - 3)**2 + (y - 4)**2 - 9) + assert vector_integrate(1, c4) == 6*pi + + pl = Plane(Point(1, 1, 1), Point(2, 3, 4), Point(2, 2, 2)) + raises(ValueError, lambda: vector_integrate(C.x*C.z*C.i + C.k, pl)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_operators.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_operators.py new file mode 100644 index 0000000000000000000000000000000000000000..5734edadd00547c67d6f864b50afd966ad8392a6 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_operators.py @@ -0,0 +1,43 @@ +from sympy.vector import CoordSys3D, Gradient, Divergence, Curl, VectorZero, Laplacian +from sympy.printing.repr import srepr + +R = CoordSys3D('R') +s1 = R.x*R.y*R.z # type: ignore +s2 = R.x + 3*R.y**2 # type: ignore +s3 = R.x**2 + R.y**2 + R.z**2 # type: ignore +v1 = R.x*R.i + R.z*R.z*R.j # type: ignore +v2 = R.x*R.i + R.y*R.j + R.z*R.k # type: ignore +v3 = R.x**2*R.i + R.y**2*R.j + R.z**2*R.k # type: ignore + + +def test_Gradient(): + assert Gradient(s1) == Gradient(R.x*R.y*R.z) + assert Gradient(s2) == Gradient(R.x + 3*R.y**2) + assert Gradient(s1).doit() == R.y*R.z*R.i + R.x*R.z*R.j + R.x*R.y*R.k + assert Gradient(s2).doit() == R.i + 6*R.y*R.j + + +def test_Divergence(): + assert Divergence(v1) == Divergence(R.x*R.i + R.z*R.z*R.j) + assert Divergence(v2) == Divergence(R.x*R.i + R.y*R.j + R.z*R.k) + assert Divergence(v1).doit() == 1 + assert Divergence(v2).doit() == 3 + # issue 22384 + Rc = CoordSys3D('R', transformation='cylindrical') + assert Divergence(Rc.i).doit() == 1/Rc.r + + +def test_Curl(): + assert Curl(v1) == Curl(R.x*R.i + R.z*R.z*R.j) + assert Curl(v2) == Curl(R.x*R.i + R.y*R.j + R.z*R.k) + assert Curl(v1).doit() == (-2*R.z)*R.i + assert Curl(v2).doit() == VectorZero() + + +def test_Laplacian(): + assert Laplacian(s3) == Laplacian(R.x**2 + R.y**2 + R.z**2) + assert Laplacian(v3) == Laplacian(R.x**2*R.i + R.y**2*R.j + R.z**2*R.k) + assert Laplacian(s3).doit() == 6 + assert Laplacian(v3).doit() == 2*R.i + 2*R.j + 2*R.k + assert srepr(Laplacian(s3)) == \ + 'Laplacian(Add(Pow(R.x, Integer(2)), Pow(R.y, Integer(2)), Pow(R.z, Integer(2))))' diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_parametricregion.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_parametricregion.py new file mode 100644 index 0000000000000000000000000000000000000000..e785b96744f9e2c39e91b997fcb70f8a921256bd --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_parametricregion.py @@ -0,0 +1,97 @@ +from sympy.core.numbers import pi +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.vector.coordsysrect import CoordSys3D +from sympy.vector.parametricregion import ParametricRegion, parametric_region_list +from sympy.geometry import Point, Segment, Curve, Ellipse, Line, Parabola, Polygon +from sympy.testing.pytest import raises +from sympy.abc import a, b, r, t, x, y, z, theta, phi + + +C = CoordSys3D('C') + +def test_ParametricRegion(): + + point = ParametricRegion((3, 4)) + assert point.definition == (3, 4) + assert point.parameters == () + assert point.limits == {} + assert point.dimensions == 0 + + # line x = y + line_xy = ParametricRegion((y, y), (y, 1, 5)) + assert line_xy .definition == (y, y) + assert line_xy.parameters == (y,) + assert line_xy.dimensions == 1 + + # line y = z + line_yz = ParametricRegion((x,t,t), x, (t, 1, 2)) + assert line_yz.definition == (x,t,t) + assert line_yz.parameters == (x, t) + assert line_yz.limits == {t: (1, 2)} + assert line_yz.dimensions == 1 + + p1 = ParametricRegion((9*a, -16*b), (a, 0, 2), (b, -1, 5)) + assert p1.definition == (9*a, -16*b) + assert p1.parameters == (a, b) + assert p1.limits == {a: (0, 2), b: (-1, 5)} + assert p1.dimensions == 2 + + p2 = ParametricRegion((t, t**3), t) + assert p2.parameters == (t,) + assert p2.limits == {} + assert p2.dimensions == 0 + + circle = ParametricRegion((r*cos(theta), r*sin(theta)), r, (theta, 0, 2*pi)) + assert circle.definition == (r*cos(theta), r*sin(theta)) + assert circle.dimensions == 1 + + halfdisc = ParametricRegion((r*cos(theta), r*sin(theta)), (r, -2, 2), (theta, 0, pi)) + assert halfdisc.definition == (r*cos(theta), r*sin(theta)) + assert halfdisc.parameters == (r, theta) + assert halfdisc.limits == {r: (-2, 2), theta: (0, pi)} + assert halfdisc.dimensions == 2 + + ellipse = ParametricRegion((a*cos(t), b*sin(t)), (t, 0, 8)) + assert ellipse.parameters == (t,) + assert ellipse.limits == {t: (0, 8)} + assert ellipse.dimensions == 1 + + cylinder = ParametricRegion((r*cos(theta), r*sin(theta), z), (r, 0, 1), (theta, 0, 2*pi), (z, 0, 4)) + assert cylinder.parameters == (r, theta, z) + assert cylinder.dimensions == 3 + + sphere = ParametricRegion((r*sin(phi)*cos(theta),r*sin(phi)*sin(theta), r*cos(phi)), + r, (theta, 0, 2*pi), (phi, 0, pi)) + assert sphere.definition == (r*sin(phi)*cos(theta),r*sin(phi)*sin(theta), r*cos(phi)) + assert sphere.parameters == (r, theta, phi) + assert sphere.dimensions == 2 + + raises(ValueError, lambda: ParametricRegion((a*t**2, 2*a*t), (a, -2))) + raises(ValueError, lambda: ParametricRegion((a, b), (a**2, sin(b)), (a, 2, 4, 6))) + + +def test_parametric_region_list(): + + point = Point(-5, 12) + assert parametric_region_list(point) == [ParametricRegion((-5, 12))] + + e = Ellipse(Point(2, 8), 2, 6) + assert parametric_region_list(e, t) == [ParametricRegion((2*cos(t) + 2, 6*sin(t) + 8), (t, 0, 2*pi))] + + c = Curve((t, t**3), (t, 5, 3)) + assert parametric_region_list(c) == [ParametricRegion((t, t**3), (t, 5, 3))] + + s = Segment(Point(2, 11, -6), Point(0, 2, 5)) + assert parametric_region_list(s, t) == [ParametricRegion((2 - 2*t, 11 - 9*t, 11*t - 6), (t, 0, 1))] + s1 = Segment(Point(0, 0), (1, 0)) + assert parametric_region_list(s1, t) == [ParametricRegion((t, 0), (t, 0, 1))] + s2 = Segment(Point(1, 2, 3), Point(1, 2, 5)) + assert parametric_region_list(s2, t) == [ParametricRegion((1, 2, 2*t + 3), (t, 0, 1))] + s3 = Segment(Point(12, 56), Point(12, 56)) + assert parametric_region_list(s3) == [ParametricRegion((12, 56))] + + poly = Polygon((1,3), (-3, 8), (2, 4)) + assert parametric_region_list(poly, t) == [ParametricRegion((1 - 4*t, 5*t + 3), (t, 0, 1)), ParametricRegion((5*t - 3, 8 - 4*t), (t, 0, 1)), ParametricRegion((2 - t, 4 - t), (t, 0, 1))] + + p1 = Parabola(Point(0, 0), Line(Point(5, 8), Point(7,8))) + raises(ValueError, lambda: parametric_region_list(p1)) diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_printing.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_printing.py new file mode 100644 index 0000000000000000000000000000000000000000..ae76905e967bdf93485f135c6a69f968e1208986 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_printing.py @@ -0,0 +1,221 @@ +# -*- coding: utf-8 -*- +from sympy.core.function import Function +from sympy.integrals.integrals import Integral +from sympy.printing.latex import latex +from sympy.printing.pretty import pretty as xpretty +from sympy.vector import CoordSys3D, Del, Vector, express +from sympy.abc import a, b, c +from sympy.testing.pytest import XFAIL + + +def pretty(expr): + """ASCII pretty-printing""" + return xpretty(expr, use_unicode=False, wrap_line=False) + + +def upretty(expr): + """Unicode pretty-printing""" + return xpretty(expr, use_unicode=True, wrap_line=False) + + +# Initialize the basic and tedious vector/dyadic expressions +# needed for testing. +# Some of the pretty forms shown denote how the expressions just +# above them should look with pretty printing. +N = CoordSys3D('N') +C = N.orient_new_axis('C', a, N.k) # type: ignore +v = [] +d = [] +v.append(Vector.zero) +v.append(N.i) # type: ignore +v.append(-N.i) # type: ignore +v.append(N.i + N.j) # type: ignore +v.append(a*N.i) # type: ignore +v.append(a*N.i - b*N.j) # type: ignore +v.append((a**2 + N.x)*N.i + N.k) # type: ignore +v.append((a**2 + b)*N.i + 3*(C.y - c)*N.k) # type: ignore +f = Function('f') +v.append(N.j - (Integral(f(b)) - C.x**2)*N.k) # type: ignore +upretty_v_8 = """\ + ⎛ 2 ⌠ ⎞ \n\ +j_N + ⎜x_C - ⎮ f(b) db⎟ k_N\n\ + ⎝ ⌡ ⎠ \ +""" +pretty_v_8 = """\ +j_N + / / \\\n\ + | 2 | |\n\ + |x_C - | f(b) db|\n\ + | | |\n\ + \\ / / \ +""" + +v.append(N.i + C.k) # type: ignore +v.append(express(N.i, C)) # type: ignore +v.append((a**2 + b)*N.i + (Integral(f(b)))*N.k) # type: ignore +upretty_v_11 = """\ +⎛ 2 ⎞ ⎛⌠ ⎞ \n\ +⎝a + b⎠ i_N + ⎜⎮ f(b) db⎟ k_N\n\ + ⎝⌡ ⎠ \ +""" +pretty_v_11 = """\ +/ 2 \\ + / / \\\n\ +\\a + b/ i_N| | |\n\ + | | f(b) db|\n\ + | | |\n\ + \\/ / \ +""" + +for x in v: + d.append(x | N.k) # type: ignore +s = 3*N.x**2*C.y # type: ignore +upretty_s = """\ + 2\n\ +3⋅y_C⋅x_N \ +""" +pretty_s = """\ + 2\n\ +3*y_C*x_N \ +""" + +# This is the pretty form for ((a**2 + b)*N.i + 3*(C.y - c)*N.k) | N.k +upretty_d_7 = """\ +⎛ 2 ⎞ \n\ +⎝a + b⎠ (i_N|k_N) + (3⋅y_C - 3⋅c) (k_N|k_N)\ +""" +pretty_d_7 = """\ +/ 2 \\ (i_N|k_N) + (3*y_C - 3*c) (k_N|k_N)\n\ +\\a + b/ \ +""" + + +def test_str_printing(): + assert str(v[0]) == '0' + assert str(v[1]) == 'N.i' + assert str(v[2]) == '(-1)*N.i' + assert str(v[3]) == 'N.i + N.j' + assert str(v[8]) == 'N.j + (C.x**2 - Integral(f(b), b))*N.k' + assert str(v[9]) == 'C.k + N.i' + assert str(s) == '3*C.y*N.x**2' + assert str(d[0]) == '0' + assert str(d[1]) == '(N.i|N.k)' + assert str(d[4]) == 'a*(N.i|N.k)' + assert str(d[5]) == 'a*(N.i|N.k) + (-b)*(N.j|N.k)' + assert str(d[8]) == ('(N.j|N.k) + (C.x**2 - ' + + 'Integral(f(b), b))*(N.k|N.k)') + + +@XFAIL +def test_pretty_printing_ascii(): + assert pretty(v[0]) == '0' + assert pretty(v[1]) == 'i_N' + assert pretty(v[5]) == '(a) i_N + (-b) j_N' + assert pretty(v[8]) == pretty_v_8 + assert pretty(v[2]) == '(-1) i_N' + assert pretty(v[11]) == pretty_v_11 + assert pretty(s) == pretty_s + assert pretty(d[0]) == '(0|0)' + assert pretty(d[5]) == '(a) (i_N|k_N) + (-b) (j_N|k_N)' + assert pretty(d[7]) == pretty_d_7 + assert pretty(d[10]) == '(cos(a)) (i_C|k_N) + (-sin(a)) (j_C|k_N)' + + +def test_pretty_print_unicode_v(): + assert upretty(v[0]) == '0' + assert upretty(v[1]) == 'i_N' + assert upretty(v[5]) == '(a) i_N + (-b) j_N' + # Make sure the printing works in other objects + assert upretty(v[5].args) == '((a) i_N, (-b) j_N)' + assert upretty(v[8]) == upretty_v_8 + assert upretty(v[2]) == '(-1) i_N' + assert upretty(v[11]) == upretty_v_11 + assert upretty(s) == upretty_s + assert upretty(d[0]) == '(0|0)' + assert upretty(d[5]) == '(a) (i_N|k_N) + (-b) (j_N|k_N)' + assert upretty(d[7]) == upretty_d_7 + assert upretty(d[10]) == '(cos(a)) (i_C|k_N) + (-sin(a)) (j_C|k_N)' + + +def test_latex_printing(): + assert latex(v[0]) == '\\mathbf{\\hat{0}}' + assert latex(v[1]) == '\\mathbf{\\hat{i}_{N}}' + assert latex(v[2]) == '- \\mathbf{\\hat{i}_{N}}' + assert latex(v[5]) == ('\\left(a\\right)\\mathbf{\\hat{i}_{N}} + ' + + '\\left(- b\\right)\\mathbf{\\hat{j}_{N}}') + assert latex(v[6]) == ('\\left(\\mathbf{{x}_{N}} + a^{2}\\right)\\mathbf{\\hat{i}_' + + '{N}} + \\mathbf{\\hat{k}_{N}}') + assert latex(v[8]) == ('\\mathbf{\\hat{j}_{N}} + \\left(\\mathbf{{x}_' + + '{C}}^{2} - \\int f{\\left(b \\right)}\\,' + + ' db\\right)\\mathbf{\\hat{k}_{N}}') + assert latex(s) == '3 \\mathbf{{y}_{C}} \\mathbf{{x}_{N}}^{2}' + assert latex(d[0]) == '(\\mathbf{\\hat{0}}|\\mathbf{\\hat{0}})' + assert latex(d[4]) == ('\\left(a\\right)\\left(\\mathbf{\\hat{i}_{N}}{\\middle|}' + + '\\mathbf{\\hat{k}_{N}}\\right)') + assert latex(d[9]) == ('\\left(\\mathbf{\\hat{k}_{C}}{\\middle|}' + + '\\mathbf{\\hat{k}_{N}}\\right) + \\left(' + + '\\mathbf{\\hat{i}_{N}}{\\middle|}\\mathbf{' + + '\\hat{k}_{N}}\\right)') + assert latex(d[11]) == ('\\left(a^{2} + b\\right)\\left(\\mathbf{\\hat{i}_{N}}' + + '{\\middle|}\\mathbf{\\hat{k}_{N}}\\right) + ' + + '\\left(\\int f{\\left(b \\right)}\\, db\\right)\\left(' + + '\\mathbf{\\hat{k}_{N}}{\\middle|}\\mathbf{' + + '\\hat{k}_{N}}\\right)') + +def test_issue_23058(): + from sympy import symbols, sin, cos, pi, UnevaluatedExpr + + delop = Del() + CC_ = CoordSys3D("C") + y = CC_.y + xhat = CC_.i + + t = symbols("t") + ten = symbols("10", positive=True) + eps, mu = 4*pi*ten**(-11), ten**(-5) + + Bx = 2 * ten**(-4) * cos(ten**5 * t) * sin(ten**(-3) * y) + vecB = Bx * xhat + vecE = (1/eps) * Integral(delop.cross(vecB/mu).doit(), t) + vecE = vecE.doit() + + vecB_str = """\ +⎛ ⎛y_C⎞ ⎛ 5 ⎞⎞ \n\ +⎜2⋅sin⎜───⎟⋅cos⎝10 ⋅t⎠⎟ i_C\n\ +⎜ ⎜ 3⎟ ⎟ \n\ +⎜ ⎝10 ⎠ ⎟ \n\ +⎜─────────────────────⎟ \n\ +⎜ 4 ⎟ \n\ +⎝ 10 ⎠ \ +""" + vecE_str = """\ +⎛ 4 ⎛ 5 ⎞ ⎛y_C⎞ ⎞ \n\ +⎜-10 ⋅sin⎝10 ⋅t⎠⋅cos⎜───⎟ ⎟ k_C\n\ +⎜ ⎜ 3⎟ ⎟ \n\ +⎜ ⎝10 ⎠ ⎟ \n\ +⎜─────────────────────────⎟ \n\ +⎝ 2⋅π ⎠ \ +""" + + assert upretty(vecB) == vecB_str + assert upretty(vecE) == vecE_str + + ten = UnevaluatedExpr(10) + eps, mu = 4*pi*ten**(-11), ten**(-5) + + Bx = 2 * ten**(-4) * cos(ten**5 * t) * sin(ten**(-3) * y) + vecB = Bx * xhat + + vecB_str = """\ +⎛ -4 ⎛ 5⎞ ⎛ -3⎞⎞ \n\ +⎝2⋅10 ⋅cos⎝t⋅10 ⎠⋅sin⎝y_C⋅10 ⎠⎠ i_C \ +""" + assert upretty(vecB) == vecB_str + +def test_custom_names(): + A = CoordSys3D('A', vector_names=['x', 'y', 'z'], + variable_names=['i', 'j', 'k']) + assert A.i.__str__() == 'A.i' + assert A.x.__str__() == 'A.x' + assert A.i._pretty_form == 'i_A' + assert A.x._pretty_form == 'x_A' + assert A.i._latex_form == r'\mathbf{{i}_{A}}' + assert A.x._latex_form == r"\mathbf{\hat{x}_{A}}" diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_vector.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_vector.py new file mode 100644 index 0000000000000000000000000000000000000000..daba6d6a02c87b41a8bf801eee9b9045897d0003 --- /dev/null +++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/sympy/vector/tests/test_vector.py @@ -0,0 +1,342 @@ +from sympy.core import Rational, S, Add, Mul, I +from sympy.simplify import simplify, trigsimp +from sympy.core.function import (Derivative, Function, diff) +from sympy.core.numbers import pi +from sympy.core.symbol import symbols +from sympy.functions.elementary.miscellaneous import sqrt +from sympy.functions.elementary.trigonometric import (cos, sin) +from sympy.integrals.integrals import Integral +from sympy.matrices.immutable import ImmutableDenseMatrix as Matrix +from sympy.vector.vector import Vector, BaseVector, VectorAdd, \ + VectorMul, VectorZero +from sympy.vector.coordsysrect import CoordSys3D +from sympy.vector.vector import Cross, Dot, cross +from sympy.testing.pytest import raises +from sympy.vector.kind import VectorKind +from sympy.core.kind import NumberKind +from sympy.testing.pytest import XFAIL + + +C = CoordSys3D('C') + +i, j, k = C.base_vectors() +a, b, c = symbols('a b c') + + +def test_cross(): + v1 = C.x * i + C.z * C.z * j + v2 = C.x * i + C.y * j + C.z * k + assert Cross(v1, v2) == Cross(C.x*C.i + C.z**2*C.j, C.x*C.i + C.y*C.j + C.z*C.k) + assert Cross(v1, v2).doit() == C.z**3*C.i + (-C.x*C.z)*C.j + (C.x*C.y - C.x*C.z**2)*C.k + assert cross(v1, v2) == C.z**3*C.i + (-C.x*C.z)*C.j + (C.x*C.y - C.x*C.z**2)*C.k + assert Cross(v1, v2) == -Cross(v2, v1) + # XXX: Cannot use Cross here. See XFAIL test below: + assert cross(v1, v2) + cross(v2, v1) == Vector.zero + + +@XFAIL +def test_cross_xfail(): + v1 = C.x * i + C.z * C.z * j + v2 = C.x * i + C.y * j + C.z * k + assert Cross(v1, v2) + Cross(v2, v1) == Vector.zero + + +def test_dot(): + v1 = C.x * i + C.z * C.z * j + v2 = C.x * i + C.y * j + C.z * k + assert Dot(v1, v2) == Dot(C.x*C.i + C.z**2*C.j, C.x*C.i + C.y*C.j + C.z*C.k) + assert Dot(v1, v2).doit() == C.x**2 + C.y*C.z**2 + assert Dot(v2, v1).doit() == C.x**2 + C.y*C.z**2 + assert Dot(v1, v2) == Dot(v2, v1) + + +def test_vector_sympy(): + """ + Test whether the Vector framework confirms to the hashing + and equality testing properties of SymPy. + """ + v1 = 3*j + assert v1 == j*3 + assert v1.components == {j: 3} + v2 = 3*i + 4*j + 5*k + v3 = 2*i + 4*j + i + 4*k + k + assert v3 == v2 + assert v3.__hash__() == v2.__hash__() + + +def test_kind(): + assert C.i.kind is VectorKind(NumberKind) + assert C.j.kind is VectorKind(NumberKind) + assert C.k.kind is VectorKind(NumberKind) + + assert C.x.kind is NumberKind + assert C.y.kind is NumberKind + assert C.z.kind is NumberKind + + assert Mul._kind_dispatcher(NumberKind, VectorKind(NumberKind)) is VectorKind(NumberKind) + assert Mul(2, C.i).kind is VectorKind(NumberKind) + + v1 = C.x * i + C.z * C.z * j + v2 = C.x * i + C.y * j + C.z * k + assert v1.kind is VectorKind(NumberKind) + assert v2.kind is VectorKind(NumberKind) + + assert (v1 + v2).kind is VectorKind(NumberKind) + assert Add(v1, v2).kind is VectorKind(NumberKind) + assert Cross(v1, v2).doit().kind is VectorKind(NumberKind) + assert VectorAdd(v1, v2).kind is VectorKind(NumberKind) + assert VectorMul(2, v1).kind is VectorKind(NumberKind) + assert VectorZero().kind is VectorKind(NumberKind) + + assert v1.projection(v2).kind is VectorKind(NumberKind) + assert v2.projection(v1).kind is VectorKind(NumberKind) + + +def test_vectoradd(): + assert isinstance(Add(C.i, C.j), VectorAdd) + v1 = C.x * i + C.z * C.z * j + v2 = C.x * i + C.y * j + C.z * k + assert isinstance(Add(v1, v2), VectorAdd) + + # https://github.com/sympy/sympy/issues/26121 + + E = Matrix([C.i, C.j, C.k]).T + a = Matrix([1, 2, 3]) + av = E*a + + assert av[0].kind == VectorKind() + assert isinstance(av[0], VectorAdd) + + +def test_vector(): + assert isinstance(i, BaseVector) + assert i != j + assert j != k + assert k != i + assert i - i == Vector.zero + assert i + Vector.zero == i + assert i - Vector.zero == i + assert Vector.zero != 0 + assert -Vector.zero == Vector.zero + + v1 = a*i + b*j + c*k + v2 = a**2*i + b**2*j + c**2*k + v3 = v1 + v2 + v4 = 2 * v1 + v5 = a * i + + assert isinstance(v1, VectorAdd) + assert v1 - v1 == Vector.zero + assert v1 + Vector.zero == v1 + assert v1.dot(i) == a + assert v1.dot(j) == b + assert v1.dot(k) == c + assert i.dot(v2) == a**2 + assert j.dot(v2) == b**2 + assert k.dot(v2) == c**2 + assert v3.dot(i) == a**2 + a + assert v3.dot(j) == b**2 + b + assert v3.dot(k) == c**2 + c + + assert v1 + v2 == v2 + v1 + assert v1 - v2 == -1 * (v2 - v1) + assert a * v1 == v1 * a + + assert isinstance(v5, VectorMul) + assert v5.base_vector == i + assert v5.measure_number == a + assert isinstance(v4, Vector) + assert isinstance(v4, VectorAdd) + assert isinstance(v4, Vector) + assert isinstance(Vector.zero, VectorZero) + assert isinstance(Vector.zero, Vector) + assert isinstance(v1 * 0, VectorZero) + + assert v1.to_matrix(C) == Matrix([[a], [b], [c]]) + + assert i.components == {i: 1} + assert v5.components == {i: a} + assert v1.components == {i: a, j: b, k: c} + + assert VectorAdd(v1, Vector.zero) == v1 + assert VectorMul(a, v1) == v1*a + assert VectorMul(1, i) == i + assert VectorAdd(v1, Vector.zero) == v1 + assert VectorMul(0, Vector.zero) == Vector.zero + raises(TypeError, lambda: v1.outer(1)) + raises(TypeError, lambda: v1.dot(1)) + + +def test_vector_magnitude_normalize(): + assert Vector.zero.magnitude() == 0 + assert Vector.zero.normalize() == Vector.zero + + assert i.magnitude() == 1 + assert j.magnitude() == 1 + assert k.magnitude() == 1 + assert i.normalize() == i + assert j.normalize() == j + assert k.normalize() == k + + v1 = a * i + assert v1.normalize() == (a/sqrt(a**2))*i + assert v1.magnitude() == sqrt(a**2) + + v2 = a*i + b*j + c*k + assert v2.magnitude() == sqrt(a**2 + b**2 + c**2) + assert v2.normalize() == v2 / v2.magnitude() + + v3 = i + j + assert v3.normalize() == (sqrt(2)/2)*C.i + (sqrt(2)/2)*C.j + + +def test_vector_simplify(): + A, s, k, m = symbols('A, s, k, m') + + test1 = (1 / a + 1 / b) * i + assert (test1 & i) != (a + b) / (a * b) + test1 = simplify(test1) + assert (test1 & i) == (a + b) / (a * b) + assert test1.simplify() == simplify(test1) + + test2 = (A**2 * s**4 / (4 * pi * k * m**3)) * i + test2 = simplify(test2) + assert (test2 & i) == (A**2 * s**4 / (4 * pi * k * m**3)) + + test3 = ((4 + 4 * a - 2 * (2 + 2 * a)) / (2 + 2 * a)) * i + test3 = simplify(test3) + assert (test3 & i) == 0 + + test4 = ((-4 * a * b**2 - 2 * b**3 - 2 * a**2 * b) / (a + b)**2) * i + test4 = simplify(test4) + assert (test4 & i) == -2 * b + + v = (sin(a)+cos(a))**2*i - j + assert trigsimp(v) == (2*sin(a + pi/4)**2)*i + (-1)*j + assert trigsimp(v) == v.trigsimp() + + assert simplify(Vector.zero) == Vector.zero + + +def test_vector_equals(): + assert (2*i).equals(j) is False + assert i.equals(i) is True + + # https://github.com/sympy/sympy/issues/25915 + A = (sqrt(2) + sqrt(6)) / sqrt(sqrt(3) + 2) + assert (A*i).equals(2*i) is True + assert (A*i).equals(3*i) is False + + # Test comparing vectors in different coordinate systems + D = C.orient_new_axis('D', pi/2, C.k) + assert (D.i).equals(C.j) is True + assert (D.i).equals(C.i) is False + + +def test_vector_conjugate(): + # https://github.com/sympy/sympy/issues/27094 + assert (I*i + (1 + I)*j + 2*k).conjugate() == -I*i + (1 - I)*j + 2*k + + +def test_vector_dot(): + assert i.dot(Vector.zero) == 0 + assert Vector.zero.dot(i) == 0 + assert i & Vector.zero == 0 + + assert i.dot(i) == 1 + assert i.dot(j) == 0 + assert i.dot(k) == 0 + assert i & i == 1 + assert i & j == 0 + assert i & k == 0 + + assert j.dot(i) == 0 + assert j.dot(j) == 1 + assert j.dot(k) == 0 + assert j & i == 0 + assert j & j == 1 + assert j & k == 0 + + assert k.dot(i) == 0 + assert k.dot(j) == 0 + assert k.dot(k) == 1 + assert k & i == 0 + assert k & j == 0 + assert k & k == 1 + + raises(TypeError, lambda: k.dot(1)) + + +def test_vector_cross(): + assert i.cross(Vector.zero) == Vector.zero + assert Vector.zero.cross(i) == Vector.zero + + assert i.cross(i) == Vector.zero + assert i.cross(j) == k + assert i.cross(k) == -j + assert i ^ i == Vector.zero + assert i ^ j == k + assert i ^ k == -j + + assert j.cross(i) == -k + assert j.cross(j) == Vector.zero + assert j.cross(k) == i + assert j ^ i == -k + assert j ^ j == Vector.zero + assert j ^ k == i + + assert k.cross(i) == j + assert k.cross(j) == -i + assert k.cross(k) == Vector.zero + assert k ^ i == j + assert k ^ j == -i + assert k ^ k == Vector.zero + + assert k.cross(1) == Cross(k, 1) + + +def test_projection(): + v1 = i + j + k + v2 = 3*i + 4*j + v3 = 0*i + 0*j + assert v1.projection(v1) == i + j + k + assert v1.projection(v2) == Rational(7, 3)*C.i + Rational(7, 3)*C.j + Rational(7, 3)*C.k + assert v1.projection(v1, scalar=True) == S.One + assert v1.projection(v2, scalar=True) == Rational(7, 3) + assert v3.projection(v1) == Vector.zero + assert v3.projection(v1, scalar=True) == S.Zero + + +def test_vector_diff_integrate(): + f = Function('f') + v = f(a)*C.i + a**2*C.j - C.k + assert Derivative(v, a) == Derivative((f(a))*C.i + + a**2*C.j + (-1)*C.k, a) + assert (diff(v, a) == v.diff(a) == Derivative(v, a).doit() == + (Derivative(f(a), a))*C.i + 2*a*C.j) + assert (Integral(v, a) == (Integral(f(a), a))*C.i + + (Integral(a**2, a))*C.j + (Integral(-1, a))*C.k) + + +def test_vector_args(): + raises(ValueError, lambda: BaseVector(3, C)) + raises(TypeError, lambda: BaseVector(0, Vector.zero)) + + +def test_srepr(): + from sympy.printing.repr import srepr + res = "CoordSys3D(Str('C'), Tuple(ImmutableDenseMatrix([[Integer(1), "\ + "Integer(0), Integer(0)], [Integer(0), Integer(1), Integer(0)], "\ + "[Integer(0), Integer(0), Integer(1)]]), VectorZero())).i" + assert srepr(C.i) == res + + +def test_scalar(): + from sympy.vector import CoordSys3D + C = CoordSys3D('C') + v1 = 3*C.i + 4*C.j + 5*C.k + v2 = 3*C.i - 4*C.j + 5*C.k + assert v1.is_Vector is True + assert v1.is_scalar is False + assert (v1.dot(v2)).is_scalar is True + assert (v1.cross(v2)).is_scalar is False