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

Scipy minimize未正确求解约束优化问题(显示成功但结果异常)

凸优化求解问题求助

问题定义

优化问题如下(其中sig₁=2.56008479,sig₂=0.24800215,c=2.098024636032762):

$$
\min_{x_1, x_2} \ (x_1 + x_2 - c)^2 \
\text{subject to:} \
\frac{x_1}{\text{sig}_1 - x_1^2} = \frac{x_2}{\text{sig}_2 - x_2^2} \
x_1, x_2 \geq 0
$$

当前实现代码

import numpy as np
from scipy.optimize import minimize, Bounds, NonlinearConstraint

n = 2
c = 2.098024636032762
sigma_eigs = np.array([2.56008479, 0.24800215])

def equations(x):
    eq = np.sum(x) - c
    return np.sum(eq**2)

# 初始猜测
x0 = np.ones(n) 

# 约束
bounds = Bounds([0, 0])  # 仅设置下限,未设置上限
non_linear_eq = lambda x: x[0]/(sigma_eigs[0]-x[0]**2) - x[1]/(sigma_eigs[1]-x[1]**2)
constr1 = NonlinearConstraint(non_linear_eq, 0, 0)

result = minimize(equations, x0, method='trust-constr', constraints=constr1, bounds=bounds)

x = result.x
print(x)

const_result = [x[i]/(sigma_eigs[i]-x[i]**2) for i in range(n)]
print("The solution is x = {}".format(x))
if np.any(x < 0):
    print("Error: some of the x values are non-positive")
else:
    print("All x values are positive")

residuals = equations(x)
print("Residuals are: {}".format(residuals))
if np.any(np.abs(residuals) > 1e-6):
    print("Error: The solution is not accurate. The residuals are high")
else:
    print("All residuals are within the tolerance")

求解问题

使用trust-constr方法得到的结果:

[-2.75911573e-08  1.22830289e+07]

输出信息:

x = [-2.75911573e-08  1.22830289e+07]
Error: some of the x values are non-positive
Residuals are: 150872747356720.12
Error: The solution is not accurate. The residuals are high

优化提示:

message: xtol termination condition is satisfied.

当前问题表现为变量发散、不满足非负约束,且残差极大;使用其他求解器会得到如[0. 0.]这类不满足精度要求的结果。

解决建议

1. 修正变量的可行域

原约束中的分母sigma_eigs[i] - x[i]^2不能为0或负数,否则分式无意义或出现数值奇异。因此需要为每个变量添加上限:x[i] < sqrt(sigma_eigs[i]),结合非负约束,Bounds应设置为:

upper_bounds = np.sqrt(sigma_eigs)
bounds = Bounds([0, 0], upper_bounds)

2. 选择合理的初始点

原初始点x0 = [1,1]中,x0[1]=1已经大于sqrt(0.24800215)≈0.498,超出可行域,导致求解器初始状态数值不稳定。建议选择可行域内的初始点,例如:

x0 = np.array([0.5, 0.4])

3. 提供约束的雅可比矩阵

手动计算约束的梯度(雅可比矩阵),避免求解器使用数值微分带来的误差,提升稳定性:

def non_linear_eq_jac(x):
    # 计算约束函数对x0的导数
    denom0 = sigma_eigs[0] - x[0]**2
    jac0 = (denom0 + 2*x[0]**2) / (denom0 ** 2)
    # 计算约束函数对x1的导数
    denom1 = sigma_eigs[1] - x[1]**2
    jac1 = -(denom1 + 2*x[1]**2) / (denom1 ** 2)
    return np.array([jac0, jac1])

constr1 = NonlinearConstraint(non_linear_eq, 0, 0, jac=non_linear_eq_jac)

4. 调整求解器参数

设置更高的精度要求和迭代次数,确保求解收敛到可行解:

options = {
    'xtol': 1e-8,
    'gtol': 1e-8,
    'maxiter': 1000,
    'verbose': 1  # 可选,查看求解过程细节
}
result = minimize(equations, x0, method='trust-constr', constraints=constr1, bounds=bounds, options=options)

修正后的完整代码

import numpy as np
from scipy.optimize import minimize, Bounds, NonlinearConstraint

n = 2
c = 2.098024636032762
sigma_eigs = np.array([2.56008479, 0.24800215])

def objective(x):
    return (x[0] + x[1] - c) ** 2

def non_linear_eq(x):
    return x[0]/(sigma_eigs[0]-x[0]**2) - x[1]/(sigma_eigs[1]-x[1]**2)

def non_linear_eq_jac(x):
    denom0 = sigma_eigs[0] - x[0]**2
    jac0 = (denom0 + 2*x[0]**2) / (denom0 ** 2)
    denom1 = sigma_eigs[1] - x[1]**2
    jac1 = -(denom1 + 2*x[1]**2) / (denom1 ** 2)
    return np.array([jac0, jac1])

# 设置可行域
upper_bounds = np.sqrt(sigma_eigs)
bounds = Bounds([0, 0], upper_bounds)

# 可行域内的初始点
x0 = np.array([0.5, 0.4])

# 带雅可比的非线性约束
constr1 = NonlinearConstraint(non_linear_eq, 0, 0, jac=non_linear_eq_jac)

# 求解器参数
options = {
    'xtol': 1e-8,
    'gtol': 1e-8,
    'maxiter': 1000
}

result = minimize(objective, x0, method='trust-constr', constraints=constr1, bounds=bounds, options=options)

x = result.x
print("优化结果x =", x)
print("约束满足情况:", non_linear_eq(x))
print("目标函数值:", objective(x))
print("是否满足非负约束:", np.all(x >= 0))
print("是否满足分母约束:", np.all(x**2 < sigma_eigs))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 02:12:40