有没有办法为scipy.optimize.root或scipy.optimize.fsolve动态创建非线性方程式?

时间:2018-10-10 06:31:58

标签: python python-3.x numpy scipy sympy

我需要解决一个大型的非线性方程组(静态桁架系统)。 这些方程是从节点(xyz)及其约束(位置,力)得出的。

目前,我们正在使用Mathematica来完成此任务,但我们想迁移到Python。 但是使用Mathematica(或EES(工程方程求解器)或SymPy),它非常方便。我在节点上放置了很多东西,或者在节点上施加了力,它起到了神奇的作用,并通过结合输入并求解它们本身来创建方程。

如果我想使用scipy.optimize.root,则必须以某种方式获得方程式。

scipy.optimize.rootscipy.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

描述整个系统。

基本上,应该有一个魔术部分可以查看方程式和约束的匹配部分。 例如。查看节点1的x方向上的所有信息,并将其合并为方程,或者搜索节点2的y方向上的力的所有信息。

scipy完全是该工作的正确工具吗? 有人有一个好主意该怎么做吗?

1 个答案:

答案 0 :(得分:0)

我认为您可能对symfit感兴趣。这是我为将scipysympy连接而编写的程序包。

我不确定您的特定方程式是什么,但是原则上您可以在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)
symfit中的

VariableParameter对象只是sympy Symbol的子类,因此您可以对所需的这些表达式进行所有的sympy操作。例如,您可以将Node定义为

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

然后通过重复应用例如

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

最后,您添加了约束并保存了:可拟合模型!检查docs以获得更多信息,或问我任何后续问题。