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

带约束整数非线性优化报错:zero-size array to reduction operation maximum

整数非线性优化问题的ValueError错误解决

我正在求解一个带两个约束条件的整数非线性优化问题,运行代码时触发如下错误:

ValueError: zero-size array to reduction operation maximum which has no identity

以下是完整代码结构:

导入依赖与初始化数据

from ypstruct import structure
import numpy as np
import xlrd
from scipy.optimize import minimize

# 输入数据
input_data= np.array([[0.009, 0.001, 0.001, 0.009, 0.001, 0.009, 0.001, 0.009, 0.001, 0.001, 0.0002, 0.0002, 0.001, 0.001, 0.001, 0.009, 0.005, 0.001],
                     [0.05, 0.05, 0.12, 0.12, 0.15, 0.15, 0.3, 0.3, 0.02, 0.02, 0.18, 0.18, 0.2, 0.2, 0.01, 0.01, 0.01, 0.01],
                     [60, 40, 60, 40, 60, 40, 60, 40, 60, 40, 60, 40, 60, 40, 60, 40, 60, 40],   
                     [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30],
                     [2000,2000,1992,1992,1965,1965,1976,1976,1979,1979,1982,1982,1984,1984,1994,1994,1991,2006],
                     [5,5,3,3,8,8,8,8,10,10,12,12,11,11,1,1,1,1]])
ngroup = 9 ; limit_per_year=9 ; starting_year = 2000

C_capital = np.zeros(ngroup*2); C_sudden_replace = np.zeros(ngroup*2)
C_Gain_Power = np.zeros(ngroup*2); penalty=np.zeros(ngroup*2)
finalcost =np.zeros(ngroup*2)
X= np.array([32,31,36,38,49,44,54,54,44,45,34,34,24,24,38,85,45,54])

目标函数

def objective (X):
   discount_rate= 0.04; TOTAL_COST=0
   penalti= 5
   for i in range(ngroup*2):
       C_capital[i]= (X[i]/((1+X[i])**discount_rate))
       C_sudden_replace[i] =(np.exp(-input_data[1,i]*X[i]))*input_data[2,i]
       C_Gain_Power[i] = (50 - X[i])* input_data[1,i]
       penalty[i] = 0
       if i % 2 ==1:
           penalty[i]= penalti*(abs((X[i]+input_data[4,i]-(X[i-1]+input_data[4,i]))))

       finalcost[i] = C_capital[i] + C_sudden_replace[i] + C_Gain_Power[i] + penalty[i]
       TOTAL_COST=TOTAL_COST+ finalcost[i]

   return TOTAL_COST

COSTOBJ = objective(X)
print(COSTOBJ)

第一个约束条件

def constraint1(X):
    matrix1= np.zeros([ngroup*2,12])
    for i in range(ngroup*2):
        d=0
        for j in range(12):
            if j<= input_data[5,i]:
               matrix1[i,j]=input_data[4,i]+X[i]+d
               d=d+1
    #print(matrix1)
    a1=int(np.min(matrix1[np.nonzero(matrix1)]))
    a2=int(np.max(matrix1[np.nonzero(matrix1)]))
    matrix2=np.zeros((1 ,int(a2-a1)+1))
    #print(matrix2)
    b=0
    for i in range(a1, a2+1):
        matrix2[0,b]=np.count_nonzero(matrix1 == i)
        b=b+1
    sortir1= int(np.max(matrix2[np.nonzero(matrix2)]))
    return limit_per_year-sortir1

CONS1= constraint1(X)
print(CONS1)

第二个约束条件

def constraint2(X):
    matrix1= np.zeros([ngroup*2,12])
    for i in range(ngroup*2):
        d=0
        for j in range(12):
            if j<= input_data[5,i]:
               matrix1[i,j]=input_data[4,i]+X[i]+d
               d=d+1
    #print(matrix1)
    sortir= int(np.min(matrix1[:, 0]))
    return sortir-starting_year

CONS2= constraint2(X)
print(CONS2)

优化执行代码(触发错误)

cons1 = {'type': 'ineq', 'fun': constraint1}
cons2 = {'type': 'ineq', 'fun': constraint2}

cons=[cons1,cons2]
sol= minimize(objective,X ,method='SLSQP', constraints=cons)

错误原因分析

这个错误本质是调用np.max()或np.min()时传入了空数组。具体到你的代码:

  • 在constraint1中,当优化器尝试某些X值时,可能导致matrix1中没有非零元素,此时matrix1[np.nonzero(matrix1)]返回空数组,np.min()和np.max()就会抛出这个错误。
  • 另外,constraint2中直接取matrix1[:,0]的最小值,若该列全为0,虽然不会触发错误,但可能不符合你的约束逻辑。

解决方法

1. 给空数组的极值计算加兜底逻辑

修改constraint1,处理空数组的情况:

def constraint1(X):
    matrix1= np.zeros([ngroup*2,12])
    for i in range(ngroup*2):
        d=0
        for j in range(12):
            if j<= input_data[5,i]:
               matrix1[i,j]=input_data[4,i]+X[i]+d
               d=d+1
    # 提取非零元素,判断是否为空
    non_zero_matrix1 = matrix1[np.nonzero(matrix1)]
    if len(non_zero_matrix1) == 0:
        # 根据业务逻辑返回一个满足约束的值,比如直接返回limit_per_year
        return limit_per_year
    
    a1=int(np.min(non_zero_matrix1))
    a2=int(np.max(non_zero_matrix1))
    matrix2=np.zeros((1 ,int(a2-a1)+1))
    b=0
    for i in range(a1, a2+1):
        matrix2[0,b]=np.count_nonzero(matrix1 == i)
        b=b+1
    
    # 同样处理matrix2的空数组情况
    non_zero_matrix2 = matrix2[np.nonzero(matrix2)]
    sortir1= int(np.max(non_zero_matrix2)) if len(non_zero_matrix2) >0 else 0
    return limit_per_year-sortir1

2. 给X添加边界约束,避免异常值

优化器可能会尝试不合理的X值(比如负数),导致input_data[4,i]+X[i]+d计算结果为0或负数,进而让matrix1出现全零行/列。给X设置合理的取值范围:

# 假设每个X元素的取值范围是1到100,可根据实际业务调整
bounds = [(1, 100) for _ in range(len(X))]
sol= minimize(objective,X ,method='SLSQP', constraints=cons, bounds=bounds)

3. 注意整数优化的局限性

scipy.optimize.minimize的SLSQP方法是针对连续变量的优化,如果你需要严格的整数解,直接运行得到的结果是连续值,需要后续取整处理,或者改用专门的整数优化工具(比如pyscipopt、Google OR-Tools)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 20:39:22