【问题标题】:Parsing AsciiMath to Python expression将 AsciiMath 解析为 Python 表达式
【发布时间】:2019-09-20 11:29:46
【问题描述】:

我试图通过 JSON 将 2 个函数传递给 python 脚本,以评估它们的等价性。我遇到的问题是输入采用AsciiMath 表示法。如果格式与 Python 表达式的格式一致,则 sympify 似乎没有问题从字符串中解析表达式。有没有办法将 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)

【问题讨论】:

  • 什么是“ASCII 数学符号”?
  • @user2357112 请看:asciimath.org
  • 这是一个解析 AsciiMath 的 python 库:github.com/favalex/python-asciimathml我用谷歌找到的,你尝试了什么?
  • 这是 AsciiMath,而不是“ASCII 数学表示法”或“ASCII 表示法”。
  • @user2357112 理解。我已经更正了语言。谢谢

标签: php python sympy mathjax asciimath


【解决方案1】:

当问这样的问题时,你应该证明这个问题。这就是我认为正在发生的事情。

使用一组表达式,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

但是使用 x 符号的相同 Python 表达式会产生 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

【讨论】:

  • 感谢您的帮助。你是对的 - 上面的例子正是问题所在
  • 如何从这里处理这个问题?我已经研究了几天,但未能制定出前进的策略
  • 非常感谢您的彻底回复。你提供了很好的背景和例子。我认为这里有足够的空间让我继续前进并尝试不同的输入。
猜你喜欢
  • 2016-04-04
  • 1970-01-01
  • 2010-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-07
  • 1970-01-01
  • 2011-06-05
相关资源
最近更新 更多