【问题标题】:Algorithm to invert strings of algebraic expressions in Python在 Python 中反转代数表达式字符串的算法
【发布时间】:2013-06-05 20:12:32
【问题描述】:

是否有一种简单的方法可以使函数反转算法,例如:

>>> value = inverse("y = 2*x+3")
>>> print(value)
"x = (y-3)/2"

如果您无法为该函数编写实际代码,请向我推荐可以使这项任务更容易的工具。该函数仅用于使用 +、-、* 和 /

进行逆算法

【问题讨论】:

  • 将表达式解析为 AST。走AST,倒置它。反编译 AST。利润。

标签: python function expression sympy symbolic-math


【解决方案1】:

你应该尝试 SymPy 来做到这一点:

from sympy import solve
from sympy.abc import x, y

e = 2*x+3-y

solve(e,x)
#[y/2 - 3/2]
solve(e,y)
#[2*x + 3]

基于此,您可以构建您的 inverse() 类似(适用于两个变量):

def inverse(string, left_string=None):
    from sympy import solve, Symbol, sympify
    string = '-' + string
    e = sympify(string.replace('=','+'))
    if left_string:
        ans = left_string + ' = ' + str(solve(e, sympify(left_string))[0])
    else:
        left = sympify(string.split('=')[0].strip().replace('-',''))
        symbols = e.free_symbols
        symbols.remove( left )
        right = list(symbols)[0]
        ans = str(right) + ' = ' + str(solve(e, right)[0])
    return ans

例子:

inverse(' x = 4*y/2')
#'y = x/2'

inverse(' y = 100/x + x**2')
#'x = -y/(3*(sqrt(-y**3/27 + 2500) + 50)**(1/3)) - (sqrt(-y**3/27 + 2500) + 50)**(1/3)'

inverse("screeny = (isox+isoy)*29/2.0344827586206895", "isoy")
#'isoy = -isox + 0.0701545778834721*screeny'

【讨论】:

  • 我认为使用sympy.sympify.free_symbols 可以简化一点。
  • DSM,你能举个例子吗?谢谢 sgpc,我会在我的项目中试试这个。
  • @DSM,谢谢!我使用 sympify 更新了答案,但是 free_symbols 呢?
【解决方案2】:

评论有点长,但这是我的想法:

import sympy

def inverse(s):
    terms = [sympy.sympify(term) for term in s.split("=")]
    eqn = sympy.Eq(*terms)
    var_to_solve_for = min(terms[1].free_symbols)
    solns = sympy.solve(eqn, var_to_solve_for)
    output_eqs = [sympy.Eq(var_to_solve_for, soln) for soln in solns]
    return output_eqs

之后我们有

>>> inverse("y = 2*x+3")
[x == y/2 - 3/2]
>>> inverse("x = 100/z + z**2")
[z == -x/(3*(sqrt(-x**3/27 + 2500) + 50)**(1/3)) - (sqrt(-x**3/27 + 2500) + 50)**(1/3), z == -x/(3*(-1/2 - sqrt(3)*I/2)*(sqrt(-x**3/27 + 2500) + 50)**(1/3)) - (-1/2 - sqrt(3)*I/2)*(sqrt(-x**3/27 + 2500) + 50)**(1/3), 
z == -x/(3*(-1/2 + sqrt(3)*I/2)*(sqrt(-x**3/27 + 2500) + 50)**(1/3)) - (-1/2 + sqrt(3)*I/2)*(sqrt(-x**3/27 + 2500) + 50)**(1/3)]

等等

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-27
    • 1970-01-01
    • 2015-12-03
    相关资源
    最近更新 更多