使用scipy fsolve求非线性函数根遇TypeError错误的解决方法
解决scipy.optimize.fsolve调用sympy符号方程的报错问题
问题代码
# calculate I0 with new Rp value from sympy import Symbol, solve, exp import sympy as sp from scipy.optimize import fsolve import numpy as np # 原代码遗漏该导入,需补充 I02 = (Isc * (1 + Rs1 / Rp) - Voc / Rp) / (np.exp(Voc / vt1) - np.exp(Rs1 * Isc / vt1)); Ipv2 = I02 * ((np.exp(Voc / vt1)) - 1) + Voc / Rp; ImpC = Pmax / VmpC; err = abs(Imp - ImpC); Rpnew = Rp; while ((err > toll) & (itI < iter)) : if ImpC < Imp : Rpnew = Rp + 0.1 * itI; else : Rpnew = Rp - 0.1 * itI; print(itI); # Calculate I0 with rpnew I02 = (Isc * (1 + Rs1 / Rpnew) - Voc / Rpnew) / (np.exp(Voc / vt1) - np.exp(Rs1 * Isc / vt1)); print(I02); Ipv2 = I02 * ((np.exp(Voc / vt1)) - 1) + Voc / Rpnew; print(Ipv2); x = sp.symbols('x'); eqn = Ipv2 - (I02 * (sp.exp((Vmp + (Rs1 * x)) / vt1) - 1)) - x - (Vmp + Rs1 * x) / Rpnew; print(eqn); print(type(eqn)); current_c = Imp; print(current_c); s = fsolve(func = eqn, x0 = current_c); print(s); ImpC = s; itI = itI + 1; err = abs(Imp - ImpC);
报错信息
TypeError Traceback (most recent call last) Cell In [65], line 43 40 print(current_c); 41 # s = fzero(eqn,current_c); 42 # s = sp.solveset(eqn, x); ---> 43 s = fsolve(func = eqn, x0 = current_c); 44 print(s); 45 ImpC = s; TypeError: 'Add' object is not callable'
报错原因
scipy.optimize.fsolve要求第一个参数是可调用的数值函数(输入数值返回对应函数值的函数),但你直接传入了sympy生成的符号表达式eqn——这个对象属于sympy.core.add.Add类型,是符号运算载体,不能像普通函数那样被调用,因此触发TypeError。
解决方案
用sympy.lambdify()将符号表达式转换为可调用的数值函数,该方法会把符号逻辑编译为基于numpy的数值计算逻辑,完全适配fsolve的要求。
修改代码中调用fsolve的片段:
# 将符号表达式转换为可调用的数值函数,指定numpy作为计算后端 func = sp.lambdify(x, eqn, 'numpy') # 使用转换后的函数调用fsolve s = fsolve(func, x0=current_c)
额外注意事项
- 原代码缺少
import numpy as np,必须补充,否则np.exp会触发未定义错误。 - 原代码存在缩进不规范问题(while循环内代码层级混乱),需统一缩进层级,否则会触发语法错误。
内容的提问来源于stack exchange,提问作者Jun
相关产品推荐
相关产品推荐

