I am done

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

View File

@ -0,0 +1,25 @@
from sympy.core.singleton import S
from sympy.core.symbol import symbols
from sympy.parsing.ast_parser import parse_expr
from sympy.testing.pytest import raises
from sympy.core.sympify import SympifyError
import warnings
def test_parse_expr():
a, b = symbols('a, b')
# tests issue_16393
assert parse_expr('a + b', {}) == a + b
raises(SympifyError, lambda: parse_expr('a + ', {}))
# tests Transform.visit_Constant
assert parse_expr('1 + 2', {}) == S(3)
assert parse_expr('1 + 2.0', {}) == S(3.0)
# tests Transform.visit_Name
assert parse_expr('Rational(1, 2)', {}) == S(1)/2
assert parse_expr('a', {'a': a}) == a
# tests issue_23092
with warnings.catch_warnings():
warnings.simplefilter('error')
assert parse_expr('6 * 7', {}) == S(42)

View File

@ -0,0 +1,178 @@
import os
from sympy.functions.elementary.trigonometric import (cos, sin)
from sympy.external import import_module
from sympy.testing.pytest import skip
from sympy.parsing.autolev import parse_autolev
antlr4 = import_module("antlr4")
if not antlr4:
disabled = True
FILE_DIR = os.path.dirname(
os.path.dirname(os.path.abspath(os.path.realpath(__file__))))
def _test_examples(in_filename, out_filename, test_name=""):
in_file_path = os.path.join(FILE_DIR, 'autolev', 'test-examples',
in_filename)
correct_file_path = os.path.join(FILE_DIR, 'autolev', 'test-examples',
out_filename)
with open(in_file_path) as f:
generated_code = parse_autolev(f, include_numeric=True)
with open(correct_file_path) as f:
for idx, line1 in enumerate(f):
if line1.startswith("#"):
break
try:
line2 = generated_code.split('\n')[idx]
assert line1.rstrip() == line2.rstrip()
except Exception:
msg = 'mismatch in ' + test_name + ' in line no: {0}'
raise AssertionError(msg.format(idx+1))
def test_rule_tests():
l = ["ruletest1", "ruletest2", "ruletest3", "ruletest4", "ruletest5",
"ruletest6", "ruletest7", "ruletest8", "ruletest9", "ruletest10",
"ruletest11", "ruletest12"]
for i in l:
in_filepath = i + ".al"
out_filepath = i + ".py"
_test_examples(in_filepath, out_filepath, i)
def test_pydy_examples():
l = ["mass_spring_damper", "chaos_pendulum", "double_pendulum",
"non_min_pendulum"]
for i in l:
in_filepath = os.path.join("pydy-example-repo", i + ".al")
out_filepath = os.path.join("pydy-example-repo", i + ".py")
_test_examples(in_filepath, out_filepath, i)
def test_autolev_tutorial():
dir_path = os.path.join(FILE_DIR, 'autolev', 'test-examples',
'autolev-tutorial')
if os.path.isdir(dir_path):
l = ["tutor1", "tutor2", "tutor3", "tutor4", "tutor5", "tutor6",
"tutor7"]
for i in l:
in_filepath = os.path.join("autolev-tutorial", i + ".al")
out_filepath = os.path.join("autolev-tutorial", i + ".py")
_test_examples(in_filepath, out_filepath, i)
def test_dynamics_online():
dir_path = os.path.join(FILE_DIR, 'autolev', 'test-examples',
'dynamics-online')
if os.path.isdir(dir_path):
ch1 = ["1-4", "1-5", "1-6", "1-7", "1-8", "1-9_1", "1-9_2", "1-9_3"]
ch2 = ["2-1", "2-2", "2-3", "2-4", "2-5", "2-6", "2-7", "2-8", "2-9",
"circular"]
ch3 = ["3-1_1", "3-1_2", "3-2_1", "3-2_2", "3-2_3", "3-2_4", "3-2_5",
"3-3"]
ch4 = ["4-1_1", "4-2_1", "4-4_1", "4-4_2", "4-5_1", "4-5_2"]
chapters = [(ch1, "ch1"), (ch2, "ch2"), (ch3, "ch3"), (ch4, "ch4")]
for ch, name in chapters:
for i in ch:
in_filepath = os.path.join("dynamics-online", name, i + ".al")
out_filepath = os.path.join("dynamics-online", name, i + ".py")
_test_examples(in_filepath, out_filepath, i)
def test_output_01():
"""Autolev example calculates the position, velocity, and acceleration of a
point and expresses in a single reference frame::
(1) FRAMES C,D,F
(2) VARIABLES FD'',DC''
(3) CONSTANTS R,L
(4) POINTS O,E
(5) SIMPROT(F,D,1,FD)
-> (6) F_D = [1, 0, 0; 0, COS(FD), -SIN(FD); 0, SIN(FD), COS(FD)]
(7) SIMPROT(D,C,2,DC)
-> (8) D_C = [COS(DC), 0, SIN(DC); 0, 1, 0; -SIN(DC), 0, COS(DC)]
(9) W_C_F> = EXPRESS(W_C_F>, F)
-> (10) W_C_F> = FD'*F1> + COS(FD)*DC'*F2> + SIN(FD)*DC'*F3>
(11) P_O_E>=R*D2>-L*C1>
(12) P_O_E>=EXPRESS(P_O_E>, D)
-> (13) P_O_E> = -L*COS(DC)*D1> + R*D2> + L*SIN(DC)*D3>
(14) V_E_F>=EXPRESS(DT(P_O_E>,F),D)
-> (15) V_E_F> = L*SIN(DC)*DC'*D1> - L*SIN(DC)*FD'*D2> + (R*FD'+L*COS(DC)*DC')*D3>
(16) A_E_F>=EXPRESS(DT(V_E_F>,F),D)
-> (17) A_E_F> = L*(COS(DC)*DC'^2+SIN(DC)*DC'')*D1> + (-R*FD'^2-2*L*COS(DC)*DC'*FD'-L*SIN(DC)*FD'')*D2> + (R*FD''+L*COS(DC)*DC''-L*SIN(DC)*DC'^2-L*SIN(DC)*FD'^2)*D3>
"""
if not antlr4:
skip('Test skipped: antlr4 is not installed.')
autolev_input = """\
FRAMES C,D,F
VARIABLES FD'',DC''
CONSTANTS R,L
POINTS O,E
SIMPROT(F,D,1,FD)
SIMPROT(D,C,2,DC)
W_C_F>=EXPRESS(W_C_F>,F)
P_O_E>=R*D2>-L*C1>
P_O_E>=EXPRESS(P_O_E>,D)
V_E_F>=EXPRESS(DT(P_O_E>,F),D)
A_E_F>=EXPRESS(DT(V_E_F>,F),D)\
"""
sympy_input = parse_autolev(autolev_input)
g = {}
l = {}
exec(sympy_input, g, l)
w_c_f = l['frame_c'].ang_vel_in(l['frame_f'])
# P_O_E> means "the position of point E wrt to point O"
p_o_e = l['point_e'].pos_from(l['point_o'])
v_e_f = l['point_e'].vel(l['frame_f'])
a_e_f = l['point_e'].acc(l['frame_f'])
# NOTE : The Autolev outputs above were manually transformed into
# equivalent SymPy physics vector expressions. Would be nice to automate
# this transformation.
expected_w_c_f = (l['fd'].diff()*l['frame_f'].x +
cos(l['fd'])*l['dc'].diff()*l['frame_f'].y +
sin(l['fd'])*l['dc'].diff()*l['frame_f'].z)
assert (w_c_f - expected_w_c_f).simplify() == 0
expected_p_o_e = (-l['l']*cos(l['dc'])*l['frame_d'].x +
l['r']*l['frame_d'].y +
l['l']*sin(l['dc'])*l['frame_d'].z)
assert (p_o_e - expected_p_o_e).simplify() == 0
expected_v_e_f = (l['l']*sin(l['dc'])*l['dc'].diff()*l['frame_d'].x -
l['l']*sin(l['dc'])*l['fd'].diff()*l['frame_d'].y +
(l['r']*l['fd'].diff() +
l['l']*cos(l['dc'])*l['dc'].diff())*l['frame_d'].z)
assert (v_e_f - expected_v_e_f).simplify() == 0
expected_a_e_f = (l['l']*(cos(l['dc'])*l['dc'].diff()**2 +
sin(l['dc'])*l['dc'].diff().diff())*l['frame_d'].x +
(-l['r']*l['fd'].diff()**2 -
2*l['l']*cos(l['dc'])*l['dc'].diff()*l['fd'].diff() -
l['l']*sin(l['dc'])*l['fd'].diff().diff())*l['frame_d'].y +
(l['r']*l['fd'].diff().diff() +
l['l']*cos(l['dc'])*l['dc'].diff().diff() -
l['l']*sin(l['dc'])*l['dc'].diff()**2 -
l['l']*sin(l['dc'])*l['fd'].diff()**2)*l['frame_d'].z)
assert (a_e_f - expected_a_e_f).simplify() == 0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,69 @@
import os
import tempfile
import sympy
from sympy.testing.pytest import raises
from sympy.parsing.latex.lark import LarkLaTeXParser, TransformToSymPyExpr, parse_latex_lark
from sympy.external import import_module
lark = import_module("lark")
# disable tests if lark is not present
disabled = lark is None
grammar_file = os.path.join(os.path.dirname(__file__), "../latex/lark/grammar/latex.lark")
modification1 = """
%override DIV_SYMBOL: DIV
%override MUL_SYMBOL: MUL | CMD_TIMES
"""
modification2 = r"""
%override number: /\d+(,\d*)?/
"""
def init_custom_parser(modification, transformer=None):
with open(grammar_file, encoding="utf-8") as f:
latex_grammar = f.read()
latex_grammar += modification
with tempfile.NamedTemporaryFile() as f:
f.write(bytes(latex_grammar, encoding="utf8"))
parser = LarkLaTeXParser(grammar_file=f.name, transformer=transformer)
return parser
def test_custom1():
# Removes the parser's ability to understand \cdot and \div.
parser = init_custom_parser(modification1)
with raises(lark.exceptions.UnexpectedCharacters):
parser.doparse(r"a \cdot b")
parser.doparse(r"x \div y")
class CustomTransformer(TransformToSymPyExpr):
def number(self, tokens):
if "," in tokens[0]:
# The Float constructor expects a dot as the decimal separator
return sympy.core.numbers.Float(tokens[0].replace(",", "."))
else:
return sympy.core.numbers.Integer(tokens[0])
def test_custom2():
# Makes the parser parse commas as the decimal separator instead of dots
parser = init_custom_parser(modification2, CustomTransformer)
with raises(lark.exceptions.UnexpectedCharacters):
# Asserting that the default parser cannot parse numbers which have commas as
# the decimal separator
parse_latex_lark("100,1")
parse_latex_lark("0,009")
parser.doparse("100,1")
parser.doparse("0,009")
parser.doparse("2,71828")
parser.doparse("3,14159")

View File

@ -0,0 +1,406 @@
from sympy.testing.pytest import raises
from sympy.parsing.sym_expr import SymPyExpression
from sympy.external import import_module
lfortran = import_module('lfortran')
if lfortran:
from sympy.codegen.ast import (Variable, IntBaseType, FloatBaseType, String,
Return, FunctionDefinition, Assignment,
Declaration, CodeBlock)
from sympy.core import Integer, Float, Add
from sympy.core.symbol import Symbol
expr1 = SymPyExpression()
expr2 = SymPyExpression()
src = """\
integer :: a, b, c, d
real :: p, q, r, s
"""
def test_sym_expr():
src1 = (
src +
"""\
d = a + b -c
"""
)
expr3 = SymPyExpression(src,'f')
expr4 = SymPyExpression(src1,'f')
ls1 = expr3.return_expr()
ls2 = expr4.return_expr()
for i in range(0, 7):
assert isinstance(ls1[i], Declaration)
assert isinstance(ls2[i], Declaration)
assert isinstance(ls2[8], Assignment)
assert ls1[0] == Declaration(
Variable(
Symbol('a'),
type = IntBaseType(String('integer')),
value = Integer(0)
)
)
assert ls1[1] == Declaration(
Variable(
Symbol('b'),
type = IntBaseType(String('integer')),
value = Integer(0)
)
)
assert ls1[2] == Declaration(
Variable(
Symbol('c'),
type = IntBaseType(String('integer')),
value = Integer(0)
)
)
assert ls1[3] == Declaration(
Variable(
Symbol('d'),
type = IntBaseType(String('integer')),
value = Integer(0)
)
)
assert ls1[4] == Declaration(
Variable(
Symbol('p'),
type = FloatBaseType(String('real')),
value = Float(0.0)
)
)
assert ls1[5] == Declaration(
Variable(
Symbol('q'),
type = FloatBaseType(String('real')),
value = Float(0.0)
)
)
assert ls1[6] == Declaration(
Variable(
Symbol('r'),
type = FloatBaseType(String('real')),
value = Float(0.0)
)
)
assert ls1[7] == Declaration(
Variable(
Symbol('s'),
type = FloatBaseType(String('real')),
value = Float(0.0)
)
)
assert ls2[8] == Assignment(
Variable(Symbol('d')),
Symbol('a') + Symbol('b') - Symbol('c')
)
def test_assignment():
src1 = (
src +
"""\
a = b
c = d
p = q
r = s
"""
)
expr1.convert_to_expr(src1, 'f')
ls1 = expr1.return_expr()
for iter in range(0, 12):
if iter < 8:
assert isinstance(ls1[iter], Declaration)
else:
assert isinstance(ls1[iter], Assignment)
assert ls1[8] == Assignment(
Variable(Symbol('a')),
Variable(Symbol('b'))
)
assert ls1[9] == Assignment(
Variable(Symbol('c')),
Variable(Symbol('d'))
)
assert ls1[10] == Assignment(
Variable(Symbol('p')),
Variable(Symbol('q'))
)
assert ls1[11] == Assignment(
Variable(Symbol('r')),
Variable(Symbol('s'))
)
def test_binop_add():
src1 = (
src +
"""\
c = a + b
d = a + c
s = p + q + r
"""
)
expr1.convert_to_expr(src1, 'f')
ls1 = expr1.return_expr()
for iter in range(8, 11):
assert isinstance(ls1[iter], Assignment)
assert ls1[8] == Assignment(
Variable(Symbol('c')),
Symbol('a') + Symbol('b')
)
assert ls1[9] == Assignment(
Variable(Symbol('d')),
Symbol('a') + Symbol('c')
)
assert ls1[10] == Assignment(
Variable(Symbol('s')),
Symbol('p') + Symbol('q') + Symbol('r')
)
def test_binop_sub():
src1 = (
src +
"""\
c = a - b
d = a - c
s = p - q - r
"""
)
expr1.convert_to_expr(src1, 'f')
ls1 = expr1.return_expr()
for iter in range(8, 11):
assert isinstance(ls1[iter], Assignment)
assert ls1[8] == Assignment(
Variable(Symbol('c')),
Symbol('a') - Symbol('b')
)
assert ls1[9] == Assignment(
Variable(Symbol('d')),
Symbol('a') - Symbol('c')
)
assert ls1[10] == Assignment(
Variable(Symbol('s')),
Symbol('p') - Symbol('q') - Symbol('r')
)
def test_binop_mul():
src1 = (
src +
"""\
c = a * b
d = a * c
s = p * q * r
"""
)
expr1.convert_to_expr(src1, 'f')
ls1 = expr1.return_expr()
for iter in range(8, 11):
assert isinstance(ls1[iter], Assignment)
assert ls1[8] == Assignment(
Variable(Symbol('c')),
Symbol('a') * Symbol('b')
)
assert ls1[9] == Assignment(
Variable(Symbol('d')),
Symbol('a') * Symbol('c')
)
assert ls1[10] == Assignment(
Variable(Symbol('s')),
Symbol('p') * Symbol('q') * Symbol('r')
)
def test_binop_div():
src1 = (
src +
"""\
c = a / b
d = a / c
s = p / q
r = q / p
"""
)
expr1.convert_to_expr(src1, 'f')
ls1 = expr1.return_expr()
for iter in range(8, 12):
assert isinstance(ls1[iter], Assignment)
assert ls1[8] == Assignment(
Variable(Symbol('c')),
Symbol('a') / Symbol('b')
)
assert ls1[9] == Assignment(
Variable(Symbol('d')),
Symbol('a') / Symbol('c')
)
assert ls1[10] == Assignment(
Variable(Symbol('s')),
Symbol('p') / Symbol('q')
)
assert ls1[11] == Assignment(
Variable(Symbol('r')),
Symbol('q') / Symbol('p')
)
def test_mul_binop():
src1 = (
src +
"""\
d = a + b - c
c = a * b + d
s = p * q / r
r = p * s + q / p
"""
)
expr1.convert_to_expr(src1, 'f')
ls1 = expr1.return_expr()
for iter in range(8, 12):
assert isinstance(ls1[iter], Assignment)
assert ls1[8] == Assignment(
Variable(Symbol('d')),
Symbol('a') + Symbol('b') - Symbol('c')
)
assert ls1[9] == Assignment(
Variable(Symbol('c')),
Symbol('a') * Symbol('b') + Symbol('d')
)
assert ls1[10] == Assignment(
Variable(Symbol('s')),
Symbol('p') * Symbol('q') / Symbol('r')
)
assert ls1[11] == Assignment(
Variable(Symbol('r')),
Symbol('p') * Symbol('s') + Symbol('q') / Symbol('p')
)
def test_function():
src1 = """\
integer function f(a,b)
integer :: x, y
f = x + y
end function
"""
expr1.convert_to_expr(src1, 'f')
for iter in expr1.return_expr():
assert isinstance(iter, FunctionDefinition)
assert iter == FunctionDefinition(
IntBaseType(String('integer')),
name=String('f'),
parameters=(
Variable(Symbol('a')),
Variable(Symbol('b'))
),
body=CodeBlock(
Declaration(
Variable(
Symbol('a'),
type=IntBaseType(String('integer')),
value=Integer(0)
)
),
Declaration(
Variable(
Symbol('b'),
type=IntBaseType(String('integer')),
value=Integer(0)
)
),
Declaration(
Variable(
Symbol('f'),
type=IntBaseType(String('integer')),
value=Integer(0)
)
),
Declaration(
Variable(
Symbol('x'),
type=IntBaseType(String('integer')),
value=Integer(0)
)
),
Declaration(
Variable(
Symbol('y'),
type=IntBaseType(String('integer')),
value=Integer(0)
)
),
Assignment(
Variable(Symbol('f')),
Add(Symbol('x'), Symbol('y'))
),
Return(Variable(Symbol('f')))
)
)
def test_var():
expr1.convert_to_expr(src, 'f')
ls = expr1.return_expr()
for iter in expr1.return_expr():
assert isinstance(iter, Declaration)
assert ls[0] == Declaration(
Variable(
Symbol('a'),
type = IntBaseType(String('integer')),
value = Integer(0)
)
)
assert ls[1] == Declaration(
Variable(
Symbol('b'),
type = IntBaseType(String('integer')),
value = Integer(0)
)
)
assert ls[2] == Declaration(
Variable(
Symbol('c'),
type = IntBaseType(String('integer')),
value = Integer(0)
)
)
assert ls[3] == Declaration(
Variable(
Symbol('d'),
type = IntBaseType(String('integer')),
value = Integer(0)
)
)
assert ls[4] == Declaration(
Variable(
Symbol('p'),
type = FloatBaseType(String('real')),
value = Float(0.0)
)
)
assert ls[5] == Declaration(
Variable(
Symbol('q'),
type = FloatBaseType(String('real')),
value = Float(0.0)
)
)
assert ls[6] == Declaration(
Variable(
Symbol('r'),
type = FloatBaseType(String('real')),
value = Float(0.0)
)
)
assert ls[7] == Declaration(
Variable(
Symbol('s'),
type = FloatBaseType(String('real')),
value = Float(0.0)
)
)
else:
def test_raise():
from sympy.parsing.fortran.fortran_parser import ASR2PyVisitor
raises(ImportError, lambda: ASR2PyVisitor())
raises(ImportError, lambda: SymPyExpression(' ', mode = 'f'))

View File

@ -0,0 +1,196 @@
import sympy
from sympy.parsing.sympy_parser import (
parse_expr,
standard_transformations,
convert_xor,
implicit_multiplication_application,
implicit_multiplication,
implicit_application,
function_exponentiation,
split_symbols,
split_symbols_custom,
_token_splittable
)
from sympy.testing.pytest import raises
def test_implicit_multiplication():
cases = {
'5x': '5*x',
'abc': 'a*b*c',
'3sin(x)': '3*sin(x)',
'(x+1)(x+2)': '(x+1)*(x+2)',
'(5 x**2)sin(x)': '(5*x**2)*sin(x)',
'2 sin(x) cos(x)': '2*sin(x)*cos(x)',
'pi x': 'pi*x',
'x pi': 'x*pi',
'E x': 'E*x',
'EulerGamma y': 'EulerGamma*y',
'E pi': 'E*pi',
'pi (x + 2)': 'pi*(x+2)',
'(x + 2) pi': '(x+2)*pi',
'pi sin(x)': 'pi*sin(x)',
}
transformations = standard_transformations + (convert_xor,)
transformations2 = transformations + (split_symbols,
implicit_multiplication)
for case in cases:
implicit = parse_expr(case, transformations=transformations2)
normal = parse_expr(cases[case], transformations=transformations)
assert(implicit == normal)
application = ['sin x', 'cos 2*x', 'sin cos x']
for case in application:
raises(SyntaxError,
lambda: parse_expr(case, transformations=transformations2))
raises(TypeError,
lambda: parse_expr('sin**2(x)', transformations=transformations2))
def test_implicit_application():
cases = {
'factorial': 'factorial',
'sin x': 'sin(x)',
'tan y**3': 'tan(y**3)',
'cos 2*x': 'cos(2*x)',
'(cot)': 'cot',
'sin cos tan x': 'sin(cos(tan(x)))'
}
transformations = standard_transformations + (convert_xor,)
transformations2 = transformations + (implicit_application,)
for case in cases:
implicit = parse_expr(case, transformations=transformations2)
normal = parse_expr(cases[case], transformations=transformations)
assert(implicit == normal), (implicit, normal)
multiplication = ['x y', 'x sin x', '2x']
for case in multiplication:
raises(SyntaxError,
lambda: parse_expr(case, transformations=transformations2))
raises(TypeError,
lambda: parse_expr('sin**2(x)', transformations=transformations2))
def test_function_exponentiation():
cases = {
'sin**2(x)': 'sin(x)**2',
'exp^y(z)': 'exp(z)^y',
'sin**2(E^(x))': 'sin(E^(x))**2'
}
transformations = standard_transformations + (convert_xor,)
transformations2 = transformations + (function_exponentiation,)
for case in cases:
implicit = parse_expr(case, transformations=transformations2)
normal = parse_expr(cases[case], transformations=transformations)
assert(implicit == normal)
other_implicit = ['x y', 'x sin x', '2x', 'sin x',
'cos 2*x', 'sin cos x']
for case in other_implicit:
raises(SyntaxError,
lambda: parse_expr(case, transformations=transformations2))
assert parse_expr('x**2', local_dict={ 'x': sympy.Symbol('x') },
transformations=transformations2) == parse_expr('x**2')
def test_symbol_splitting():
# By default Greek letter names should not be split (lambda is a keyword
# so skip it)
transformations = standard_transformations + (split_symbols,)
greek_letters = ('alpha', 'beta', 'gamma', 'delta', 'epsilon', 'zeta',
'eta', 'theta', 'iota', 'kappa', 'mu', 'nu', 'xi',
'omicron', 'pi', 'rho', 'sigma', 'tau', 'upsilon',
'phi', 'chi', 'psi', 'omega')
for letter in greek_letters:
assert(parse_expr(letter, transformations=transformations) ==
parse_expr(letter))
# Make sure symbol splitting resolves names
transformations += (implicit_multiplication,)
local_dict = { 'e': sympy.E }
cases = {
'xe': 'E*x',
'Iy': 'I*y',
'ee': 'E*E',
}
for case, expected in cases.items():
assert(parse_expr(case, local_dict=local_dict,
transformations=transformations) ==
parse_expr(expected))
# Make sure custom splitting works
def can_split(symbol):
if symbol not in ('unsplittable', 'names'):
return _token_splittable(symbol)
return False
transformations = standard_transformations
transformations += (split_symbols_custom(can_split),
implicit_multiplication)
assert(parse_expr('unsplittable', transformations=transformations) ==
parse_expr('unsplittable'))
assert(parse_expr('names', transformations=transformations) ==
parse_expr('names'))
assert(parse_expr('xy', transformations=transformations) ==
parse_expr('x*y'))
for letter in greek_letters:
assert(parse_expr(letter, transformations=transformations) ==
parse_expr(letter))
def test_all_implicit_steps():
cases = {
'2x': '2*x', # implicit multiplication
'x y': 'x*y',
'xy': 'x*y',
'sin x': 'sin(x)', # add parentheses
'2sin x': '2*sin(x)',
'x y z': 'x*y*z',
'sin(2 * 3x)': 'sin(2 * 3 * x)',
'sin(x) (1 + cos(x))': 'sin(x) * (1 + cos(x))',
'(x + 2) sin(x)': '(x + 2) * sin(x)',
'(x + 2) sin x': '(x + 2) * sin(x)',
'sin(sin x)': 'sin(sin(x))',
'sin x!': 'sin(factorial(x))',
'sin x!!': 'sin(factorial2(x))',
'factorial': 'factorial', # don't apply a bare function
'x sin x': 'x * sin(x)', # both application and multiplication
'xy sin x': 'x * y * sin(x)',
'(x+2)(x+3)': '(x + 2) * (x+3)',
'x**2 + 2xy + y**2': 'x**2 + 2 * x * y + y**2', # split the xy
'pi': 'pi', # don't mess with constants
'None': 'None',
'ln sin x': 'ln(sin(x))', # multiple implicit function applications
'factorial': 'factorial', # don't add parentheses
'sin x**2': 'sin(x**2)', # implicit application to an exponential
'alpha': 'Symbol("alpha")', # don't split Greek letters/subscripts
'x_2': 'Symbol("x_2")',
'sin^2 x**2': 'sin(x**2)**2', # function raised to a power
'sin**3(x)': 'sin(x)**3',
'(factorial)': 'factorial',
'tan 3x': 'tan(3*x)',
'sin^2(3*E^(x))': 'sin(3*E**(x))**2',
'sin**2(E^(3x))': 'sin(E**(3*x))**2',
'sin^2 (3x*E^(x))': 'sin(3*x*E^x)**2',
'pi sin x': 'pi*sin(x)',
}
transformations = standard_transformations + (convert_xor,)
transformations2 = transformations + (implicit_multiplication_application,)
for case in cases:
implicit = parse_expr(case, transformations=transformations2)
normal = parse_expr(cases[case], transformations=transformations)
assert(implicit == normal)
def test_no_methods_implicit_multiplication():
# Issue 21020
u = sympy.Symbol('u')
transformations = standard_transformations + \
(implicit_multiplication,)
expr = parse_expr('x.is_polynomial(x)', transformations=transformations)
assert expr == True
expr = parse_expr('(exp(x) / (1 + exp(2x))).subs(exp(x), u)',
transformations=transformations)
assert expr == u/(u**2 + 1)

View File

@ -0,0 +1,358 @@
from sympy.testing.pytest import raises, XFAIL
from sympy.external import import_module
from sympy.concrete.products import Product
from sympy.concrete.summations import Sum
from sympy.core.add import Add
from sympy.core.function import (Derivative, Function)
from sympy.core.mul import Mul
from sympy.core.numbers import (E, oo)
from sympy.core.power import Pow
from sympy.core.relational import (GreaterThan, LessThan, StrictGreaterThan, StrictLessThan, Unequality)
from sympy.core.symbol import Symbol
from sympy.functions.combinatorial.factorials import (binomial, factorial)
from sympy.functions.elementary.complexes import (Abs, conjugate)
from sympy.functions.elementary.exponential import (exp, log)
from sympy.functions.elementary.integers import (ceiling, floor)
from sympy.functions.elementary.miscellaneous import (root, sqrt)
from sympy.functions.elementary.trigonometric import (asin, cos, csc, sec, sin, tan)
from sympy.integrals.integrals import Integral
from sympy.series.limits import Limit
from sympy.core.relational import Eq, Ne, Lt, Le, Gt, Ge
from sympy.physics.quantum.state import Bra, Ket
from sympy.abc import x, y, z, a, b, c, t, k, n
antlr4 = import_module("antlr4")
# disable tests if antlr4-python3-runtime is not present
disabled = antlr4 is None
theta = Symbol('theta')
f = Function('f')
# shorthand definitions
def _Add(a, b):
return Add(a, b, evaluate=False)
def _Mul(a, b):
return Mul(a, b, evaluate=False)
def _Pow(a, b):
return Pow(a, b, evaluate=False)
def _Sqrt(a):
return sqrt(a, evaluate=False)
def _Conjugate(a):
return conjugate(a, evaluate=False)
def _Abs(a):
return Abs(a, evaluate=False)
def _factorial(a):
return factorial(a, evaluate=False)
def _exp(a):
return exp(a, evaluate=False)
def _log(a, b):
return log(a, b, evaluate=False)
def _binomial(n, k):
return binomial(n, k, evaluate=False)
def test_import():
from sympy.parsing.latex._build_latex_antlr import (
build_parser,
check_antlr_version,
dir_latex_antlr
)
# XXX: It would be better to come up with a test for these...
del build_parser, check_antlr_version, dir_latex_antlr
# These LaTeX strings should parse to the corresponding SymPy expression
GOOD_PAIRS = [
(r"0", 0),
(r"1", 1),
(r"-3.14", -3.14),
(r"(-7.13)(1.5)", _Mul(-7.13, 1.5)),
(r"x", x),
(r"2x", 2*x),
(r"x^2", x**2),
(r"x^\frac{1}{2}", _Pow(x, _Pow(2, -1))),
(r"x^{3 + 1}", x**_Add(3, 1)),
(r"-c", -c),
(r"a \cdot b", a * b),
(r"a / b", a / b),
(r"a \div b", a / b),
(r"a + b", a + b),
(r"a + b - a", _Add(a+b, -a)),
(r"a^2 + b^2 = c^2", Eq(a**2 + b**2, c**2)),
(r"(x + y) z", _Mul(_Add(x, y), z)),
(r"a'b+ab'", _Add(_Mul(Symbol("a'"), b), _Mul(a, Symbol("b'")))),
(r"y''_1", Symbol("y_{1}''")),
(r"y_1''", Symbol("y_{1}''")),
(r"\left(x + y\right) z", _Mul(_Add(x, y), z)),
(r"\left( x + y\right ) z", _Mul(_Add(x, y), z)),
(r"\left( x + y\right ) z", _Mul(_Add(x, y), z)),
(r"\left[x + y\right] z", _Mul(_Add(x, y), z)),
(r"\left\{x + y\right\} z", _Mul(_Add(x, y), z)),
(r"1+1", _Add(1, 1)),
(r"0+1", _Add(0, 1)),
(r"1*2", _Mul(1, 2)),
(r"0*1", _Mul(0, 1)),
(r"1 \times 2 ", _Mul(1, 2)),
(r"x = y", Eq(x, y)),
(r"x \neq y", Ne(x, y)),
(r"x < y", Lt(x, y)),
(r"x > y", Gt(x, y)),
(r"x \leq y", Le(x, y)),
(r"x \geq y", Ge(x, y)),
(r"x \le y", Le(x, y)),
(r"x \ge y", Ge(x, y)),
(r"\lfloor x \rfloor", floor(x)),
(r"\lceil x \rceil", ceiling(x)),
(r"\langle x |", Bra('x')),
(r"| x \rangle", Ket('x')),
(r"\sin \theta", sin(theta)),
(r"\sin(\theta)", sin(theta)),
(r"\sin^{-1} a", asin(a)),
(r"\sin a \cos b", _Mul(sin(a), cos(b))),
(r"\sin \cos \theta", sin(cos(theta))),
(r"\sin(\cos \theta)", sin(cos(theta))),
(r"\frac{a}{b}", a / b),
(r"\dfrac{a}{b}", a / b),
(r"\tfrac{a}{b}", a / b),
(r"\frac12", _Pow(2, -1)),
(r"\frac12y", _Mul(_Pow(2, -1), y)),
(r"\frac1234", _Mul(_Pow(2, -1), 34)),
(r"\frac2{3}", _Mul(2, _Pow(3, -1))),
(r"\frac{\sin{x}}2", _Mul(sin(x), _Pow(2, -1))),
(r"\frac{a + b}{c}", _Mul(a + b, _Pow(c, -1))),
(r"\frac{7}{3}", _Mul(7, _Pow(3, -1))),
(r"(\csc x)(\sec y)", csc(x)*sec(y)),
(r"\lim_{x \to 3} a", Limit(a, x, 3, dir='+-')),
(r"\lim_{x \rightarrow 3} a", Limit(a, x, 3, dir='+-')),
(r"\lim_{x \Rightarrow 3} a", Limit(a, x, 3, dir='+-')),
(r"\lim_{x \longrightarrow 3} a", Limit(a, x, 3, dir='+-')),
(r"\lim_{x \Longrightarrow 3} a", Limit(a, x, 3, dir='+-')),
(r"\lim_{x \to 3^{+}} a", Limit(a, x, 3, dir='+')),
(r"\lim_{x \to 3^{-}} a", Limit(a, x, 3, dir='-')),
(r"\lim_{x \to 3^+} a", Limit(a, x, 3, dir='+')),
(r"\lim_{x \to 3^-} a", Limit(a, x, 3, dir='-')),
(r"\infty", oo),
(r"\lim_{x \to \infty} \frac{1}{x}", Limit(_Pow(x, -1), x, oo)),
(r"\frac{d}{dx} x", Derivative(x, x)),
(r"\frac{d}{dt} x", Derivative(x, t)),
(r"f(x)", f(x)),
(r"f(x, y)", f(x, y)),
(r"f(x, y, z)", f(x, y, z)),
(r"f'_1(x)", Function("f_{1}'")(x)),
(r"f_{1}''(x+y)", Function("f_{1}''")(x+y)),
(r"\frac{d f(x)}{dx}", Derivative(f(x), x)),
(r"\frac{d\theta(x)}{dx}", Derivative(Function('theta')(x), x)),
(r"x \neq y", Unequality(x, y)),
(r"|x|", _Abs(x)),
(r"||x||", _Abs(Abs(x))),
(r"|x||y|", _Abs(x)*_Abs(y)),
(r"||x||y||", _Abs(_Abs(x)*_Abs(y))),
(r"\pi^{|xy|}", Symbol('pi')**_Abs(x*y)),
(r"\int x dx", Integral(x, x)),
(r"\int x d\theta", Integral(x, theta)),
(r"\int (x^2 - y)dx", Integral(x**2 - y, x)),
(r"\int x + a dx", Integral(_Add(x, a), x)),
(r"\int da", Integral(1, a)),
(r"\int_0^7 dx", Integral(1, (x, 0, 7))),
(r"\int\limits_{0}^{1} x dx", Integral(x, (x, 0, 1))),
(r"\int_a^b x dx", Integral(x, (x, a, b))),
(r"\int^b_a x dx", Integral(x, (x, a, b))),
(r"\int_{a}^b x dx", Integral(x, (x, a, b))),
(r"\int^{b}_a x dx", Integral(x, (x, a, b))),
(r"\int_{a}^{b} x dx", Integral(x, (x, a, b))),
(r"\int^{b}_{a} x dx", Integral(x, (x, a, b))),
(r"\int_{f(a)}^{f(b)} f(z) dz", Integral(f(z), (z, f(a), f(b)))),
(r"\int (x+a)", Integral(_Add(x, a), x)),
(r"\int a + b + c dx", Integral(_Add(_Add(a, b), c), x)),
(r"\int \frac{dz}{z}", Integral(Pow(z, -1), z)),
(r"\int \frac{3 dz}{z}", Integral(3*Pow(z, -1), z)),
(r"\int \frac{1}{x} dx", Integral(Pow(x, -1), x)),
(r"\int \frac{1}{a} + \frac{1}{b} dx",
Integral(_Add(_Pow(a, -1), Pow(b, -1)), x)),
(r"\int \frac{3 \cdot d\theta}{\theta}",
Integral(3*_Pow(theta, -1), theta)),
(r"\int \frac{1}{x} + 1 dx", Integral(_Add(_Pow(x, -1), 1), x)),
(r"x_0", Symbol('x_{0}')),
(r"x_{1}", Symbol('x_{1}')),
(r"x_a", Symbol('x_{a}')),
(r"x_{b}", Symbol('x_{b}')),
(r"h_\theta", Symbol('h_{theta}')),
(r"h_{\theta}", Symbol('h_{theta}')),
(r"h_{\theta}(x_0, x_1)",
Function('h_{theta}')(Symbol('x_{0}'), Symbol('x_{1}'))),
(r"x!", _factorial(x)),
(r"100!", _factorial(100)),
(r"\theta!", _factorial(theta)),
(r"(x + 1)!", _factorial(_Add(x, 1))),
(r"(x!)!", _factorial(_factorial(x))),
(r"x!!!", _factorial(_factorial(_factorial(x)))),
(r"5!7!", _Mul(_factorial(5), _factorial(7))),
(r"\sqrt{x}", sqrt(x)),
(r"\sqrt{x + b}", sqrt(_Add(x, b))),
(r"\sqrt[3]{\sin x}", root(sin(x), 3)),
(r"\sqrt[y]{\sin x}", root(sin(x), y)),
(r"\sqrt[\theta]{\sin x}", root(sin(x), theta)),
(r"\sqrt{\frac{12}{6}}", _Sqrt(_Mul(12, _Pow(6, -1)))),
(r"\overline{z}", _Conjugate(z)),
(r"\overline{\overline{z}}", _Conjugate(_Conjugate(z))),
(r"\overline{x + y}", _Conjugate(_Add(x, y))),
(r"\overline{x} + \overline{y}", _Conjugate(x) + _Conjugate(y)),
(r"x < y", StrictLessThan(x, y)),
(r"x \leq y", LessThan(x, y)),
(r"x > y", StrictGreaterThan(x, y)),
(r"x \geq y", GreaterThan(x, y)),
(r"\mathit{x}", Symbol('x')),
(r"\mathit{test}", Symbol('test')),
(r"\mathit{TEST}", Symbol('TEST')),
(r"\mathit{HELLO world}", Symbol('HELLO world')),
(r"\sum_{k = 1}^{3} c", Sum(c, (k, 1, 3))),
(r"\sum_{k = 1}^3 c", Sum(c, (k, 1, 3))),
(r"\sum^{3}_{k = 1} c", Sum(c, (k, 1, 3))),
(r"\sum^3_{k = 1} c", Sum(c, (k, 1, 3))),
(r"\sum_{k = 1}^{10} k^2", Sum(k**2, (k, 1, 10))),
(r"\sum_{n = 0}^{\infty} \frac{1}{n!}",
Sum(_Pow(_factorial(n), -1), (n, 0, oo))),
(r"\prod_{a = b}^{c} x", Product(x, (a, b, c))),
(r"\prod_{a = b}^c x", Product(x, (a, b, c))),
(r"\prod^{c}_{a = b} x", Product(x, (a, b, c))),
(r"\prod^c_{a = b} x", Product(x, (a, b, c))),
(r"\exp x", _exp(x)),
(r"\exp(x)", _exp(x)),
(r"\lg x", _log(x, 10)),
(r"\ln x", _log(x, E)),
(r"\ln xy", _log(x*y, E)),
(r"\log x", _log(x, E)),
(r"\log xy", _log(x*y, E)),
(r"\log_{2} x", _log(x, 2)),
(r"\log_{a} x", _log(x, a)),
(r"\log_{11} x", _log(x, 11)),
(r"\log_{a^2} x", _log(x, _Pow(a, 2))),
(r"[x]", x),
(r"[a + b]", _Add(a, b)),
(r"\frac{d}{dx} [ \tan x ]", Derivative(tan(x), x)),
(r"\binom{n}{k}", _binomial(n, k)),
(r"\tbinom{n}{k}", _binomial(n, k)),
(r"\dbinom{n}{k}", _binomial(n, k)),
(r"\binom{n}{0}", _binomial(n, 0)),
(r"x^\binom{n}{k}", _Pow(x, _binomial(n, k))),
(r"a \, b", _Mul(a, b)),
(r"a \thinspace b", _Mul(a, b)),
(r"a \: b", _Mul(a, b)),
(r"a \medspace b", _Mul(a, b)),
(r"a \; b", _Mul(a, b)),
(r"a \thickspace b", _Mul(a, b)),
(r"a \quad b", _Mul(a, b)),
(r"a \qquad b", _Mul(a, b)),
(r"a \! b", _Mul(a, b)),
(r"a \negthinspace b", _Mul(a, b)),
(r"a \negmedspace b", _Mul(a, b)),
(r"a \negthickspace b", _Mul(a, b)),
(r"\int x \, dx", Integral(x, x)),
(r"\log_2 x", _log(x, 2)),
(r"\log_a x", _log(x, a)),
(r"5^0 - 4^0", _Add(_Pow(5, 0), _Mul(-1, _Pow(4, 0)))),
(r"3x - 1", _Add(_Mul(3, x), -1))
]
def test_parseable():
from sympy.parsing.latex import parse_latex
for latex_str, sympy_expr in GOOD_PAIRS:
assert parse_latex(latex_str) == sympy_expr, latex_str
# These bad LaTeX strings should raise a LaTeXParsingError when parsed
BAD_STRINGS = [
r"(",
r")",
r"\frac{d}{dx}",
r"(\frac{d}{dx})",
r"\sqrt{}",
r"\sqrt",
r"\overline{}",
r"\overline",
r"{",
r"}",
r"\mathit{x + y}",
r"\mathit{21}",
r"\frac{2}{}",
r"\frac{}{2}",
r"\int",
r"!",
r"!0",
r"_",
r"^",
r"|",
r"||x|",
r"()",
r"((((((((((((((((()))))))))))))))))",
r"-",
r"\frac{d}{dx} + \frac{d}{dt}",
r"f(x,,y)",
r"f(x,y,",
r"\sin^x",
r"\cos^2",
r"@",
r"#",
r"$",
r"%",
r"&",
r"*",
r"" "\\",
r"~",
r"\frac{(2 + x}{1 - x)}",
]
def test_not_parseable():
from sympy.parsing.latex import parse_latex, LaTeXParsingError
for latex_str in BAD_STRINGS:
with raises(LaTeXParsingError):
parse_latex(latex_str)
# At time of migration from latex2sympy, should fail but doesn't
FAILING_BAD_STRINGS = [
r"\cos 1 \cos",
r"f(,",
r"f()",
r"a \div \div b",
r"a \cdot \cdot b",
r"a // b",
r"a +",
r"1.1.1",
r"1 +",
r"a / b /",
]
@XFAIL
def test_failing_not_parseable():
from sympy.parsing.latex import parse_latex, LaTeXParsingError
for latex_str in FAILING_BAD_STRINGS:
with raises(LaTeXParsingError):
parse_latex(latex_str)
# In strict mode, FAILING_BAD_STRINGS would fail
def test_strict_mode():
from sympy.parsing.latex import parse_latex, LaTeXParsingError
for latex_str in FAILING_BAD_STRINGS:
with raises(LaTeXParsingError):
parse_latex(latex_str, strict=True)

View File

@ -0,0 +1,16 @@
from sympy.external import import_module
from sympy.testing.pytest import ignore_warnings, raises
antlr4 = import_module("antlr4", warn_not_installed=False)
# disable tests if antlr4-python3-runtime is not present
if antlr4:
disabled = True
def test_no_import():
from sympy.parsing.latex import parse_latex
with ignore_warnings(UserWarning):
with raises(ImportError):
parse_latex('1 + 1')

View File

@ -0,0 +1,595 @@
from sympy.testing.pytest import XFAIL
from sympy.parsing.latex.lark import parse_latex_lark
from sympy.external import import_module
from sympy.concrete.products import Product
from sympy.concrete.summations import Sum
from sympy.core.function import Derivative, Function
from sympy.core.numbers import E, oo, Rational
from sympy.core.power import Pow
from sympy.core.parameters import evaluate
from sympy.core.relational import GreaterThan, LessThan, StrictGreaterThan, StrictLessThan, Unequality
from sympy.core.symbol import Symbol
from sympy.functions.combinatorial.factorials import binomial, factorial
from sympy.functions.elementary.complexes import Abs, conjugate
from sympy.functions.elementary.exponential import exp, log
from sympy.functions.elementary.integers import ceiling, floor
from sympy.functions.elementary.miscellaneous import root, sqrt, Min, Max
from sympy.functions.elementary.trigonometric import asin, cos, csc, sec, sin, tan
from sympy.integrals.integrals import Integral
from sympy.series.limits import Limit
from sympy.core.relational import Eq, Ne, Lt, Le, Gt, Ge
from sympy.physics.quantum import Bra, Ket, InnerProduct
from sympy.abc import x, y, z, a, b, c, d, t, k, n
from .test_latex import theta, f, _Add, _Mul, _Pow, _Sqrt, _Conjugate, _Abs, _factorial, _exp, _binomial
lark = import_module("lark")
# disable tests if lark is not present
disabled = lark is None
# shorthand definitions that are only needed for the Lark LaTeX parser
def _Min(*args):
return Min(*args, evaluate=False)
def _Max(*args):
return Max(*args, evaluate=False)
def _log(a, b=E):
if b == E:
return log(a, evaluate=False)
else:
return log(a, b, evaluate=False)
# These LaTeX strings should parse to the corresponding SymPy expression
SYMBOL_EXPRESSION_PAIRS = [
(r"x_0", Symbol('x_{0}')),
(r"x_{1}", Symbol('x_{1}')),
(r"x_a", Symbol('x_{a}')),
(r"x_{b}", Symbol('x_{b}')),
(r"h_\theta", Symbol('h_{theta}')),
(r"h_{\theta}", Symbol('h_{theta}')),
(r"y''_1", Symbol("y_{1}''")),
(r"y_1''", Symbol("y_{1}''")),
(r"\mathit{x}", Symbol('x')),
(r"\mathit{test}", Symbol('test')),
(r"\mathit{TEST}", Symbol('TEST')),
(r"\mathit{HELLO world}", Symbol('HELLO world'))
]
UNEVALUATED_SIMPLE_EXPRESSION_PAIRS = [
(r"0", 0),
(r"1", 1),
(r"-3.14", -3.14),
(r"(-7.13)(1.5)", _Mul(-7.13, 1.5)),
(r"1+1", _Add(1, 1)),
(r"0+1", _Add(0, 1)),
(r"1*2", _Mul(1, 2)),
(r"0*1", _Mul(0, 1)),
(r"x", x),
(r"2x", 2 * x),
(r"3x - 1", _Add(_Mul(3, x), -1)),
(r"-c", -c),
(r"\infty", oo),
(r"a \cdot b", a * b),
(r"1 \times 2 ", _Mul(1, 2)),
(r"a / b", a / b),
(r"a \div b", a / b),
(r"a + b", a + b),
(r"a + b - a", _Add(a + b, -a)),
(r"(x + y) z", _Mul(_Add(x, y), z)),
(r"a'b+ab'", _Add(_Mul(Symbol("a'"), b), _Mul(a, Symbol("b'"))))
]
EVALUATED_SIMPLE_EXPRESSION_PAIRS = [
(r"(-7.13)(1.5)", -10.695),
(r"1+1", 2),
(r"0+1", 1),
(r"1*2", 2),
(r"0*1", 0),
(r"2x", 2 * x),
(r"3x - 1", 3 * x - 1),
(r"-c", -c),
(r"a \cdot b", a * b),
(r"1 \times 2 ", 2),
(r"a / b", a / b),
(r"a \div b", a / b),
(r"a + b", a + b),
(r"a + b - a", b),
(r"(x + y) z", (x + y) * z),
]
UNEVALUATED_FRACTION_EXPRESSION_PAIRS = [
(r"\frac{a}{b}", a / b),
(r"\dfrac{a}{b}", a / b),
(r"\tfrac{a}{b}", a / b),
(r"\frac12", _Mul(1, _Pow(2, -1))),
(r"\frac12y", _Mul(_Mul(1, _Pow(2, -1)), y)),
(r"\frac1234", _Mul(_Mul(1, _Pow(2, -1)), 34)),
(r"\frac2{3}", _Mul(2, _Pow(3, -1))),
(r"\frac{a + b}{c}", _Mul(a + b, _Pow(c, -1))),
(r"\frac{7}{3}", _Mul(7, _Pow(3, -1)))
]
EVALUATED_FRACTION_EXPRESSION_PAIRS = [
(r"\frac{a}{b}", a / b),
(r"\dfrac{a}{b}", a / b),
(r"\tfrac{a}{b}", a / b),
(r"\frac12", Rational(1, 2)),
(r"\frac12y", y / 2),
(r"\frac1234", 17),
(r"\frac2{3}", Rational(2, 3)),
(r"\frac{a + b}{c}", (a + b) / c),
(r"\frac{7}{3}", Rational(7, 3))
]
RELATION_EXPRESSION_PAIRS = [
(r"x = y", Eq(x, y)),
(r"x \neq y", Ne(x, y)),
(r"x < y", Lt(x, y)),
(r"x > y", Gt(x, y)),
(r"x \leq y", Le(x, y)),
(r"x \geq y", Ge(x, y)),
(r"x \le y", Le(x, y)),
(r"x \ge y", Ge(x, y)),
(r"x < y", StrictLessThan(x, y)),
(r"x \leq y", LessThan(x, y)),
(r"x > y", StrictGreaterThan(x, y)),
(r"x \geq y", GreaterThan(x, y)),
(r"x \neq y", Unequality(x, y)), # same as 2nd one in the list
(r"a^2 + b^2 = c^2", Eq(a**2 + b**2, c**2))
]
UNEVALUATED_POWER_EXPRESSION_PAIRS = [
(r"x^2", x ** 2),
(r"x^\frac{1}{2}", _Pow(x, _Mul(1, _Pow(2, -1)))),
(r"x^{3 + 1}", x ** _Add(3, 1)),
(r"\pi^{|xy|}", Symbol('pi') ** _Abs(x * y)),
(r"5^0 - 4^0", _Add(_Pow(5, 0), _Mul(-1, _Pow(4, 0))))
]
EVALUATED_POWER_EXPRESSION_PAIRS = [
(r"x^2", x ** 2),
(r"x^\frac{1}{2}", sqrt(x)),
(r"x^{3 + 1}", x ** 4),
(r"\pi^{|xy|}", Symbol('pi') ** _Abs(x * y)),
(r"5^0 - 4^0", 0)
]
UNEVALUATED_INTEGRAL_EXPRESSION_PAIRS = [
(r"\int x dx", Integral(_Mul(1, x), x)),
(r"\int x \, dx", Integral(_Mul(1, x), x)),
(r"\int x d\theta", Integral(_Mul(1, x), theta)),
(r"\int (x^2 - y)dx", Integral(_Mul(1, x ** 2 - y), x)),
(r"\int x + a dx", Integral(_Mul(1, _Add(x, a)), x)),
(r"\int da", Integral(_Mul(1, 1), a)),
(r"\int_0^7 dx", Integral(_Mul(1, 1), (x, 0, 7))),
(r"\int\limits_{0}^{1} x dx", Integral(_Mul(1, x), (x, 0, 1))),
(r"\int_a^b x dx", Integral(_Mul(1, x), (x, a, b))),
(r"\int^b_a x dx", Integral(_Mul(1, x), (x, a, b))),
(r"\int_{a}^b x dx", Integral(_Mul(1, x), (x, a, b))),
(r"\int^{b}_a x dx", Integral(_Mul(1, x), (x, a, b))),
(r"\int_{a}^{b} x dx", Integral(_Mul(1, x), (x, a, b))),
(r"\int^{b}_{a} x dx", Integral(_Mul(1, x), (x, a, b))),
(r"\int_{f(a)}^{f(b)} f(z) dz", Integral(f(z), (z, f(a), f(b)))),
(r"\int a + b + c dx", Integral(_Mul(1, _Add(_Add(a, b), c)), x)),
(r"\int \frac{dz}{z}", Integral(_Mul(1, _Mul(1, Pow(z, -1))), z)),
(r"\int \frac{3 dz}{z}", Integral(_Mul(1, _Mul(3, _Pow(z, -1))), z)),
(r"\int \frac{1}{x} dx", Integral(_Mul(1, _Mul(1, Pow(x, -1))), x)),
(r"\int \frac{1}{a} + \frac{1}{b} dx",
Integral(_Mul(1, _Add(_Mul(1, _Pow(a, -1)), _Mul(1, Pow(b, -1)))), x)),
(r"\int \frac{1}{x} + 1 dx", Integral(_Mul(1, _Add(_Mul(1, _Pow(x, -1)), 1)), x))
]
EVALUATED_INTEGRAL_EXPRESSION_PAIRS = [
(r"\int x dx", Integral(x, x)),
(r"\int x \, dx", Integral(x, x)),
(r"\int x d\theta", Integral(x, theta)),
(r"\int (x^2 - y)dx", Integral(x ** 2 - y, x)),
(r"\int x + a dx", Integral(x + a, x)),
(r"\int da", Integral(1, a)),
(r"\int_0^7 dx", Integral(1, (x, 0, 7))),
(r"\int\limits_{0}^{1} x dx", Integral(x, (x, 0, 1))),
(r"\int_a^b x dx", Integral(x, (x, a, b))),
(r"\int^b_a x dx", Integral(x, (x, a, b))),
(r"\int_{a}^b x dx", Integral(x, (x, a, b))),
(r"\int^{b}_a x dx", Integral(x, (x, a, b))),
(r"\int_{a}^{b} x dx", Integral(x, (x, a, b))),
(r"\int^{b}_{a} x dx", Integral(x, (x, a, b))),
(r"\int_{f(a)}^{f(b)} f(z) dz", Integral(f(z), (z, f(a), f(b)))),
(r"\int a + b + c dx", Integral(a + b + c, x)),
(r"\int \frac{dz}{z}", Integral(Pow(z, -1), z)),
(r"\int \frac{3 dz}{z}", Integral(3 * Pow(z, -1), z)),
(r"\int \frac{1}{x} dx", Integral(1 / x, x)),
(r"\int \frac{1}{a} + \frac{1}{b} dx", Integral(1 / a + 1 / b, x)),
(r"\int \frac{1}{x} + 1 dx", Integral(1 / x + 1, x))
]
DERIVATIVE_EXPRESSION_PAIRS = [
(r"\frac{d}{dx} x", Derivative(x, x)),
(r"\frac{d}{dt} x", Derivative(x, t)),
(r"\frac{d}{dx} ( \tan x )", Derivative(tan(x), x)),
(r"\frac{d f(x)}{dx}", Derivative(f(x), x)),
(r"\frac{d\theta(x)}{dx}", Derivative(Function('theta')(x), x))
]
TRIGONOMETRIC_EXPRESSION_PAIRS = [
(r"\sin \theta", sin(theta)),
(r"\sin(\theta)", sin(theta)),
(r"\sin^{-1} a", asin(a)),
(r"\sin a \cos b", _Mul(sin(a), cos(b))),
(r"\sin \cos \theta", sin(cos(theta))),
(r"\sin(\cos \theta)", sin(cos(theta))),
(r"(\csc x)(\sec y)", csc(x) * sec(y)),
(r"\frac{\sin{x}}2", _Mul(sin(x), _Pow(2, -1)))
]
UNEVALUATED_LIMIT_EXPRESSION_PAIRS = [
(r"\lim_{x \to 3} a", Limit(a, x, 3, dir="+-")),
(r"\lim_{x \rightarrow 3} a", Limit(a, x, 3, dir="+-")),
(r"\lim_{x \Rightarrow 3} a", Limit(a, x, 3, dir="+-")),
(r"\lim_{x \longrightarrow 3} a", Limit(a, x, 3, dir="+-")),
(r"\lim_{x \Longrightarrow 3} a", Limit(a, x, 3, dir="+-")),
(r"\lim_{x \to 3^{+}} a", Limit(a, x, 3, dir="+")),
(r"\lim_{x \to 3^{-}} a", Limit(a, x, 3, dir="-")),
(r"\lim_{x \to 3^+} a", Limit(a, x, 3, dir="+")),
(r"\lim_{x \to 3^-} a", Limit(a, x, 3, dir="-")),
(r"\lim_{x \to \infty} \frac{1}{x}", Limit(_Mul(1, _Pow(x, -1)), x, oo))
]
EVALUATED_LIMIT_EXPRESSION_PAIRS = [
(r"\lim_{x \to \infty} \frac{1}{x}", Limit(1 / x, x, oo))
]
UNEVALUATED_SQRT_EXPRESSION_PAIRS = [
(r"\sqrt{x}", sqrt(x)),
(r"\sqrt{x + b}", sqrt(_Add(x, b))),
(r"\sqrt[3]{\sin x}", _Pow(sin(x), _Pow(3, -1))),
# the above test needed to be handled differently than the ones below because root
# acts differently if its second argument is a number
(r"\sqrt[y]{\sin x}", root(sin(x), y)),
(r"\sqrt[\theta]{\sin x}", root(sin(x), theta)),
(r"\sqrt{\frac{12}{6}}", _Sqrt(_Mul(12, _Pow(6, -1))))
]
EVALUATED_SQRT_EXPRESSION_PAIRS = [
(r"\sqrt{x}", sqrt(x)),
(r"\sqrt{x + b}", sqrt(x + b)),
(r"\sqrt[3]{\sin x}", root(sin(x), 3)),
(r"\sqrt[y]{\sin x}", root(sin(x), y)),
(r"\sqrt[\theta]{\sin x}", root(sin(x), theta)),
(r"\sqrt{\frac{12}{6}}", sqrt(2))
]
UNEVALUATED_FACTORIAL_EXPRESSION_PAIRS = [
(r"x!", _factorial(x)),
(r"100!", _factorial(100)),
(r"\theta!", _factorial(theta)),
(r"(x + 1)!", _factorial(_Add(x, 1))),
(r"(x!)!", _factorial(_factorial(x))),
(r"x!!!", _factorial(_factorial(_factorial(x)))),
(r"5!7!", _Mul(_factorial(5), _factorial(7)))
]
EVALUATED_FACTORIAL_EXPRESSION_PAIRS = [
(r"x!", factorial(x)),
(r"100!", factorial(100)),
(r"\theta!", factorial(theta)),
(r"(x + 1)!", factorial(x + 1)),
(r"(x!)!", factorial(factorial(x))),
(r"x!!!", factorial(factorial(factorial(x)))),
(r"5!7!", factorial(5) * factorial(7))
]
UNEVALUATED_SUM_EXPRESSION_PAIRS = [
(r"\sum_{k = 1}^{3} c", Sum(_Mul(1, c), (k, 1, 3))),
(r"\sum_{k = 1}^3 c", Sum(_Mul(1, c), (k, 1, 3))),
(r"\sum^{3}_{k = 1} c", Sum(_Mul(1, c), (k, 1, 3))),
(r"\sum^3_{k = 1} c", Sum(_Mul(1, c), (k, 1, 3))),
(r"\sum_{k = 1}^{10} k^2", Sum(_Mul(1, k ** 2), (k, 1, 10))),
(r"\sum_{n = 0}^{\infty} \frac{1}{n!}",
Sum(_Mul(1, _Mul(1, _Pow(_factorial(n), -1))), (n, 0, oo)))
]
EVALUATED_SUM_EXPRESSION_PAIRS = [
(r"\sum_{k = 1}^{3} c", Sum(c, (k, 1, 3))),
(r"\sum_{k = 1}^3 c", Sum(c, (k, 1, 3))),
(r"\sum^{3}_{k = 1} c", Sum(c, (k, 1, 3))),
(r"\sum^3_{k = 1} c", Sum(c, (k, 1, 3))),
(r"\sum_{k = 1}^{10} k^2", Sum(k ** 2, (k, 1, 10))),
(r"\sum_{n = 0}^{\infty} \frac{1}{n!}", Sum(1 / factorial(n), (n, 0, oo)))
]
UNEVALUATED_PRODUCT_EXPRESSION_PAIRS = [
(r"\prod_{a = b}^{c} x", Product(x, (a, b, c))),
(r"\prod_{a = b}^c x", Product(x, (a, b, c))),
(r"\prod^{c}_{a = b} x", Product(x, (a, b, c))),
(r"\prod^c_{a = b} x", Product(x, (a, b, c)))
]
APPLIED_FUNCTION_EXPRESSION_PAIRS = [
(r"f(x)", f(x)),
(r"f(x, y)", f(x, y)),
(r"f(x, y, z)", f(x, y, z)),
(r"f'_1(x)", Function("f_{1}'")(x)),
(r"f_{1}''(x+y)", Function("f_{1}''")(x + y)),
(r"h_{\theta}(x_0, x_1)",
Function('h_{theta}')(Symbol('x_{0}'), Symbol('x_{1}')))
]
UNEVALUATED_COMMON_FUNCTION_EXPRESSION_PAIRS = [
(r"|x|", _Abs(x)),
(r"||x||", _Abs(Abs(x))),
(r"|x||y|", _Abs(x) * _Abs(y)),
(r"||x||y||", _Abs(_Abs(x) * _Abs(y))),
(r"\lfloor x \rfloor", floor(x)),
(r"\lceil x \rceil", ceiling(x)),
(r"\exp x", _exp(x)),
(r"\exp(x)", _exp(x)),
(r"\lg x", _log(x, 10)),
(r"\ln x", _log(x)),
(r"\ln xy", _log(x * y)),
(r"\log x", _log(x)),
(r"\log xy", _log(x * y)),
(r"\log_{2} x", _log(x, 2)),
(r"\log_{a} x", _log(x, a)),
(r"\log_{11} x", _log(x, 11)),
(r"\log_{a^2} x", _log(x, _Pow(a, 2))),
(r"\log_2 x", _log(x, 2)),
(r"\log_a x", _log(x, a)),
(r"\overline{z}", _Conjugate(z)),
(r"\overline{\overline{z}}", _Conjugate(_Conjugate(z))),
(r"\overline{x + y}", _Conjugate(_Add(x, y))),
(r"\overline{x} + \overline{y}", _Conjugate(x) + _Conjugate(y)),
(r"\min(a, b)", _Min(a, b)),
(r"\min(a, b, c - d, xy)", _Min(a, b, c - d, x * y)),
(r"\max(a, b)", _Max(a, b)),
(r"\max(a, b, c - d, xy)", _Max(a, b, c - d, x * y)),
# physics things don't have an `evaluate=False` variant
(r"\langle x |", Bra('x')),
(r"| x \rangle", Ket('x')),
(r"\langle x | y \rangle", InnerProduct(Bra('x'), Ket('y'))),
]
EVALUATED_COMMON_FUNCTION_EXPRESSION_PAIRS = [
(r"|x|", Abs(x)),
(r"||x||", Abs(Abs(x))),
(r"|x||y|", Abs(x) * Abs(y)),
(r"||x||y||", Abs(Abs(x) * Abs(y))),
(r"\lfloor x \rfloor", floor(x)),
(r"\lceil x \rceil", ceiling(x)),
(r"\exp x", exp(x)),
(r"\exp(x)", exp(x)),
(r"\lg x", log(x, 10)),
(r"\ln x", log(x)),
(r"\ln xy", log(x * y)),
(r"\log x", log(x)),
(r"\log xy", log(x * y)),
(r"\log_{2} x", log(x, 2)),
(r"\log_{a} x", log(x, a)),
(r"\log_{11} x", log(x, 11)),
(r"\log_{a^2} x", log(x, _Pow(a, 2))),
(r"\log_2 x", log(x, 2)),
(r"\log_a x", log(x, a)),
(r"\overline{z}", conjugate(z)),
(r"\overline{\overline{z}}", conjugate(conjugate(z))),
(r"\overline{x + y}", conjugate(x + y)),
(r"\overline{x} + \overline{y}", conjugate(x) + conjugate(y)),
(r"\min(a, b)", Min(a, b)),
(r"\min(a, b, c - d, xy)", Min(a, b, c - d, x * y)),
(r"\max(a, b)", Max(a, b)),
(r"\max(a, b, c - d, xy)", Max(a, b, c - d, x * y)),
(r"\langle x |", Bra('x')),
(r"| x \rangle", Ket('x')),
(r"\langle x | y \rangle", InnerProduct(Bra('x'), Ket('y'))),
]
SPACING_RELATED_EXPRESSION_PAIRS = [
(r"a \, b", _Mul(a, b)),
(r"a \thinspace b", _Mul(a, b)),
(r"a \: b", _Mul(a, b)),
(r"a \medspace b", _Mul(a, b)),
(r"a \; b", _Mul(a, b)),
(r"a \thickspace b", _Mul(a, b)),
(r"a \quad b", _Mul(a, b)),
(r"a \qquad b", _Mul(a, b)),
(r"a \! b", _Mul(a, b)),
(r"a \negthinspace b", _Mul(a, b)),
(r"a \negmedspace b", _Mul(a, b)),
(r"a \negthickspace b", _Mul(a, b))
]
UNEVALUATED_BINOMIAL_EXPRESSION_PAIRS = [
(r"\binom{n}{k}", _binomial(n, k)),
(r"\tbinom{n}{k}", _binomial(n, k)),
(r"\dbinom{n}{k}", _binomial(n, k)),
(r"\binom{n}{0}", _binomial(n, 0)),
(r"x^\binom{n}{k}", _Pow(x, _binomial(n, k)))
]
EVALUATED_BINOMIAL_EXPRESSION_PAIRS = [
(r"\binom{n}{k}", binomial(n, k)),
(r"\tbinom{n}{k}", binomial(n, k)),
(r"\dbinom{n}{k}", binomial(n, k)),
(r"\binom{n}{0}", binomial(n, 0)),
(r"x^\binom{n}{k}", x ** binomial(n, k))
]
MISCELLANEOUS_EXPRESSION_PAIRS = [
(r"\left(x + y\right) z", _Mul(_Add(x, y), z)),
(r"\left( x + y\right ) z", _Mul(_Add(x, y), z)),
(r"\left( x + y\right ) z", _Mul(_Add(x, y), z)),
]
def test_symbol_expressions():
expected_failures = {6, 7}
for i, (latex_str, sympy_expr) in enumerate(SYMBOL_EXPRESSION_PAIRS):
if i in expected_failures:
continue
with evaluate(False):
assert parse_latex_lark(latex_str) == sympy_expr, latex_str
def test_simple_expressions():
expected_failures = {20}
for i, (latex_str, sympy_expr) in enumerate(UNEVALUATED_SIMPLE_EXPRESSION_PAIRS):
if i in expected_failures:
continue
with evaluate(False):
assert parse_latex_lark(latex_str) == sympy_expr, latex_str
for i, (latex_str, sympy_expr) in enumerate(EVALUATED_SIMPLE_EXPRESSION_PAIRS):
if i in expected_failures:
continue
assert parse_latex_lark(latex_str) == sympy_expr, latex_str
def test_fraction_expressions():
for latex_str, sympy_expr in UNEVALUATED_FRACTION_EXPRESSION_PAIRS:
with evaluate(False):
assert parse_latex_lark(latex_str) == sympy_expr, latex_str
for latex_str, sympy_expr in EVALUATED_FRACTION_EXPRESSION_PAIRS:
assert parse_latex_lark(latex_str) == sympy_expr, latex_str
def test_relation_expressions():
for latex_str, sympy_expr in RELATION_EXPRESSION_PAIRS:
with evaluate(False):
assert parse_latex_lark(latex_str) == sympy_expr, latex_str
def test_power_expressions():
expected_failures = {3}
for i, (latex_str, sympy_expr) in enumerate(UNEVALUATED_POWER_EXPRESSION_PAIRS):
if i in expected_failures:
continue
with evaluate(False):
assert parse_latex_lark(latex_str) == sympy_expr, latex_str
for i, (latex_str, sympy_expr) in enumerate(EVALUATED_POWER_EXPRESSION_PAIRS):
if i in expected_failures:
continue
assert parse_latex_lark(latex_str) == sympy_expr, latex_str
def test_integral_expressions():
expected_failures = {14}
for i, (latex_str, sympy_expr) in enumerate(UNEVALUATED_INTEGRAL_EXPRESSION_PAIRS):
if i in expected_failures:
continue
with evaluate(False):
assert parse_latex_lark(latex_str) == sympy_expr, i
for i, (latex_str, sympy_expr) in enumerate(EVALUATED_INTEGRAL_EXPRESSION_PAIRS):
if i in expected_failures:
continue
assert parse_latex_lark(latex_str) == sympy_expr, latex_str
def test_derivative_expressions():
expected_failures = {3, 4}
for i, (latex_str, sympy_expr) in enumerate(DERIVATIVE_EXPRESSION_PAIRS):
if i in expected_failures:
continue
with evaluate(False):
assert parse_latex_lark(latex_str) == sympy_expr, latex_str
for i, (latex_str, sympy_expr) in enumerate(DERIVATIVE_EXPRESSION_PAIRS):
if i in expected_failures:
continue
assert parse_latex_lark(latex_str) == sympy_expr, latex_str
def test_trigonometric_expressions():
expected_failures = {3}
for i, (latex_str, sympy_expr) in enumerate(TRIGONOMETRIC_EXPRESSION_PAIRS):
if i in expected_failures:
continue
with evaluate(False):
assert parse_latex_lark(latex_str) == sympy_expr, latex_str
def test_limit_expressions():
for latex_str, sympy_expr in UNEVALUATED_LIMIT_EXPRESSION_PAIRS:
with evaluate(False):
assert parse_latex_lark(latex_str) == sympy_expr, latex_str
def test_square_root_expressions():
for latex_str, sympy_expr in UNEVALUATED_SQRT_EXPRESSION_PAIRS:
with evaluate(False):
assert parse_latex_lark(latex_str) == sympy_expr, latex_str
for latex_str, sympy_expr in EVALUATED_SQRT_EXPRESSION_PAIRS:
assert parse_latex_lark(latex_str) == sympy_expr, latex_str
def test_factorial_expressions():
for latex_str, sympy_expr in UNEVALUATED_FACTORIAL_EXPRESSION_PAIRS:
with evaluate(False):
assert parse_latex_lark(latex_str) == sympy_expr, latex_str
for latex_str, sympy_expr in EVALUATED_FACTORIAL_EXPRESSION_PAIRS:
assert parse_latex_lark(latex_str) == sympy_expr, latex_str
def test_sum_expressions():
for latex_str, sympy_expr in UNEVALUATED_SUM_EXPRESSION_PAIRS:
with evaluate(False):
assert parse_latex_lark(latex_str) == sympy_expr, latex_str
for latex_str, sympy_expr in EVALUATED_SUM_EXPRESSION_PAIRS:
assert parse_latex_lark(latex_str) == sympy_expr, latex_str
def test_product_expressions():
for latex_str, sympy_expr in UNEVALUATED_PRODUCT_EXPRESSION_PAIRS:
with evaluate(False):
assert parse_latex_lark(latex_str) == sympy_expr, latex_str
@XFAIL
def test_applied_function_expressions():
expected_failures = {0, 3, 4} # 0 is ambiguous, and the others require not-yet-added features
# not sure why 1, and 2 are failing
for i, (latex_str, sympy_expr) in enumerate(APPLIED_FUNCTION_EXPRESSION_PAIRS):
if i in expected_failures:
continue
with evaluate(False):
assert parse_latex_lark(latex_str) == sympy_expr, latex_str
def test_common_function_expressions():
for latex_str, sympy_expr in UNEVALUATED_COMMON_FUNCTION_EXPRESSION_PAIRS:
with evaluate(False):
assert parse_latex_lark(latex_str) == sympy_expr, latex_str
for latex_str, sympy_expr in EVALUATED_COMMON_FUNCTION_EXPRESSION_PAIRS:
assert parse_latex_lark(latex_str) == sympy_expr, latex_str
# unhandled bug causing these to fail
@XFAIL
def test_spacing():
for latex_str, sympy_expr in SPACING_RELATED_EXPRESSION_PAIRS:
with evaluate(False):
assert parse_latex_lark(latex_str) == sympy_expr, latex_str
def test_binomial_expressions():
for latex_str, sympy_expr in UNEVALUATED_BINOMIAL_EXPRESSION_PAIRS:
with evaluate(False):
assert parse_latex_lark(latex_str) == sympy_expr, latex_str
for latex_str, sympy_expr in EVALUATED_BINOMIAL_EXPRESSION_PAIRS:
assert parse_latex_lark(latex_str) == sympy_expr, latex_str
def test_miscellaneous_expressions():
for latex_str, sympy_expr in MISCELLANEOUS_EXPRESSION_PAIRS:
with evaluate(False):
assert parse_latex_lark(latex_str) == sympy_expr, latex_str

View File

@ -0,0 +1,280 @@
from sympy import sin, Function, symbols, Dummy, Lambda, cos
from sympy.parsing.mathematica import parse_mathematica, MathematicaParser
from sympy.core.sympify import sympify
from sympy.abc import n, w, x, y, z
from sympy.testing.pytest import raises
def test_mathematica():
d = {
'- 6x': '-6*x',
'Sin[x]^2': 'sin(x)**2',
'2(x-1)': '2*(x-1)',
'3y+8': '3*y+8',
'ArcSin[2x+9(4-x)^2]/x': 'asin(2*x+9*(4-x)**2)/x',
'x+y': 'x+y',
'355/113': '355/113',
'2.718281828': '2.718281828',
'Cos(1/2 * π)': 'Cos(π/2)',
'Sin[12]': 'sin(12)',
'Exp[Log[4]]': 'exp(log(4))',
'(x+1)(x+3)': '(x+1)*(x+3)',
'Cos[ArcCos[3.6]]': 'cos(acos(3.6))',
'Cos[x]==Sin[y]': 'Eq(cos(x), sin(y))',
'2*Sin[x+y]': '2*sin(x+y)',
'Sin[x]+Cos[y]': 'sin(x)+cos(y)',
'Sin[Cos[x]]': 'sin(cos(x))',
'2*Sqrt[x+y]': '2*sqrt(x+y)', # Test case from the issue 4259
'+Sqrt[2]': 'sqrt(2)',
'-Sqrt[2]': '-sqrt(2)',
'-1/Sqrt[2]': '-1/sqrt(2)',
'-(1/Sqrt[3])': '-(1/sqrt(3))',
'1/(2*Sqrt[5])': '1/(2*sqrt(5))',
'Mod[5,3]': 'Mod(5,3)',
'-Mod[5,3]': '-Mod(5,3)',
'(x+1)y': '(x+1)*y',
'x(y+1)': 'x*(y+1)',
'Sin[x]Cos[y]': 'sin(x)*cos(y)',
'Sin[x]^2Cos[y]^2': 'sin(x)**2*cos(y)**2',
'Cos[x]^2(1 - Cos[y]^2)': 'cos(x)**2*(1-cos(y)**2)',
'x y': 'x*y',
'x y': 'x*y',
'2 x': '2*x',
'x 8': 'x*8',
'2 8': '2*8',
'4.x': '4.*x',
'4. 3': '4.*3',
'4. 3.': '4.*3.',
'1 2 3': '1*2*3',
' - 2 * Sqrt[ 2 3 * ( 1 + 5 ) ] ': '-2*sqrt(2*3*(1+5))',
'Log[2,4]': 'log(4,2)',
'Log[Log[2,4],4]': 'log(4,log(4,2))',
'Exp[Sqrt[2]^2Log[2, 8]]': 'exp(sqrt(2)**2*log(8,2))',
'ArcSin[Cos[0]]': 'asin(cos(0))',
'Log2[16]': 'log(16,2)',
'Max[1,-2,3,-4]': 'Max(1,-2,3,-4)',
'Min[1,-2,3]': 'Min(1,-2,3)',
'Exp[I Pi/2]': 'exp(I*pi/2)',
'ArcTan[x,y]': 'atan2(y,x)',
'Pochhammer[x,y]': 'rf(x,y)',
'ExpIntegralEi[x]': 'Ei(x)',
'SinIntegral[x]': 'Si(x)',
'CosIntegral[x]': 'Ci(x)',
'AiryAi[x]': 'airyai(x)',
'AiryAiPrime[5]': 'airyaiprime(5)',
'AiryBi[x]': 'airybi(x)',
'AiryBiPrime[7]': 'airybiprime(7)',
'LogIntegral[4]': ' li(4)',
'PrimePi[7]': 'primepi(7)',
'Prime[5]': 'prime(5)',
'PrimeQ[5]': 'isprime(5)',
'Rational[2,19]': 'Rational(2,19)', # test case for issue 25716
}
for e in d:
assert parse_mathematica(e) == sympify(d[e])
# The parsed form of this expression should not evaluate the Lambda object:
assert parse_mathematica("Sin[#]^2 + Cos[#]^2 &[x]") == sin(x)**2 + cos(x)**2
d1, d2, d3 = symbols("d1:4", cls=Dummy)
assert parse_mathematica("Sin[#] + Cos[#3] &").dummy_eq(Lambda((d1, d2, d3), sin(d1) + cos(d3)))
assert parse_mathematica("Sin[#^2] &").dummy_eq(Lambda(d1, sin(d1**2)))
assert parse_mathematica("Function[x, x^3]") == Lambda(x, x**3)
assert parse_mathematica("Function[{x, y}, x^2 + y^2]") == Lambda((x, y), x**2 + y**2)
def test_parser_mathematica_tokenizer():
parser = MathematicaParser()
chain = lambda expr: parser._from_tokens_to_fullformlist(parser._from_mathematica_to_tokens(expr))
# Basic patterns
assert chain("x") == "x"
assert chain("42") == "42"
assert chain(".2") == ".2"
assert chain("+x") == "x"
assert chain("-1") == "-1"
assert chain("- 3") == "-3"
assert chain("α") == "α"
assert chain("+Sin[x]") == ["Sin", "x"]
assert chain("-Sin[x]") == ["Times", "-1", ["Sin", "x"]]
assert chain("x(a+1)") == ["Times", "x", ["Plus", "a", "1"]]
assert chain("(x)") == "x"
assert chain("(+x)") == "x"
assert chain("-a") == ["Times", "-1", "a"]
assert chain("(-x)") == ["Times", "-1", "x"]
assert chain("(x + y)") == ["Plus", "x", "y"]
assert chain("3 + 4") == ["Plus", "3", "4"]
assert chain("a - 3") == ["Plus", "a", "-3"]
assert chain("a - b") == ["Plus", "a", ["Times", "-1", "b"]]
assert chain("7 * 8") == ["Times", "7", "8"]
assert chain("a + b*c") == ["Plus", "a", ["Times", "b", "c"]]
assert chain("a + b* c* d + 2 * e") == ["Plus", "a", ["Times", "b", "c", "d"], ["Times", "2", "e"]]
assert chain("a / b") == ["Times", "a", ["Power", "b", "-1"]]
# Missing asterisk (*) patterns:
assert chain("x y") == ["Times", "x", "y"]
assert chain("3 4") == ["Times", "3", "4"]
assert chain("a[b] c") == ["Times", ["a", "b"], "c"]
assert chain("(x) (y)") == ["Times", "x", "y"]
assert chain("3 (a)") == ["Times", "3", "a"]
assert chain("(a) b") == ["Times", "a", "b"]
assert chain("4.2") == "4.2"
assert chain("4 2") == ["Times", "4", "2"]
assert chain("4 2") == ["Times", "4", "2"]
assert chain("3 . 4") == ["Dot", "3", "4"]
assert chain("4. 2") == ["Times", "4.", "2"]
assert chain("x.y") == ["Dot", "x", "y"]
assert chain("4.y") == ["Times", "4.", "y"]
assert chain("4 .y") == ["Dot", "4", "y"]
assert chain("x.4") == ["Times", "x", ".4"]
assert chain("x0.3") == ["Times", "x0", ".3"]
assert chain("x. 4") == ["Dot", "x", "4"]
# Comments
assert chain("a (* +b *) + c") == ["Plus", "a", "c"]
assert chain("a (* + b *) + (**)c (* +d *) + e") == ["Plus", "a", "c", "e"]
assert chain("""a + (*
+ b
*) c + (* d
*) e
""") == ["Plus", "a", "c", "e"]
# Operators couples + and -, * and / are mutually associative:
# (i.e. expression gets flattened when mixing these operators)
assert chain("a*b/c") == ["Times", "a", "b", ["Power", "c", "-1"]]
assert chain("a/b*c") == ["Times", "a", ["Power", "b", "-1"], "c"]
assert chain("a+b-c") == ["Plus", "a", "b", ["Times", "-1", "c"]]
assert chain("a-b+c") == ["Plus", "a", ["Times", "-1", "b"], "c"]
assert chain("-a + b -c ") == ["Plus", ["Times", "-1", "a"], "b", ["Times", "-1", "c"]]
assert chain("a/b/c*d") == ["Times", "a", ["Power", "b", "-1"], ["Power", "c", "-1"], "d"]
assert chain("a/b/c") == ["Times", "a", ["Power", "b", "-1"], ["Power", "c", "-1"]]
assert chain("a-b-c") == ["Plus", "a", ["Times", "-1", "b"], ["Times", "-1", "c"]]
assert chain("1/a") == ["Times", "1", ["Power", "a", "-1"]]
assert chain("1/a/b") == ["Times", "1", ["Power", "a", "-1"], ["Power", "b", "-1"]]
assert chain("-1/a*b") == ["Times", "-1", ["Power", "a", "-1"], "b"]
# Enclosures of various kinds, i.e. ( ) [ ] [[ ]] { }
assert chain("(a + b) + c") == ["Plus", ["Plus", "a", "b"], "c"]
assert chain(" a + (b + c) + d ") == ["Plus", "a", ["Plus", "b", "c"], "d"]
assert chain("a * (b + c)") == ["Times", "a", ["Plus", "b", "c"]]
assert chain("a b (c d)") == ["Times", "a", "b", ["Times", "c", "d"]]
assert chain("{a, b, 2, c}") == ["List", "a", "b", "2", "c"]
assert chain("{a, {b, c}}") == ["List", "a", ["List", "b", "c"]]
assert chain("{{a}}") == ["List", ["List", "a"]]
assert chain("a[b, c]") == ["a", "b", "c"]
assert chain("a[[b, c]]") == ["Part", "a", "b", "c"]
assert chain("a[b[c]]") == ["a", ["b", "c"]]
assert chain("a[[b, c[[d, {e,f}]]]]") == ["Part", "a", "b", ["Part", "c", "d", ["List", "e", "f"]]]
assert chain("a[b[[c,d]]]") == ["a", ["Part", "b", "c", "d"]]
assert chain("a[[b[c]]]") == ["Part", "a", ["b", "c"]]
assert chain("a[[b[[c]]]]") == ["Part", "a", ["Part", "b", "c"]]
assert chain("a[[b[c[[d]]]]]") == ["Part", "a", ["b", ["Part", "c", "d"]]]
assert chain("a[b[[c[d]]]]") == ["a", ["Part", "b", ["c", "d"]]]
assert chain("x[[a+1, b+2, c+3]]") == ["Part", "x", ["Plus", "a", "1"], ["Plus", "b", "2"], ["Plus", "c", "3"]]
assert chain("x[a+1, b+2, c+3]") == ["x", ["Plus", "a", "1"], ["Plus", "b", "2"], ["Plus", "c", "3"]]
assert chain("{a+1, b+2, c+3}") == ["List", ["Plus", "a", "1"], ["Plus", "b", "2"], ["Plus", "c", "3"]]
# Flat operator:
assert chain("a*b*c*d*e") == ["Times", "a", "b", "c", "d", "e"]
assert chain("a +b + c+ d+e") == ["Plus", "a", "b", "c", "d", "e"]
# Right priority operator:
assert chain("a^b") == ["Power", "a", "b"]
assert chain("a^b^c") == ["Power", "a", ["Power", "b", "c"]]
assert chain("a^b^c^d") == ["Power", "a", ["Power", "b", ["Power", "c", "d"]]]
# Left priority operator:
assert chain("a/.b") == ["ReplaceAll", "a", "b"]
assert chain("a/.b/.c/.d") == ["ReplaceAll", ["ReplaceAll", ["ReplaceAll", "a", "b"], "c"], "d"]
assert chain("a//b") == ["a", "b"]
assert chain("a//b//c") == [["a", "b"], "c"]
assert chain("a//b//c//d") == [[["a", "b"], "c"], "d"]
# Compound expressions
assert chain("a;b") == ["CompoundExpression", "a", "b"]
assert chain("a;") == ["CompoundExpression", "a", "Null"]
assert chain("a;b;") == ["CompoundExpression", "a", "b", "Null"]
assert chain("a[b;c]") == ["a", ["CompoundExpression", "b", "c"]]
assert chain("a[b,c;d,e]") == ["a", "b", ["CompoundExpression", "c", "d"], "e"]
assert chain("a[b,c;,d]") == ["a", "b", ["CompoundExpression", "c", "Null"], "d"]
# New lines
assert chain("a\nb\n") == ["CompoundExpression", "a", "b"]
assert chain("a\n\nb\n (c \nd) \n") == ["CompoundExpression", "a", "b", ["Times", "c", "d"]]
assert chain("\na; b\nc") == ["CompoundExpression", "a", "b", "c"]
assert chain("a + \nb\n") == ["Plus", "a", "b"]
assert chain("a\nb; c; d\n e; (f \n g); h + \n i") == ["CompoundExpression", "a", "b", "c", "d", "e", ["Times", "f", "g"], ["Plus", "h", "i"]]
assert chain("\n{\na\nb; c; d\n e (f \n g); h + \n i\n\n}\n") == ["List", ["CompoundExpression", ["Times", "a", "b"], "c", ["Times", "d", "e", ["Times", "f", "g"]], ["Plus", "h", "i"]]]
# Patterns
assert chain("y_") == ["Pattern", "y", ["Blank"]]
assert chain("y_.") == ["Optional", ["Pattern", "y", ["Blank"]]]
assert chain("y__") == ["Pattern", "y", ["BlankSequence"]]
assert chain("y___") == ["Pattern", "y", ["BlankNullSequence"]]
assert chain("a[b_.,c_]") == ["a", ["Optional", ["Pattern", "b", ["Blank"]]], ["Pattern", "c", ["Blank"]]]
assert chain("b_. c") == ["Times", ["Optional", ["Pattern", "b", ["Blank"]]], "c"]
# Slots for lambda functions
assert chain("#") == ["Slot", "1"]
assert chain("#3") == ["Slot", "3"]
assert chain("#n") == ["Slot", "n"]
assert chain("##") == ["SlotSequence", "1"]
assert chain("##a") == ["SlotSequence", "a"]
# Lambda functions
assert chain("x&") == ["Function", "x"]
assert chain("#&") == ["Function", ["Slot", "1"]]
assert chain("#+3&") == ["Function", ["Plus", ["Slot", "1"], "3"]]
assert chain("#1 + #2&") == ["Function", ["Plus", ["Slot", "1"], ["Slot", "2"]]]
assert chain("# + #&") == ["Function", ["Plus", ["Slot", "1"], ["Slot", "1"]]]
assert chain("#&[x]") == [["Function", ["Slot", "1"]], "x"]
assert chain("#1 + #2 & [x, y]") == [["Function", ["Plus", ["Slot", "1"], ["Slot", "2"]]], "x", "y"]
assert chain("#1^2#2^3&") == ["Function", ["Times", ["Power", ["Slot", "1"], "2"], ["Power", ["Slot", "2"], "3"]]]
# Strings inside Mathematica expressions:
assert chain('"abc"') == ["_Str", "abc"]
assert chain('"a\\"b"') == ["_Str", 'a"b']
# This expression does not make sense mathematically, it's just testing the parser:
assert chain('x + "abc" ^ 3') == ["Plus", "x", ["Power", ["_Str", "abc"], "3"]]
assert chain('"a (* b *) c"') == ["_Str", "a (* b *) c"]
assert chain('"a" (* b *) ') == ["_Str", "a"]
assert chain('"a [ b] "') == ["_Str", "a [ b] "]
raises(SyntaxError, lambda: chain('"'))
raises(SyntaxError, lambda: chain('"\\"'))
raises(SyntaxError, lambda: chain('"abc'))
raises(SyntaxError, lambda: chain('"abc\\"def'))
# Invalid expressions:
raises(SyntaxError, lambda: chain("(,"))
raises(SyntaxError, lambda: chain("()"))
raises(SyntaxError, lambda: chain("a (* b"))
def test_parser_mathematica_exp_alt():
parser = MathematicaParser()
convert_chain2 = lambda expr: parser._from_fullformlist_to_fullformsympy(parser._from_fullform_to_fullformlist(expr))
convert_chain3 = lambda expr: parser._from_fullformsympy_to_sympy(convert_chain2(expr))
Sin, Times, Plus, Power = symbols("Sin Times Plus Power", cls=Function)
full_form1 = "Sin[Times[x, y]]"
full_form2 = "Plus[Times[x, y], z]"
full_form3 = "Sin[Times[x, Plus[y, z], Power[w, n]]]]"
full_form4 = "Rational[Rational[x, y], z]"
assert parser._from_fullform_to_fullformlist(full_form1) == ["Sin", ["Times", "x", "y"]]
assert parser._from_fullform_to_fullformlist(full_form2) == ["Plus", ["Times", "x", "y"], "z"]
assert parser._from_fullform_to_fullformlist(full_form3) == ["Sin", ["Times", "x", ["Plus", "y", "z"], ["Power", "w", "n"]]]
assert parser._from_fullform_to_fullformlist(full_form4) == ["Rational", ["Rational", "x", "y"], "z"]
assert convert_chain2(full_form1) == Sin(Times(x, y))
assert convert_chain2(full_form2) == Plus(Times(x, y), z)
assert convert_chain2(full_form3) == Sin(Times(x, Plus(y, z), Power(w, n)))
assert convert_chain3(full_form1) == sin(x*y)
assert convert_chain3(full_form2) == x*y + z
assert convert_chain3(full_form3) == sin(x*(y + z)*w**n)

View File

@ -0,0 +1,50 @@
from sympy.parsing.maxima import parse_maxima
from sympy.core.numbers import (E, Rational, oo)
from sympy.core.symbol import Symbol
from sympy.functions.combinatorial.factorials import factorial
from sympy.functions.elementary.complexes import Abs
from sympy.functions.elementary.exponential import log
from sympy.functions.elementary.trigonometric import (cos, sin)
from sympy.abc import x
n = Symbol('n', integer=True)
def test_parser():
assert Abs(parse_maxima('float(1/3)') - 0.333333333) < 10**(-5)
assert parse_maxima('13^26') == 91733330193268616658399616009
assert parse_maxima('sin(%pi/2) + cos(%pi/3)') == Rational(3, 2)
assert parse_maxima('log(%e)') == 1
def test_injection():
parse_maxima('c: x+1', globals=globals())
# c created by parse_maxima
assert c == x + 1 # noqa:F821
parse_maxima('g: sqrt(81)', globals=globals())
# g created by parse_maxima
assert g == 9 # noqa:F821
def test_maxima_functions():
assert parse_maxima('expand( (x+1)^2)') == x**2 + 2*x + 1
assert parse_maxima('factor( x**2 + 2*x + 1)') == (x + 1)**2
assert parse_maxima('2*cos(x)^2 + sin(x)^2') == 2*cos(x)**2 + sin(x)**2
assert parse_maxima('trigexpand(sin(2*x)+cos(2*x))') == \
-1 + 2*cos(x)**2 + 2*cos(x)*sin(x)
assert parse_maxima('solve(x^2-4,x)') == [-2, 2]
assert parse_maxima('limit((1+1/x)^x,x,inf)') == E
assert parse_maxima('limit(sqrt(-x)/x,x,0,minus)') is -oo
assert parse_maxima('diff(x^x, x)') == x**x*(1 + log(x))
assert parse_maxima('sum(k, k, 1, n)', name_dict={
"n": Symbol('n', integer=True),
"k": Symbol('k', integer=True)
}) == (n**2 + n)/2
assert parse_maxima('product(k, k, 1, n)', name_dict={
"n": Symbol('n', integer=True),
"k": Symbol('k', integer=True)
}) == factorial(n)
assert parse_maxima('ratsimp((x^2-1)/(x+1))') == x - 1
assert Abs( parse_maxima(
'float(sec(%pi/3) + csc(%pi/3))') - 3.154700538379252) < 10**(-5)

View File

@ -0,0 +1,209 @@
from sympy.parsing.sym_expr import SymPyExpression
from sympy.testing.pytest import raises
from sympy.external import import_module
lfortran = import_module('lfortran')
cin = import_module('clang.cindex', import_kwargs = {'fromlist': ['cindex']})
if lfortran and cin:
from sympy.codegen.ast import (Variable, IntBaseType, FloatBaseType, String,
Declaration, FloatType)
from sympy.core import Integer, Float
from sympy.core.symbol import Symbol
expr1 = SymPyExpression()
src = """\
integer :: a, b, c, d
real :: p, q, r, s
"""
def test_c_parse():
src1 = """\
int a, b = 4;
float c, d = 2.4;
"""
expr1.convert_to_expr(src1, 'c')
ls = expr1.return_expr()
assert ls[0] == Declaration(
Variable(
Symbol('a'),
type=IntBaseType(String('intc'))
)
)
assert ls[1] == Declaration(
Variable(
Symbol('b'),
type=IntBaseType(String('intc')),
value=Integer(4)
)
)
assert ls[2] == Declaration(
Variable(
Symbol('c'),
type=FloatType(
String('float32'),
nbits=Integer(32),
nmant=Integer(23),
nexp=Integer(8)
)
)
)
assert ls[3] == Declaration(
Variable(
Symbol('d'),
type=FloatType(
String('float32'),
nbits=Integer(32),
nmant=Integer(23),
nexp=Integer(8)
),
value=Float('2.3999999999999999', precision=53)
)
)
def test_fortran_parse():
expr = SymPyExpression(src, 'f')
ls = expr.return_expr()
assert ls[0] == Declaration(
Variable(
Symbol('a'),
type=IntBaseType(String('integer')),
value=Integer(0)
)
)
assert ls[1] == Declaration(
Variable(
Symbol('b'),
type=IntBaseType(String('integer')),
value=Integer(0)
)
)
assert ls[2] == Declaration(
Variable(
Symbol('c'),
type=IntBaseType(String('integer')),
value=Integer(0)
)
)
assert ls[3] == Declaration(
Variable(
Symbol('d'),
type=IntBaseType(String('integer')),
value=Integer(0)
)
)
assert ls[4] == Declaration(
Variable(
Symbol('p'),
type=FloatBaseType(String('real')),
value=Float('0.0', precision=53)
)
)
assert ls[5] == Declaration(
Variable(
Symbol('q'),
type=FloatBaseType(String('real')),
value=Float('0.0', precision=53)
)
)
assert ls[6] == Declaration(
Variable(
Symbol('r'),
type=FloatBaseType(String('real')),
value=Float('0.0', precision=53)
)
)
assert ls[7] == Declaration(
Variable(
Symbol('s'),
type=FloatBaseType(String('real')),
value=Float('0.0', precision=53)
)
)
def test_convert_py():
src1 = (
src +
"""\
a = b + c
s = p * q / r
"""
)
expr1.convert_to_expr(src1, 'f')
exp_py = expr1.convert_to_python()
assert exp_py == [
'a = 0',
'b = 0',
'c = 0',
'd = 0',
'p = 0.0',
'q = 0.0',
'r = 0.0',
's = 0.0',
'a = b + c',
's = p*q/r'
]
def test_convert_fort():
src1 = (
src +
"""\
a = b + c
s = p * q / r
"""
)
expr1.convert_to_expr(src1, 'f')
exp_fort = expr1.convert_to_fortran()
assert exp_fort == [
' integer*4 a',
' integer*4 b',
' integer*4 c',
' integer*4 d',
' real*8 p',
' real*8 q',
' real*8 r',
' real*8 s',
' a = b + c',
' s = p*q/r'
]
def test_convert_c():
src1 = (
src +
"""\
a = b + c
s = p * q / r
"""
)
expr1.convert_to_expr(src1, 'f')
exp_c = expr1.convert_to_c()
assert exp_c == [
'int a = 0',
'int b = 0',
'int c = 0',
'int d = 0',
'double p = 0.0',
'double q = 0.0',
'double r = 0.0',
'double s = 0.0',
'a = b + c;',
's = p*q/r;'
]
def test_exceptions():
src = 'int a;'
raises(ValueError, lambda: SymPyExpression(src))
raises(ValueError, lambda: SymPyExpression(mode = 'c'))
raises(NotImplementedError, lambda: SymPyExpression(src, mode = 'd'))
elif not lfortran and not cin:
def test_raise():
raises(ImportError, lambda: SymPyExpression('int a;', 'c'))
raises(ImportError, lambda: SymPyExpression('integer :: a', 'f'))

View File

@ -0,0 +1,372 @@
# -*- coding: utf-8 -*-
import sys
import builtins
import types
from sympy.assumptions import Q
from sympy.core import Symbol, Function, Float, Rational, Integer, I, Mul, Pow, Eq, Lt, Le, Gt, Ge, Ne
from sympy.functions import exp, factorial, factorial2, sin, Min, Max
from sympy.logic import And
from sympy.series import Limit
from sympy.testing.pytest import raises, skip
from sympy.parsing.sympy_parser import (
parse_expr, standard_transformations, rationalize, TokenError,
split_symbols, implicit_multiplication, convert_equals_signs,
convert_xor, function_exponentiation, lambda_notation, auto_symbol,
repeated_decimals, implicit_multiplication_application,
auto_number, factorial_notation, implicit_application,
_transformation, T
)
def test_sympy_parser():
x = Symbol('x')
inputs = {
'2*x': 2 * x,
'3.00': Float(3),
'22/7': Rational(22, 7),
'2+3j': 2 + 3*I,
'exp(x)': exp(x),
'x!': factorial(x),
'x!!': factorial2(x),
'(x + 1)! - 1': factorial(x + 1) - 1,
'3.[3]': Rational(10, 3),
'.0[3]': Rational(1, 30),
'3.2[3]': Rational(97, 30),
'1.3[12]': Rational(433, 330),
'1 + 3.[3]': Rational(13, 3),
'1 + .0[3]': Rational(31, 30),
'1 + 3.2[3]': Rational(127, 30),
'.[0011]': Rational(1, 909),
'0.1[00102] + 1': Rational(366697, 333330),
'1.[0191]': Rational(10190, 9999),
'10!': 3628800,
'-(2)': -Integer(2),
'[-1, -2, 3]': [Integer(-1), Integer(-2), Integer(3)],
'Symbol("x").free_symbols': x.free_symbols,
"S('S(3).n(n=3)')": Float(3, 3),
'factorint(12, visual=True)': Mul(
Pow(2, 2, evaluate=False),
Pow(3, 1, evaluate=False),
evaluate=False),
'Limit(sin(x), x, 0, dir="-")': Limit(sin(x), x, 0, dir='-'),
'Q.even(x)': Q.even(x),
}
for text, result in inputs.items():
assert parse_expr(text) == result
raises(TypeError, lambda:
parse_expr('x', standard_transformations))
raises(TypeError, lambda:
parse_expr('x', transformations=lambda x,y: 1))
raises(TypeError, lambda:
parse_expr('x', transformations=(lambda x,y: 1,)))
raises(TypeError, lambda: parse_expr('x', transformations=((),)))
raises(TypeError, lambda: parse_expr('x', {}, [], []))
raises(TypeError, lambda: parse_expr('x', [], [], {}))
raises(TypeError, lambda: parse_expr('x', [], [], {}))
def test_rationalize():
inputs = {
'0.123': Rational(123, 1000)
}
transformations = standard_transformations + (rationalize,)
for text, result in inputs.items():
assert parse_expr(text, transformations=transformations) == result
def test_factorial_fail():
inputs = ['x!!!', 'x!!!!', '(!)']
for text in inputs:
try:
parse_expr(text)
assert False
except TokenError:
assert True
def test_repeated_fail():
inputs = ['1[1]', '.1e1[1]', '0x1[1]', '1.1j[1]', '1.1[1 + 1]',
'0.1[[1]]', '0x1.1[1]']
# All are valid Python, so only raise TypeError for invalid indexing
for text in inputs:
raises(TypeError, lambda: parse_expr(text))
inputs = ['0.1[', '0.1[1', '0.1[]']
for text in inputs:
raises((TokenError, SyntaxError), lambda: parse_expr(text))
def test_repeated_dot_only():
assert parse_expr('.[1]') == Rational(1, 9)
assert parse_expr('1 + .[1]') == Rational(10, 9)
def test_local_dict():
local_dict = {
'my_function': lambda x: x + 2
}
inputs = {
'my_function(2)': Integer(4)
}
for text, result in inputs.items():
assert parse_expr(text, local_dict=local_dict) == result
def test_local_dict_split_implmult():
t = standard_transformations + (split_symbols, implicit_multiplication,)
w = Symbol('w', real=True)
y = Symbol('y')
assert parse_expr('yx', local_dict={'x':w}, transformations=t) == y*w
def test_local_dict_symbol_to_fcn():
x = Symbol('x')
d = {'foo': Function('bar')}
assert parse_expr('foo(x)', local_dict=d) == d['foo'](x)
d = {'foo': Symbol('baz')}
raises(TypeError, lambda: parse_expr('foo(x)', local_dict=d))
def test_global_dict():
global_dict = {
'Symbol': Symbol
}
inputs = {
'Q & S': And(Symbol('Q'), Symbol('S'))
}
for text, result in inputs.items():
assert parse_expr(text, global_dict=global_dict) == result
def test_no_globals():
# Replicate creating the default global_dict:
default_globals = {}
exec('from sympy import *', default_globals)
builtins_dict = vars(builtins)
for name, obj in builtins_dict.items():
if isinstance(obj, types.BuiltinFunctionType):
default_globals[name] = obj
default_globals['max'] = Max
default_globals['min'] = Min
# Need to include Symbol or parse_expr will not work:
default_globals.pop('Symbol')
global_dict = {'Symbol':Symbol}
for name in default_globals:
obj = parse_expr(name, global_dict=global_dict)
assert obj == Symbol(name)
def test_issue_2515():
raises(TokenError, lambda: parse_expr('(()'))
raises(TokenError, lambda: parse_expr('"""'))
def test_issue_7663():
x = Symbol('x')
e = '2*(x+1)'
assert parse_expr(e, evaluate=0) == parse_expr(e, evaluate=False)
assert parse_expr(e, evaluate=0).equals(2*(x+1))
def test_recursive_evaluate_false_10560():
inputs = {
'4*-3' : '4*-3',
'-4*3' : '(-4)*3',
"-2*x*y": '(-2)*x*y',
"x*-4*x": "x*(-4)*x"
}
for text, result in inputs.items():
assert parse_expr(text, evaluate=False) == parse_expr(result, evaluate=False)
def test_function_evaluate_false():
inputs = [
'Abs(0)', 'im(0)', 're(0)', 'sign(0)', 'arg(0)', 'conjugate(0)',
'acos(0)', 'acot(0)', 'acsc(0)', 'asec(0)', 'asin(0)', 'atan(0)',
'acosh(0)', 'acoth(0)', 'acsch(0)', 'asech(0)', 'asinh(0)', 'atanh(0)',
'cos(0)', 'cot(0)', 'csc(0)', 'sec(0)', 'sin(0)', 'tan(0)',
'cosh(0)', 'coth(0)', 'csch(0)', 'sech(0)', 'sinh(0)', 'tanh(0)',
'exp(0)', 'log(0)', 'sqrt(0)',
]
for case in inputs:
expr = parse_expr(case, evaluate=False)
assert case == str(expr) != str(expr.doit())
assert str(parse_expr('ln(0)', evaluate=False)) == 'log(0)'
assert str(parse_expr('cbrt(0)', evaluate=False)) == '0**(1/3)'
def test_issue_10773():
inputs = {
'-10/5': '(-10)/5',
'-10/-5' : '(-10)/(-5)',
}
for text, result in inputs.items():
assert parse_expr(text, evaluate=False) == parse_expr(result, evaluate=False)
def test_split_symbols():
transformations = standard_transformations + \
(split_symbols, implicit_multiplication,)
x = Symbol('x')
y = Symbol('y')
xy = Symbol('xy')
assert parse_expr("xy") == xy
assert parse_expr("xy", transformations=transformations) == x*y
def test_split_symbols_function():
transformations = standard_transformations + \
(split_symbols, implicit_multiplication,)
x = Symbol('x')
y = Symbol('y')
a = Symbol('a')
f = Function('f')
assert parse_expr("ay(x+1)", transformations=transformations) == a*y*(x+1)
assert parse_expr("af(x+1)", transformations=transformations,
local_dict={'f':f}) == a*f(x+1)
def test_functional_exponent():
t = standard_transformations + (convert_xor, function_exponentiation)
x = Symbol('x')
y = Symbol('y')
a = Symbol('a')
yfcn = Function('y')
assert parse_expr("sin^2(x)", transformations=t) == (sin(x))**2
assert parse_expr("sin^y(x)", transformations=t) == (sin(x))**y
assert parse_expr("exp^y(x)", transformations=t) == (exp(x))**y
assert parse_expr("E^y(x)", transformations=t) == exp(yfcn(x))
assert parse_expr("a^y(x)", transformations=t) == a**(yfcn(x))
def test_match_parentheses_implicit_multiplication():
transformations = standard_transformations + \
(implicit_multiplication,)
raises(TokenError, lambda: parse_expr('(1,2),(3,4]',transformations=transformations))
def test_convert_equals_signs():
transformations = standard_transformations + \
(convert_equals_signs, )
x = Symbol('x')
y = Symbol('y')
assert parse_expr("1*2=x", transformations=transformations) == Eq(2, x)
assert parse_expr("y = x", transformations=transformations) == Eq(y, x)
assert parse_expr("(2*y = x) = False",
transformations=transformations) == Eq(Eq(2*y, x), False)
def test_parse_function_issue_3539():
x = Symbol('x')
f = Function('f')
assert parse_expr('f(x)') == f(x)
def test_issue_24288():
inputs = {
"1 < 2": Lt(1, 2, evaluate=False),
"1 <= 2": Le(1, 2, evaluate=False),
"1 > 2": Gt(1, 2, evaluate=False),
"1 >= 2": Ge(1, 2, evaluate=False),
"1 != 2": Ne(1, 2, evaluate=False),
"1 == 2": Eq(1, 2, evaluate=False)
}
for text, result in inputs.items():
assert parse_expr(text, evaluate=False) == result
def test_split_symbols_numeric():
transformations = (
standard_transformations +
(implicit_multiplication_application,))
n = Symbol('n')
expr1 = parse_expr('2**n * 3**n')
expr2 = parse_expr('2**n3**n', transformations=transformations)
assert expr1 == expr2 == 2**n*3**n
expr1 = parse_expr('n12n34', transformations=transformations)
assert expr1 == n*12*n*34
def test_unicode_names():
assert parse_expr('α') == Symbol('α')
def test_python3_features():
# Make sure the tokenizer can handle Python 3-only features
if sys.version_info < (3, 8):
skip("test_python3_features requires Python 3.8 or newer")
assert parse_expr("123_456") == 123456
assert parse_expr("1.2[3_4]") == parse_expr("1.2[34]") == Rational(611, 495)
assert parse_expr("1.2[012_012]") == parse_expr("1.2[012012]") == Rational(400, 333)
assert parse_expr('.[3_4]') == parse_expr('.[34]') == Rational(34, 99)
assert parse_expr('.1[3_4]') == parse_expr('.1[34]') == Rational(133, 990)
assert parse_expr('123_123.123_123[3_4]') == parse_expr('123123.123123[34]') == Rational(12189189189211, 99000000)
def test_issue_19501():
x = Symbol('x')
eq = parse_expr('E**x(1+x)', local_dict={'x': x}, transformations=(
standard_transformations +
(implicit_multiplication_application,)))
assert eq.free_symbols == {x}
def test_parsing_definitions():
from sympy.abc import x
assert len(_transformation) == 12 # if this changes, extend below
assert _transformation[0] == lambda_notation
assert _transformation[1] == auto_symbol
assert _transformation[2] == repeated_decimals
assert _transformation[3] == auto_number
assert _transformation[4] == factorial_notation
assert _transformation[5] == implicit_multiplication_application
assert _transformation[6] == convert_xor
assert _transformation[7] == implicit_application
assert _transformation[8] == implicit_multiplication
assert _transformation[9] == convert_equals_signs
assert _transformation[10] == function_exponentiation
assert _transformation[11] == rationalize
assert T[:5] == T[0,1,2,3,4] == standard_transformations
t = _transformation
assert T[-1, 0] == (t[len(t) - 1], t[0])
assert T[:5, 8] == standard_transformations + (t[8],)
assert parse_expr('0.3x^2', transformations='all') == 3*x**2/10
assert parse_expr('sin 3x', transformations='implicit') == sin(3*x)
def test_builtins():
cases = [
('abs(x)', 'Abs(x)'),
('max(x, y)', 'Max(x, y)'),
('min(x, y)', 'Min(x, y)'),
('pow(x, y)', 'Pow(x, y)'),
]
for built_in_func_call, sympy_func_call in cases:
assert parse_expr(built_in_func_call) == parse_expr(sympy_func_call)
assert str(parse_expr('pow(38, -1, 97)')) == '23'
def test_issue_22822():
raises(ValueError, lambda: parse_expr('x', {'': 1}))
data = {'some_parameter': None}
assert parse_expr('some_parameter is None', data) is True