You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python求解含8个未知量的复非线性方程组问题

求解Python复非线性方程组的实用方法(无需拆分实部虚部)

你遇到的fsolve报错完全在预料之中——scipy.optimize.fsolve本质是root函数的简化包装,默认使用的hybr求解器只支持实数输入输出,碰到复数方程组自然会抛出类型错误。下面给你两个无需手动拆分实部虚部的解决方案,直接处理复数运算:

方法1:使用scipy.optimize.root(推荐,兼容现有代码)

root函数的lm(Levenberg-Marquardt)求解器原生支持复数运算,只需要调整初始猜测的类型,并指定方法即可。修改你的代码如下:

from scipy.optimize import root
import numpy as np

# 先补充定义你代码中用到的全局变量(示例值,根据实际情况替换)
k0 = 1.0
k1 = 0.8
k2 = 0.5
a1 = 1.0
a1L = 2.0
a12L = 3.0

A = 1
def equations(p):
    B,C,D,F,G,H,I,J = p
    return (
        A+B-C-D,
        1j*k0*(A-B) -1j*k1*(C-D),
        B*np.exp(1j*k1*a1) + D*np.exp(-1j*k1*a1) - F*np.exp(1j*k0*a1) - G*np.exp(-1j*k0*a1),
        1j*k1*( C*np.exp(1j*k1*a1) - D*np.exp(-1j*k1*a1) ) - 1j*k0*( F*np.exp(1j*k0*a1) - G*np.exp(-1j*k0*a1) ),
        F*np.exp(1j*k0*a1L) + G*np.exp(-1j*k0*a1L) - H*np.exp(-k2*a1L) - I*np.exp(k2*a1L),
        1j*k0*( F*np.exp(1j*k0*a1L) - G*np.exp(-1j*k0*a1L) )- k2*( -H*np.exp(-k2*a1L) + I*np.exp(k2*a1L) ),
        H*np.exp(-k2*a12L) + I*np.exp(k2*a12L) - J*np.exp(1j*k0*a12L),
        k2*( -H*np.exp(-k2*a12L) + I*np.exp(k2*a12L) ) - 1j*k0*J*np.exp(1j*k0*a12L)
    )

# 将初始猜测设为复数类型数组
initial_guess = np.array([-1,-1,-1,-1,-1,-1,-1,-1], dtype=np.complex128)
result = root(equations, initial_guess, method='lm')

if result.success:
    B, C, D, F, G, H, I, J = result.x
    print("求解成功!得到的解:")
    print(f"B={B}\nC={C}\nD={D}\nF={F}\nG={G}\nH={H}\nI={I}\nJ={J}")
else:
    print(f"求解失败:{result.message}")

关键说明:

  • 把初始猜测转为np.complex128类型,明确告诉求解器我们要处理复数问题
  • 指定method='lm',该方法专门针对非线性最小二乘问题,完美支持复数运算
  • 可以直接复用你原有的equations函数,不需要做任何修改

方法2:使用mpmath库(高精度复数求解)

如果你的问题需要更高精度的计算,或者希望更简洁的复数支持,可以试试mpmath库的findroot函数——它天生支持复数方程组,甚至可以处理符号运算:

import mpmath as mp

# 设置计算精度(比如20位小数)
mp.mp.dps = 20

# 定义参数(同样根据实际值替换)
k0 = mp.mpf(1.0)
k1 = mp.mpf(0.8)
k2 = mp.mpf(0.5)
a1 = mp.mpf(1.0)
a1L = mp.mpf(2.0)
a12L = mp.mpf(3.0)
A = mp.mpf(1)

def equations(p):
    B,C,D,F,G,H,I,J = p
    return [
        A+B-C-D,
        1j*k0*(A-B) -1j*k1*(C-D),
        B*mp.e**(1j*k1*a1) + D*mp.e**(-1j*k1*a1) - F*mp.e**(1j*k0*a1) - G*mp.e**(-1j*k0*a1),
        1j*k1*( C*mp.e**(1j*k1*a1) - D*mp.e**(-1j*k1*a1) ) - 1j*k0*( F*mp.e**(1j*k0*a1) - G*mp.e**(-1j*k0*a1) ),
        F*mp.e**(1j*k0*a1L) + G*mp.e**(-1j*k0*a1L) - H*mp.e**(-k2*a1L) - I*mp.e**(k2*a1L),
        1j*k0*( F*mp.e**(1j*k0*a1L) - G*mp.e**(-1j*k0*a1L) )- k2*( -H*mp.e**(-k2*a1L) + I*mp.e**(k2*a1L) ),
        H*mp.e**(-k2*a12L) + I*mp.e**(k2*a12L) - J*mp.e**(1j*k0*a12L),
        k2*( -H*mp.e**(-k2*a12L) + I*mp.e**(k2*a12L) ) - 1j*k0*J*mp.e**(1j*k0*a12L)
    ]

# 初始猜测可以是实数或复数
initial_guess = [-1,-1,-1,-1,-1,-1,-1,-1]
solution = mp.findroot(equations, initial_guess)

B, C, D, F, G, H, I, J = solution
print("高精度求解结果:")
print(f"B={B}\nC={C}\nD={D}\nF={F}\nG={G}\nH={H}\nI={I}\nJ={J}")

关键说明:

  • mpmath的指数运算要用mp.e**代替np.exp,确保复数计算的精度
  • 可以自由调整mp.mp.dps来设置计算精度,适合对结果精度要求高的场景
  • 无需手动指定复数类型,函数会自动处理复数输入输出

额外提示

非线性方程组可能存在多个解,初始猜测的选择会直接影响求解结果。如果第一次求解得到的解不符合预期,可以尝试调整初始猜测值,或者尝试不同的求解器方法(比如root的broyden1方法也支持复数)。

内容的提问来源于stack exchange,提问作者Mattias Johnson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:16:16