从(解析)Sympy 结果中提取值的可靠方法
Reliable way to extract values from (parse) Sympy result
我正在使用 SymPy, a Python library for symbolic mathematics, to reduce inequalities 以编程方式读入,例如
from sympy.solvers.inequalities import reduce_rational_inequalities
# In reality, these inequalities are read in programmatically
inequality1 = 'x - 0.5 >= 0.0'
inequality2 = '0.49 - x**2 >= 0.0'
listOfInequalities = [sympy.parse_expr(inequality1), sympy.parse_expr (inequality2)]
ReducedInequalities = reduce_rational_inequalities([listOfInequalities], x)
产生对应于 x 在 0.5 和 0.7 之间的正确结果:
0.5≤∧≤0.7
或者,表示为字符串:
strReducedInequalities = str(ReducedInequalities)
\begin{equation*}(0.5 <= x) & (x <= 0.7)\end{equation*}
我的问题是,是否有可靠的方法来解析这样的结果以提取常量 0.5 和 0.7?我可以搜索结果 strReducedInequalities,或者可能使用正则表达式来查找字符串的位置,例如 '(' 和 '<= x' 以提取 0.5。但这看起来很脆弱:如果 SymPy 要更改其输出格式化,代码可能会中断。
更可靠的是结构化的遍历输出的方式,例如strReducedInequalities可以表示为
[expression1, joiner, expression2]
哪里
- expression1 表示 (0.5 <= x)
- 加入者代表&
- expression2 表示 (x <= 0.7)
然后 expression1 可能会分解为
[constant, inequality_type, variable]
哪里
- 常量 = 0.5
- inequality_type表示<=(小于等于)
- 变量 = x
解决方案
以下是我如何实施来自 @smichr 的优秀解决方案:
from sympy import *
from sympy.core.relational import Relational
x = symbols('x')
eq = solve([x >= 0.5, x <= 0.7])
[(i.rhs, i.rel_op, i.lhs) for i in [i.canonical for i in eq.atoms(Relational)]]
或者在我原来的问题中使用程序生成的列表方法:
from sympy import *
from sympy.core.relational import Relational
x = symbols('x')
# In reality, these inequalities are read in programmatically
inequality1 = 'x - 0.5 >= 0.0'
inequality2 = '0.49 - x**2 >= 0.0'
listOfInequalities = [parse_expr(inequality1), parse_expr (inequality2)]
eq = solve(listOfInequalities)
[(i.rhs, i.rel_op, i.lhs) for i in [i.canonical for i in eq.atoms(Relational)]]
使用任一方法的结果:
[(0.500000000000000, '>=', x), (0.700000000000000, '<=', x)]
如果关系已经解决,那么一侧有一个符号,另一侧有一个值,canonical
方法会将它们按顺序排列,所以符号在左边:
>>> eq
(1/2 <= x) & (x <= 7/10)
>>> [(i.rhs, i.rel_op, i.lhs) for i in [i.canonical for i in eq.atoms(Relational)]]
[(7/10, '<=', x), (1/2, '>=', x)]
我正在使用 SymPy, a Python library for symbolic mathematics, to reduce inequalities 以编程方式读入,例如
from sympy.solvers.inequalities import reduce_rational_inequalities
# In reality, these inequalities are read in programmatically
inequality1 = 'x - 0.5 >= 0.0'
inequality2 = '0.49 - x**2 >= 0.0'
listOfInequalities = [sympy.parse_expr(inequality1), sympy.parse_expr (inequality2)]
ReducedInequalities = reduce_rational_inequalities([listOfInequalities], x)
产生对应于 x 在 0.5 和 0.7 之间的正确结果:
0.5≤∧≤0.7
或者,表示为字符串:
strReducedInequalities = str(ReducedInequalities)
\begin{equation*}(0.5 <= x) & (x <= 0.7)\end{equation*}
我的问题是,是否有可靠的方法来解析这样的结果以提取常量 0.5 和 0.7?我可以搜索结果 strReducedInequalities,或者可能使用正则表达式来查找字符串的位置,例如 '(' 和 '<= x' 以提取 0.5。但这看起来很脆弱:如果 SymPy 要更改其输出格式化,代码可能会中断。
更可靠的是结构化的遍历输出的方式,例如strReducedInequalities可以表示为
[expression1, joiner, expression2]
哪里
- expression1 表示 (0.5 <= x)
- 加入者代表&
- expression2 表示 (x <= 0.7)
然后 expression1 可能会分解为
[constant, inequality_type, variable]
哪里
- 常量 = 0.5
- inequality_type表示<=(小于等于)
- 变量 = x
解决方案
以下是我如何实施来自 @smichr 的优秀解决方案:
from sympy import *
from sympy.core.relational import Relational
x = symbols('x')
eq = solve([x >= 0.5, x <= 0.7])
[(i.rhs, i.rel_op, i.lhs) for i in [i.canonical for i in eq.atoms(Relational)]]
或者在我原来的问题中使用程序生成的列表方法:
from sympy import *
from sympy.core.relational import Relational
x = symbols('x')
# In reality, these inequalities are read in programmatically
inequality1 = 'x - 0.5 >= 0.0'
inequality2 = '0.49 - x**2 >= 0.0'
listOfInequalities = [parse_expr(inequality1), parse_expr (inequality2)]
eq = solve(listOfInequalities)
[(i.rhs, i.rel_op, i.lhs) for i in [i.canonical for i in eq.atoms(Relational)]]
使用任一方法的结果:
[(0.500000000000000, '>=', x), (0.700000000000000, '<=', x)]
如果关系已经解决,那么一侧有一个符号,另一侧有一个值,canonical
方法会将它们按顺序排列,所以符号在左边:
>>> eq
(1/2 <= x) & (x <= 7/10)
>>> [(i.rhs, i.rel_op, i.lhs) for i in [i.canonical for i in eq.atoms(Relational)]]
[(7/10, '<=', x), (1/2, '>=', x)]