Определить и решить уравнение без избыточности (Python) - PullRequest
0 голосов
/ 12 июля 2020

Стандартный способ создания уравнений физики кажется подходом, найденным здесь: уравнение физики в python Вы берете свое уравнение, в этом сообщении stackoverflow это было s = v*t и либо напишите несколько функций , например:

def s(v, t):
    return v*t

def v(s, t):
    return s/t

def t(s, v):
    return s/v

Или вы делаете то же самое в одном большом уравнении с ветвями

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, есть ли чистый работоспособный стандартный метод, или я должен придумывать решение самостоятельно?

1 Ответ

1 голос
/ 12 июля 2020

В экосистеме 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 вместо библиотеки манипуляций с символами c, но может легко решить эти простые проблемы . Я бы посоветовал использовать sympy, если у вас есть символьные c уравнения, просто показывая их как альтернативу

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]
...