Sympy中nsolve无法求解非线性方程组不动点问题求助
用SymPy求解非线性方程组不动点的问题
尝试用SymPy的nsolve求解非线性方程组以确定不动点,提供初始猜测后始终报错“nsolve failed”;改用solve函数返回空列表sol=[]。尝试用解析方法求解,但不确定方法是否正确。相关代码如下:
f1_num = sp.N(f1.subs(subs)) f2_num = sp.N(f2.subs(subs)) f3_num = sp.N(f3.subs(subs)) initial_guess = (g1_val, g2_val, 0.0) # choose g3 guess 0 # Attempt to solve for g1,g2,g3 try: sol = sp.nsolve([f1_num, f2_num, f3_num], (g1, g2, g3), (g1_val, g2_val, 0.02), tol=1e-12, maxsteps=200) results.append(sol) except Exception as e: results.append(None) print(f"Column {j}: nsolve failed ({e})") # fallback: try a few different initial guesses for guess in [(g1_val, g2_val, 0.4), (1.0, 1.0, 0.5), (0.5, 0.5, 0.6)]: try: sol = sp.nsolve([f1_num, f2_num, f3_num], (g1, g2, g3), guess) print("sol=", sol) print("Found sol with guess", guess, ":", sol) break except Exception as e2: print("guess", guess, "failed:", e2) g1_fp1 = [None] * num_cols g1_fp2 = [None] * num_cols g2_fp = [None] * num_cols #............................. # Analytical solution #............................. for j in range (num_cols): try: roots_f3 = sp.nsolve(f3_num, g1) if roots_f3: g1_fp1[j] = float(sp.re(roots_f3[0])) print(f"g1 roots from f3=",g1_fp1[j]) else: g1_fp1[j] = np.nan except Exception as e: print(f"f3 solution failed ({e})") g1_fp1[j] = np.nan #type(sol_f3) try: roots_f1 = sp.nsolve(f1_num, g1) if roots_f1: g1_fp2[j]= float(sp.re(roots_f1[0])) print(f"g1 roots from f1=",g1_fp2[j]) else: g1_fp2[j] = np.nan except Exception as e: print(f"f1 solution failed ({e})") g1_fp2[j] = np.nan try: roots_f2 = sp.nsolve(f2_num, g2) if roots_f2: g2_fp[j] = float(sp.re(roots_f2[0])) print(f"g2 roots from f2=",g2_fp[j]) else: g2_fp[j] = np.nan except Exception as e: print(f"f2 solution failed ({e})") g2_fp[j] = np.nan
问题排查与解决建议
- 不要提前数值化符号表达式:
sp.N()会把符号表达式转为数值对象,nsolve更适合处理纯符号形式的方程组,数值化后可能丢失关键符号信息,导致求解失败。应保留符号表达式,求解时再代入参数,直接用符号方程组调用nsolve。 - 验证方程组是否存在解:先手动代入初始猜测计算每个方程的残差,判断初始点是否靠近解;也可以用Matplotlib绘制方程的曲线,直观查看是否存在交点。
- 调整数值求解参数:
- 增大
maxsteps值,默认迭代次数可能不足以让算法收敛; - 先放宽
tol阈值找到粗略解,再以此为初始点进行精细求解; - 指定不同的求解算法,比如
nsolve(..., method='lm')(Levenberg-Marquardt算法),适配不同类型的非线性方程组。
- 增大
- 修正解析求解逻辑:当前单独对每个方程求解单个变量的方式错误,方程组的解需要满足所有方程同时成立,单独解单方程得到的根不是方程组的解。正确的解析求解应使用符号消元法,比如从一个方程解出某变量,代入其他方程逐步简化。
- 检查符号变量与替换参数:确保
g1、g2、g3是SymPy符号变量(sp.symbols('g1 g2 g3')),且subs中的替换没有误替换掉需要求解的变量。
内容的提问来源于stack exchange,提问作者user5830353
相关产品推荐
相关产品推荐

