python - 有没有一种为 scipy.optimize.root 或 scipy.optimize.fsolve 动态创建非线性方程的好方法?
问题描述
我需要求解一个大型非线性方程组(静态桁架系统)。这些方程源自节点 (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
来描述整个系统。
基本上应该有一些神奇的部分来查看方程和约束的匹配部分。例如,查看所有关于节点 1x
方向的信息并将其合并到方程中,或者搜索所有y
关于节点 2 方向力的信息。
是scipy
适合这项工作的正确工具吗?有人知道如何做到这一点吗?
解决方案
我想你可能对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
symfit 中的Parameter
对象只是 sympy 的Symbol
子类,因此您可以对这些表达式进行所有您想要的 sympy 操作。例如,您可以将您的节点定义为
>>> x, x_0 = symbols('x, x_0')
>>> Node = x - x_0
然后通过重复应用来制作模型的线条,例如
>>> Node.subs({x: x1, x_0: 2})
x1 - 2
最后你添加你的约束和 presto:fittable 模型!查看文档以获取更多信息或询问我任何后续问题。
推荐阅读
- python - Django - MongoDb - GraphQL 查询返回一个空数组
- datepicker - Nativescript RadDataForm DatePicker 编辑器将样式更改为轮子
- amazon-web-services - 当主体设置为 aws lambda.amazonaws.com 时访问被拒绝
- json - Serilog 不解析文件名模板
- android - 颤振 - “无法找到 Android SDK。”
- java - Selenium 从日期选择器中选择第一个和最后一个活动日期
- excel - 如何对由公式组成的Excel工作表中的列进行排序?
- flutter - 创建带有嵌套粘性标题的列表
- python - 如何防止groupby超类索引?
- vue.js - 如何触发来自 Vue.js 的 http 请求?