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

Sympy solve求解符号方程组仅得2个正确值的问题排查

符号方程组求解偏差问题

问题背景

使用SymPy的solve函数求解8个gamma变量的符号方程组时,仅gamma6和gamma7的结果符合预期,其余6个变量计算值与目标值偏差极大。

原代码

import numpy as np
from sympy import symbols, exp, Eq, solve

gamma0, gamma1, gamma2, gamma3, gamma4, gamma5, gamma6, gamma7 = symbols('gamma0 gamma1 gamma2 gamma3 gamma4 gamma5 gamma6 gamma7')
gamma = [gamma0, gamma1, gamma2, gamma3, gamma4, gamma5, gamma6, gamma7]
x = symbols('x')
a = 20
b = 5

u =[
    [0.388518*gamma0*exp(-2.012490*x) - 0.675612*gamma1*exp(-0.369901*x) + 0.336576*gamma2*exp(0.369901*x) - 0.103503*gamma3*exp(2.012490*x) + 20.168718, 
    0.163057*gamma4*exp(-2.421891*x) - 0.951601*gamma5*exp(-0.951784*x) + 0.086427*gamma6*exp(0.754538*x) - 0.045759*gamma7*exp(2.528248*x) + 2.394974],

    [-0.900008*gamma0*exp(-2.012490*x) - 0.520883*gamma1*exp(-0.369901*x) + 0.398678*gamma2*exp(0.369901*x) - 0.168303*gamma3*exp(2.012490*x) + 20.034468, 
    -0.976653*gamma4*exp(-2.421891*x) - 0.238418*gamma5*exp(-0.951784*x) + 0.122769*gamma6*exp(0.754538*x) - 0.080425*gamma7*exp(2.528248*x) + 2.329339],

    [-0.168303*gamma0*exp(-2.012490*x) - 0.398678*gamma1*exp(-0.369901*x) + 0.520883*gamma2*exp(0.369901*x) - 0.900008*gamma3*exp(2.012490*x) + 19.932869, 
    -0.095726*gamma4*exp(-2.421891*x) - 0.120587*gamma5*exp(-0.951784*x) + 0.326236*gamma6*exp(0.754538*x) - 0.963388*gamma7*exp(2.528248*x) + 2.504797], 

    [-0.103503*gamma0*exp(-2.012490*x) - 0.336576*gamma1*exp(-0.369901*x) + 0.675612*gamma2*exp(0.369901*x) + 0.388518*gamma3*exp(2.012490*x) + 19.892514, 
    -0.101960*gamma4*exp(-2.421891*x) - 0.151889*gamma5*exp(-0.951784*x) + 0.933288*gamma6*exp(0.754538*x) + 0.251633*gamma7*exp(2.528248*x) + 3.335936]
    ]

# Define the symbolic equations
eqns = [
    Eq(u[0][0].subs(x, 0), 0),
    Eq(u[1][0].subs(x, 0), 0),
    Eq(u[0][0].subs(x, b), u[0][1].subs(x, b)),
    Eq(u[1][0].subs(x, b), u[1][1].subs(x, b)),
    Eq(u[2][0].subs(x, b), u[2][1].subs(x, b)),
    Eq(u[3][0].subs(x, b), u[3][1].subs(x, b)),
    Eq(u[2][1].subs(x, a), 0),
    Eq(u[3][1].subs(x, a), 0)
]

# Solve the equations for the gamma variables
gamma_symbols = [gamma0, gamma1, gamma2, gamma3, gamma4, gamma5, gamma6, gamma7]
solutions = solve(eqns, gamma_symbols)

# Print the solutions
for symbol, value in solutions.items():
    print(f"{symbol}: {value}")

预期结果

gamma0: 3.3451862507144963721760546900288
gamma1: 30.086443529744653795656405805539
gamma2: -3.3917670835986188504875542362514
gamma3: 0.00013878499955117735347592615338105
gamma4: -775727.3319427781475689057795114
gamma5: -941.09415775171256674990468706789
gamma6: -0.0000010944407599058234322536821517657
gamma7: 0.00000000000000000000013958849298737787410748516872778

实际运行结果

gamma0: -2953067.95180723
gamma1: -1383474.12048191      
gamma2: -13623.4036144577      
gamma3: 1.03375979503954       
gamma4: -8212497765.78320      
gamma5: -15039124.0279307      
gamma6: -0.00000109854435279209
gamma7: 1.40162266686094E-22  

问题分析与解决方法

核心原因

这个方程组本质是线性方程组,但其中包含如exp(2.528248*20)这类超大指数项,导致系数矩阵的条件数极高(病态矩阵)。SymPy的solve默认符号求解,面对低精度浮点数构成的病态系统时,误差会被急剧放大,最终得到偏离预期的结果。

可行解决方案

1. 转为数值线性方程组求解(推荐)

将方程组整理为Ax = b的矩阵形式,使用SciPy的最小二乘法求解,该方法对病态矩阵的数值误差有更好的鲁棒性:

import numpy as np
from scipy.linalg import lstsq

# 构建系数矩阵A和右端向量b
A = []
b = []

# 方程1: u[0][0](x=0) = 0
A.append([0.388518, -0.675612, 0.336576, -0.103503, 0, 0, 0, 0])
b.append(-20.168718)

# 方程2: u[1][0](x=0) = 0
A.append([-0.900008, -0.520883, 0.398678, -0.168303, 0, 0, 0, 0])
b.append(-20.034468)

# 计算x=5处的指数值
exp1 = np.exp(-2.012490*5)
exp2 = np.exp(-0.369901*5)
exp3 = np.exp(0.369901*5)
exp4 = np.exp(2.012490*5)
exp5 = np.exp(-2.421891*5)
exp6 = np.exp(-0.951784*5)
exp7 = np.exp(0.754538*5)
exp8 = np.exp(2.528248*5)

# 方程3: u[0][0](x=5) - u[0][1](x=5) = 0
A.append([0.388518*exp1, -0.675612*exp2, 0.336576*exp3, -0.103503*exp4,
          -0.163057*exp5, 0.951601*exp6, -0.086427*exp7, 0.045759*exp8])
b.append(2.394974 - 20.168718)

# 方程4: u[1][0](x=5) - u[1][1](x=5) = 0
A.append([-0.900008*exp1, -0.520883*exp2, 0.398678*exp3, -0.168303*exp4,
          0.976653*exp5, 0.238418*exp6, -0.122769*exp7, 0.080425*exp8])
b.append(2.329339 - 20.034468)

# 方程5: u[2][0](x=5) - u[2][1](x=5) = 0
A.append([-0.168303*exp1, -0.398678*exp2, 0.520883*exp3, -0.900008*exp4,
          0.095726*exp5, 0.120587*exp6, -0.326236*exp7, 0.963388*exp8])
b.append(2.504797 - 19.932869)

# 方程6: u[3][0](x=5) - u[3][1](x=5) = 0
A.append([-0.103503*exp1, -0.336576*exp2, 0.675612*exp3, 0.388518*exp4,
          0.101960*exp5, 0.151889*exp6, -0.933288*exp7, -0.251633*exp8])
b.append(3.335936 - 19.892514)

# 计算x=20处的指数值
exp5_a = np.exp(-2.421891*20)
exp6_a = np.exp(-0.951784*20)
exp7_a = np.exp(0.754538*20)
exp8_a = np.exp(2.528248*20)

# 方程7: u[2][1](x=20) = 0
A.append([0,0,0,0, -0.095726*exp5_a, -0.120587*exp6_a, 0.326236*exp7_a, -0.963388*exp8_a])
b.append(-2.504797)

# 方程8: u[3][1](x=20) = 0
A.append([0,0,0,0, -0.101960*exp5_a, -0.151889*exp6_a, 0.933288*exp7_a, 0.251633*exp8_a])
b.append(-3.335936)

# 转换为数值数组
A = np.array(A, dtype=np.float64)
b = np.array(b, dtype=np.float64)

# 最小二乘法求解
gamma, _, _, _ = lstsq(A, b)

# 输出结果
gamma_names = ['gamma0','gamma1','gamma2','gamma3','gamma4','gamma5','gamma6','gamma7']
for name, val in zip(gamma_names, gamma):
    print(f"{name}: {val}")

2. 提高SymPy求解精度

将所有浮点数替换为SymPy的高精度浮点数(如Float(0.388518, precision=50)),减少低精度带来的误差累积,再用solve求解。

3. 拆分方程组

观察方程组结构,先解x=0处的方程得到gamma0-gamma3的关系,再解x=20处的方程得到gamma4-gamma7的关系,最后代入x=5处的衔接条件求解,降低系统耦合度。

内容的提问来源于stack exchange,提问作者Ectobius Rex

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 07:17:05