无冗余地定义和求解方程 (Python)
Define and solve Equation without redundancy (Python)
建立物理方程的标准方法似乎是在这里找到的方法:
你拿你的方程式,在那个 Whosebug post 它是 s = v*t
并且要么写多个函数,像这样:
def s(v, t):
return v*t
def v(s, t):
return s/t
def t(s, v):
return s/v
或者你在一个大的 if 分支方程中做同样的事情
def solve_svt_equation(v=None, t=None, s=None):
if v is not None and t is not None:
return v * t # s case
elif s is not None and t: # t not None and not 0
return s / t # v case
elif s is not None and v: # v not None and not 0
return s / v
print(solve_svt_equation(v=10, t=2))
print(solve_svt_equation(s=2, t=7))
如果只有一个物理方程,程序员将不得不实现,这将是一种无需担心的可行方法。但是,如果您需要实现多个方程式,这种方法很容易出错并且很快就会变得混乱。
对于我即将进行的编码项目,大约有 50 个这样的方程式。我假设我处于许多程序员已经遇到的常见情况。
由于 v*t - s = 0
完全定义了等式,可能会有一个解决方案,程序员只需编写一次等式。它可能看起来像是虚构的想法(或其他任何东西):
Equation svt = Equation("v*t - s")
svt['s'] = 12
svt['v'] = 6
print(svt.get('t'))
所以我的问题是 Python 库中是否有这样的解决方案,是否有干净可行的标准方法,还是我必须自己想出解决方案?
Python 生态系统中有很多库可以处理这些问题
一个是SymPy
代码可能如下所示:
import sympy
def solve_svt_equation(v=None, t=None, s=None):
velocity, space, time = sympy.symbols("v s t")
expr = velocity * time - space
if v:
expr = expr.subs(velocity, v)
if t:
expr = expr.subs(time, t)
if s:
expr = expr.subs(space, s)
return sympy.solve(expr)
print(solve_svt_equation(v=10, t=2)) # [20]
print(solve_svt_equation(s=2, t=7)) # [2/7], sympy defaults to rational numbers
print(solve_svt_equation(s=2, t=7, v=1)) # [], no solution
print(solve_svt_equation(s=2)) # [{t: 2/v}], symbolic solution for t
可能更容易概括的替代方案可能是:
def solve_svt_equation(v=None, t=None, s=None):
velocity, space, time = sympy.symbols("v s t")
expr = velocity * time - space
vals = {velocity: v, space: s, time: t}
for symbol, val in vals.items():
if val:
expr = expr.subs(symbol, val)
return sympy.solve(expr)
如果您想从字符串生成表达式,可以使用 sympy.parsing.sympy_parser.parse_expr
制作与您的示例非常相似的内容
svt_expr = sympy.parsing.sympy_parser.parse_expr("v*t - s")
svt_expr = svt_expr.subs("s", 12)
svt_expr = svt_expr.subs("v", 6)
print(sympy.solve(svt_expr, "t")) # [2]
另一个很棒的库是 z3,它是一个 SMT 求解器而不是符号操作库,但可以轻松解决这些简单的问题。如果你有符号方程,我建议使用 sympy,只是将它显示为替代
import z3
v, s, t = z3.Reals("v s t")
equation = v * t == s
z3.solve([equation, s == 12, v == 6]) # Prints [v = 6, s = 12, t = 2]
建立物理方程的标准方法似乎是在这里找到的方法:
s = v*t
并且要么写多个函数,像这样:
def s(v, t):
return v*t
def v(s, t):
return s/t
def t(s, v):
return s/v
或者你在一个大的 if 分支方程中做同样的事情
def solve_svt_equation(v=None, t=None, s=None):
if v is not None and t is not None:
return v * t # s case
elif s is not None and t: # t not None and not 0
return s / t # v case
elif s is not None and v: # v not None and not 0
return s / v
print(solve_svt_equation(v=10, t=2))
print(solve_svt_equation(s=2, t=7))
如果只有一个物理方程,程序员将不得不实现,这将是一种无需担心的可行方法。但是,如果您需要实现多个方程式,这种方法很容易出错并且很快就会变得混乱。
对于我即将进行的编码项目,大约有 50 个这样的方程式。我假设我处于许多程序员已经遇到的常见情况。
由于 v*t - s = 0
完全定义了等式,可能会有一个解决方案,程序员只需编写一次等式。它可能看起来像是虚构的想法(或其他任何东西):
Equation svt = Equation("v*t - s")
svt['s'] = 12
svt['v'] = 6
print(svt.get('t'))
所以我的问题是 Python 库中是否有这样的解决方案,是否有干净可行的标准方法,还是我必须自己想出解决方案?
Python 生态系统中有很多库可以处理这些问题
一个是SymPy
代码可能如下所示:
import sympy
def solve_svt_equation(v=None, t=None, s=None):
velocity, space, time = sympy.symbols("v s t")
expr = velocity * time - space
if v:
expr = expr.subs(velocity, v)
if t:
expr = expr.subs(time, t)
if s:
expr = expr.subs(space, s)
return sympy.solve(expr)
print(solve_svt_equation(v=10, t=2)) # [20]
print(solve_svt_equation(s=2, t=7)) # [2/7], sympy defaults to rational numbers
print(solve_svt_equation(s=2, t=7, v=1)) # [], no solution
print(solve_svt_equation(s=2)) # [{t: 2/v}], symbolic solution for t
可能更容易概括的替代方案可能是:
def solve_svt_equation(v=None, t=None, s=None):
velocity, space, time = sympy.symbols("v s t")
expr = velocity * time - space
vals = {velocity: v, space: s, time: t}
for symbol, val in vals.items():
if val:
expr = expr.subs(symbol, val)
return sympy.solve(expr)
如果您想从字符串生成表达式,可以使用 sympy.parsing.sympy_parser.parse_expr
制作与您的示例非常相似的内容svt_expr = sympy.parsing.sympy_parser.parse_expr("v*t - s")
svt_expr = svt_expr.subs("s", 12)
svt_expr = svt_expr.subs("v", 6)
print(sympy.solve(svt_expr, "t")) # [2]
另一个很棒的库是 z3,它是一个 SMT 求解器而不是符号操作库,但可以轻松解决这些简单的问题。如果你有符号方程,我建议使用 sympy,只是将它显示为替代
import z3
v, s, t = z3.Reals("v s t")
equation = v * t == s
z3.solve([equation, s == 12, v == 6]) # Prints [v = 6, s = 12, t = 2]