我正在寻找一种通用的Python方法来将文本处理成可解的方程。
例如:
可能有一些常量需要初始化
e1,e2=0.58,0.62
ma1,ma2=0.85,1.15
mw=0.8
Cpa,Cpw=1.023,4.193
dba,dbr=0.0,25.0
和一组方程(写在这里是为了可读性而不是求解器)
Q=e1*ma1*Cpa*(tw1-dba)
Q=ma1*Cpa*(dbs-dba)
Q=mw*Cpw*(tw1-tw2)
Q=e2*ma2*Cpa*(dbr-tw2)
Q=ma2*Cpa*(dbr-dbo)
这留下了 5 个未知数,因此系统大概可以被求解。
Q, dbo, dbr, tw1, tw2
实际系统是非线性的,而且要复杂得多。
我已经使用 scipy、Delphi、Sage 解决了这个简单的示例...所以我不寻找解决部分。
这些方程直接输入到文本编辑器中,我想要一个 Python 程序为我提供一组未知数和一组误差函数。
y = mysolver.fsolve(f, x)
所以,对于上面的例子
x=[Q,dbo,dbr,tw1,tw2]
f=[Q-e1*ma1*Cpa*(tw1-dba), Q-ma1*Cpa*(dbs-dba), Q-mw*Cpw*(tw1-tw2),
Q-e2*ma2*Cpa*(dbr-tw2), Q-ma2*Cpa*(dbr-dbo)]
我只是不知道如何提取未知数并创建误差函数。
我尝试了compile.parse()函数,它似乎给出了结构化的分割。
任何人都可以提供一些关于最佳方法的想法吗?
最佳答案
实际上,我在 python 中实现了完全相同的东西。我也熟悉 Eureka 和你提到的其他程序。你可以在 xyzsolve.appspot.com 上看到我的实现(抱歉这个无耻的插件)。整个实现都是用Python实现的。我将列出代码经历的迭代:
迭代#0:对方程中的每个变量进行简单的搜索替换,并将该变量替换为其值。例如,如果 x 和 y 的值为 1.1 和 2.2,则 x * y 将变为 1.1 * 2.2。获得转换后的字符串后,您可以使用 eval 并将其值放入残差(或 f 向量,在您的情况下)。 Scipy 的 fsolve/fmin 函数允许您将附加参数传递到残差函数中,因此请充分利用它。 IE。传递一个包含每个命名变量索引的字典。您的字典应包含类似 {'x': 0, 'y':1} 的内容,然后您可以对每个方程进行搜索和替换。这可行,但速度非常慢,因为每次调用残差函数时都必须执行搜索替换。
迭代#1:与迭代#0 相同,只是直接用 x 数组元素替换变量,因此“y”将变为“x[1]”。事实上,您可以执行所有这些操作来生成函数字符串;看起来像“def f(x): return x[0]+x[1], x[0] - x[1]”的东西。然后您可以使用 python 中的 exec 函数创建传递给 fsolve/fmin 的函数。速度不会受到影响,如果您的方程采用有效的 python 语法形式,您可以在此时停止。如果您想支持更广泛的方程输入格式,您不能用这种方法做更多的事情。
迭代#2:实现自定义词法分析器和解析器。这并不像听起来那么难。我用过http://www.evanfosmark.com/2009/02/sexy-lexing-with-python/对于词法分析器。我创建了一个递归下降解析器(这一点也不难,大约 100 行代码)来解析每个方程。这为您提供了方程式格式的完全灵 active 。我只是在单独的列表中跟踪方程两边出现的变量和常量。当解析器解析方程时,它会构建一个类似于“var_000 + var_001 * var_002”的方程字符串,依此类推。最后,我将“var_000”替换为 x 向量中的适当索引。所以'var_000'变成'x[0]'等等。如果您愿意,您可以构建 AST 并进行许多更复杂的转换,但我在这里停止了。
最后,您可能还需要考虑输入方程的类型。有相当多无害的非线性方程无法用 fsolve 求解(它使用 MINPACK hybrdj)。您可能还需要一种输入初始猜测的方法。
我很想知道是否有其他替代方法可以做到这一点。
关于python - 重新排列求解器的方程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1169593/