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

Scipy minimize添加b₁<b₂<b₃约束报错,求解决方案

问题:添加b₁<b₂<b₃约束时scipy.minimize触发TypeError错误

我正在编写最小化程序,通过拟合b₁、b₂、b₃,寻找预测值r与实际值x之间的最小平方和误差。使用scipy.optimize.minimize函数,已为三个变量设置有效边界,但添加b₁<b₂<b₃约束时触发错误:

TypeError: numpy boolean subtract, the - operator, is not supported, use the bitwise_xor, the ^ operator, or the logical_xor function instead

无约束时拟合结果符合预期,但部分数据点无法满足b₁<b₂<b₃要求,需要解决约束添加问题。

原代码

import numpy as np
import pandas as pd
import sys
import math
import numpy as np
from scipy.optimize import curve_fit
import os
from scipy.optimize import minimize

def psd_fun(c_s):
    b_1 = c_s[0]
    b_2 = c_s[1]
    b_3 = c_s[2]
    a = np.arange(-1.0, 1.01, 0.10)
    b = np.linspace(-1.0, 5.0, 40)
    c = []
    x=282.335
    p_1 = 0.109
    p_2 = 0.102
    p_3 = 0.789
    pt = 0.440

    d1=[]
    d2=[]
    d3=[]
    d12=[]
    d22=[]
    d32=[]
    for i in b:
        z=10**i
        c += [z]
    for i in c:
        d1 += [p_1*(1-math.exp(-(i/b_1)))*pt]
        d2 += [p_2 * (1 - math.exp(-(i / b_2))) * pt]
        d3 += [p_3 * (1 - math.exp(-(i / b_3))) * pt]

    for i in range(1,len(d3),1):
        d12 += [((d1[i]-d1[i-1])/(p_1*pt)*c[i])]
        d22 +=[(d2[i]-d2[i-1])/(p_2*pt)*c[i]]
        d32 +=[(d3[i]-d3[i-1])/(p_3*pt)*c[i]]

    r = sum(d12)*p_1*pt+sum(d22)*p_2*pt+sum(d32)*p_3*pt
    r1 = (r-x)**2
    return r1

cons = ({'type': 'ineq', 'fun': lambda c_s:  np.array([c_s[0] <= c_s[1]])},
        {'type': 'ineq', 'fun': lambda c_s: np.array([c_s[1] <= c_s[2]])})

bnds = ((0.1, 2.5), (15, 500), (400, 10000))
min_res = minimize(psd_fun, [2.5,276,435], bounds = bnds, constraints=cons)
print(min_res)

错误原因

scipy.optimize.minimize的不等式约束(type='ineq')要求约束函数返回数值型数组/标量,且返回值需≥0。原代码中直接返回布尔数组(c_s[0] <= c_s[1]生成True/False),优化器在后续数值运算中会尝试对布尔值执行减法等操作,触发类型错误。

修正方案

将布尔比较转换为数值型的差值表达式,确保约束函数返回≥0的数值:

  • 对于b₁ ≤ b₂,等价于b₂ - b₁ ≥ 0,约束函数返回c_s[1] - c_s[0]
  • 对于b₂ ≤ b₃,等价于b₃ - b₂ ≥ 0,约束函数返回c_s[2] - c_s[1]

如果需要严格小于(b₁ < b₂ < b₃),可以在差值中加上一个极小的正数(如1e-8),避免数值精度问题导致变量相等的情况。

修正后的代码(仅修改约束部分)

# 修正约束定义
cons = ({'type': 'ineq', 'fun': lambda c_s:  c_s[1] - c_s[0]},  # b2 - b1 >=0 → b1 <= b2
        {'type': 'ineq', 'fun': lambda c_s: c_s[2] - c_s[1]})  # b3 - b2 >=0 → b2 <= b3

# 若需要严格小于,可改为:
# cons = ({'type': 'ineq', 'fun': lambda c_s:  c_s[1] - c_s[0] - 1e-8},
#         {'type': 'ineq', 'fun': lambda c_s: c_s[2] - c_s[1] - 1e-8})

bnds = ((0.1, 2.5), (15, 500), (400, 10000))
min_res = minimize(psd_fun, [2.5,276,435], bounds = bnds, constraints=cons)
print(min_res)

验证结果

修改后运行代码,约束会正常生效,不会触发类型错误。以你的无约束结果为例,其本身已经满足b₁<b₂<b₃,添加约束后会得到类似的收敛结果,同时确保所有拟合结果都符合b₁≤b₂≤b₃(或严格小于)的要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 03:14:59