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

使用Scipy求解带约束线性方程组的异常问题求助

约束线性方程组求解问题排查与解决

需要求解带约束的线性方程组 (AX = b),其中:

  • (A) 是8×8分块对角矩阵
  • (X = [x1, y1, x2, y2, x3, y3, x4, y4]^T),(b) 是8×1向量
  • 约束条件:
    • (0.5(y1 + y2) = 0)
    • (0.5(x3 + x4) = 0)
    • (0.5(y3 + y4) = 0)

尝试过两种方法均未得到正确结果:

  • 将约束整合为11×8矩阵,用伪逆求解,解不满足约束
  • 改用Scipy的SLSQP优化器构造最小二乘问题,求解器显示成功且解满足约束,但代入 (AX) 后结果与 (b) 偏差极大,接近全零向量

原问题代码

import numpy as np
from scipy import optimize

A = np.array([
    [-261.60,  11.26,      0.0,    0.0,     0.0,    0.0,     0.0,    0.0],
    [   4.07, -12.75,      0.0,    0.0,     0.0,    0.0,     0.0,    0.0],
    [    0.0,    0.0,  -158.63,  -5.65,     0.0,    0.0,     0.0,    0.0],
    [    0.0,    0.0,    -2.81, -12.14,     0.0,    0.0,     0.0,    0.0],
    [    0.0,    0.0,      0.0,    0.0, -265.99,  19.29,     0.0,    0.0],
    [    0.0,    0.0,      0.0,    0.0,   12.59, -12.34,     0.0,    0.0],
    [    0.0,    0.0,      0.0,    0.0,     0.0,    0.0, -166.25, -12.63],
    [    0.0,    0.0,      0.0,    0.0,     0.0,    0.0,   -8.40, -11.14]
])

b = np.array([
     -6.95,
     16.35,
     -0.96,
     16.35,
     19.19,
    -15.85,
    -12.36,
    -15.63]).reshape(-1, 1)

def objective_function(x):
    return np.sum((np.dot(A, x) - b)**2)

def constraints(x):
    return np.array([
        0.5*(x[1] + x[3]),  # 0.5*(y1 + y2) = 0
        0.5*(x[4] + x[6]),  # 0.5*(x3 + x4) = 0
        0.5*(x[5] + x[7])   # 0.5*(y3 + y4) = 0
    ])

cons = {'type': 'eq', 'fun': constraints}
options = {'disp': True, 'verbose': 4}

res = optimize.minimize(objective_function, np.zeros(8), method='SLSQP', constraints=cons, options={'disp': True})

x_optimized = res.x

# Checking if solution was found
print(np.matmul(A, x_optimized))

原代码输出结果

[ 0.01723619  0.00041891  0.01781721 -0.00034223  0.0113301  -0.00848171
  0.01008367  0.00781168]

问题根源分析

核心问题是矩阵维度不匹配导致目标函数计算错误:

  • (b) 被reshape为(8,1)列向量,但优化输入的 (x) 是一维数组(8,),计算 (A@x) 得到一维数组(8,),与列向量 (b) 做减法时,numpy会广播为(8,8)矩阵,平方求和后得到的是所有元素的平方和,完全偏离了原本要最小化的 (|Ax - b|_2^2) 目标。

解决方案

修正后的SLSQP优化代码

import numpy as np
from scipy import optimize

A = np.array([
    [-261.60,  11.26,      0.0,    0.0,     0.0,    0.0,     0.0,    0.0],
    [   4.07, -12.75,      0.0,    0.0,     0.0,    0.0,     0.0,    0.0],
    [    0.0,    0.0,  -158.63,  -5.65,     0.0,    0.0,     0.0,    0.0],
    [    0.0,    0.0,    -2.81, -12.14,     0.0,    0.0,     0.0,    0.0],
    [    0.0,    0.0,      0.0,    0.0, -265.99,  19.29,     0.0,    0.0],
    [    0.0,    0.0,      0.0,    0.0,   12.59, -12.34,     0.0,    0.0],
    [    0.0,    0.0,      0.0,    0.0,     0.0,    0.0, -166.25, -12.63],
    [    0.0,    0.0,      0.0,    0.0,     0.0,    0.0,   -8.40, -11.14]
])

# 保持b为一维数组,与Ax输出维度匹配
b = np.array([
     -6.95,
     16.35,
     -0.96,
     16.35,
     19.19,
    -15.85,
    -12.36,
    -15.63
])

def objective_function(x):
    # 计算真实的残差平方和
    return np.sum((A @ x - b)**2)

def constraints(x):
    # 去掉冗余的0.5,约束等价且计算更高效
    return np.array([
        x[1] + x[3],  # y1 + y2 = 0
        x[4] + x[6],  # x3 + x4 = 0
        x[5] + x[7]   # y3 + y4 = 0
    ])

cons = {'type': 'eq', 'fun': constraints}
# 增加迭代次数确保收敛充分
options = {'disp': True, 'maxiter': 1000}

res = optimize.minimize(objective_function, np.zeros(8), method='SLSQP', constraints=cons, options=options)

x_optimized = res.x

# 验证结果
print("优化得到的X:", x_optimized)
print("Ax的结果:", A @ x_optimized)
print("与b的误差:", A @ x_optimized - b)

更高效的带约束线性最小二乘方法

使用scipy.optimize.lsq_linear专门求解带约束的线性最小二乘问题,效率更高:

from scipy.optimize import lsq_linear

# 构造约束矩阵C和向量d,满足Cx = d
C = np.array([
    [0, 1, 0, 1, 0, 0, 0, 0],
    [0, 0, 0, 0, 1, 0, 1, 0],
    [0, 0, 0, 0, 0, 1, 0, 1]
])
d = np.array([0, 0, 0])

res_lsq = lsq_linear(A, b, bounds=(-np.inf, np.inf), constraints={'type': 'eq', 'fun': lambda x: C @ x - d})
print("lsq_linear得到的X:", res_lsq.x)
print("Ax的结果:", A @ res_lsq.x)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 16:55:53