如何动态生成方程适配SciPy fsolve函数求解非线性方程组
报错核心原因
返回给fsolve的eq_list元素是字符串类型,而非fsolve要求的浮点型残差值(即等式左侧减右侧的计算结果)。
解决方案
方案1:eval执行字符串表达式(轻量场景适用)
仅适合方程字符串为你自行构造、无外部不可信输入的场景:
- 先预处理eq_list:将原等式字符串(如
a*b = 2.6)转换为残差形式的字符串(如a*b - 2.6),删除等号,统一用左侧减右侧的格式 - 在目标函数内循环执行eval得到数值结果
代码示例:
import scipy.optimize as opt # 方程内用到的特殊函数需提前导入,例如exp、sin等 from math import exp # 预处理后的11个残差字符串示例 eq_list = [ "a*b - 2.6", "a*k - 4.6", # 剩余9个方程按相同格式补充 ] def f(variables): a,b,c,d,e,f,g,h,i,j,k = variables res = [] for eq_str in eq_list: res.append(eval(eq_str)) return res solution = opt.fsolve(f, (0.1, 1,1,0.1,1,1,1,1,1,1,1)) print(solution)
方案2:SymPy符号计算生成可调用函数(复杂场景推荐)
安全性、稳定性、计算效率均优于eval方案,支持动态解析字符串方程:
代码示例:
import scipy.optimize as opt import sympy as sp # 定义所有符号变量 a,b,c,d,e,f,g,h,i,j,k = sp.symbols('a b c d e f g h i j k') var_list = [a,b,c,d,e,f,g,h,i,j,k] eq_list = [] # 如果是字符串格式的方程,用parse_expr转换为符号表达式,示例: str_eq_list = [ "a*b - 2.6", "a*k - 4.6", # 剩余9个方程字符串补充到此处 ] for s in str_eq_list: eq_list.append(sp.parse_expr(s)) # 编译为数值计算函数 calc_func = sp.lambdify(var_list, eq_list, modules='numpy') # 包装为fsolve适配的目标函数 def target(variables): return calc_func(*variables) solution = opt.fsolve(target, (0.1, 1,1,0.1,1,1,1,1,1,1,1)) print(solution)
注意事项
- 所有方程内用到的自定义函数、数学函数,需要在对应作用域提前导入,否则会出现未定义报错
- 初始值的设置会直接影响求解结果的正确性,如果出现收敛失败的情况,可调整初始值的取值范围重试
内容的提问来源于stack exchange,提问作者Waqar ul islam
相关产品推荐
相关产品推荐

