123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- 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)
|