Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/algebras/__pycache__/__init__.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/algebras/__pycache__/quaternion.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/algebras/tests/__init__.py +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/algebras/tests/__pycache__/__init__.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/algebras/tests/__pycache__/test_quaternion.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/algebras/tests/test_quaternion.py +437 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/calculus/tests/__init__.py +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/calculus/tests/test_accumulationbounds.py +336 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/calculus/tests/test_euler.py +74 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/calculus/tests/test_singularities.py +122 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/calculus/tests/test_util.py +392 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/diffgeom/__pycache__/__init__.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/diffgeom/__pycache__/diffgeom.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/diffgeom/__pycache__/rn.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/diffgeom/tests/__init__.py +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/diffgeom/tests/__pycache__/__init__.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/diffgeom/tests/__pycache__/test_class_structure.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/diffgeom/tests/__pycache__/test_diffgeom.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/diffgeom/tests/__pycache__/test_function_diffgeom_book.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/diffgeom/tests/__pycache__/test_hyperbolic_space.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/diffgeom/tests/test_class_structure.py +33 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/diffgeom/tests/test_diffgeom.py +342 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/diffgeom/tests/test_function_diffgeom_book.py +145 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/diffgeom/tests/test_hyperbolic_space.py +91 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/__init__.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/basisdependent.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/coordsysrect.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/deloperator.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/dyadic.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/functions.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/implicitregion.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/integrals.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/kind.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/operators.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/orienters.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/parametricregion.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/point.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/scalar.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/vector.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/tests/__init__.py +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/__init__.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_coordsysrect.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_dyadic.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_field_functions.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_functions.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_implicitregion.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_integrals.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_operators.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_parametricregion.cpython-312.pyc +0 -0
- URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_printing.cpython-312.pyc +0 -0
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/algebras/__pycache__/__init__.cpython-312.pyc
ADDED
|
Binary file (281 Bytes). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/algebras/__pycache__/quaternion.cpython-312.pyc
ADDED
|
Binary file (62.5 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/algebras/tests/__init__.py
ADDED
|
File without changes
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/algebras/tests/__pycache__/__init__.cpython-312.pyc
ADDED
|
Binary file (212 Bytes). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/algebras/tests/__pycache__/test_quaternion.cpython-312.pyc
ADDED
|
Binary file (36.5 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/algebras/tests/test_quaternion.py
ADDED
|
@@ -0,0 +1,437 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.testing.pytest import slow
|
| 2 |
+
from sympy.core.function import diff
|
| 3 |
+
from sympy.core.function import expand
|
| 4 |
+
from sympy.core.numbers import (E, I, Rational, pi)
|
| 5 |
+
from sympy.core.singleton import S
|
| 6 |
+
from sympy.core.symbol import (Symbol, symbols)
|
| 7 |
+
from sympy.functions.elementary.complexes import (Abs, conjugate, im, re, sign)
|
| 8 |
+
from sympy.functions.elementary.exponential import log
|
| 9 |
+
from sympy.functions.elementary.miscellaneous import sqrt
|
| 10 |
+
from sympy.functions.elementary.trigonometric import (acos, asin, cos, sin, atan2, atan)
|
| 11 |
+
from sympy.integrals.integrals import integrate
|
| 12 |
+
from sympy.matrices.dense import Matrix
|
| 13 |
+
from sympy.simplify import simplify
|
| 14 |
+
from sympy.simplify.trigsimp import trigsimp
|
| 15 |
+
from sympy.algebras.quaternion import Quaternion
|
| 16 |
+
from sympy.testing.pytest import raises
|
| 17 |
+
import math
|
| 18 |
+
from itertools import permutations, product
|
| 19 |
+
|
| 20 |
+
w, x, y, z = symbols('w:z')
|
| 21 |
+
phi = symbols('phi')
|
| 22 |
+
|
| 23 |
+
def test_quaternion_construction():
|
| 24 |
+
q = Quaternion(w, x, y, z)
|
| 25 |
+
assert q + q == Quaternion(2*w, 2*x, 2*y, 2*z)
|
| 26 |
+
|
| 27 |
+
q2 = Quaternion.from_axis_angle((sqrt(3)/3, sqrt(3)/3, sqrt(3)/3),
|
| 28 |
+
pi*Rational(2, 3))
|
| 29 |
+
assert q2 == Quaternion(S.Half, S.Half,
|
| 30 |
+
S.Half, S.Half)
|
| 31 |
+
|
| 32 |
+
M = Matrix([[cos(phi), -sin(phi), 0], [sin(phi), cos(phi), 0], [0, 0, 1]])
|
| 33 |
+
q3 = trigsimp(Quaternion.from_rotation_matrix(M))
|
| 34 |
+
assert q3 == Quaternion(
|
| 35 |
+
sqrt(2)*sqrt(cos(phi) + 1)/2, 0, 0, sqrt(2 - 2*cos(phi))*sign(sin(phi))/2)
|
| 36 |
+
|
| 37 |
+
nc = Symbol('nc', commutative=False)
|
| 38 |
+
raises(ValueError, lambda: Quaternion(w, x, nc, z))
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
def test_quaternion_construction_norm():
|
| 42 |
+
q1 = Quaternion(*symbols('a:d'))
|
| 43 |
+
|
| 44 |
+
q2 = Quaternion(w, x, y, z)
|
| 45 |
+
assert expand((q1*q2).norm()**2 - (q1.norm()**2 * q2.norm()**2)) == 0
|
| 46 |
+
|
| 47 |
+
q3 = Quaternion(w, x, y, z, norm=1)
|
| 48 |
+
assert (q1 * q3).norm() == q1.norm()
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
def test_issue_25254():
|
| 52 |
+
# calculating the inverse cached the norm which caused problems
|
| 53 |
+
# when multiplying
|
| 54 |
+
p = Quaternion(1, 0, 0, 0)
|
| 55 |
+
q = Quaternion.from_axis_angle((1, 1, 1), 3 * math.pi/4)
|
| 56 |
+
qi = q.inverse() # this operation cached the norm
|
| 57 |
+
test = q * p * qi
|
| 58 |
+
assert ((test - p).norm() < 1E-10)
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
def test_to_and_from_Matrix():
|
| 62 |
+
q = Quaternion(w, x, y, z)
|
| 63 |
+
q_full = Quaternion.from_Matrix(q.to_Matrix())
|
| 64 |
+
q_vect = Quaternion.from_Matrix(q.to_Matrix(True))
|
| 65 |
+
assert (q - q_full).is_zero_quaternion()
|
| 66 |
+
assert (q.vector_part() - q_vect).is_zero_quaternion()
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
def test_product_matrices():
|
| 70 |
+
q1 = Quaternion(w, x, y, z)
|
| 71 |
+
q2 = Quaternion(*(symbols("a:d")))
|
| 72 |
+
assert (q1 * q2).to_Matrix() == q1.product_matrix_left * q2.to_Matrix()
|
| 73 |
+
assert (q1 * q2).to_Matrix() == q2.product_matrix_right * q1.to_Matrix()
|
| 74 |
+
|
| 75 |
+
R1 = (q1.product_matrix_left * q1.product_matrix_right.T)[1:, 1:]
|
| 76 |
+
R2 = simplify(q1.to_rotation_matrix()*q1.norm()**2)
|
| 77 |
+
assert R1 == R2
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
def test_quaternion_axis_angle():
|
| 81 |
+
|
| 82 |
+
test_data = [ # axis, angle, expected_quaternion
|
| 83 |
+
((1, 0, 0), 0, (1, 0, 0, 0)),
|
| 84 |
+
((1, 0, 0), pi/2, (sqrt(2)/2, sqrt(2)/2, 0, 0)),
|
| 85 |
+
((0, 1, 0), pi/2, (sqrt(2)/2, 0, sqrt(2)/2, 0)),
|
| 86 |
+
((0, 0, 1), pi/2, (sqrt(2)/2, 0, 0, sqrt(2)/2)),
|
| 87 |
+
((1, 0, 0), pi, (0, 1, 0, 0)),
|
| 88 |
+
((0, 1, 0), pi, (0, 0, 1, 0)),
|
| 89 |
+
((0, 0, 1), pi, (0, 0, 0, 1)),
|
| 90 |
+
((1, 1, 1), pi, (0, 1/sqrt(3),1/sqrt(3),1/sqrt(3))),
|
| 91 |
+
((sqrt(3)/3, sqrt(3)/3, sqrt(3)/3), pi*2/3, (S.Half, S.Half, S.Half, S.Half))
|
| 92 |
+
]
|
| 93 |
+
|
| 94 |
+
for axis, angle, expected in test_data:
|
| 95 |
+
assert Quaternion.from_axis_angle(axis, angle) == Quaternion(*expected)
|
| 96 |
+
|
| 97 |
+
|
| 98 |
+
def test_quaternion_axis_angle_simplification():
|
| 99 |
+
result = Quaternion.from_axis_angle((1, 2, 3), asin(4))
|
| 100 |
+
assert result.a == cos(asin(4)/2)
|
| 101 |
+
assert result.b == sqrt(14)*sin(asin(4)/2)/14
|
| 102 |
+
assert result.c == sqrt(14)*sin(asin(4)/2)/7
|
| 103 |
+
assert result.d == 3*sqrt(14)*sin(asin(4)/2)/14
|
| 104 |
+
|
| 105 |
+
def test_quaternion_complex_real_addition():
|
| 106 |
+
a = symbols("a", complex=True)
|
| 107 |
+
b = symbols("b", real=True)
|
| 108 |
+
# This symbol is not complex:
|
| 109 |
+
c = symbols("c", commutative=False)
|
| 110 |
+
|
| 111 |
+
q = Quaternion(w, x, y, z)
|
| 112 |
+
assert a + q == Quaternion(w + re(a), x + im(a), y, z)
|
| 113 |
+
assert 1 + q == Quaternion(1 + w, x, y, z)
|
| 114 |
+
assert I + q == Quaternion(w, 1 + x, y, z)
|
| 115 |
+
assert b + q == Quaternion(w + b, x, y, z)
|
| 116 |
+
raises(ValueError, lambda: c + q)
|
| 117 |
+
raises(ValueError, lambda: q * c)
|
| 118 |
+
raises(ValueError, lambda: c * q)
|
| 119 |
+
|
| 120 |
+
assert -q == Quaternion(-w, -x, -y, -z)
|
| 121 |
+
|
| 122 |
+
q1 = Quaternion(3 + 4*I, 2 + 5*I, 0, 7 + 8*I, real_field = False)
|
| 123 |
+
q2 = Quaternion(1, 4, 7, 8)
|
| 124 |
+
|
| 125 |
+
assert q1 + (2 + 3*I) == Quaternion(5 + 7*I, 2 + 5*I, 0, 7 + 8*I)
|
| 126 |
+
assert q2 + (2 + 3*I) == Quaternion(3, 7, 7, 8)
|
| 127 |
+
assert q1 * (2 + 3*I) == \
|
| 128 |
+
Quaternion((2 + 3*I)*(3 + 4*I), (2 + 3*I)*(2 + 5*I), 0, (2 + 3*I)*(7 + 8*I))
|
| 129 |
+
assert q2 * (2 + 3*I) == Quaternion(-10, 11, 38, -5)
|
| 130 |
+
|
| 131 |
+
q1 = Quaternion(1, 2, 3, 4)
|
| 132 |
+
q0 = Quaternion(0, 0, 0, 0)
|
| 133 |
+
assert q1 + q0 == q1
|
| 134 |
+
assert q1 - q0 == q1
|
| 135 |
+
assert q1 - q1 == q0
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
def test_quaternion_subs():
|
| 139 |
+
q = Quaternion.from_axis_angle((0, 0, 1), phi)
|
| 140 |
+
assert q.subs(phi, 0) == Quaternion(1, 0, 0, 0)
|
| 141 |
+
|
| 142 |
+
|
| 143 |
+
def test_quaternion_evalf():
|
| 144 |
+
assert (Quaternion(sqrt(2), 0, 0, sqrt(3)).evalf() ==
|
| 145 |
+
Quaternion(sqrt(2).evalf(), 0, 0, sqrt(3).evalf()))
|
| 146 |
+
assert (Quaternion(1/sqrt(2), 0, 0, 1/sqrt(2)).evalf() ==
|
| 147 |
+
Quaternion((1/sqrt(2)).evalf(), 0, 0, (1/sqrt(2)).evalf()))
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
def test_quaternion_functions():
|
| 151 |
+
q = Quaternion(w, x, y, z)
|
| 152 |
+
q1 = Quaternion(1, 2, 3, 4)
|
| 153 |
+
q0 = Quaternion(0, 0, 0, 0)
|
| 154 |
+
|
| 155 |
+
assert conjugate(q) == Quaternion(w, -x, -y, -z)
|
| 156 |
+
assert q.norm() == sqrt(w**2 + x**2 + y**2 + z**2)
|
| 157 |
+
assert q.normalize() == Quaternion(w, x, y, z) / sqrt(w**2 + x**2 + y**2 + z**2)
|
| 158 |
+
assert q.inverse() == Quaternion(w, -x, -y, -z) / (w**2 + x**2 + y**2 + z**2)
|
| 159 |
+
assert q.inverse() == q.pow(-1)
|
| 160 |
+
raises(ValueError, lambda: q0.inverse())
|
| 161 |
+
assert q.pow(2) == Quaternion(w**2 - x**2 - y**2 - z**2, 2*w*x, 2*w*y, 2*w*z)
|
| 162 |
+
assert q**(2) == Quaternion(w**2 - x**2 - y**2 - z**2, 2*w*x, 2*w*y, 2*w*z)
|
| 163 |
+
assert q1.pow(-2) == Quaternion(
|
| 164 |
+
Rational(-7, 225), Rational(-1, 225), Rational(-1, 150), Rational(-2, 225))
|
| 165 |
+
assert q1**(-2) == Quaternion(
|
| 166 |
+
Rational(-7, 225), Rational(-1, 225), Rational(-1, 150), Rational(-2, 225))
|
| 167 |
+
assert q1.pow(-0.5) == NotImplemented
|
| 168 |
+
raises(TypeError, lambda: q1**(-0.5))
|
| 169 |
+
|
| 170 |
+
assert q1.exp() == \
|
| 171 |
+
Quaternion(E * cos(sqrt(29)),
|
| 172 |
+
2 * sqrt(29) * E * sin(sqrt(29)) / 29,
|
| 173 |
+
3 * sqrt(29) * E * sin(sqrt(29)) / 29,
|
| 174 |
+
4 * sqrt(29) * E * sin(sqrt(29)) / 29)
|
| 175 |
+
assert q1.log() == \
|
| 176 |
+
Quaternion(log(sqrt(30)),
|
| 177 |
+
2 * sqrt(29) * acos(sqrt(30)/30) / 29,
|
| 178 |
+
3 * sqrt(29) * acos(sqrt(30)/30) / 29,
|
| 179 |
+
4 * sqrt(29) * acos(sqrt(30)/30) / 29)
|
| 180 |
+
|
| 181 |
+
assert q1.pow_cos_sin(2) == \
|
| 182 |
+
Quaternion(30 * cos(2 * acos(sqrt(30)/30)),
|
| 183 |
+
60 * sqrt(29) * sin(2 * acos(sqrt(30)/30)) / 29,
|
| 184 |
+
90 * sqrt(29) * sin(2 * acos(sqrt(30)/30)) / 29,
|
| 185 |
+
120 * sqrt(29) * sin(2 * acos(sqrt(30)/30)) / 29)
|
| 186 |
+
|
| 187 |
+
assert diff(Quaternion(x, x, x, x), x) == Quaternion(1, 1, 1, 1)
|
| 188 |
+
|
| 189 |
+
assert integrate(Quaternion(x, x, x, x), x) == \
|
| 190 |
+
Quaternion(x**2 / 2, x**2 / 2, x**2 / 2, x**2 / 2)
|
| 191 |
+
|
| 192 |
+
assert Quaternion(1, x, x**2, x**3).integrate(x) == \
|
| 193 |
+
Quaternion(x, x**2/2, x**3/3, x**4/4)
|
| 194 |
+
|
| 195 |
+
assert Quaternion(sin(x), cos(x), sin(2*x), cos(2*x)).integrate(x) == \
|
| 196 |
+
Quaternion(-cos(x), sin(x), -cos(2*x)/2, sin(2*x)/2)
|
| 197 |
+
|
| 198 |
+
assert Quaternion(x**2, y**2, z**2, x*y*z).integrate(x, y) == \
|
| 199 |
+
Quaternion(x**3*y/3, x*y**3/3, x*y*z**2, x**2*y**2*z/4)
|
| 200 |
+
|
| 201 |
+
assert Quaternion.rotate_point((1, 1, 1), q1) == (S.One / 5, 1, S(7) / 5)
|
| 202 |
+
n = Symbol('n')
|
| 203 |
+
raises(TypeError, lambda: q1**n)
|
| 204 |
+
n = Symbol('n', integer=True)
|
| 205 |
+
raises(TypeError, lambda: q1**n)
|
| 206 |
+
|
| 207 |
+
assert Quaternion(22, 23, 55, 8).scalar_part() == 22
|
| 208 |
+
assert Quaternion(w, x, y, z).scalar_part() == w
|
| 209 |
+
|
| 210 |
+
assert Quaternion(22, 23, 55, 8).vector_part() == Quaternion(0, 23, 55, 8)
|
| 211 |
+
assert Quaternion(w, x, y, z).vector_part() == Quaternion(0, x, y, z)
|
| 212 |
+
|
| 213 |
+
assert q1.axis() == Quaternion(0, 2*sqrt(29)/29, 3*sqrt(29)/29, 4*sqrt(29)/29)
|
| 214 |
+
assert q1.axis().pow(2) == Quaternion(-1, 0, 0, 0)
|
| 215 |
+
assert q0.axis().scalar_part() == 0
|
| 216 |
+
assert (q.axis() == Quaternion(0,
|
| 217 |
+
x/sqrt(x**2 + y**2 + z**2),
|
| 218 |
+
y/sqrt(x**2 + y**2 + z**2),
|
| 219 |
+
z/sqrt(x**2 + y**2 + z**2)))
|
| 220 |
+
|
| 221 |
+
assert q0.is_pure() is True
|
| 222 |
+
assert q1.is_pure() is False
|
| 223 |
+
assert Quaternion(0, 0, 0, 3).is_pure() is True
|
| 224 |
+
assert Quaternion(0, 2, 10, 3).is_pure() is True
|
| 225 |
+
assert Quaternion(w, 2, 10, 3).is_pure() is None
|
| 226 |
+
|
| 227 |
+
assert q1.angle() == 2*atan(sqrt(29))
|
| 228 |
+
assert q.angle() == 2*atan2(sqrt(x**2 + y**2 + z**2), w)
|
| 229 |
+
|
| 230 |
+
assert Quaternion.arc_coplanar(q1, Quaternion(2, 4, 6, 8)) is True
|
| 231 |
+
assert Quaternion.arc_coplanar(q1, Quaternion(1, -2, -3, -4)) is True
|
| 232 |
+
assert Quaternion.arc_coplanar(q1, Quaternion(1, 8, 12, 16)) is True
|
| 233 |
+
assert Quaternion.arc_coplanar(q1, Quaternion(1, 2, 3, 4)) is True
|
| 234 |
+
assert Quaternion.arc_coplanar(q1, Quaternion(w, 4, 6, 8)) is True
|
| 235 |
+
assert Quaternion.arc_coplanar(q1, Quaternion(2, 7, 4, 1)) is False
|
| 236 |
+
assert Quaternion.arc_coplanar(q1, Quaternion(w, x, y, z)) is None
|
| 237 |
+
raises(ValueError, lambda: Quaternion.arc_coplanar(q1, q0))
|
| 238 |
+
|
| 239 |
+
assert Quaternion.vector_coplanar(
|
| 240 |
+
Quaternion(0, 8, 12, 16),
|
| 241 |
+
Quaternion(0, 4, 6, 8),
|
| 242 |
+
Quaternion(0, 2, 3, 4)) is True
|
| 243 |
+
assert Quaternion.vector_coplanar(
|
| 244 |
+
Quaternion(0, 0, 0, 0), Quaternion(0, 4, 6, 8), Quaternion(0, 2, 3, 4)) is True
|
| 245 |
+
assert Quaternion.vector_coplanar(
|
| 246 |
+
Quaternion(0, 8, 2, 6), Quaternion(0, 1, 6, 6), Quaternion(0, 0, 3, 4)) is False
|
| 247 |
+
assert Quaternion.vector_coplanar(
|
| 248 |
+
Quaternion(0, 1, 3, 4),
|
| 249 |
+
Quaternion(0, 4, w, 6),
|
| 250 |
+
Quaternion(0, 6, 8, 1)) is None
|
| 251 |
+
raises(ValueError, lambda:
|
| 252 |
+
Quaternion.vector_coplanar(q0, Quaternion(0, 4, 6, 8), q1))
|
| 253 |
+
|
| 254 |
+
assert Quaternion(0, 1, 2, 3).parallel(Quaternion(0, 2, 4, 6)) is True
|
| 255 |
+
assert Quaternion(0, 1, 2, 3).parallel(Quaternion(0, 2, 2, 6)) is False
|
| 256 |
+
assert Quaternion(0, 1, 2, 3).parallel(Quaternion(w, x, y, 6)) is None
|
| 257 |
+
raises(ValueError, lambda: q0.parallel(q1))
|
| 258 |
+
|
| 259 |
+
assert Quaternion(0, 1, 2, 3).orthogonal(Quaternion(0, -2, 1, 0)) is True
|
| 260 |
+
assert Quaternion(0, 2, 4, 7).orthogonal(Quaternion(0, 2, 2, 6)) is False
|
| 261 |
+
assert Quaternion(0, 2, 4, 7).orthogonal(Quaternion(w, x, y, 6)) is None
|
| 262 |
+
raises(ValueError, lambda: q0.orthogonal(q1))
|
| 263 |
+
|
| 264 |
+
assert q1.index_vector() == Quaternion(
|
| 265 |
+
0, 2*sqrt(870)/29,
|
| 266 |
+
3*sqrt(870)/29,
|
| 267 |
+
4*sqrt(870)/29)
|
| 268 |
+
assert Quaternion(0, 3, 9, 4).index_vector() == Quaternion(0, 3, 9, 4)
|
| 269 |
+
|
| 270 |
+
assert Quaternion(4, 3, 9, 4).mensor() == log(sqrt(122))
|
| 271 |
+
assert Quaternion(3, 3, 0, 2).mensor() == log(sqrt(22))
|
| 272 |
+
|
| 273 |
+
assert q0.is_zero_quaternion() is True
|
| 274 |
+
assert q1.is_zero_quaternion() is False
|
| 275 |
+
assert Quaternion(w, 0, 0, 0).is_zero_quaternion() is None
|
| 276 |
+
|
| 277 |
+
def test_quaternion_conversions():
|
| 278 |
+
q1 = Quaternion(1, 2, 3, 4)
|
| 279 |
+
|
| 280 |
+
assert q1.to_axis_angle() == ((2 * sqrt(29)/29,
|
| 281 |
+
3 * sqrt(29)/29,
|
| 282 |
+
4 * sqrt(29)/29),
|
| 283 |
+
2 * acos(sqrt(30)/30))
|
| 284 |
+
|
| 285 |
+
assert (q1.to_rotation_matrix() ==
|
| 286 |
+
Matrix([[Rational(-2, 3), Rational(2, 15), Rational(11, 15)],
|
| 287 |
+
[Rational(2, 3), Rational(-1, 3), Rational(2, 3)],
|
| 288 |
+
[Rational(1, 3), Rational(14, 15), Rational(2, 15)]]))
|
| 289 |
+
|
| 290 |
+
assert (q1.to_rotation_matrix((1, 1, 1)) ==
|
| 291 |
+
Matrix([
|
| 292 |
+
[Rational(-2, 3), Rational(2, 15), Rational(11, 15), Rational(4, 5)],
|
| 293 |
+
[Rational(2, 3), Rational(-1, 3), Rational(2, 3), S.Zero],
|
| 294 |
+
[Rational(1, 3), Rational(14, 15), Rational(2, 15), Rational(-2, 5)],
|
| 295 |
+
[S.Zero, S.Zero, S.Zero, S.One]]))
|
| 296 |
+
|
| 297 |
+
theta = symbols("theta", real=True)
|
| 298 |
+
q2 = Quaternion(cos(theta/2), 0, 0, sin(theta/2))
|
| 299 |
+
|
| 300 |
+
assert trigsimp(q2.to_rotation_matrix()) == Matrix([
|
| 301 |
+
[cos(theta), -sin(theta), 0],
|
| 302 |
+
[sin(theta), cos(theta), 0],
|
| 303 |
+
[0, 0, 1]])
|
| 304 |
+
|
| 305 |
+
assert q2.to_axis_angle() == ((0, 0, sin(theta/2)/Abs(sin(theta/2))),
|
| 306 |
+
2*acos(cos(theta/2)))
|
| 307 |
+
|
| 308 |
+
assert trigsimp(q2.to_rotation_matrix((1, 1, 1))) == Matrix([
|
| 309 |
+
[cos(theta), -sin(theta), 0, sin(theta) - cos(theta) + 1],
|
| 310 |
+
[sin(theta), cos(theta), 0, -sin(theta) - cos(theta) + 1],
|
| 311 |
+
[0, 0, 1, 0],
|
| 312 |
+
[0, 0, 0, 1]])
|
| 313 |
+
|
| 314 |
+
|
| 315 |
+
def test_rotation_matrix_homogeneous():
|
| 316 |
+
q = Quaternion(w, x, y, z)
|
| 317 |
+
R1 = q.to_rotation_matrix(homogeneous=True) * q.norm()**2
|
| 318 |
+
R2 = simplify(q.to_rotation_matrix(homogeneous=False) * q.norm()**2)
|
| 319 |
+
assert R1 == R2
|
| 320 |
+
|
| 321 |
+
|
| 322 |
+
def test_quaternion_rotation_iss1593():
|
| 323 |
+
"""
|
| 324 |
+
There was a sign mistake in the definition,
|
| 325 |
+
of the rotation matrix. This tests that particular sign mistake.
|
| 326 |
+
See issue 1593 for reference.
|
| 327 |
+
See wikipedia
|
| 328 |
+
https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation#Quaternion-derived_rotation_matrix
|
| 329 |
+
for the correct definition
|
| 330 |
+
"""
|
| 331 |
+
q = Quaternion(cos(phi/2), sin(phi/2), 0, 0)
|
| 332 |
+
assert(trigsimp(q.to_rotation_matrix()) == Matrix([
|
| 333 |
+
[1, 0, 0],
|
| 334 |
+
[0, cos(phi), -sin(phi)],
|
| 335 |
+
[0, sin(phi), cos(phi)]]))
|
| 336 |
+
|
| 337 |
+
|
| 338 |
+
def test_quaternion_multiplication():
|
| 339 |
+
q1 = Quaternion(3 + 4*I, 2 + 5*I, 0, 7 + 8*I, real_field = False)
|
| 340 |
+
q2 = Quaternion(1, 2, 3, 5)
|
| 341 |
+
q3 = Quaternion(1, 1, 1, y)
|
| 342 |
+
|
| 343 |
+
assert Quaternion._generic_mul(S(4), S.One) == 4
|
| 344 |
+
assert (Quaternion._generic_mul(S(4), q1) ==
|
| 345 |
+
Quaternion(12 + 16*I, 8 + 20*I, 0, 28 + 32*I))
|
| 346 |
+
assert q2.mul(2) == Quaternion(2, 4, 6, 10)
|
| 347 |
+
assert q2.mul(q3) == Quaternion(-5*y - 4, 3*y - 2, 9 - 2*y, y + 4)
|
| 348 |
+
assert q2.mul(q3) == q2*q3
|
| 349 |
+
|
| 350 |
+
z = symbols('z', complex=True)
|
| 351 |
+
z_quat = Quaternion(re(z), im(z), 0, 0)
|
| 352 |
+
q = Quaternion(*symbols('q:4', real=True))
|
| 353 |
+
|
| 354 |
+
assert z * q == z_quat * q
|
| 355 |
+
assert q * z == q * z_quat
|
| 356 |
+
|
| 357 |
+
|
| 358 |
+
def test_issue_16318():
|
| 359 |
+
#for rtruediv
|
| 360 |
+
q0 = Quaternion(0, 0, 0, 0)
|
| 361 |
+
raises(ValueError, lambda: 1/q0)
|
| 362 |
+
#for rotate_point
|
| 363 |
+
q = Quaternion(1, 2, 3, 4)
|
| 364 |
+
(axis, angle) = q.to_axis_angle()
|
| 365 |
+
assert Quaternion.rotate_point((1, 1, 1), (axis, angle)) == (S.One / 5, 1, S(7) / 5)
|
| 366 |
+
#test for to_axis_angle
|
| 367 |
+
q = Quaternion(-1, 1, 1, 1)
|
| 368 |
+
axis = (-sqrt(3)/3, -sqrt(3)/3, -sqrt(3)/3)
|
| 369 |
+
angle = 2*pi/3
|
| 370 |
+
assert (axis, angle) == q.to_axis_angle()
|
| 371 |
+
|
| 372 |
+
|
| 373 |
+
@slow
|
| 374 |
+
def test_to_euler():
|
| 375 |
+
q = Quaternion(w, x, y, z)
|
| 376 |
+
q_normalized = q.normalize()
|
| 377 |
+
|
| 378 |
+
seqs = ['zxy', 'zyx', 'zyz', 'zxz']
|
| 379 |
+
seqs += [seq.upper() for seq in seqs]
|
| 380 |
+
|
| 381 |
+
for seq in seqs:
|
| 382 |
+
euler_from_q = q.to_euler(seq)
|
| 383 |
+
q_back = simplify(Quaternion.from_euler(euler_from_q, seq))
|
| 384 |
+
assert q_back == q_normalized
|
| 385 |
+
|
| 386 |
+
|
| 387 |
+
def test_to_euler_iss24504():
|
| 388 |
+
"""
|
| 389 |
+
There was a mistake in the degenerate case testing
|
| 390 |
+
See issue 24504 for reference.
|
| 391 |
+
"""
|
| 392 |
+
q = Quaternion.from_euler((phi, 0, 0), 'zyz')
|
| 393 |
+
assert trigsimp(q.to_euler('zyz'), inverse=True) == (phi, 0, 0)
|
| 394 |
+
|
| 395 |
+
|
| 396 |
+
def test_to_euler_numerical_singilarities():
|
| 397 |
+
|
| 398 |
+
def test_one_case(angles, seq):
|
| 399 |
+
q = Quaternion.from_euler(angles, seq)
|
| 400 |
+
assert q.to_euler(seq) == angles
|
| 401 |
+
|
| 402 |
+
# symmetric
|
| 403 |
+
test_one_case((pi/2, 0, 0), 'zyz')
|
| 404 |
+
test_one_case((pi/2, 0, 0), 'ZYZ')
|
| 405 |
+
test_one_case((pi/2, pi, 0), 'zyz')
|
| 406 |
+
test_one_case((pi/2, pi, 0), 'ZYZ')
|
| 407 |
+
|
| 408 |
+
# asymmetric
|
| 409 |
+
test_one_case((pi/2, pi/2, 0), 'zyx')
|
| 410 |
+
test_one_case((pi/2, -pi/2, 0), 'zyx')
|
| 411 |
+
test_one_case((pi/2, pi/2, 0), 'ZYX')
|
| 412 |
+
test_one_case((pi/2, -pi/2, 0), 'ZYX')
|
| 413 |
+
|
| 414 |
+
|
| 415 |
+
@slow
|
| 416 |
+
def test_to_euler_options():
|
| 417 |
+
def test_one_case(q):
|
| 418 |
+
angles1 = Matrix(q.to_euler(seq, True, True))
|
| 419 |
+
angles2 = Matrix(q.to_euler(seq, False, False))
|
| 420 |
+
angle_errors = simplify(angles1-angles2).evalf()
|
| 421 |
+
for angle_error in angle_errors:
|
| 422 |
+
# forcing angles to set {-pi, pi}
|
| 423 |
+
angle_error = (angle_error + pi) % (2 * pi) - pi
|
| 424 |
+
assert angle_error < 10e-7
|
| 425 |
+
|
| 426 |
+
for xyz in ('xyz', 'XYZ'):
|
| 427 |
+
for seq_tuple in permutations(xyz):
|
| 428 |
+
for symmetric in (True, False):
|
| 429 |
+
if symmetric:
|
| 430 |
+
seq = ''.join([seq_tuple[0], seq_tuple[1], seq_tuple[0]])
|
| 431 |
+
else:
|
| 432 |
+
seq = ''.join(seq_tuple)
|
| 433 |
+
|
| 434 |
+
for elements in product([-1, 0, 1], repeat=4):
|
| 435 |
+
q = Quaternion(*elements)
|
| 436 |
+
if not q.is_zero_quaternion():
|
| 437 |
+
test_one_case(q)
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/calculus/tests/__init__.py
ADDED
|
File without changes
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/calculus/tests/test_accumulationbounds.py
ADDED
|
@@ -0,0 +1,336 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.core.numbers import (E, Rational, oo, pi, zoo)
|
| 2 |
+
from sympy.core.singleton import S
|
| 3 |
+
from sympy.core.symbol import Symbol
|
| 4 |
+
from sympy.functions.elementary.exponential import (exp, log)
|
| 5 |
+
from sympy.functions.elementary.miscellaneous import (Max, Min, sqrt)
|
| 6 |
+
from sympy.functions.elementary.trigonometric import (cos, sin, tan)
|
| 7 |
+
from sympy.calculus.accumulationbounds import AccumBounds
|
| 8 |
+
from sympy.core import Add, Mul, Pow
|
| 9 |
+
from sympy.core.expr import unchanged
|
| 10 |
+
from sympy.testing.pytest import raises, XFAIL
|
| 11 |
+
from sympy.abc import x
|
| 12 |
+
|
| 13 |
+
a = Symbol('a', real=True)
|
| 14 |
+
B = AccumBounds
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def test_AccumBounds():
|
| 18 |
+
assert B(1, 2).args == (1, 2)
|
| 19 |
+
assert B(1, 2).delta is S.One
|
| 20 |
+
assert B(1, 2).mid == Rational(3, 2)
|
| 21 |
+
assert B(1, 3).is_real == True
|
| 22 |
+
|
| 23 |
+
assert B(1, 1) is S.One
|
| 24 |
+
|
| 25 |
+
assert B(1, 2) + 1 == B(2, 3)
|
| 26 |
+
assert 1 + B(1, 2) == B(2, 3)
|
| 27 |
+
assert B(1, 2) + B(2, 3) == B(3, 5)
|
| 28 |
+
|
| 29 |
+
assert -B(1, 2) == B(-2, -1)
|
| 30 |
+
|
| 31 |
+
assert B(1, 2) - 1 == B(0, 1)
|
| 32 |
+
assert 1 - B(1, 2) == B(-1, 0)
|
| 33 |
+
assert B(2, 3) - B(1, 2) == B(0, 2)
|
| 34 |
+
|
| 35 |
+
assert x + B(1, 2) == Add(B(1, 2), x)
|
| 36 |
+
assert a + B(1, 2) == B(1 + a, 2 + a)
|
| 37 |
+
assert B(1, 2) - x == Add(B(1, 2), -x)
|
| 38 |
+
|
| 39 |
+
assert B(-oo, 1) + oo == B(-oo, oo)
|
| 40 |
+
assert B(1, oo) + oo is oo
|
| 41 |
+
assert B(1, oo) - oo == B(-oo, oo)
|
| 42 |
+
assert (-oo - B(-1, oo)) is -oo
|
| 43 |
+
assert B(-oo, 1) - oo is -oo
|
| 44 |
+
|
| 45 |
+
assert B(1, oo) - oo == B(-oo, oo)
|
| 46 |
+
assert B(-oo, 1) - (-oo) == B(-oo, oo)
|
| 47 |
+
assert (oo - B(1, oo)) == B(-oo, oo)
|
| 48 |
+
assert (-oo - B(1, oo)) is -oo
|
| 49 |
+
|
| 50 |
+
assert B(1, 2)/2 == B(S.Half, 1)
|
| 51 |
+
assert 2/B(2, 3) == B(Rational(2, 3), 1)
|
| 52 |
+
assert 1/B(-1, 1) == B(-oo, oo)
|
| 53 |
+
|
| 54 |
+
assert abs(B(1, 2)) == B(1, 2)
|
| 55 |
+
assert abs(B(-2, -1)) == B(1, 2)
|
| 56 |
+
assert abs(B(-2, 1)) == B(0, 2)
|
| 57 |
+
assert abs(B(-1, 2)) == B(0, 2)
|
| 58 |
+
c = Symbol('c')
|
| 59 |
+
raises(ValueError, lambda: B(0, c))
|
| 60 |
+
raises(ValueError, lambda: B(1, -1))
|
| 61 |
+
r = Symbol('r', real=True)
|
| 62 |
+
raises(ValueError, lambda: B(r, r - 1))
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
def test_AccumBounds_mul():
|
| 66 |
+
assert B(1, 2)*2 == B(2, 4)
|
| 67 |
+
assert 2*B(1, 2) == B(2, 4)
|
| 68 |
+
assert B(1, 2)*B(2, 3) == B(2, 6)
|
| 69 |
+
assert B(0, 2)*B(2, oo) == B(0, oo)
|
| 70 |
+
l, r = B(-oo, oo), B(-a, a)
|
| 71 |
+
assert l*r == B(-oo, oo)
|
| 72 |
+
assert r*l == B(-oo, oo)
|
| 73 |
+
l, r = B(1, oo), B(-3, -2)
|
| 74 |
+
assert l*r == B(-oo, -2)
|
| 75 |
+
assert r*l == B(-oo, -2)
|
| 76 |
+
assert B(1, 2)*0 == 0
|
| 77 |
+
assert B(1, oo)*0 == B(0, oo)
|
| 78 |
+
assert B(-oo, 1)*0 == B(-oo, 0)
|
| 79 |
+
assert B(-oo, oo)*0 == B(-oo, oo)
|
| 80 |
+
|
| 81 |
+
assert B(1, 2)*x == Mul(B(1, 2), x, evaluate=False)
|
| 82 |
+
|
| 83 |
+
assert B(0, 2)*oo == B(0, oo)
|
| 84 |
+
assert B(-2, 0)*oo == B(-oo, 0)
|
| 85 |
+
assert B(0, 2)*(-oo) == B(-oo, 0)
|
| 86 |
+
assert B(-2, 0)*(-oo) == B(0, oo)
|
| 87 |
+
assert B(-1, 1)*oo == B(-oo, oo)
|
| 88 |
+
assert B(-1, 1)*(-oo) == B(-oo, oo)
|
| 89 |
+
assert B(-oo, oo)*oo == B(-oo, oo)
|
| 90 |
+
|
| 91 |
+
|
| 92 |
+
def test_AccumBounds_div():
|
| 93 |
+
assert B(-1, 3)/B(3, 4) == B(Rational(-1, 3), 1)
|
| 94 |
+
assert B(-2, 4)/B(-3, 4) == B(-oo, oo)
|
| 95 |
+
assert B(-3, -2)/B(-4, 0) == B(S.Half, oo)
|
| 96 |
+
|
| 97 |
+
# these two tests can have a better answer
|
| 98 |
+
# after Union of B is improved
|
| 99 |
+
assert B(-3, -2)/B(-2, 1) == B(-oo, oo)
|
| 100 |
+
assert B(2, 3)/B(-2, 2) == B(-oo, oo)
|
| 101 |
+
|
| 102 |
+
assert B(-3, -2)/B(0, 4) == B(-oo, Rational(-1, 2))
|
| 103 |
+
assert B(2, 4)/B(-3, 0) == B(-oo, Rational(-2, 3))
|
| 104 |
+
assert B(2, 4)/B(0, 3) == B(Rational(2, 3), oo)
|
| 105 |
+
|
| 106 |
+
assert B(0, 1)/B(0, 1) == B(0, oo)
|
| 107 |
+
assert B(-1, 0)/B(0, 1) == B(-oo, 0)
|
| 108 |
+
assert B(-1, 2)/B(-2, 2) == B(-oo, oo)
|
| 109 |
+
|
| 110 |
+
assert 1/B(-1, 2) == B(-oo, oo)
|
| 111 |
+
assert 1/B(0, 2) == B(S.Half, oo)
|
| 112 |
+
assert (-1)/B(0, 2) == B(-oo, Rational(-1, 2))
|
| 113 |
+
assert 1/B(-oo, 0) == B(-oo, 0)
|
| 114 |
+
assert 1/B(-1, 0) == B(-oo, -1)
|
| 115 |
+
assert (-2)/B(-oo, 0) == B(0, oo)
|
| 116 |
+
assert 1/B(-oo, -1) == B(-1, 0)
|
| 117 |
+
|
| 118 |
+
assert B(1, 2)/a == Mul(B(1, 2), 1/a, evaluate=False)
|
| 119 |
+
|
| 120 |
+
assert B(1, 2)/0 == B(1, 2)*zoo
|
| 121 |
+
assert B(1, oo)/oo == B(0, oo)
|
| 122 |
+
assert B(1, oo)/(-oo) == B(-oo, 0)
|
| 123 |
+
assert B(-oo, -1)/oo == B(-oo, 0)
|
| 124 |
+
assert B(-oo, -1)/(-oo) == B(0, oo)
|
| 125 |
+
assert B(-oo, oo)/oo == B(-oo, oo)
|
| 126 |
+
assert B(-oo, oo)/(-oo) == B(-oo, oo)
|
| 127 |
+
assert B(-1, oo)/oo == B(0, oo)
|
| 128 |
+
assert B(-1, oo)/(-oo) == B(-oo, 0)
|
| 129 |
+
assert B(-oo, 1)/oo == B(-oo, 0)
|
| 130 |
+
assert B(-oo, 1)/(-oo) == B(0, oo)
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
def test_issue_18795():
|
| 134 |
+
r = Symbol('r', real=True)
|
| 135 |
+
a = B(-1,1)
|
| 136 |
+
c = B(7, oo)
|
| 137 |
+
b = B(-oo, oo)
|
| 138 |
+
assert c - tan(r) == B(7-tan(r), oo)
|
| 139 |
+
assert b + tan(r) == B(-oo, oo)
|
| 140 |
+
assert (a + r)/a == B(-oo, oo)*B(r - 1, r + 1)
|
| 141 |
+
assert (b + a)/a == B(-oo, oo)
|
| 142 |
+
|
| 143 |
+
|
| 144 |
+
def test_AccumBounds_func():
|
| 145 |
+
assert (x**2 + 2*x + 1).subs(x, B(-1, 1)) == B(-1, 4)
|
| 146 |
+
assert exp(B(0, 1)) == B(1, E)
|
| 147 |
+
assert exp(B(-oo, oo)) == B(0, oo)
|
| 148 |
+
assert log(B(3, 6)) == B(log(3), log(6))
|
| 149 |
+
|
| 150 |
+
|
| 151 |
+
@XFAIL
|
| 152 |
+
def test_AccumBounds_powf():
|
| 153 |
+
nn = Symbol('nn', nonnegative=True)
|
| 154 |
+
assert B(1 + nn, 2 + nn)**B(1, 2) == B(1 + nn, (2 + nn)**2)
|
| 155 |
+
i = Symbol('i', integer=True, negative=True)
|
| 156 |
+
assert B(1, 2)**i == B(2**i, 1)
|
| 157 |
+
|
| 158 |
+
|
| 159 |
+
def test_AccumBounds_pow():
|
| 160 |
+
assert B(0, 2)**2 == B(0, 4)
|
| 161 |
+
assert B(-1, 1)**2 == B(0, 1)
|
| 162 |
+
assert B(1, 2)**2 == B(1, 4)
|
| 163 |
+
assert B(-1, 2)**3 == B(-1, 8)
|
| 164 |
+
assert B(-1, 1)**0 == 1
|
| 165 |
+
|
| 166 |
+
assert B(1, 2)**Rational(5, 2) == B(1, 4*sqrt(2))
|
| 167 |
+
assert B(0, 2)**S.Half == B(0, sqrt(2))
|
| 168 |
+
|
| 169 |
+
neg = Symbol('neg', negative=True)
|
| 170 |
+
assert unchanged(Pow, B(neg, 1), S.Half)
|
| 171 |
+
nn = Symbol('nn', nonnegative=True)
|
| 172 |
+
assert B(nn, nn + 1)**S.Half == B(sqrt(nn), sqrt(nn + 1))
|
| 173 |
+
assert B(nn, nn + 1)**nn == B(nn**nn, (nn + 1)**nn)
|
| 174 |
+
assert unchanged(Pow, B(nn, nn + 1), x)
|
| 175 |
+
i = Symbol('i', integer=True)
|
| 176 |
+
assert B(1, 2)**i == B(Min(1, 2**i), Max(1, 2**i))
|
| 177 |
+
i = Symbol('i', integer=True, nonnegative=True)
|
| 178 |
+
assert B(1, 2)**i == B(1, 2**i)
|
| 179 |
+
assert B(0, 1)**i == B(0**i, 1)
|
| 180 |
+
|
| 181 |
+
assert B(1, 5)**(-2) == B(Rational(1, 25), 1)
|
| 182 |
+
assert B(-1, 3)**(-2) == B(0, oo)
|
| 183 |
+
assert B(0, 2)**(-3) == B(Rational(1, 8), oo)
|
| 184 |
+
assert B(-2, 0)**(-3) == B(-oo, -Rational(1, 8))
|
| 185 |
+
assert B(0, 2)**(-2) == B(Rational(1, 4), oo)
|
| 186 |
+
assert B(-1, 2)**(-3) == B(-oo, oo)
|
| 187 |
+
assert B(-3, -2)**(-3) == B(Rational(-1, 8), Rational(-1, 27))
|
| 188 |
+
assert B(-3, -2)**(-2) == B(Rational(1, 9), Rational(1, 4))
|
| 189 |
+
assert B(0, oo)**S.Half == B(0, oo)
|
| 190 |
+
assert B(-oo, 0)**(-2) == B(0, oo)
|
| 191 |
+
assert B(-2, 0)**(-2) == B(Rational(1, 4), oo)
|
| 192 |
+
|
| 193 |
+
assert B(Rational(1, 3), S.Half)**oo is S.Zero
|
| 194 |
+
assert B(0, S.Half)**oo is S.Zero
|
| 195 |
+
assert B(S.Half, 1)**oo == B(0, oo)
|
| 196 |
+
assert B(0, 1)**oo == B(0, oo)
|
| 197 |
+
assert B(2, 3)**oo is oo
|
| 198 |
+
assert B(1, 2)**oo == B(0, oo)
|
| 199 |
+
assert B(S.Half, 3)**oo == B(0, oo)
|
| 200 |
+
assert B(Rational(-1, 3), Rational(-1, 4))**oo is S.Zero
|
| 201 |
+
assert B(-1, Rational(-1, 2))**oo is S.NaN
|
| 202 |
+
assert B(-3, -2)**oo is zoo
|
| 203 |
+
assert B(-2, -1)**oo is S.NaN
|
| 204 |
+
assert B(-2, Rational(-1, 2))**oo is S.NaN
|
| 205 |
+
assert B(Rational(-1, 2), S.Half)**oo is S.Zero
|
| 206 |
+
assert B(Rational(-1, 2), 1)**oo == B(0, oo)
|
| 207 |
+
assert B(Rational(-2, 3), 2)**oo == B(0, oo)
|
| 208 |
+
assert B(-1, 1)**oo == B(-oo, oo)
|
| 209 |
+
assert B(-1, S.Half)**oo == B(-oo, oo)
|
| 210 |
+
assert B(-1, 2)**oo == B(-oo, oo)
|
| 211 |
+
assert B(-2, S.Half)**oo == B(-oo, oo)
|
| 212 |
+
|
| 213 |
+
assert B(1, 2)**x == Pow(B(1, 2), x, evaluate=False)
|
| 214 |
+
|
| 215 |
+
assert B(2, 3)**(-oo) is S.Zero
|
| 216 |
+
assert B(0, 2)**(-oo) == B(0, oo)
|
| 217 |
+
assert B(-1, 2)**(-oo) == B(-oo, oo)
|
| 218 |
+
|
| 219 |
+
assert (tan(x)**sin(2*x)).subs(x, B(0, pi/2)) == \
|
| 220 |
+
Pow(B(-oo, oo), B(0, 1))
|
| 221 |
+
|
| 222 |
+
|
| 223 |
+
def test_AccumBounds_exponent():
|
| 224 |
+
# base is 0
|
| 225 |
+
z = 0**B(a, a + S.Half)
|
| 226 |
+
assert z.subs(a, 0) == B(0, 1)
|
| 227 |
+
assert z.subs(a, 1) == 0
|
| 228 |
+
p = z.subs(a, -1)
|
| 229 |
+
assert p.is_Pow and p.args == (0, B(-1, -S.Half))
|
| 230 |
+
# base > 0
|
| 231 |
+
# when base is 1 the type of bounds does not matter
|
| 232 |
+
assert 1**B(a, a + 1) == 1
|
| 233 |
+
# otherwise we need to know if 0 is in the bounds
|
| 234 |
+
assert S.Half**B(-2, 2) == B(S(1)/4, 4)
|
| 235 |
+
assert 2**B(-2, 2) == B(S(1)/4, 4)
|
| 236 |
+
|
| 237 |
+
# +eps may introduce +oo
|
| 238 |
+
# if there is a negative integer exponent
|
| 239 |
+
assert B(0, 1)**B(S(1)/2, 1) == B(0, 1)
|
| 240 |
+
assert B(0, 1)**B(0, 1) == B(0, 1)
|
| 241 |
+
|
| 242 |
+
# positive bases have positive bounds
|
| 243 |
+
assert B(2, 3)**B(-3, -2) == B(S(1)/27, S(1)/4)
|
| 244 |
+
assert B(2, 3)**B(-3, 2) == B(S(1)/27, 9)
|
| 245 |
+
|
| 246 |
+
# bounds generating imaginary parts unevaluated
|
| 247 |
+
assert unchanged(Pow, B(-1, 1), B(1, 2))
|
| 248 |
+
assert B(0, S(1)/2)**B(1, oo) == B(0, S(1)/2)
|
| 249 |
+
assert B(0, 1)**B(1, oo) == B(0, oo)
|
| 250 |
+
assert B(0, 2)**B(1, oo) == B(0, oo)
|
| 251 |
+
assert B(0, oo)**B(1, oo) == B(0, oo)
|
| 252 |
+
assert B(S(1)/2, 1)**B(1, oo) == B(0, oo)
|
| 253 |
+
assert B(S(1)/2, 1)**B(-oo, -1) == B(0, oo)
|
| 254 |
+
assert B(S(1)/2, 1)**B(-oo, oo) == B(0, oo)
|
| 255 |
+
assert B(S(1)/2, 2)**B(1, oo) == B(0, oo)
|
| 256 |
+
assert B(S(1)/2, 2)**B(-oo, -1) == B(0, oo)
|
| 257 |
+
assert B(S(1)/2, 2)**B(-oo, oo) == B(0, oo)
|
| 258 |
+
assert B(S(1)/2, oo)**B(1, oo) == B(0, oo)
|
| 259 |
+
assert B(S(1)/2, oo)**B(-oo, -1) == B(0, oo)
|
| 260 |
+
assert B(S(1)/2, oo)**B(-oo, oo) == B(0, oo)
|
| 261 |
+
assert B(1, 2)**B(1, oo) == B(0, oo)
|
| 262 |
+
assert B(1, 2)**B(-oo, -1) == B(0, oo)
|
| 263 |
+
assert B(1, 2)**B(-oo, oo) == B(0, oo)
|
| 264 |
+
assert B(1, oo)**B(1, oo) == B(0, oo)
|
| 265 |
+
assert B(1, oo)**B(-oo, -1) == B(0, oo)
|
| 266 |
+
assert B(1, oo)**B(-oo, oo) == B(0, oo)
|
| 267 |
+
assert B(2, oo)**B(1, oo) == B(2, oo)
|
| 268 |
+
assert B(2, oo)**B(-oo, -1) == B(0, S(1)/2)
|
| 269 |
+
assert B(2, oo)**B(-oo, oo) == B(0, oo)
|
| 270 |
+
|
| 271 |
+
|
| 272 |
+
def test_comparison_AccumBounds():
|
| 273 |
+
assert (B(1, 3) < 4) == S.true
|
| 274 |
+
assert (B(1, 3) < -1) == S.false
|
| 275 |
+
assert (B(1, 3) < 2).rel_op == '<'
|
| 276 |
+
assert (B(1, 3) <= 2).rel_op == '<='
|
| 277 |
+
|
| 278 |
+
assert (B(1, 3) > 4) == S.false
|
| 279 |
+
assert (B(1, 3) > -1) == S.true
|
| 280 |
+
assert (B(1, 3) > 2).rel_op == '>'
|
| 281 |
+
assert (B(1, 3) >= 2).rel_op == '>='
|
| 282 |
+
|
| 283 |
+
assert (B(1, 3) < B(4, 6)) == S.true
|
| 284 |
+
assert (B(1, 3) < B(2, 4)).rel_op == '<'
|
| 285 |
+
assert (B(1, 3) < B(-2, 0)) == S.false
|
| 286 |
+
|
| 287 |
+
assert (B(1, 3) <= B(4, 6)) == S.true
|
| 288 |
+
assert (B(1, 3) <= B(-2, 0)) == S.false
|
| 289 |
+
|
| 290 |
+
assert (B(1, 3) > B(4, 6)) == S.false
|
| 291 |
+
assert (B(1, 3) > B(-2, 0)) == S.true
|
| 292 |
+
|
| 293 |
+
assert (B(1, 3) >= B(4, 6)) == S.false
|
| 294 |
+
assert (B(1, 3) >= B(-2, 0)) == S.true
|
| 295 |
+
|
| 296 |
+
# issue 13499
|
| 297 |
+
assert (cos(x) > 0).subs(x, oo) == (B(-1, 1) > 0)
|
| 298 |
+
|
| 299 |
+
c = Symbol('c')
|
| 300 |
+
raises(TypeError, lambda: (B(0, 1) < c))
|
| 301 |
+
raises(TypeError, lambda: (B(0, 1) <= c))
|
| 302 |
+
raises(TypeError, lambda: (B(0, 1) > c))
|
| 303 |
+
raises(TypeError, lambda: (B(0, 1) >= c))
|
| 304 |
+
|
| 305 |
+
|
| 306 |
+
def test_contains_AccumBounds():
|
| 307 |
+
assert (1 in B(1, 2)) == S.true
|
| 308 |
+
raises(TypeError, lambda: a in B(1, 2))
|
| 309 |
+
assert 0 in B(-1, 0)
|
| 310 |
+
raises(TypeError, lambda:
|
| 311 |
+
(cos(1)**2 + sin(1)**2 - 1) in B(-1, 0))
|
| 312 |
+
assert (-oo in B(1, oo)) == S.true
|
| 313 |
+
assert (oo in B(-oo, 0)) == S.true
|
| 314 |
+
|
| 315 |
+
# issue 13159
|
| 316 |
+
assert Mul(0, B(-1, 1)) == Mul(B(-1, 1), 0) == 0
|
| 317 |
+
import itertools
|
| 318 |
+
for perm in itertools.permutations([0, B(-1, 1), x]):
|
| 319 |
+
assert Mul(*perm) == 0
|
| 320 |
+
|
| 321 |
+
|
| 322 |
+
def test_intersection_AccumBounds():
|
| 323 |
+
assert B(0, 3).intersection(B(1, 2)) == B(1, 2)
|
| 324 |
+
assert B(0, 3).intersection(B(1, 4)) == B(1, 3)
|
| 325 |
+
assert B(0, 3).intersection(B(-1, 2)) == B(0, 2)
|
| 326 |
+
assert B(0, 3).intersection(B(-1, 4)) == B(0, 3)
|
| 327 |
+
assert B(0, 1).intersection(B(2, 3)) == S.EmptySet
|
| 328 |
+
raises(TypeError, lambda: B(0, 3).intersection(1))
|
| 329 |
+
|
| 330 |
+
|
| 331 |
+
def test_union_AccumBounds():
|
| 332 |
+
assert B(0, 3).union(B(1, 2)) == B(0, 3)
|
| 333 |
+
assert B(0, 3).union(B(1, 4)) == B(0, 4)
|
| 334 |
+
assert B(0, 3).union(B(-1, 2)) == B(-1, 3)
|
| 335 |
+
assert B(0, 3).union(B(-1, 4)) == B(-1, 4)
|
| 336 |
+
raises(TypeError, lambda: B(0, 3).union(1))
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/calculus/tests/test_euler.py
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.core.function import (Derivative as D, Function)
|
| 2 |
+
from sympy.core.relational import Eq
|
| 3 |
+
from sympy.core.symbol import (Symbol, symbols)
|
| 4 |
+
from sympy.functions.elementary.trigonometric import (cos, sin)
|
| 5 |
+
from sympy.testing.pytest import raises
|
| 6 |
+
from sympy.calculus.euler import euler_equations as euler
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
def test_euler_interface():
|
| 10 |
+
x = Function('x')
|
| 11 |
+
y = Symbol('y')
|
| 12 |
+
t = Symbol('t')
|
| 13 |
+
raises(TypeError, lambda: euler())
|
| 14 |
+
raises(TypeError, lambda: euler(D(x(t), t)*y(t), [x(t), y]))
|
| 15 |
+
raises(ValueError, lambda: euler(D(x(t), t)*x(y), [x(t), x(y)]))
|
| 16 |
+
raises(TypeError, lambda: euler(D(x(t), t)**2, x(0)))
|
| 17 |
+
raises(TypeError, lambda: euler(D(x(t), t)*y(t), [t]))
|
| 18 |
+
assert euler(D(x(t), t)**2/2, {x(t)}) == [Eq(-D(x(t), t, t), 0)]
|
| 19 |
+
assert euler(D(x(t), t)**2/2, x(t), {t}) == [Eq(-D(x(t), t, t), 0)]
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
def test_euler_pendulum():
|
| 23 |
+
x = Function('x')
|
| 24 |
+
t = Symbol('t')
|
| 25 |
+
L = D(x(t), t)**2/2 + cos(x(t))
|
| 26 |
+
assert euler(L, x(t), t) == [Eq(-sin(x(t)) - D(x(t), t, t), 0)]
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def test_euler_henonheiles():
|
| 30 |
+
x = Function('x')
|
| 31 |
+
y = Function('y')
|
| 32 |
+
t = Symbol('t')
|
| 33 |
+
L = sum(D(z(t), t)**2/2 - z(t)**2/2 for z in [x, y])
|
| 34 |
+
L += -x(t)**2*y(t) + y(t)**3/3
|
| 35 |
+
assert euler(L, [x(t), y(t)], t) == [Eq(-2*x(t)*y(t) - x(t) -
|
| 36 |
+
D(x(t), t, t), 0),
|
| 37 |
+
Eq(-x(t)**2 + y(t)**2 -
|
| 38 |
+
y(t) - D(y(t), t, t), 0)]
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
def test_euler_sineg():
|
| 42 |
+
psi = Function('psi')
|
| 43 |
+
t = Symbol('t')
|
| 44 |
+
x = Symbol('x')
|
| 45 |
+
L = D(psi(t, x), t)**2/2 - D(psi(t, x), x)**2/2 + cos(psi(t, x))
|
| 46 |
+
assert euler(L, psi(t, x), [t, x]) == [Eq(-sin(psi(t, x)) -
|
| 47 |
+
D(psi(t, x), t, t) +
|
| 48 |
+
D(psi(t, x), x, x), 0)]
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
def test_euler_high_order():
|
| 52 |
+
# an example from hep-th/0309038
|
| 53 |
+
m = Symbol('m')
|
| 54 |
+
k = Symbol('k')
|
| 55 |
+
x = Function('x')
|
| 56 |
+
y = Function('y')
|
| 57 |
+
t = Symbol('t')
|
| 58 |
+
L = (m*D(x(t), t)**2/2 + m*D(y(t), t)**2/2 -
|
| 59 |
+
k*D(x(t), t)*D(y(t), t, t) + k*D(y(t), t)*D(x(t), t, t))
|
| 60 |
+
assert euler(L, [x(t), y(t)]) == [Eq(2*k*D(y(t), t, t, t) -
|
| 61 |
+
m*D(x(t), t, t), 0),
|
| 62 |
+
Eq(-2*k*D(x(t), t, t, t) -
|
| 63 |
+
m*D(y(t), t, t), 0)]
|
| 64 |
+
|
| 65 |
+
w = Symbol('w')
|
| 66 |
+
L = D(x(t, w), t, w)**2/2
|
| 67 |
+
assert euler(L) == [Eq(D(x(t, w), t, t, w, w), 0)]
|
| 68 |
+
|
| 69 |
+
def test_issue_18653():
|
| 70 |
+
x, y, z = symbols("x y z")
|
| 71 |
+
f, g, h = symbols("f g h", cls=Function, args=(x, y))
|
| 72 |
+
f, g, h = f(), g(), h()
|
| 73 |
+
expr2 = f.diff(x)*h.diff(z)
|
| 74 |
+
assert euler(expr2, (f,), (x, y)) == []
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/calculus/tests/test_singularities.py
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.core.numbers import (I, Rational, pi, oo)
|
| 2 |
+
from sympy.core.singleton import S
|
| 3 |
+
from sympy.core.symbol import Symbol, Dummy
|
| 4 |
+
from sympy.core.function import Lambda
|
| 5 |
+
from sympy.functions.elementary.exponential import (exp, log)
|
| 6 |
+
from sympy.functions.elementary.trigonometric import sec, csc
|
| 7 |
+
from sympy.functions.elementary.hyperbolic import (coth, sech,
|
| 8 |
+
atanh, asech, acoth, acsch)
|
| 9 |
+
from sympy.functions.elementary.miscellaneous import sqrt
|
| 10 |
+
from sympy.calculus.singularities import (
|
| 11 |
+
singularities,
|
| 12 |
+
is_increasing,
|
| 13 |
+
is_strictly_increasing,
|
| 14 |
+
is_decreasing,
|
| 15 |
+
is_strictly_decreasing,
|
| 16 |
+
is_monotonic
|
| 17 |
+
)
|
| 18 |
+
from sympy.sets import Interval, FiniteSet, Union, ImageSet
|
| 19 |
+
from sympy.testing.pytest import raises
|
| 20 |
+
from sympy.abc import x, y
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
def test_singularities():
|
| 24 |
+
x = Symbol('x')
|
| 25 |
+
assert singularities(x**2, x) == S.EmptySet
|
| 26 |
+
assert singularities(x/(x**2 + 3*x + 2), x) == FiniteSet(-2, -1)
|
| 27 |
+
assert singularities(1/(x**2 + 1), x) == FiniteSet(I, -I)
|
| 28 |
+
assert singularities(x/(x**3 + 1), x) == \
|
| 29 |
+
FiniteSet(-1, (1 - sqrt(3) * I) / 2, (1 + sqrt(3) * I) / 2)
|
| 30 |
+
assert singularities(1/(y**2 + 2*I*y + 1), y) == \
|
| 31 |
+
FiniteSet(-I + sqrt(2)*I, -I - sqrt(2)*I)
|
| 32 |
+
_n = Dummy('n')
|
| 33 |
+
assert singularities(sech(x), x).dummy_eq(Union(
|
| 34 |
+
ImageSet(Lambda(_n, 2*_n*I*pi + I*pi/2), S.Integers),
|
| 35 |
+
ImageSet(Lambda(_n, 2*_n*I*pi + 3*I*pi/2), S.Integers)))
|
| 36 |
+
assert singularities(coth(x), x).dummy_eq(Union(
|
| 37 |
+
ImageSet(Lambda(_n, 2*_n*I*pi + I*pi), S.Integers),
|
| 38 |
+
ImageSet(Lambda(_n, 2*_n*I*pi), S.Integers)))
|
| 39 |
+
assert singularities(atanh(x), x) == FiniteSet(-1, 1)
|
| 40 |
+
assert singularities(acoth(x), x) == FiniteSet(-1, 1)
|
| 41 |
+
assert singularities(asech(x), x) == FiniteSet(0)
|
| 42 |
+
assert singularities(acsch(x), x) == FiniteSet(0)
|
| 43 |
+
|
| 44 |
+
x = Symbol('x', real=True)
|
| 45 |
+
assert singularities(1/(x**2 + 1), x) == S.EmptySet
|
| 46 |
+
assert singularities(exp(1/x), x, S.Reals) == FiniteSet(0)
|
| 47 |
+
assert singularities(exp(1/x), x, Interval(1, 2)) == S.EmptySet
|
| 48 |
+
assert singularities(log((x - 2)**2), x, Interval(1, 3)) == FiniteSet(2)
|
| 49 |
+
raises(NotImplementedError, lambda: singularities(x**-oo, x))
|
| 50 |
+
assert singularities(sec(x), x, Interval(0, 3*pi)) == FiniteSet(
|
| 51 |
+
pi/2, 3*pi/2, 5*pi/2)
|
| 52 |
+
assert singularities(csc(x), x, Interval(0, 3*pi)) == FiniteSet(
|
| 53 |
+
0, pi, 2*pi, 3*pi)
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def test_is_increasing():
|
| 57 |
+
"""Test whether is_increasing returns correct value."""
|
| 58 |
+
a = Symbol('a', negative=True)
|
| 59 |
+
|
| 60 |
+
assert is_increasing(x**3 - 3*x**2 + 4*x, S.Reals)
|
| 61 |
+
assert is_increasing(-x**2, Interval(-oo, 0))
|
| 62 |
+
assert not is_increasing(-x**2, Interval(0, oo))
|
| 63 |
+
assert not is_increasing(4*x**3 - 6*x**2 - 72*x + 30, Interval(-2, 3))
|
| 64 |
+
assert is_increasing(x**2 + y, Interval(1, oo), x)
|
| 65 |
+
assert is_increasing(-x**2*a, Interval(1, oo), x)
|
| 66 |
+
assert is_increasing(1)
|
| 67 |
+
|
| 68 |
+
assert is_increasing(4*x**3 - 6*x**2 - 72*x + 30, Interval(-2, 3)) is False
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
def test_is_strictly_increasing():
|
| 72 |
+
"""Test whether is_strictly_increasing returns correct value."""
|
| 73 |
+
assert is_strictly_increasing(
|
| 74 |
+
4*x**3 - 6*x**2 - 72*x + 30, Interval.Ropen(-oo, -2))
|
| 75 |
+
assert is_strictly_increasing(
|
| 76 |
+
4*x**3 - 6*x**2 - 72*x + 30, Interval.Lopen(3, oo))
|
| 77 |
+
assert not is_strictly_increasing(
|
| 78 |
+
4*x**3 - 6*x**2 - 72*x + 30, Interval.open(-2, 3))
|
| 79 |
+
assert not is_strictly_increasing(-x**2, Interval(0, oo))
|
| 80 |
+
assert not is_strictly_decreasing(1)
|
| 81 |
+
|
| 82 |
+
assert is_strictly_increasing(4*x**3 - 6*x**2 - 72*x + 30, Interval.open(-2, 3)) is False
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
def test_is_decreasing():
|
| 86 |
+
"""Test whether is_decreasing returns correct value."""
|
| 87 |
+
b = Symbol('b', positive=True)
|
| 88 |
+
|
| 89 |
+
assert is_decreasing(1/(x**2 - 3*x), Interval.open(Rational(3,2), 3))
|
| 90 |
+
assert is_decreasing(1/(x**2 - 3*x), Interval.open(1.5, 3))
|
| 91 |
+
assert is_decreasing(1/(x**2 - 3*x), Interval.Lopen(3, oo))
|
| 92 |
+
assert not is_decreasing(1/(x**2 - 3*x), Interval.Ropen(-oo, Rational(3, 2)))
|
| 93 |
+
assert not is_decreasing(-x**2, Interval(-oo, 0))
|
| 94 |
+
assert not is_decreasing(-x**2*b, Interval(-oo, 0), x)
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
def test_is_strictly_decreasing():
|
| 98 |
+
"""Test whether is_strictly_decreasing returns correct value."""
|
| 99 |
+
assert is_strictly_decreasing(1/(x**2 - 3*x), Interval.Lopen(3, oo))
|
| 100 |
+
assert not is_strictly_decreasing(
|
| 101 |
+
1/(x**2 - 3*x), Interval.Ropen(-oo, Rational(3, 2)))
|
| 102 |
+
assert not is_strictly_decreasing(-x**2, Interval(-oo, 0))
|
| 103 |
+
assert not is_strictly_decreasing(1)
|
| 104 |
+
assert is_strictly_decreasing(1/(x**2 - 3*x), Interval.open(Rational(3,2), 3))
|
| 105 |
+
assert is_strictly_decreasing(1/(x**2 - 3*x), Interval.open(1.5, 3))
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
def test_is_monotonic():
|
| 109 |
+
"""Test whether is_monotonic returns correct value."""
|
| 110 |
+
assert is_monotonic(1/(x**2 - 3*x), Interval.open(Rational(3,2), 3))
|
| 111 |
+
assert is_monotonic(1/(x**2 - 3*x), Interval.open(1.5, 3))
|
| 112 |
+
assert is_monotonic(1/(x**2 - 3*x), Interval.Lopen(3, oo))
|
| 113 |
+
assert is_monotonic(x**3 - 3*x**2 + 4*x, S.Reals)
|
| 114 |
+
assert not is_monotonic(-x**2, S.Reals)
|
| 115 |
+
assert is_monotonic(x**2 + y + 1, Interval(1, 2), x)
|
| 116 |
+
raises(NotImplementedError, lambda: is_monotonic(x**2 + y + 1))
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
def test_issue_23401():
|
| 120 |
+
x = Symbol('x')
|
| 121 |
+
expr = (x + 1)/(-1.0e-3*x**2 + 0.1*x + 0.1)
|
| 122 |
+
assert is_increasing(expr, Interval(1,2), x)
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/calculus/tests/test_util.py
ADDED
|
@@ -0,0 +1,392 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.core.function import Lambda
|
| 2 |
+
from sympy.core.numbers import (E, I, Rational, oo, pi)
|
| 3 |
+
from sympy.core.relational import Eq
|
| 4 |
+
from sympy.core.singleton import S
|
| 5 |
+
from sympy.core.symbol import (Dummy, Symbol)
|
| 6 |
+
from sympy.functions.elementary.complexes import (Abs, re)
|
| 7 |
+
from sympy.functions.elementary.exponential import (exp, log)
|
| 8 |
+
from sympy.functions.elementary.integers import frac
|
| 9 |
+
from sympy.functions.elementary.miscellaneous import sqrt
|
| 10 |
+
from sympy.functions.elementary.piecewise import Piecewise
|
| 11 |
+
from sympy.functions.elementary.trigonometric import (
|
| 12 |
+
cos, cot, csc, sec, sin, tan, asin, acos, atan, acot, asec, acsc)
|
| 13 |
+
from sympy.functions.elementary.hyperbolic import (sinh, cosh, tanh, coth,
|
| 14 |
+
sech, csch, asinh, acosh, atanh, acoth, asech, acsch)
|
| 15 |
+
from sympy.functions.special.gamma_functions import gamma
|
| 16 |
+
from sympy.functions.special.error_functions import expint
|
| 17 |
+
from sympy.matrices.expressions.matexpr import MatrixSymbol
|
| 18 |
+
from sympy.simplify.simplify import simplify
|
| 19 |
+
from sympy.calculus.util import (function_range, continuous_domain, not_empty_in,
|
| 20 |
+
periodicity, lcim, is_convex,
|
| 21 |
+
stationary_points, minimum, maximum)
|
| 22 |
+
from sympy.sets.sets import (Interval, FiniteSet, Complement, Union)
|
| 23 |
+
from sympy.sets.fancysets import ImageSet
|
| 24 |
+
from sympy.sets.conditionset import ConditionSet
|
| 25 |
+
from sympy.testing.pytest import XFAIL, raises, _both_exp_pow, slow
|
| 26 |
+
from sympy.abc import x, y
|
| 27 |
+
|
| 28 |
+
a = Symbol('a', real=True)
|
| 29 |
+
|
| 30 |
+
def test_function_range():
|
| 31 |
+
assert function_range(sin(x), x, Interval(-pi/2, pi/2)
|
| 32 |
+
) == Interval(-1, 1)
|
| 33 |
+
assert function_range(sin(x), x, Interval(0, pi)
|
| 34 |
+
) == Interval(0, 1)
|
| 35 |
+
assert function_range(tan(x), x, Interval(0, pi)
|
| 36 |
+
) == Interval(-oo, oo)
|
| 37 |
+
assert function_range(tan(x), x, Interval(pi/2, pi)
|
| 38 |
+
) == Interval(-oo, 0)
|
| 39 |
+
assert function_range((x + 3)/(x - 2), x, Interval(-5, 5)
|
| 40 |
+
) == Union(Interval(-oo, Rational(2, 7)), Interval(Rational(8, 3), oo))
|
| 41 |
+
assert function_range(1/(x**2), x, Interval(-1, 1)
|
| 42 |
+
) == Interval(1, oo)
|
| 43 |
+
assert function_range(exp(x), x, Interval(-1, 1)
|
| 44 |
+
) == Interval(exp(-1), exp(1))
|
| 45 |
+
assert function_range(log(x) - x, x, S.Reals
|
| 46 |
+
) == Interval(-oo, -1)
|
| 47 |
+
assert function_range(sqrt(3*x - 1), x, Interval(0, 2)
|
| 48 |
+
) == Interval(0, sqrt(5))
|
| 49 |
+
assert function_range(x*(x - 1) - (x**2 - x), x, S.Reals
|
| 50 |
+
) == FiniteSet(0)
|
| 51 |
+
assert function_range(x*(x - 1) - (x**2 - x) + y, x, S.Reals
|
| 52 |
+
) == FiniteSet(y)
|
| 53 |
+
assert function_range(sin(x), x, Union(Interval(-5, -3), FiniteSet(4))
|
| 54 |
+
) == Union(Interval(-sin(3), 1), FiniteSet(sin(4)))
|
| 55 |
+
assert function_range(cos(x), x, Interval(-oo, -4)
|
| 56 |
+
) == Interval(-1, 1)
|
| 57 |
+
assert function_range(cos(x), x, S.EmptySet) == S.EmptySet
|
| 58 |
+
assert function_range(x/sqrt(x**2+1), x, S.Reals) == Interval.open(-1,1)
|
| 59 |
+
raises(NotImplementedError, lambda : function_range(
|
| 60 |
+
exp(x)*(sin(x) - cos(x))/2 - x, x, S.Reals))
|
| 61 |
+
raises(NotImplementedError, lambda : function_range(
|
| 62 |
+
sin(x) + x, x, S.Reals)) # issue 13273
|
| 63 |
+
raises(NotImplementedError, lambda : function_range(
|
| 64 |
+
log(x), x, S.Integers))
|
| 65 |
+
raises(NotImplementedError, lambda : function_range(
|
| 66 |
+
sin(x)/2, x, S.Naturals))
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
@slow
|
| 70 |
+
def test_function_range1():
|
| 71 |
+
assert function_range(tan(x)**2 + tan(3*x)**2 + 1, x, S.Reals) == Interval(1,oo)
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
def test_continuous_domain():
|
| 75 |
+
assert continuous_domain(sin(x), x, Interval(0, 2*pi)) == Interval(0, 2*pi)
|
| 76 |
+
assert continuous_domain(tan(x), x, Interval(0, 2*pi)) == \
|
| 77 |
+
Union(Interval(0, pi/2, False, True), Interval(pi/2, pi*Rational(3, 2), True, True),
|
| 78 |
+
Interval(pi*Rational(3, 2), 2*pi, True, False))
|
| 79 |
+
assert continuous_domain(cot(x), x, Interval(0, 2*pi)) == Union(
|
| 80 |
+
Interval.open(0, pi), Interval.open(pi, 2*pi))
|
| 81 |
+
assert continuous_domain((x - 1)/((x - 1)**2), x, S.Reals) == \
|
| 82 |
+
Union(Interval(-oo, 1, True, True), Interval(1, oo, True, True))
|
| 83 |
+
assert continuous_domain(log(x) + log(4*x - 1), x, S.Reals) == \
|
| 84 |
+
Interval(Rational(1, 4), oo, True, True)
|
| 85 |
+
assert continuous_domain(1/sqrt(x - 3), x, S.Reals) == Interval(3, oo, True, True)
|
| 86 |
+
assert continuous_domain(1/x - 2, x, S.Reals) == \
|
| 87 |
+
Union(Interval.open(-oo, 0), Interval.open(0, oo))
|
| 88 |
+
assert continuous_domain(1/(x**2 - 4) + 2, x, S.Reals) == \
|
| 89 |
+
Union(Interval.open(-oo, -2), Interval.open(-2, 2), Interval.open(2, oo))
|
| 90 |
+
assert continuous_domain((x+1)**pi, x, S.Reals) == Interval(-1, oo)
|
| 91 |
+
assert continuous_domain((x+1)**(pi/2), x, S.Reals) == Interval(-1, oo)
|
| 92 |
+
assert continuous_domain(x**x, x, S.Reals) == Interval(0, oo)
|
| 93 |
+
assert continuous_domain((x+1)**log(x**2), x, S.Reals) == Union(
|
| 94 |
+
Interval.Ropen(-1, 0), Interval.open(0, oo))
|
| 95 |
+
domain = continuous_domain(log(tan(x)**2 + 1), x, S.Reals)
|
| 96 |
+
assert not domain.contains(3*pi/2)
|
| 97 |
+
assert domain.contains(5)
|
| 98 |
+
d = Symbol('d', even=True, zero=False)
|
| 99 |
+
assert continuous_domain(x**(1/d), x, S.Reals) == Interval(0, oo)
|
| 100 |
+
n = Dummy('n')
|
| 101 |
+
assert continuous_domain(1/sin(x), x, S.Reals).dummy_eq(Complement(
|
| 102 |
+
S.Reals, Union(ImageSet(Lambda(n, 2*n*pi + pi), S.Integers),
|
| 103 |
+
ImageSet(Lambda(n, 2*n*pi), S.Integers))))
|
| 104 |
+
assert continuous_domain(sin(x) + cos(x), x, S.Reals) == S.Reals
|
| 105 |
+
assert continuous_domain(asin(x), x, S.Reals) == Interval(-1, 1) # issue #21786
|
| 106 |
+
assert continuous_domain(1/acos(log(x)), x, S.Reals) == Interval.Ropen(exp(-1), E)
|
| 107 |
+
assert continuous_domain(sinh(x)+cosh(x), x, S.Reals) == S.Reals
|
| 108 |
+
assert continuous_domain(tanh(x)+sech(x), x, S.Reals) == S.Reals
|
| 109 |
+
assert continuous_domain(atan(x)+asinh(x), x, S.Reals) == S.Reals
|
| 110 |
+
assert continuous_domain(acosh(x), x, S.Reals) == Interval(1, oo)
|
| 111 |
+
assert continuous_domain(atanh(x), x, S.Reals) == Interval.open(-1, 1)
|
| 112 |
+
assert continuous_domain(atanh(x)+acosh(x), x, S.Reals) == S.EmptySet
|
| 113 |
+
assert continuous_domain(asech(x), x, S.Reals) == Interval.Lopen(0, 1)
|
| 114 |
+
assert continuous_domain(acoth(x), x, S.Reals) == Union(
|
| 115 |
+
Interval.open(-oo, -1), Interval.open(1, oo))
|
| 116 |
+
assert continuous_domain(asec(x), x, S.Reals) == Union(
|
| 117 |
+
Interval(-oo, -1), Interval(1, oo))
|
| 118 |
+
assert continuous_domain(acsc(x), x, S.Reals) == Union(
|
| 119 |
+
Interval(-oo, -1), Interval(1, oo))
|
| 120 |
+
for f in (coth, acsch, csch):
|
| 121 |
+
assert continuous_domain(f(x), x, S.Reals) == Union(
|
| 122 |
+
Interval.open(-oo, 0), Interval.open(0, oo))
|
| 123 |
+
assert continuous_domain(acot(x), x, S.Reals).contains(0) == False
|
| 124 |
+
assert continuous_domain(1/(exp(x) - x), x, S.Reals) == Complement(
|
| 125 |
+
S.Reals, ConditionSet(x, Eq(-x + exp(x), 0), S.Reals))
|
| 126 |
+
assert continuous_domain(frac(x**2), x, Interval(-2,-1)) == Union(
|
| 127 |
+
Interval.open(-2, -sqrt(3)), Interval.open(-sqrt(2), -1),
|
| 128 |
+
Interval.open(-sqrt(3), -sqrt(2)))
|
| 129 |
+
assert continuous_domain(frac(x), x, S.Reals) == Complement(
|
| 130 |
+
S.Reals, S.Integers)
|
| 131 |
+
raises(NotImplementedError, lambda : continuous_domain(
|
| 132 |
+
1/(x**2+1), x, S.Complexes))
|
| 133 |
+
raises(NotImplementedError, lambda : continuous_domain(
|
| 134 |
+
gamma(x), x, Interval(-5,0)))
|
| 135 |
+
assert continuous_domain(x + gamma(pi), x, S.Reals) == S.Reals
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
@XFAIL
|
| 139 |
+
def test_continuous_domain_acot():
|
| 140 |
+
acot_cont = Piecewise((pi+acot(x), x<0), (acot(x), True))
|
| 141 |
+
assert continuous_domain(acot_cont, x, S.Reals) == S.Reals
|
| 142 |
+
|
| 143 |
+
@XFAIL
|
| 144 |
+
def test_continuous_domain_gamma():
|
| 145 |
+
assert continuous_domain(gamma(x), x, S.Reals).contains(-1) == False
|
| 146 |
+
|
| 147 |
+
@XFAIL
|
| 148 |
+
def test_continuous_domain_neg_power():
|
| 149 |
+
assert continuous_domain((x-2)**(1-x), x, S.Reals) == Interval.open(2, oo)
|
| 150 |
+
|
| 151 |
+
|
| 152 |
+
def test_not_empty_in():
|
| 153 |
+
assert not_empty_in(FiniteSet(x, 2*x).intersect(Interval(1, 2, True, False)), x) == \
|
| 154 |
+
Interval(S.Half, 2, True, False)
|
| 155 |
+
assert not_empty_in(FiniteSet(x, x**2).intersect(Interval(1, 2)), x) == \
|
| 156 |
+
Union(Interval(-sqrt(2), -1), Interval(1, 2))
|
| 157 |
+
assert not_empty_in(FiniteSet(x**2 + x, x).intersect(Interval(2, 4)), x) == \
|
| 158 |
+
Union(Interval(-sqrt(17)/2 - S.Half, -2),
|
| 159 |
+
Interval(1, Rational(-1, 2) + sqrt(17)/2), Interval(2, 4))
|
| 160 |
+
assert not_empty_in(FiniteSet(x/(x - 1)).intersect(S.Reals), x) == \
|
| 161 |
+
Complement(S.Reals, FiniteSet(1))
|
| 162 |
+
assert not_empty_in(FiniteSet(a/(a - 1)).intersect(S.Reals), a) == \
|
| 163 |
+
Complement(S.Reals, FiniteSet(1))
|
| 164 |
+
assert not_empty_in(FiniteSet((x**2 - 3*x + 2)/(x - 1)).intersect(S.Reals), x) == \
|
| 165 |
+
Complement(S.Reals, FiniteSet(1))
|
| 166 |
+
assert not_empty_in(FiniteSet(3, 4, x/(x - 1)).intersect(Interval(2, 3)), x) == \
|
| 167 |
+
Interval(-oo, oo)
|
| 168 |
+
assert not_empty_in(FiniteSet(4, x/(x - 1)).intersect(Interval(2, 3)), x) == \
|
| 169 |
+
Interval(S(3)/2, 2)
|
| 170 |
+
assert not_empty_in(FiniteSet(x/(x**2 - 1)).intersect(S.Reals), x) == \
|
| 171 |
+
Complement(S.Reals, FiniteSet(-1, 1))
|
| 172 |
+
assert not_empty_in(FiniteSet(x, x**2).intersect(Union(Interval(1, 3, True, True),
|
| 173 |
+
Interval(4, 5))), x) == \
|
| 174 |
+
Union(Interval(-sqrt(5), -2), Interval(-sqrt(3), -1, True, True),
|
| 175 |
+
Interval(1, 3, True, True), Interval(4, 5))
|
| 176 |
+
assert not_empty_in(FiniteSet(1).intersect(Interval(3, 4)), x) == S.EmptySet
|
| 177 |
+
assert not_empty_in(FiniteSet(x**2/(x + 2)).intersect(Interval(1, oo)), x) == \
|
| 178 |
+
Union(Interval(-2, -1, True, False), Interval(2, oo))
|
| 179 |
+
raises(ValueError, lambda: not_empty_in(x))
|
| 180 |
+
raises(ValueError, lambda: not_empty_in(Interval(0, 1), x))
|
| 181 |
+
raises(NotImplementedError,
|
| 182 |
+
lambda: not_empty_in(FiniteSet(x).intersect(S.Reals), x, a))
|
| 183 |
+
|
| 184 |
+
|
| 185 |
+
@_both_exp_pow
|
| 186 |
+
def test_periodicity():
|
| 187 |
+
assert periodicity(sin(2*x), x) == pi
|
| 188 |
+
assert periodicity((-2)*tan(4*x), x) == pi/4
|
| 189 |
+
assert periodicity(sin(x)**2, x) == 2*pi
|
| 190 |
+
assert periodicity(3**tan(3*x), x) == pi/3
|
| 191 |
+
assert periodicity(tan(x)*cos(x), x) == 2*pi
|
| 192 |
+
assert periodicity(sin(x)**(tan(x)), x) == 2*pi
|
| 193 |
+
assert periodicity(tan(x)*sec(x), x) == 2*pi
|
| 194 |
+
assert periodicity(sin(2*x)*cos(2*x) - y, x) == pi/2
|
| 195 |
+
assert periodicity(tan(x) + cot(x), x) == pi
|
| 196 |
+
assert periodicity(sin(x) - cos(2*x), x) == 2*pi
|
| 197 |
+
assert periodicity(sin(x) - 1, x) == 2*pi
|
| 198 |
+
assert periodicity(sin(4*x) + sin(x)*cos(x), x) == pi
|
| 199 |
+
assert periodicity(exp(sin(x)), x) == 2*pi
|
| 200 |
+
assert periodicity(log(cot(2*x)) - sin(cos(2*x)), x) == pi
|
| 201 |
+
assert periodicity(sin(2*x)*exp(tan(x) - csc(2*x)), x) == pi
|
| 202 |
+
assert periodicity(cos(sec(x) - csc(2*x)), x) == 2*pi
|
| 203 |
+
assert periodicity(tan(sin(2*x)), x) == pi
|
| 204 |
+
assert periodicity(2*tan(x)**2, x) == pi
|
| 205 |
+
assert periodicity(sin(x%4), x) == 4
|
| 206 |
+
assert periodicity(sin(x)%4, x) == 2*pi
|
| 207 |
+
assert periodicity(tan((3*x-2)%4), x) == Rational(4, 3)
|
| 208 |
+
assert periodicity((sqrt(2)*(x+1)+x) % 3, x) == 3 / (sqrt(2)+1)
|
| 209 |
+
assert periodicity((x**2+1) % x, x) is None
|
| 210 |
+
assert periodicity(sin(re(x)), x) == 2*pi
|
| 211 |
+
assert periodicity(sin(x)**2 + cos(x)**2, x) is S.Zero
|
| 212 |
+
assert periodicity(tan(x), y) is S.Zero
|
| 213 |
+
assert periodicity(sin(x) + I*cos(x), x) == 2*pi
|
| 214 |
+
assert periodicity(x - sin(2*y), y) == pi
|
| 215 |
+
|
| 216 |
+
assert periodicity(exp(x), x) is None
|
| 217 |
+
assert periodicity(exp(I*x), x) == 2*pi
|
| 218 |
+
assert periodicity(exp(I*a), a) == 2*pi
|
| 219 |
+
assert periodicity(exp(a), a) is None
|
| 220 |
+
assert periodicity(exp(log(sin(a) + I*cos(2*a)), evaluate=False), a) == 2*pi
|
| 221 |
+
assert periodicity(exp(log(sin(2*a) + I*cos(a)), evaluate=False), a) == 2*pi
|
| 222 |
+
assert periodicity(exp(sin(a)), a) == 2*pi
|
| 223 |
+
assert periodicity(exp(2*I*a), a) == pi
|
| 224 |
+
assert periodicity(exp(a + I*sin(a)), a) is None
|
| 225 |
+
assert periodicity(exp(cos(a/2) + sin(a)), a) == 4*pi
|
| 226 |
+
assert periodicity(log(x), x) is None
|
| 227 |
+
assert periodicity(exp(x)**sin(x), x) is None
|
| 228 |
+
assert periodicity(sin(x)**y, y) is None
|
| 229 |
+
|
| 230 |
+
assert periodicity(Abs(sin(Abs(sin(x)))), x) == pi
|
| 231 |
+
assert all(periodicity(Abs(f(x)), x) == pi for f in (
|
| 232 |
+
cos, sin, sec, csc, tan, cot))
|
| 233 |
+
assert periodicity(Abs(sin(tan(x))), x) == pi
|
| 234 |
+
assert periodicity(Abs(sin(sin(x) + tan(x))), x) == 2*pi
|
| 235 |
+
assert periodicity(sin(x) > S.Half, x) == 2*pi
|
| 236 |
+
|
| 237 |
+
assert periodicity(x > 2, x) is None
|
| 238 |
+
assert periodicity(x**3 - x**2 + 1, x) is None
|
| 239 |
+
assert periodicity(Abs(x), x) is None
|
| 240 |
+
assert periodicity(Abs(x**2 - 1), x) is None
|
| 241 |
+
|
| 242 |
+
assert periodicity((x**2 + 4)%2, x) is None
|
| 243 |
+
assert periodicity((E**x)%3, x) is None
|
| 244 |
+
|
| 245 |
+
assert periodicity(sin(expint(1, x))/expint(1, x), x) is None
|
| 246 |
+
# returning `None` for any Piecewise
|
| 247 |
+
p = Piecewise((0, x < -1), (x**2, x <= 1), (log(x), True))
|
| 248 |
+
assert periodicity(p, x) is None
|
| 249 |
+
|
| 250 |
+
m = MatrixSymbol('m', 3, 3)
|
| 251 |
+
raises(NotImplementedError, lambda: periodicity(sin(m), m))
|
| 252 |
+
raises(NotImplementedError, lambda: periodicity(sin(m[0, 0]), m))
|
| 253 |
+
raises(NotImplementedError, lambda: periodicity(sin(m), m[0, 0]))
|
| 254 |
+
raises(NotImplementedError, lambda: periodicity(sin(m[0, 0]), m[0, 0]))
|
| 255 |
+
|
| 256 |
+
|
| 257 |
+
def test_periodicity_check():
|
| 258 |
+
assert periodicity(tan(x), x, check=True) == pi
|
| 259 |
+
assert periodicity(sin(x) + cos(x), x, check=True) == 2*pi
|
| 260 |
+
assert periodicity(sec(x), x) == 2*pi
|
| 261 |
+
assert periodicity(sin(x*y), x) == 2*pi/abs(y)
|
| 262 |
+
assert periodicity(Abs(sec(sec(x))), x) == pi
|
| 263 |
+
|
| 264 |
+
|
| 265 |
+
def test_lcim():
|
| 266 |
+
assert lcim([S.Half, S(2), S(3)]) == 6
|
| 267 |
+
assert lcim([pi/2, pi/4, pi]) == pi
|
| 268 |
+
assert lcim([2*pi, pi/2]) == 2*pi
|
| 269 |
+
assert lcim([S.One, 2*pi]) is None
|
| 270 |
+
assert lcim([S(2) + 2*E, E/3 + Rational(1, 3), S.One + E]) == S(2) + 2*E
|
| 271 |
+
|
| 272 |
+
|
| 273 |
+
def test_is_convex():
|
| 274 |
+
assert is_convex(1/x, x, domain=Interval.open(0, oo)) == True
|
| 275 |
+
assert is_convex(1/x, x, domain=Interval(-oo, 0)) == False
|
| 276 |
+
assert is_convex(x**2, x, domain=Interval(0, oo)) == True
|
| 277 |
+
assert is_convex(1/x**3, x, domain=Interval.Lopen(0, oo)) == True
|
| 278 |
+
assert is_convex(-1/x**3, x, domain=Interval.Ropen(-oo, 0)) == True
|
| 279 |
+
assert is_convex(log(x) ,x) == False
|
| 280 |
+
assert is_convex(x**2+y**2, x, y) == True
|
| 281 |
+
assert is_convex(cos(x) + cos(y), x) == False
|
| 282 |
+
assert is_convex(8*x**2 - 2*y**2, x, y) == False
|
| 283 |
+
|
| 284 |
+
|
| 285 |
+
def test_stationary_points():
|
| 286 |
+
assert stationary_points(sin(x), x, Interval(-pi/2, pi/2)
|
| 287 |
+
) == {-pi/2, pi/2}
|
| 288 |
+
assert stationary_points(sin(x), x, Interval.Ropen(0, pi/4)
|
| 289 |
+
) is S.EmptySet
|
| 290 |
+
assert stationary_points(tan(x), x,
|
| 291 |
+
) is S.EmptySet
|
| 292 |
+
assert stationary_points(sin(x)*cos(x), x, Interval(0, pi)
|
| 293 |
+
) == {pi/4, pi*Rational(3, 4)}
|
| 294 |
+
assert stationary_points(sec(x), x, Interval(0, pi)
|
| 295 |
+
) == {0, pi}
|
| 296 |
+
assert stationary_points((x+3)*(x-2), x
|
| 297 |
+
) == FiniteSet(Rational(-1, 2))
|
| 298 |
+
assert stationary_points((x + 3)/(x - 2), x, Interval(-5, 5)
|
| 299 |
+
) is S.EmptySet
|
| 300 |
+
assert stationary_points((x**2+3)/(x-2), x
|
| 301 |
+
) == {2 - sqrt(7), 2 + sqrt(7)}
|
| 302 |
+
assert stationary_points((x**2+3)/(x-2), x, Interval(0, 5)
|
| 303 |
+
) == {2 + sqrt(7)}
|
| 304 |
+
assert stationary_points(x**4 + x**3 - 5*x**2, x, S.Reals
|
| 305 |
+
) == FiniteSet(-2, 0, Rational(5, 4))
|
| 306 |
+
assert stationary_points(exp(x), x
|
| 307 |
+
) is S.EmptySet
|
| 308 |
+
assert stationary_points(log(x) - x, x, S.Reals
|
| 309 |
+
) == {1}
|
| 310 |
+
assert stationary_points(cos(x), x, Union(Interval(0, 5), Interval(-6, -3))
|
| 311 |
+
) == {0, -pi, pi}
|
| 312 |
+
assert stationary_points(y, x, S.Reals
|
| 313 |
+
) == S.Reals
|
| 314 |
+
assert stationary_points(y, x, S.EmptySet) == S.EmptySet
|
| 315 |
+
|
| 316 |
+
|
| 317 |
+
def test_maximum():
|
| 318 |
+
assert maximum(sin(x), x) is S.One
|
| 319 |
+
assert maximum(sin(x), x, Interval(0, 1)) == sin(1)
|
| 320 |
+
assert maximum(tan(x), x) is oo
|
| 321 |
+
assert maximum(tan(x), x, Interval(-pi/4, pi/4)) is S.One
|
| 322 |
+
assert maximum(sin(x)*cos(x), x, S.Reals) == S.Half
|
| 323 |
+
assert simplify(maximum(sin(x)*cos(x), x, Interval(pi*Rational(3, 8), pi*Rational(5, 8)))
|
| 324 |
+
) == sqrt(2)/4
|
| 325 |
+
assert maximum((x+3)*(x-2), x) is oo
|
| 326 |
+
assert maximum((x+3)*(x-2), x, Interval(-5, 0)) == S(14)
|
| 327 |
+
assert maximum((x+3)/(x-2), x, Interval(-5, 0)) == Rational(2, 7)
|
| 328 |
+
assert simplify(maximum(-x**4-x**3+x**2+10, x)
|
| 329 |
+
) == 41*sqrt(41)/512 + Rational(5419, 512)
|
| 330 |
+
assert maximum(exp(x), x, Interval(-oo, 2)) == exp(2)
|
| 331 |
+
assert maximum(log(x) - x, x, S.Reals) is S.NegativeOne
|
| 332 |
+
assert maximum(cos(x), x, Union(Interval(0, 5), Interval(-6, -3))
|
| 333 |
+
) is S.One
|
| 334 |
+
assert maximum(cos(x)-sin(x), x, S.Reals) == sqrt(2)
|
| 335 |
+
assert maximum(y, x, S.Reals) == y
|
| 336 |
+
assert maximum(abs(a**3 + a), a, Interval(0, 2)) == 10
|
| 337 |
+
assert maximum(abs(60*a**3 + 24*a), a, Interval(0, 2)) == 528
|
| 338 |
+
assert maximum(abs(12*a*(5*a**2 + 2)), a, Interval(0, 2)) == 528
|
| 339 |
+
assert maximum(x/sqrt(x**2+1), x, S.Reals) == 1
|
| 340 |
+
|
| 341 |
+
raises(ValueError, lambda : maximum(sin(x), x, S.EmptySet))
|
| 342 |
+
raises(ValueError, lambda : maximum(log(cos(x)), x, S.EmptySet))
|
| 343 |
+
raises(ValueError, lambda : maximum(1/(x**2 + y**2 + 1), x, S.EmptySet))
|
| 344 |
+
raises(ValueError, lambda : maximum(sin(x), sin(x)))
|
| 345 |
+
raises(ValueError, lambda : maximum(sin(x), x*y, S.EmptySet))
|
| 346 |
+
raises(ValueError, lambda : maximum(sin(x), S.One))
|
| 347 |
+
|
| 348 |
+
|
| 349 |
+
def test_minimum():
|
| 350 |
+
assert minimum(sin(x), x) is S.NegativeOne
|
| 351 |
+
assert minimum(sin(x), x, Interval(1, 4)) == sin(4)
|
| 352 |
+
assert minimum(tan(x), x) is -oo
|
| 353 |
+
assert minimum(tan(x), x, Interval(-pi/4, pi/4)) is S.NegativeOne
|
| 354 |
+
assert minimum(sin(x)*cos(x), x, S.Reals) == Rational(-1, 2)
|
| 355 |
+
assert simplify(minimum(sin(x)*cos(x), x, Interval(pi*Rational(3, 8), pi*Rational(5, 8)))
|
| 356 |
+
) == -sqrt(2)/4
|
| 357 |
+
assert minimum((x+3)*(x-2), x) == Rational(-25, 4)
|
| 358 |
+
assert minimum((x+3)/(x-2), x, Interval(-5, 0)) == Rational(-3, 2)
|
| 359 |
+
assert minimum(x**4-x**3+x**2+10, x) == S(10)
|
| 360 |
+
assert minimum(exp(x), x, Interval(-2, oo)) == exp(-2)
|
| 361 |
+
assert minimum(log(x) - x, x, S.Reals) is -oo
|
| 362 |
+
assert minimum(cos(x), x, Union(Interval(0, 5), Interval(-6, -3))
|
| 363 |
+
) is S.NegativeOne
|
| 364 |
+
assert minimum(cos(x)-sin(x), x, S.Reals) == -sqrt(2)
|
| 365 |
+
assert minimum(y, x, S.Reals) == y
|
| 366 |
+
assert minimum(x/sqrt(x**2+1), x, S.Reals) == -1
|
| 367 |
+
|
| 368 |
+
raises(ValueError, lambda : minimum(sin(x), x, S.EmptySet))
|
| 369 |
+
raises(ValueError, lambda : minimum(log(cos(x)), x, S.EmptySet))
|
| 370 |
+
raises(ValueError, lambda : minimum(1/(x**2 + y**2 + 1), x, S.EmptySet))
|
| 371 |
+
raises(ValueError, lambda : minimum(sin(x), sin(x)))
|
| 372 |
+
raises(ValueError, lambda : minimum(sin(x), x*y, S.EmptySet))
|
| 373 |
+
raises(ValueError, lambda : minimum(sin(x), S.One))
|
| 374 |
+
|
| 375 |
+
|
| 376 |
+
def test_issue_19869():
|
| 377 |
+
assert (maximum(sqrt(3)*(x - 1)/(3*sqrt(x**2 + 1)), x)
|
| 378 |
+
) == sqrt(3)/3
|
| 379 |
+
|
| 380 |
+
|
| 381 |
+
def test_issue_16469():
|
| 382 |
+
f = abs(a)
|
| 383 |
+
assert function_range(f, a, S.Reals) == Interval(0, oo, False, True)
|
| 384 |
+
|
| 385 |
+
|
| 386 |
+
@_both_exp_pow
|
| 387 |
+
def test_issue_18747():
|
| 388 |
+
assert periodicity(exp(pi*I*(x/4 + S.Half/2)), x) == 8
|
| 389 |
+
|
| 390 |
+
|
| 391 |
+
def test_issue_25942():
|
| 392 |
+
assert (acos(x) > pi/3).as_set() == Interval.Ropen(-1, S(1)/2)
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/diffgeom/__pycache__/__init__.cpython-312.pyc
ADDED
|
Binary file (926 Bytes). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/diffgeom/__pycache__/diffgeom.cpython-312.pyc
ADDED
|
Binary file (93.5 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/diffgeom/__pycache__/rn.cpython-312.pyc
ADDED
|
Binary file (7.46 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/diffgeom/tests/__init__.py
ADDED
|
File without changes
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/diffgeom/tests/__pycache__/__init__.cpython-312.pyc
ADDED
|
Binary file (212 Bytes). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/diffgeom/tests/__pycache__/test_class_structure.cpython-312.pyc
ADDED
|
Binary file (2.75 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/diffgeom/tests/__pycache__/test_diffgeom.cpython-312.pyc
ADDED
|
Binary file (35 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/diffgeom/tests/__pycache__/test_function_diffgeom_book.cpython-312.pyc
ADDED
|
Binary file (13.3 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/diffgeom/tests/__pycache__/test_hyperbolic_space.cpython-312.pyc
ADDED
|
Binary file (4.14 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/diffgeom/tests/test_class_structure.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.diffgeom import Manifold, Patch, CoordSystem, Point
|
| 2 |
+
from sympy.core.function import Function
|
| 3 |
+
from sympy.core.symbol import symbols
|
| 4 |
+
from sympy.testing.pytest import warns_deprecated_sympy
|
| 5 |
+
|
| 6 |
+
m = Manifold('m', 2)
|
| 7 |
+
p = Patch('p', m)
|
| 8 |
+
a, b = symbols('a b')
|
| 9 |
+
cs = CoordSystem('cs', p, [a, b])
|
| 10 |
+
x, y = symbols('x y')
|
| 11 |
+
f = Function('f')
|
| 12 |
+
s1, s2 = cs.coord_functions()
|
| 13 |
+
v1, v2 = cs.base_vectors()
|
| 14 |
+
f1, f2 = cs.base_oneforms()
|
| 15 |
+
|
| 16 |
+
def test_point():
|
| 17 |
+
point = Point(cs, [x, y])
|
| 18 |
+
assert point != Point(cs, [2, y])
|
| 19 |
+
#TODO assert point.subs(x, 2) == Point(cs, [2, y])
|
| 20 |
+
#TODO assert point.free_symbols == set([x, y])
|
| 21 |
+
|
| 22 |
+
def test_subs():
|
| 23 |
+
assert s1.subs(s1, s2) == s2
|
| 24 |
+
assert v1.subs(v1, v2) == v2
|
| 25 |
+
assert f1.subs(f1, f2) == f2
|
| 26 |
+
assert (x*f(s1) + y).subs(s1, s2) == x*f(s2) + y
|
| 27 |
+
assert (f(s1)*v1).subs(v1, v2) == f(s1)*v2
|
| 28 |
+
assert (y*f(s1)*f1).subs(f1, f2) == y*f(s1)*f2
|
| 29 |
+
|
| 30 |
+
def test_deprecated():
|
| 31 |
+
with warns_deprecated_sympy():
|
| 32 |
+
cs_wname = CoordSystem('cs', p, ['a', 'b'])
|
| 33 |
+
assert cs_wname == cs_wname.func(*cs_wname.args)
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/diffgeom/tests/test_diffgeom.py
ADDED
|
@@ -0,0 +1,342 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.core import Lambda, Symbol, symbols
|
| 2 |
+
from sympy.diffgeom.rn import R2, R2_p, R2_r, R3_r, R3_c, R3_s, R2_origin
|
| 3 |
+
from sympy.diffgeom import (Manifold, Patch, CoordSystem, Commutator, Differential, TensorProduct,
|
| 4 |
+
WedgeProduct, BaseCovarDerivativeOp, CovarDerivativeOp, LieDerivative,
|
| 5 |
+
covariant_order, contravariant_order, twoform_to_matrix, metric_to_Christoffel_1st,
|
| 6 |
+
metric_to_Christoffel_2nd, metric_to_Riemann_components,
|
| 7 |
+
metric_to_Ricci_components, intcurve_diffequ, intcurve_series)
|
| 8 |
+
from sympy.simplify import trigsimp, simplify
|
| 9 |
+
from sympy.functions import sqrt, atan2, sin
|
| 10 |
+
from sympy.matrices import Matrix
|
| 11 |
+
from sympy.testing.pytest import raises, nocache_fail
|
| 12 |
+
from sympy.testing.pytest import warns_deprecated_sympy
|
| 13 |
+
|
| 14 |
+
TP = TensorProduct
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def test_coordsys_transform():
|
| 18 |
+
# test inverse transforms
|
| 19 |
+
p, q, r, s = symbols('p q r s')
|
| 20 |
+
rel = {('first', 'second'): [(p, q), (q, -p)]}
|
| 21 |
+
R2_pq = CoordSystem('first', R2_origin, [p, q], rel)
|
| 22 |
+
R2_rs = CoordSystem('second', R2_origin, [r, s], rel)
|
| 23 |
+
r, s = R2_rs.symbols
|
| 24 |
+
assert R2_rs.transform(R2_pq) == Matrix([[-s], [r]])
|
| 25 |
+
|
| 26 |
+
# inverse transform impossible case
|
| 27 |
+
a, b = symbols('a b', positive=True)
|
| 28 |
+
rel = {('first', 'second'): [(a,), (-a,)]}
|
| 29 |
+
R2_a = CoordSystem('first', R2_origin, [a], rel)
|
| 30 |
+
R2_b = CoordSystem('second', R2_origin, [b], rel)
|
| 31 |
+
# This transformation is uninvertible because there is no positive a, b satisfying a = -b
|
| 32 |
+
with raises(NotImplementedError):
|
| 33 |
+
R2_b.transform(R2_a)
|
| 34 |
+
|
| 35 |
+
# inverse transform ambiguous case
|
| 36 |
+
c, d = symbols('c d')
|
| 37 |
+
rel = {('first', 'second'): [(c,), (c**2,)]}
|
| 38 |
+
R2_c = CoordSystem('first', R2_origin, [c], rel)
|
| 39 |
+
R2_d = CoordSystem('second', R2_origin, [d], rel)
|
| 40 |
+
# The transform method should throw if it finds multiple inverses for a coordinate transformation.
|
| 41 |
+
with raises(ValueError):
|
| 42 |
+
R2_d.transform(R2_c)
|
| 43 |
+
|
| 44 |
+
# test indirect transformation
|
| 45 |
+
a, b, c, d, e, f = symbols('a, b, c, d, e, f')
|
| 46 |
+
rel = {('C1', 'C2'): [(a, b), (2*a, 3*b)],
|
| 47 |
+
('C2', 'C3'): [(c, d), (3*c, 2*d)]}
|
| 48 |
+
C1 = CoordSystem('C1', R2_origin, (a, b), rel)
|
| 49 |
+
C2 = CoordSystem('C2', R2_origin, (c, d), rel)
|
| 50 |
+
C3 = CoordSystem('C3', R2_origin, (e, f), rel)
|
| 51 |
+
a, b = C1.symbols
|
| 52 |
+
c, d = C2.symbols
|
| 53 |
+
e, f = C3.symbols
|
| 54 |
+
assert C2.transform(C1) == Matrix([c/2, d/3])
|
| 55 |
+
assert C1.transform(C3) == Matrix([6*a, 6*b])
|
| 56 |
+
assert C3.transform(C1) == Matrix([e/6, f/6])
|
| 57 |
+
assert C3.transform(C2) == Matrix([e/3, f/2])
|
| 58 |
+
|
| 59 |
+
a, b, c, d, e, f = symbols('a, b, c, d, e, f')
|
| 60 |
+
rel = {('C1', 'C2'): [(a, b), (2*a, 3*b + 1)],
|
| 61 |
+
('C3', 'C2'): [(e, f), (-e - 2, 2*f)]}
|
| 62 |
+
C1 = CoordSystem('C1', R2_origin, (a, b), rel)
|
| 63 |
+
C2 = CoordSystem('C2', R2_origin, (c, d), rel)
|
| 64 |
+
C3 = CoordSystem('C3', R2_origin, (e, f), rel)
|
| 65 |
+
a, b = C1.symbols
|
| 66 |
+
c, d = C2.symbols
|
| 67 |
+
e, f = C3.symbols
|
| 68 |
+
assert C2.transform(C1) == Matrix([c/2, (d - 1)/3])
|
| 69 |
+
assert C1.transform(C3) == Matrix([-2*a - 2, (3*b + 1)/2])
|
| 70 |
+
assert C3.transform(C1) == Matrix([-e/2 - 1, (2*f - 1)/3])
|
| 71 |
+
assert C3.transform(C2) == Matrix([-e - 2, 2*f])
|
| 72 |
+
|
| 73 |
+
# old signature uses Lambda
|
| 74 |
+
a, b, c, d, e, f = symbols('a, b, c, d, e, f')
|
| 75 |
+
rel = {('C1', 'C2'): Lambda((a, b), (2*a, 3*b + 1)),
|
| 76 |
+
('C3', 'C2'): Lambda((e, f), (-e - 2, 2*f))}
|
| 77 |
+
C1 = CoordSystem('C1', R2_origin, (a, b), rel)
|
| 78 |
+
C2 = CoordSystem('C2', R2_origin, (c, d), rel)
|
| 79 |
+
C3 = CoordSystem('C3', R2_origin, (e, f), rel)
|
| 80 |
+
a, b = C1.symbols
|
| 81 |
+
c, d = C2.symbols
|
| 82 |
+
e, f = C3.symbols
|
| 83 |
+
assert C2.transform(C1) == Matrix([c/2, (d - 1)/3])
|
| 84 |
+
assert C1.transform(C3) == Matrix([-2*a - 2, (3*b + 1)/2])
|
| 85 |
+
assert C3.transform(C1) == Matrix([-e/2 - 1, (2*f - 1)/3])
|
| 86 |
+
assert C3.transform(C2) == Matrix([-e - 2, 2*f])
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
def test_R2():
|
| 90 |
+
x0, y0, r0, theta0 = symbols('x0, y0, r0, theta0', real=True)
|
| 91 |
+
point_r = R2_r.point([x0, y0])
|
| 92 |
+
point_p = R2_p.point([r0, theta0])
|
| 93 |
+
|
| 94 |
+
# r**2 = x**2 + y**2
|
| 95 |
+
assert (R2.r**2 - R2.x**2 - R2.y**2).rcall(point_r) == 0
|
| 96 |
+
assert trigsimp( (R2.r**2 - R2.x**2 - R2.y**2).rcall(point_p) ) == 0
|
| 97 |
+
assert trigsimp(R2.e_r(R2.x**2 + R2.y**2).rcall(point_p).doit()) == 2*r0
|
| 98 |
+
|
| 99 |
+
# polar->rect->polar == Id
|
| 100 |
+
a, b = symbols('a b', positive=True)
|
| 101 |
+
m = Matrix([[a], [b]])
|
| 102 |
+
|
| 103 |
+
#TODO assert m == R2_r.transform(R2_p, R2_p.transform(R2_r, [a, b])).applyfunc(simplify)
|
| 104 |
+
assert m == R2_p.transform(R2_r, R2_r.transform(R2_p, m)).applyfunc(simplify)
|
| 105 |
+
|
| 106 |
+
# deprecated method
|
| 107 |
+
with warns_deprecated_sympy():
|
| 108 |
+
assert m == R2_p.coord_tuple_transform_to(
|
| 109 |
+
R2_r, R2_r.coord_tuple_transform_to(R2_p, m)).applyfunc(simplify)
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
def test_R3():
|
| 113 |
+
a, b, c = symbols('a b c', positive=True)
|
| 114 |
+
m = Matrix([[a], [b], [c]])
|
| 115 |
+
|
| 116 |
+
assert m == R3_c.transform(R3_r, R3_r.transform(R3_c, m)).applyfunc(simplify)
|
| 117 |
+
#TODO assert m == R3_r.transform(R3_c, R3_c.transform(R3_r, m)).applyfunc(simplify)
|
| 118 |
+
assert m == R3_s.transform(
|
| 119 |
+
R3_r, R3_r.transform(R3_s, m)).applyfunc(simplify)
|
| 120 |
+
#TODO assert m == R3_r.transform(R3_s, R3_s.transform(R3_r, m)).applyfunc(simplify)
|
| 121 |
+
assert m == R3_s.transform(
|
| 122 |
+
R3_c, R3_c.transform(R3_s, m)).applyfunc(simplify)
|
| 123 |
+
#TODO assert m == R3_c.transform(R3_s, R3_s.transform(R3_c, m)).applyfunc(simplify)
|
| 124 |
+
|
| 125 |
+
with warns_deprecated_sympy():
|
| 126 |
+
assert m == R3_c.coord_tuple_transform_to(
|
| 127 |
+
R3_r, R3_r.coord_tuple_transform_to(R3_c, m)).applyfunc(simplify)
|
| 128 |
+
#TODO assert m == R3_r.coord_tuple_transform_to(R3_c, R3_c.coord_tuple_transform_to(R3_r, m)).applyfunc(simplify)
|
| 129 |
+
assert m == R3_s.coord_tuple_transform_to(
|
| 130 |
+
R3_r, R3_r.coord_tuple_transform_to(R3_s, m)).applyfunc(simplify)
|
| 131 |
+
#TODO assert m == R3_r.coord_tuple_transform_to(R3_s, R3_s.coord_tuple_transform_to(R3_r, m)).applyfunc(simplify)
|
| 132 |
+
assert m == R3_s.coord_tuple_transform_to(
|
| 133 |
+
R3_c, R3_c.coord_tuple_transform_to(R3_s, m)).applyfunc(simplify)
|
| 134 |
+
#TODO assert m == R3_c.coord_tuple_transform_to(R3_s, R3_s.coord_tuple_transform_to(R3_c, m)).applyfunc(simplify)
|
| 135 |
+
|
| 136 |
+
|
| 137 |
+
def test_CoordinateSymbol():
|
| 138 |
+
x, y = R2_r.symbols
|
| 139 |
+
r, theta = R2_p.symbols
|
| 140 |
+
assert y.rewrite(R2_p) == r*sin(theta)
|
| 141 |
+
|
| 142 |
+
|
| 143 |
+
def test_point():
|
| 144 |
+
x, y = symbols('x, y')
|
| 145 |
+
p = R2_r.point([x, y])
|
| 146 |
+
assert p.free_symbols == {x, y}
|
| 147 |
+
assert p.coords(R2_r) == p.coords() == Matrix([x, y])
|
| 148 |
+
assert p.coords(R2_p) == Matrix([sqrt(x**2 + y**2), atan2(y, x)])
|
| 149 |
+
|
| 150 |
+
|
| 151 |
+
def test_commutator():
|
| 152 |
+
assert Commutator(R2.e_x, R2.e_y) == 0
|
| 153 |
+
assert Commutator(R2.x*R2.e_x, R2.x*R2.e_x) == 0
|
| 154 |
+
assert Commutator(R2.x*R2.e_x, R2.x*R2.e_y) == R2.x*R2.e_y
|
| 155 |
+
c = Commutator(R2.e_x, R2.e_r)
|
| 156 |
+
assert c(R2.x) == R2.y*(R2.x**2 + R2.y**2)**(-1)*sin(R2.theta)
|
| 157 |
+
|
| 158 |
+
|
| 159 |
+
def test_differential():
|
| 160 |
+
xdy = R2.x*R2.dy
|
| 161 |
+
dxdy = Differential(xdy)
|
| 162 |
+
assert xdy.rcall(None) == xdy
|
| 163 |
+
assert dxdy(R2.e_x, R2.e_y) == 1
|
| 164 |
+
assert dxdy(R2.e_x, R2.x*R2.e_y) == R2.x
|
| 165 |
+
assert Differential(dxdy) == 0
|
| 166 |
+
|
| 167 |
+
|
| 168 |
+
def test_products():
|
| 169 |
+
assert TensorProduct(
|
| 170 |
+
R2.dx, R2.dy)(R2.e_x, R2.e_y) == R2.dx(R2.e_x)*R2.dy(R2.e_y) == 1
|
| 171 |
+
assert TensorProduct(R2.dx, R2.dy)(None, R2.e_y) == R2.dx
|
| 172 |
+
assert TensorProduct(R2.dx, R2.dy)(R2.e_x, None) == R2.dy
|
| 173 |
+
assert TensorProduct(R2.dx, R2.dy)(R2.e_x) == R2.dy
|
| 174 |
+
assert TensorProduct(R2.x, R2.dx) == R2.x*R2.dx
|
| 175 |
+
assert TensorProduct(
|
| 176 |
+
R2.e_x, R2.e_y)(R2.x, R2.y) == R2.e_x(R2.x) * R2.e_y(R2.y) == 1
|
| 177 |
+
assert TensorProduct(R2.e_x, R2.e_y)(None, R2.y) == R2.e_x
|
| 178 |
+
assert TensorProduct(R2.e_x, R2.e_y)(R2.x, None) == R2.e_y
|
| 179 |
+
assert TensorProduct(R2.e_x, R2.e_y)(R2.x) == R2.e_y
|
| 180 |
+
assert TensorProduct(R2.x, R2.e_x) == R2.x * R2.e_x
|
| 181 |
+
assert TensorProduct(
|
| 182 |
+
R2.dx, R2.e_y)(R2.e_x, R2.y) == R2.dx(R2.e_x) * R2.e_y(R2.y) == 1
|
| 183 |
+
assert TensorProduct(R2.dx, R2.e_y)(None, R2.y) == R2.dx
|
| 184 |
+
assert TensorProduct(R2.dx, R2.e_y)(R2.e_x, None) == R2.e_y
|
| 185 |
+
assert TensorProduct(R2.dx, R2.e_y)(R2.e_x) == R2.e_y
|
| 186 |
+
assert TensorProduct(R2.x, R2.e_x) == R2.x * R2.e_x
|
| 187 |
+
assert TensorProduct(
|
| 188 |
+
R2.e_x, R2.dy)(R2.x, R2.e_y) == R2.e_x(R2.x) * R2.dy(R2.e_y) == 1
|
| 189 |
+
assert TensorProduct(R2.e_x, R2.dy)(None, R2.e_y) == R2.e_x
|
| 190 |
+
assert TensorProduct(R2.e_x, R2.dy)(R2.x, None) == R2.dy
|
| 191 |
+
assert TensorProduct(R2.e_x, R2.dy)(R2.x) == R2.dy
|
| 192 |
+
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
|
| 193 |
+
|
| 194 |
+
assert WedgeProduct(R2.dx, R2.dy)(R2.e_x, R2.e_y) == 1
|
| 195 |
+
assert WedgeProduct(R2.e_x, R2.e_y)(R2.x, R2.y) == 1
|
| 196 |
+
|
| 197 |
+
|
| 198 |
+
def test_lie_derivative():
|
| 199 |
+
assert LieDerivative(R2.e_x, R2.y) == R2.e_x(R2.y) == 0
|
| 200 |
+
assert LieDerivative(R2.e_x, R2.x) == R2.e_x(R2.x) == 1
|
| 201 |
+
assert LieDerivative(R2.e_x, R2.e_x) == Commutator(R2.e_x, R2.e_x) == 0
|
| 202 |
+
assert LieDerivative(R2.e_x, R2.e_r) == Commutator(R2.e_x, R2.e_r)
|
| 203 |
+
assert LieDerivative(R2.e_x + R2.e_y, R2.x) == 1
|
| 204 |
+
assert LieDerivative(
|
| 205 |
+
R2.e_x, TensorProduct(R2.dx, R2.dy))(R2.e_x, R2.e_y) == 0
|
| 206 |
+
|
| 207 |
+
|
| 208 |
+
@nocache_fail
|
| 209 |
+
def test_covar_deriv():
|
| 210 |
+
ch = metric_to_Christoffel_2nd(TP(R2.dx, R2.dx) + TP(R2.dy, R2.dy))
|
| 211 |
+
cvd = BaseCovarDerivativeOp(R2_r, 0, ch)
|
| 212 |
+
assert cvd(R2.x) == 1
|
| 213 |
+
# This line fails if the cache is disabled:
|
| 214 |
+
assert cvd(R2.x*R2.e_x) == R2.e_x
|
| 215 |
+
cvd = CovarDerivativeOp(R2.x*R2.e_x, ch)
|
| 216 |
+
assert cvd(R2.x) == R2.x
|
| 217 |
+
assert cvd(R2.x*R2.e_x) == R2.x*R2.e_x
|
| 218 |
+
|
| 219 |
+
|
| 220 |
+
def test_intcurve_diffequ():
|
| 221 |
+
t = symbols('t')
|
| 222 |
+
start_point = R2_r.point([1, 0])
|
| 223 |
+
vector_field = -R2.y*R2.e_x + R2.x*R2.e_y
|
| 224 |
+
equations, init_cond = intcurve_diffequ(vector_field, t, start_point)
|
| 225 |
+
assert str(equations) == '[f_1(t) + Derivative(f_0(t), t), -f_0(t) + Derivative(f_1(t), t)]'
|
| 226 |
+
assert str(init_cond) == '[f_0(0) - 1, f_1(0)]'
|
| 227 |
+
equations, init_cond = intcurve_diffequ(vector_field, t, start_point, R2_p)
|
| 228 |
+
assert str(
|
| 229 |
+
equations) == '[Derivative(f_0(t), t), Derivative(f_1(t), t) - 1]'
|
| 230 |
+
assert str(init_cond) == '[f_0(0) - 1, f_1(0)]'
|
| 231 |
+
|
| 232 |
+
|
| 233 |
+
def test_helpers_and_coordinate_dependent():
|
| 234 |
+
one_form = R2.dr + R2.dx
|
| 235 |
+
two_form = Differential(R2.x*R2.dr + R2.r*R2.dx)
|
| 236 |
+
three_form = Differential(
|
| 237 |
+
R2.y*two_form) + Differential(R2.x*Differential(R2.r*R2.dr))
|
| 238 |
+
metric = TensorProduct(R2.dx, R2.dx) + TensorProduct(R2.dy, R2.dy)
|
| 239 |
+
metric_ambig = TensorProduct(R2.dx, R2.dx) + TensorProduct(R2.dr, R2.dr)
|
| 240 |
+
misform_a = TensorProduct(R2.dr, R2.dr) + R2.dr
|
| 241 |
+
misform_b = R2.dr**4
|
| 242 |
+
misform_c = R2.dx*R2.dy
|
| 243 |
+
twoform_not_sym = TensorProduct(R2.dx, R2.dx) + TensorProduct(R2.dx, R2.dy)
|
| 244 |
+
twoform_not_TP = WedgeProduct(R2.dx, R2.dy)
|
| 245 |
+
|
| 246 |
+
one_vector = R2.e_x + R2.e_y
|
| 247 |
+
two_vector = TensorProduct(R2.e_x, R2.e_y)
|
| 248 |
+
three_vector = TensorProduct(R2.e_x, R2.e_y, R2.e_x)
|
| 249 |
+
two_wp = WedgeProduct(R2.e_x,R2.e_y)
|
| 250 |
+
|
| 251 |
+
assert covariant_order(one_form) == 1
|
| 252 |
+
assert covariant_order(two_form) == 2
|
| 253 |
+
assert covariant_order(three_form) == 3
|
| 254 |
+
assert covariant_order(two_form + metric) == 2
|
| 255 |
+
assert covariant_order(two_form + metric_ambig) == 2
|
| 256 |
+
assert covariant_order(two_form + twoform_not_sym) == 2
|
| 257 |
+
assert covariant_order(two_form + twoform_not_TP) == 2
|
| 258 |
+
|
| 259 |
+
assert contravariant_order(one_vector) == 1
|
| 260 |
+
assert contravariant_order(two_vector) == 2
|
| 261 |
+
assert contravariant_order(three_vector) == 3
|
| 262 |
+
assert contravariant_order(two_vector + two_wp) == 2
|
| 263 |
+
|
| 264 |
+
raises(ValueError, lambda: covariant_order(misform_a))
|
| 265 |
+
raises(ValueError, lambda: covariant_order(misform_b))
|
| 266 |
+
raises(ValueError, lambda: covariant_order(misform_c))
|
| 267 |
+
|
| 268 |
+
assert twoform_to_matrix(metric) == Matrix([[1, 0], [0, 1]])
|
| 269 |
+
assert twoform_to_matrix(twoform_not_sym) == Matrix([[1, 0], [1, 0]])
|
| 270 |
+
assert twoform_to_matrix(twoform_not_TP) == Matrix([[0, -1], [1, 0]])
|
| 271 |
+
|
| 272 |
+
raises(ValueError, lambda: twoform_to_matrix(one_form))
|
| 273 |
+
raises(ValueError, lambda: twoform_to_matrix(three_form))
|
| 274 |
+
raises(ValueError, lambda: twoform_to_matrix(metric_ambig))
|
| 275 |
+
|
| 276 |
+
raises(ValueError, lambda: metric_to_Christoffel_1st(twoform_not_sym))
|
| 277 |
+
raises(ValueError, lambda: metric_to_Christoffel_2nd(twoform_not_sym))
|
| 278 |
+
raises(ValueError, lambda: metric_to_Riemann_components(twoform_not_sym))
|
| 279 |
+
raises(ValueError, lambda: metric_to_Ricci_components(twoform_not_sym))
|
| 280 |
+
|
| 281 |
+
|
| 282 |
+
def test_correct_arguments():
|
| 283 |
+
raises(ValueError, lambda: R2.e_x(R2.e_x))
|
| 284 |
+
raises(ValueError, lambda: R2.e_x(R2.dx))
|
| 285 |
+
|
| 286 |
+
raises(ValueError, lambda: Commutator(R2.e_x, R2.x))
|
| 287 |
+
raises(ValueError, lambda: Commutator(R2.dx, R2.e_x))
|
| 288 |
+
|
| 289 |
+
raises(ValueError, lambda: Differential(Differential(R2.e_x)))
|
| 290 |
+
|
| 291 |
+
raises(ValueError, lambda: R2.dx(R2.x))
|
| 292 |
+
|
| 293 |
+
raises(ValueError, lambda: LieDerivative(R2.dx, R2.dx))
|
| 294 |
+
raises(ValueError, lambda: LieDerivative(R2.x, R2.dx))
|
| 295 |
+
|
| 296 |
+
raises(ValueError, lambda: CovarDerivativeOp(R2.dx, []))
|
| 297 |
+
raises(ValueError, lambda: CovarDerivativeOp(R2.x, []))
|
| 298 |
+
|
| 299 |
+
a = Symbol('a')
|
| 300 |
+
raises(ValueError, lambda: intcurve_series(R2.dx, a, R2_r.point([1, 2])))
|
| 301 |
+
raises(ValueError, lambda: intcurve_series(R2.x, a, R2_r.point([1, 2])))
|
| 302 |
+
|
| 303 |
+
raises(ValueError, lambda: intcurve_diffequ(R2.dx, a, R2_r.point([1, 2])))
|
| 304 |
+
raises(ValueError, lambda: intcurve_diffequ(R2.x, a, R2_r.point([1, 2])))
|
| 305 |
+
|
| 306 |
+
raises(ValueError, lambda: contravariant_order(R2.e_x + R2.dx))
|
| 307 |
+
raises(ValueError, lambda: covariant_order(R2.e_x + R2.dx))
|
| 308 |
+
|
| 309 |
+
raises(ValueError, lambda: contravariant_order(R2.e_x*R2.e_y))
|
| 310 |
+
raises(ValueError, lambda: covariant_order(R2.dx*R2.dy))
|
| 311 |
+
|
| 312 |
+
def test_simplify():
|
| 313 |
+
x, y = R2_r.coord_functions()
|
| 314 |
+
dx, dy = R2_r.base_oneforms()
|
| 315 |
+
ex, ey = R2_r.base_vectors()
|
| 316 |
+
assert simplify(x) == x
|
| 317 |
+
assert simplify(x*y) == x*y
|
| 318 |
+
assert simplify(dx*dy) == dx*dy
|
| 319 |
+
assert simplify(ex*ey) == ex*ey
|
| 320 |
+
assert ((1-x)*dx)/(1-x)**2 == dx/(1-x)
|
| 321 |
+
|
| 322 |
+
|
| 323 |
+
def test_issue_17917():
|
| 324 |
+
X = R2.x*R2.e_x - R2.y*R2.e_y
|
| 325 |
+
Y = (R2.x**2 + R2.y**2)*R2.e_x - R2.x*R2.y*R2.e_y
|
| 326 |
+
assert LieDerivative(X, Y).expand() == (
|
| 327 |
+
R2.x**2*R2.e_x - 3*R2.y**2*R2.e_x - R2.x*R2.y*R2.e_y)
|
| 328 |
+
|
| 329 |
+
def test_deprecations():
|
| 330 |
+
m = Manifold('M', 2)
|
| 331 |
+
p = Patch('P', m)
|
| 332 |
+
with warns_deprecated_sympy():
|
| 333 |
+
CoordSystem('Car2d', p, names=['x', 'y'])
|
| 334 |
+
|
| 335 |
+
with warns_deprecated_sympy():
|
| 336 |
+
c = CoordSystem('Car2d', p, ['x', 'y'])
|
| 337 |
+
|
| 338 |
+
with warns_deprecated_sympy():
|
| 339 |
+
list(m.patches)
|
| 340 |
+
|
| 341 |
+
with warns_deprecated_sympy():
|
| 342 |
+
list(c.transforms)
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/diffgeom/tests/test_function_diffgeom_book.py
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sympy.diffgeom.rn import R2, R2_p, R2_r, R3_r
|
| 2 |
+
from sympy.diffgeom import intcurve_series, Differential, WedgeProduct
|
| 3 |
+
from sympy.core import symbols, Function, Derivative
|
| 4 |
+
from sympy.simplify import trigsimp, simplify
|
| 5 |
+
from sympy.functions import sqrt, atan2, sin, cos
|
| 6 |
+
from sympy.matrices import Matrix
|
| 7 |
+
|
| 8 |
+
# Most of the functionality is covered in the
|
| 9 |
+
# test_functional_diffgeom_ch* tests which are based on the
|
| 10 |
+
# example from the paper of Sussman and Wisdom.
|
| 11 |
+
# If they do not cover something, additional tests are added in other test
|
| 12 |
+
# functions.
|
| 13 |
+
|
| 14 |
+
# From "Functional Differential Geometry" as of 2011
|
| 15 |
+
# by Sussman and Wisdom.
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
def test_functional_diffgeom_ch2():
|
| 19 |
+
x0, y0, r0, theta0 = symbols('x0, y0, r0, theta0', real=True)
|
| 20 |
+
x, y = symbols('x, y', real=True)
|
| 21 |
+
f = Function('f')
|
| 22 |
+
|
| 23 |
+
assert (R2_p.point_to_coords(R2_r.point([x0, y0])) ==
|
| 24 |
+
Matrix([sqrt(x0**2 + y0**2), atan2(y0, x0)]))
|
| 25 |
+
assert (R2_r.point_to_coords(R2_p.point([r0, theta0])) ==
|
| 26 |
+
Matrix([r0*cos(theta0), r0*sin(theta0)]))
|
| 27 |
+
|
| 28 |
+
assert R2_p.jacobian(R2_r, [r0, theta0]) == Matrix(
|
| 29 |
+
[[cos(theta0), -r0*sin(theta0)], [sin(theta0), r0*cos(theta0)]])
|
| 30 |
+
|
| 31 |
+
field = f(R2.x, R2.y)
|
| 32 |
+
p1_in_rect = R2_r.point([x0, y0])
|
| 33 |
+
p1_in_polar = R2_p.point([sqrt(x0**2 + y0**2), atan2(y0, x0)])
|
| 34 |
+
assert field.rcall(p1_in_rect) == f(x0, y0)
|
| 35 |
+
assert field.rcall(p1_in_polar) == f(x0, y0)
|
| 36 |
+
|
| 37 |
+
p_r = R2_r.point([x0, y0])
|
| 38 |
+
p_p = R2_p.point([r0, theta0])
|
| 39 |
+
assert R2.x(p_r) == x0
|
| 40 |
+
assert R2.x(p_p) == r0*cos(theta0)
|
| 41 |
+
assert R2.r(p_p) == r0
|
| 42 |
+
assert R2.r(p_r) == sqrt(x0**2 + y0**2)
|
| 43 |
+
assert R2.theta(p_r) == atan2(y0, x0)
|
| 44 |
+
|
| 45 |
+
h = R2.x*R2.r**2 + R2.y**3
|
| 46 |
+
assert h.rcall(p_r) == x0*(x0**2 + y0**2) + y0**3
|
| 47 |
+
assert h.rcall(p_p) == r0**3*sin(theta0)**3 + r0**3*cos(theta0)
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
def test_functional_diffgeom_ch3():
|
| 51 |
+
x0, y0 = symbols('x0, y0', real=True)
|
| 52 |
+
x, y, t = symbols('x, y, t', real=True)
|
| 53 |
+
f = Function('f')
|
| 54 |
+
b1 = Function('b1')
|
| 55 |
+
b2 = Function('b2')
|
| 56 |
+
p_r = R2_r.point([x0, y0])
|
| 57 |
+
|
| 58 |
+
s_field = f(R2.x, R2.y)
|
| 59 |
+
v_field = b1(R2.x)*R2.e_x + b2(R2.y)*R2.e_y
|
| 60 |
+
assert v_field.rcall(s_field).rcall(p_r).doit() == b1(
|
| 61 |
+
x0)*Derivative(f(x0, y0), x0) + b2(y0)*Derivative(f(x0, y0), y0)
|
| 62 |
+
|
| 63 |
+
assert R2.e_x(R2.r**2).rcall(p_r) == 2*x0
|
| 64 |
+
v = R2.e_x + 2*R2.e_y
|
| 65 |
+
s = R2.r**2 + 3*R2.x
|
| 66 |
+
assert v.rcall(s).rcall(p_r).doit() == 2*x0 + 4*y0 + 3
|
| 67 |
+
|
| 68 |
+
circ = -R2.y*R2.e_x + R2.x*R2.e_y
|
| 69 |
+
series = intcurve_series(circ, t, R2_r.point([1, 0]), coeffs=True)
|
| 70 |
+
series_x, series_y = zip(*series)
|
| 71 |
+
assert all(
|
| 72 |
+
term == cos(t).taylor_term(i, t) for i, term in enumerate(series_x))
|
| 73 |
+
assert all(
|
| 74 |
+
term == sin(t).taylor_term(i, t) for i, term in enumerate(series_y))
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
def test_functional_diffgeom_ch4():
|
| 78 |
+
x0, y0, theta0 = symbols('x0, y0, theta0', real=True)
|
| 79 |
+
x, y, r, theta = symbols('x, y, r, theta', real=True)
|
| 80 |
+
r0 = symbols('r0', positive=True)
|
| 81 |
+
f = Function('f')
|
| 82 |
+
b1 = Function('b1')
|
| 83 |
+
b2 = Function('b2')
|
| 84 |
+
p_r = R2_r.point([x0, y0])
|
| 85 |
+
p_p = R2_p.point([r0, theta0])
|
| 86 |
+
|
| 87 |
+
f_field = b1(R2.x, R2.y)*R2.dx + b2(R2.x, R2.y)*R2.dy
|
| 88 |
+
assert f_field.rcall(R2.e_x).rcall(p_r) == b1(x0, y0)
|
| 89 |
+
assert f_field.rcall(R2.e_y).rcall(p_r) == b2(x0, y0)
|
| 90 |
+
|
| 91 |
+
s_field_r = f(R2.x, R2.y)
|
| 92 |
+
df = Differential(s_field_r)
|
| 93 |
+
assert df(R2.e_x).rcall(p_r).doit() == Derivative(f(x0, y0), x0)
|
| 94 |
+
assert df(R2.e_y).rcall(p_r).doit() == Derivative(f(x0, y0), y0)
|
| 95 |
+
|
| 96 |
+
s_field_p = f(R2.r, R2.theta)
|
| 97 |
+
df = Differential(s_field_p)
|
| 98 |
+
assert trigsimp(df(R2.e_x).rcall(p_p).doit()) == (
|
| 99 |
+
cos(theta0)*Derivative(f(r0, theta0), r0) -
|
| 100 |
+
sin(theta0)*Derivative(f(r0, theta0), theta0)/r0)
|
| 101 |
+
assert trigsimp(df(R2.e_y).rcall(p_p).doit()) == (
|
| 102 |
+
sin(theta0)*Derivative(f(r0, theta0), r0) +
|
| 103 |
+
cos(theta0)*Derivative(f(r0, theta0), theta0)/r0)
|
| 104 |
+
|
| 105 |
+
assert R2.dx(R2.e_x).rcall(p_r) == 1
|
| 106 |
+
assert R2.dx(R2.e_x) == 1
|
| 107 |
+
assert R2.dx(R2.e_y).rcall(p_r) == 0
|
| 108 |
+
assert R2.dx(R2.e_y) == 0
|
| 109 |
+
|
| 110 |
+
circ = -R2.y*R2.e_x + R2.x*R2.e_y
|
| 111 |
+
assert R2.dx(circ).rcall(p_r).doit() == -y0
|
| 112 |
+
assert R2.dy(circ).rcall(p_r) == x0
|
| 113 |
+
assert R2.dr(circ).rcall(p_r) == 0
|
| 114 |
+
assert simplify(R2.dtheta(circ).rcall(p_r)) == 1
|
| 115 |
+
|
| 116 |
+
assert (circ - R2.e_theta).rcall(s_field_r).rcall(p_r) == 0
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
def test_functional_diffgeom_ch6():
|
| 120 |
+
u0, u1, u2, v0, v1, v2, w0, w1, w2 = symbols('u0:3, v0:3, w0:3', real=True)
|
| 121 |
+
|
| 122 |
+
u = u0*R2.e_x + u1*R2.e_y
|
| 123 |
+
v = v0*R2.e_x + v1*R2.e_y
|
| 124 |
+
wp = WedgeProduct(R2.dx, R2.dy)
|
| 125 |
+
assert wp(u, v) == u0*v1 - u1*v0
|
| 126 |
+
|
| 127 |
+
u = u0*R3_r.e_x + u1*R3_r.e_y + u2*R3_r.e_z
|
| 128 |
+
v = v0*R3_r.e_x + v1*R3_r.e_y + v2*R3_r.e_z
|
| 129 |
+
w = w0*R3_r.e_x + w1*R3_r.e_y + w2*R3_r.e_z
|
| 130 |
+
wp = WedgeProduct(R3_r.dx, R3_r.dy, R3_r.dz)
|
| 131 |
+
assert wp(
|
| 132 |
+
u, v, w) == Matrix(3, 3, [u0, u1, u2, v0, v1, v2, w0, w1, w2]).det()
|
| 133 |
+
|
| 134 |
+
a, b, c = symbols('a, b, c', cls=Function)
|
| 135 |
+
a_f = a(R3_r.x, R3_r.y, R3_r.z)
|
| 136 |
+
b_f = b(R3_r.x, R3_r.y, R3_r.z)
|
| 137 |
+
c_f = c(R3_r.x, R3_r.y, R3_r.z)
|
| 138 |
+
theta = a_f*R3_r.dx + b_f*R3_r.dy + c_f*R3_r.dz
|
| 139 |
+
dtheta = Differential(theta)
|
| 140 |
+
da = Differential(a_f)
|
| 141 |
+
db = Differential(b_f)
|
| 142 |
+
dc = Differential(c_f)
|
| 143 |
+
expr = dtheta - WedgeProduct(
|
| 144 |
+
da, R3_r.dx) - WedgeProduct(db, R3_r.dy) - WedgeProduct(dc, R3_r.dz)
|
| 145 |
+
assert expr.rcall(R3_r.e_x, R3_r.e_y) == 0
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/diffgeom/tests/test_hyperbolic_space.py
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
r'''
|
| 2 |
+
unit test describing the hyperbolic half-plane with the Poincare metric. This
|
| 3 |
+
is a basic model of hyperbolic geometry on the (positive) half-space
|
| 4 |
+
|
| 5 |
+
{(x,y) \in R^2 | y > 0}
|
| 6 |
+
|
| 7 |
+
with the Riemannian metric
|
| 8 |
+
|
| 9 |
+
ds^2 = (dx^2 + dy^2)/y^2
|
| 10 |
+
|
| 11 |
+
It has constant negative scalar curvature = -2
|
| 12 |
+
|
| 13 |
+
https://en.wikipedia.org/wiki/Poincare_half-plane_model
|
| 14 |
+
'''
|
| 15 |
+
from sympy.matrices.dense import diag
|
| 16 |
+
from sympy.diffgeom import (twoform_to_matrix,
|
| 17 |
+
metric_to_Christoffel_1st, metric_to_Christoffel_2nd,
|
| 18 |
+
metric_to_Riemann_components, metric_to_Ricci_components)
|
| 19 |
+
import sympy.diffgeom.rn
|
| 20 |
+
from sympy.tensor.array import ImmutableDenseNDimArray
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
def test_H2():
|
| 24 |
+
TP = sympy.diffgeom.TensorProduct
|
| 25 |
+
R2 = sympy.diffgeom.rn.R2
|
| 26 |
+
y = R2.y
|
| 27 |
+
dy = R2.dy
|
| 28 |
+
dx = R2.dx
|
| 29 |
+
g = (TP(dx, dx) + TP(dy, dy))*y**(-2)
|
| 30 |
+
automat = twoform_to_matrix(g)
|
| 31 |
+
mat = diag(y**(-2), y**(-2))
|
| 32 |
+
assert mat == automat
|
| 33 |
+
|
| 34 |
+
gamma1 = metric_to_Christoffel_1st(g)
|
| 35 |
+
assert gamma1[0, 0, 0] == 0
|
| 36 |
+
assert gamma1[0, 0, 1] == -y**(-3)
|
| 37 |
+
assert gamma1[0, 1, 0] == -y**(-3)
|
| 38 |
+
assert gamma1[0, 1, 1] == 0
|
| 39 |
+
|
| 40 |
+
assert gamma1[1, 1, 1] == -y**(-3)
|
| 41 |
+
assert gamma1[1, 1, 0] == 0
|
| 42 |
+
assert gamma1[1, 0, 1] == 0
|
| 43 |
+
assert gamma1[1, 0, 0] == y**(-3)
|
| 44 |
+
|
| 45 |
+
gamma2 = metric_to_Christoffel_2nd(g)
|
| 46 |
+
assert gamma2[0, 0, 0] == 0
|
| 47 |
+
assert gamma2[0, 0, 1] == -y**(-1)
|
| 48 |
+
assert gamma2[0, 1, 0] == -y**(-1)
|
| 49 |
+
assert gamma2[0, 1, 1] == 0
|
| 50 |
+
|
| 51 |
+
assert gamma2[1, 1, 1] == -y**(-1)
|
| 52 |
+
assert gamma2[1, 1, 0] == 0
|
| 53 |
+
assert gamma2[1, 0, 1] == 0
|
| 54 |
+
assert gamma2[1, 0, 0] == y**(-1)
|
| 55 |
+
|
| 56 |
+
Rm = metric_to_Riemann_components(g)
|
| 57 |
+
assert Rm[0, 0, 0, 0] == 0
|
| 58 |
+
assert Rm[0, 0, 0, 1] == 0
|
| 59 |
+
assert Rm[0, 0, 1, 0] == 0
|
| 60 |
+
assert Rm[0, 0, 1, 1] == 0
|
| 61 |
+
|
| 62 |
+
assert Rm[0, 1, 0, 0] == 0
|
| 63 |
+
assert Rm[0, 1, 0, 1] == -y**(-2)
|
| 64 |
+
assert Rm[0, 1, 1, 0] == y**(-2)
|
| 65 |
+
assert Rm[0, 1, 1, 1] == 0
|
| 66 |
+
|
| 67 |
+
assert Rm[1, 0, 0, 0] == 0
|
| 68 |
+
assert Rm[1, 0, 0, 1] == y**(-2)
|
| 69 |
+
assert Rm[1, 0, 1, 0] == -y**(-2)
|
| 70 |
+
assert Rm[1, 0, 1, 1] == 0
|
| 71 |
+
|
| 72 |
+
assert Rm[1, 1, 0, 0] == 0
|
| 73 |
+
assert Rm[1, 1, 0, 1] == 0
|
| 74 |
+
assert Rm[1, 1, 1, 0] == 0
|
| 75 |
+
assert Rm[1, 1, 1, 1] == 0
|
| 76 |
+
|
| 77 |
+
Ric = metric_to_Ricci_components(g)
|
| 78 |
+
assert Ric[0, 0] == -y**(-2)
|
| 79 |
+
assert Ric[0, 1] == 0
|
| 80 |
+
assert Ric[1, 0] == 0
|
| 81 |
+
assert Ric[0, 0] == -y**(-2)
|
| 82 |
+
|
| 83 |
+
assert Ric == ImmutableDenseNDimArray([-y**(-2), 0, 0, -y**(-2)], (2, 2))
|
| 84 |
+
|
| 85 |
+
## scalar curvature is -2
|
| 86 |
+
#TODO - it would be nice to have index contraction built-in
|
| 87 |
+
R = (Ric[0, 0] + Ric[1, 1])*y**2
|
| 88 |
+
assert R == -2
|
| 89 |
+
|
| 90 |
+
## Gauss curvature is -1
|
| 91 |
+
assert R/2 == -1
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/__init__.cpython-312.pyc
ADDED
|
Binary file (1.92 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/basisdependent.cpython-312.pyc
ADDED
|
Binary file (17.7 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/coordsysrect.cpython-312.pyc
ADDED
|
Binary file (40.8 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/deloperator.cpython-312.pyc
ADDED
|
Binary file (4.09 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/dyadic.cpython-312.pyc
ADDED
|
Binary file (12.8 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/functions.cpython-312.pyc
ADDED
|
Binary file (17.8 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/implicitregion.cpython-312.pyc
ADDED
|
Binary file (20.7 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/integrals.cpython-312.pyc
ADDED
|
Binary file (8.95 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/kind.cpython-312.pyc
ADDED
|
Binary file (2.66 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/operators.cpython-312.pyc
ADDED
|
Binary file (15 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/orienters.cpython-312.pyc
ADDED
|
Binary file (15.4 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/parametricregion.cpython-312.pyc
ADDED
|
Binary file (8.55 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/point.cpython-312.pyc
ADDED
|
Binary file (5.38 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/scalar.cpython-312.pyc
ADDED
|
Binary file (3.32 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/__pycache__/vector.cpython-312.pyc
ADDED
|
Binary file (28.7 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/tests/__init__.py
ADDED
|
File without changes
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/__init__.cpython-312.pyc
ADDED
|
Binary file (210 Bytes). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_coordsysrect.cpython-312.pyc
ADDED
|
Binary file (52.6 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_dyadic.cpython-312.pyc
ADDED
|
Binary file (12.2 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_field_functions.cpython-312.pyc
ADDED
|
Binary file (40.2 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_functions.cpython-312.pyc
ADDED
|
Binary file (30.1 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_implicitregion.cpython-312.pyc
ADDED
|
Binary file (10.5 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_integrals.cpython-312.pyc
ADDED
|
Binary file (13.2 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_operators.cpython-312.pyc
ADDED
|
Binary file (6.18 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_parametricregion.cpython-312.pyc
ADDED
|
Binary file (9.04 kB). View file
|
|
|
URSA/.venv_ursa/lib/python3.12/site-packages/sympy/vector/tests/__pycache__/test_printing.cpython-312.pyc
ADDED
|
Binary file (12 kB). View file
|
|
|