如何为CVXPY优化问题的选择变量添加防频繁启停约束?
解决方案
问题分析
你当前的核心需求是避免容量选择出现0,1,0,1这类频繁启停的波动,对应的约束可以基于代表是否开启容量的selection[:,1]变量编写。另外你原代码存在一处小问题:原有代码中定义的cost_constraint是求和表达式,不是合法的等式/不等式约束,加入约束列表会导致报错,需要先移除。
约束实现
你提到的「某点位判定为1后,接下来2个点位必须为0」有两种常见的实现逻辑,按需选择即可:
方案1:严格禁止1之后的2个周期出现任何1(不允许连续开)
该方案完全禁止连续开启,也禁止间隔1个周期后再次开启,完全符合你描述的字面要求:
# 提取是否开启容量的标识:1代表开启,0代表关闭 on = selection[:, 1] no_fluctuation_constraints = [] # 遍历所有可约束的位置(最后2个位置后无足够周期,无需约束) for i in range(len(on) - 2): no_fluctuation_constraints.append(on[i] + on[i+1] + on[i+2] <= 1)
方案2:允许连续开启,仅禁止1,0,1式的启停波动
该方案匹配你给出的示例中允许[0,0,1,1,0,0]这类连续开启的场景,仅禁止开启1个周期就关闭、间隔1个周期又开启的频繁波动:
on = selection[:, 1] no_fluctuation_constraints = [] for i in range(2, len(on)): # 禁止出现前前位为1、前位为0、当前位为1的1,0,1序列 no_fluctuation_constraints.append(on[i-2] + on[i] <= 1 + on[i-1])
完整修改后的代码
把约束加入原有的约束列表即可,修改后完整代码如下(同时修复了原代码中变量名重复冲突的问题):
import cvxpy as cp import numpy as np # Volume and cost full_cost = [[0, data] for data in [0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45,0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.45, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4]] cost_arr = np.array(full_cost) ex = np.array([[0, 17100] for data in [i for i in range(0, 96)]]) # Minimum volume required v_min = 300000 # Selection variable selection = cp.Variable(shape=ex.shape, boolean=True) # 基础约束 assignment_constraint = cp.sum(selection,axis=1) == 1 volume_= cp.sum(cp.multiply(ex,selection)) volume_constraint = volume_ >= v_min # 防波动约束(方案1和方案2按需选择其一即可) on = selection[:, 1] no_fluctuation_constraints = [] # 方案1:严格禁止1之后2个周期出现1 # for i in range(len(on) - 2): # no_fluctuation_constraints.append(on[i] + on[i+1] + on[i+2] <= 1) # 方案2:允许连续开,仅禁止1,0,1波动 for i in range(2, len(on)): no_fluctuation_constraints.append(on[i-2] + on[i] <= 1 + on[i-1]) # 合并所有约束 constraints = [assignment_constraint, volume_constraint] + no_fluctuation_constraints # 目标函数 cost = cp.sum(cp.multiply(cost_arr, selection)) # Problem definition assign_problem = cp.Problem(cp.Minimize(cost), constraints) assign_problem.solve(solver=cp.CPLEX, verbose=True) # Find solution in ex variable assignments = [np.where(r==1)[0][0] for r in selection.value] c = [ ex[i][assignments[i]] for i in range(len(assignments)) ] best_volume = np.sum(np.multiply(ex,selection.value)) best_cost = np.sum(np.multiply(cost_arr,selection.value)) print(best_cost) print(c)
内容的提问来源于stack exchange,提问作者Aidan Donnelly
相关产品推荐
相关产品推荐

