Разбор выражения AsciiMath в Python - PullRequest
0 голосов
/ 02 мая 2019

Я пытаюсь передать 2 функции скрипту Python через JSON, чтобы оценить их эквивалентность.У меня проблема заключается в том, что ввод в AsciiMath записи.Кажется, sympify не имеет проблем с синтаксическим анализом выражений из строк, если формат соответствует формату выражений Python.Есть ли способ разбить нотацию AsciiMath на что-то, что Python может интерпретировать?Мне не удалось найти ни одной библиотеки, предлагающей такую ​​функцию.

PHP:

$data = array("2*x", "x*2"); // returns true as expected
$data = array("2x", "x2"); // AsciiMath notation does not work
$result = shell_exec('python /path/check.py ' . escapeshellarg(json_encode($data)));

Python:

import sys, json
from sympy import *

# Load the json data sent from PHP
try:
    data = json.loads(sys.argv[1])
except:
    sys.exit(1)

x = Symbol('x')

# Convert string inputs to expressions
user_response = sympify(data[0])
correct_answer = sympify(data[1])

# Perform equivalence comparison
result = user_response == correct_answer

# Return result
print json.dumps(result)

1 Ответ

2 голосов
/ 02 мая 2019

Задавая такой вопрос, вы должны продемонстрировать проблему.Вот что, я думаю, происходит.

С одним набором выражений sympify отлично работает:

In [144]: sympify('2*x')==sympify('x*2')                                             
Out[144]: True

Но с другой парой:

In [145]: sympify('2x')==sympify('x2')                                               
---------------------------------------------------------------------------
SyntaxError                               Traceback (most recent call last)
/usr/local/lib/python3.6/dist-packages/sympy/core/sympify.py in sympify(a, locals, convert_xor, strict, rational, evaluate)
    367         a = a.replace('\n', '')
--> 368         expr = parse_expr(a, local_dict=locals, transformations=transformations, evaluate=evaluate)
    369     except (TokenError, SyntaxError) as exc:
 ...
SympifyError: Sympify of expression 'could not parse '2x'' failed, because of exception being raised:
SyntaxError: invalid syntax (<string>, line 1)

Этотолько для строки «2x».Для другой строки:

In [146]: sympify('x2')                                                              
Out[146]: x₂

sympify ожидает строки, которые могут быть вычислены в sympy среде

Преобразует произвольное выражение в тип, который может использоваться внутриSymPy.

Там написано arbitrary, но документы несколько более строгие, как описано.

It currently accepts as arguments:
   - any object defined in sympy
   - standard numeric python types: int, long, float, Decimal
   - strings (like "0.09" or "2e-19")
   - booleans, including ``None`` (will leave ``None`` unchanged)
   - lists, sets or tuples containing any of the above

В контексте вопроса это означает выражения, использующие xкоторый был определен с помощью

x = Symbol('x')

, но у тех, кто использует y, могут возникнуть проблемы.

===

sympify создает выражение sympy:

In [161]: expr = sympify('2*x')                                                      

In [162]: type(expr)                                                                 
Out[162]: sympy.core.mul.Mul

, который затем можно «оценить» различными способами.Я мог бы описать это как «модифицированный», за исключением того, что sympy подчеркивает, что выражение является неизменным.Все эти действия создают новые выражения или значения:

In [163]: expr.subs(x,21)                                                            
Out[163]: 42

In [164]: expr.diff(x)                                                               
Out[164]: 2

In [165]: expr.integrate(x)                                                          
Out[165]: 
 2
x 

===

Также такое выражение не может быть оценено основным интерпретатором Python,

Определить новый символи выражение:

In [166]: y = Symbol('y')                                                            
In [167]: expr = sympify('2*y')                                                      

In [168]: expr                                                                       
Out[168]: 2⋅y

Переназначение y на целое число Python не меняет значение expr:

In [169]: y = 21                                                                         
In [170]: expr                                                                       
Out[170]: 2⋅y

, но позволяет оценитьобычное выражение Python:

In [171]: 2*y                                                                        
Out[171]: 42

Но то же самое выражение Python с использованием символа x создает выражение sympy:

In [172]: 2*x                                                                        
Out[172]: 2⋅x

===

https://docs.sympy.org/latest/modules/parsing.html

Этот модуль parsing имеет средства обработки выражений типа '2x'.По крайней мере, документы показывают:

(снова в сеансе isympy):

In [173]: from sympy.parsing.sympy_parser import parse_expr                          

In [174]: from sympy.parsing.sympy_parser import parse_expr, standard_transformations
     ...: , implicit_multiplication_application                                      

In [175]: transformations=(standard_transformations + (implicit_multiplication_applic
     ...: ation,))                                                                   

In [176]: parse_expr('2x', transformations=transformations)                          
Out[176]: 2⋅x

In [177]: parse_expr('x2', transformations=transformations)                          
Out[177]: 2⋅x

Так что он справляется с вашим примером, но я не знаю достаточно asciimatch, чтобызнать, сколько еще работает.

На этой странице также говорится о LaTeX парсере, https://docs.sympy.org/latest/modules/parsing.html#experimental-latex-parsing

...