Есть ли хороший способ динамически создавать нелинейные уравнения для scipy.optimize.root или scipy.optimize.fsolve? - PullRequest
0 голосов
/ 10 октября 2018

Мне нужно решить большую систему нелинейных уравнений (статическая ферменная система).Уравнения выводятся из узлов (xyz) и их ограничений (положение, силы).

На данный момент мы используем Mathematica для этой задачи, но мы хотели бы перейти на Python.Но с Mathematica (или EES (решение инженерных уравнений) или SymPy) это довольно удобно.Я добавляю кучу вещей в подобные позиции узлов или силы на узлах, и это делает некоторую магию и создает уравнения самостоятельно, комбинируя входные данные и решая их.

Если я хочу использовать scipy.optimize.root, мне нужно как-тополучить уравнения.

scipy.optimize.root и scipy.optimize.fsolve нужны уравнения в следующем формате:

def func(x):
    out = [x[0]*cos(x[1]) - 4], 
           x[1]*x[0] - x[1] - 5)
    return out

Но в моем случае будет до 5000 уравнений, которые определяют систему.

Одна вещь, которая пришла мне в голову, - это использовать eval() и как-то смешать уравнения в строку.

В конце я хотел бы использовать объектно-ориентированный подход, в которомузел или ограничение знает, как преобразовать себя в уравнение.Очень простым скелетом может быть

n = Node(5, 2, 6)
n.to_equation()

f = ForceConstraint(1, 2, 3)
f.to_equation()

, и это каким-то образом преобразуется в уравнения типа

x[0] - 5, 
x[1] - 2,
x[2] - 6,
x[2] ** 2 - x[1] * x[0] # and some non-linear stuff

для описания всей системы.

По сути, должно быть какое-то волшебствочасть, которая смотрит на совпадающие части уравнений и ограничений.Например, просмотрите всю информацию, имеющуюся у вас в направлении x Узла1, и объедините ее в уравнения, или найдите всю информацию о силах в направлении y в Узле 2.

Является ли scipy правильным инструментомдля работы вообще?У кого-нибудь есть хорошая идея, как это сделать?

1 Ответ

0 голосов
/ 12 октября 2018

Думаю, вас заинтересует symfit.Это пакет, который я написал для соединения scipy с sympy.

Я не совсем уверен, каковы ваши конкретные уравнения, но любое выражение, которое вы можете написать в sympy, в принципе может быть передано symfit.Например, для приведенного выше простого примера вы могли бы написать:

from symfit import parameters, variables, Fit
import numpy as np

x0, x1, x2 = parameters('x0, x1, x2')
y0, y1, y2, y3 = variables('y0, y1, y2, y3')

model_dict = {
    y0: x0 - 5,
    y1: x1 - 2,
    y2: x2 - 6,
    y3: x2 ** 2 - x1 * x0
}

fit = Fit(model_dict, y0=np.array(0.0), y1=np.array(0.0), y2=np.array(0.0), y3=np.array(0.0))
fit_result = fit.execute()
print(fit_result)

Variable и Parameter объекты в symfit - это просто подклассы Symbol sympy, поэтому вы можете выполнять все манипуляции с этими выражениямичто ты хочешь.Например, вы могли бы определить свой узел как

>>> x, x_0 = symbols('x, x_0')
>>> Node = x - x_0

, а затем создать линии своей модели, многократно применяя, например,

>>> Node.subs({x: x1, x_0: 2})
x1 - 2

Наконец, вы добавляете ограничение и модель presto: fittable!Обратитесь к документам для получения дополнительной информации или задайте мне любой дополнительный вопрос.

...