CVXPY中如何实现变量大于0时满足最小阈值的条件约束
泵调度凸优化模型最小运行阈值约束实现
你当前的模型是带整数变量的混合整数凸优化问题,要实现「单周期运行时长只能为0,或≥设定最小阈值Y」的半连续变量约束,核心是用二进制指示变量绑定启停状态和运行时长上下界,具体实现如下:
实现逻辑
约束的本质是把running_time[i]定义为半连续变量:
- 引入二进制指示变量
k[i],取值只能是0或1:k[i]=1代表第i个周期泵开机运行,k[i]=0代表第i个周期泵完全停机 - 对每个周期i绑定两组线性约束:
- 停机状态(k[i]=0):运行时长强制为0
- 开机状态(k[i]=1):运行时长不小于最小阈值Y,且不超过当前周期的总可用时长
注意:你原有代码里的
k是连续变量,无法实现0/1指示作用,必须修改为二进制布尔类型,你使用的CPLEX求解器原生支持这类混合整数约束,不需要额外配置。
修改后的完整代码
N = len(periods_minutes) # 这里的MIN_RUN_TIME就是你要求的阈值Y,可根据需求调整为20/25等数值 MIN_RUN_TIME = 25 running_time = cp.Variable(N, integer=True) # 核心修改:k设为二进制0-1变量,标记周期i泵是否开机 k = cp.Variable(N, boolean=True) mins = np.ones(N) * MIN_RUN_TIME maxs = np.ones(N) * periods_minutes print(mins) # 常量参数 pump_flow = float(self.pump_data[len(self.pump_data)-1]["Flow"]) pump_energy = float(self.pump_data[len(self.pump_data)-1]["Energy"]) pump_flow_per_minute = pump_flow * 60 # 优化目标计算 cost_of_running = cp.multiply((running_time/60), energy_costs * pump_energy) sum_of_energy = cp.sum(cost_of_running) volume_cp = cp.sum(running_time*pump_flow_per_minute) period_volume = running_time * pump_flow_per_minute # 蓄水池液位计算 FACTOR = 1/self.SURFACE_AREA flow_in = running_time * pump_flow_per_minute flow_diff = (flow_in - flow_out) / 1000 res_level = cp.cumsum(flow_diff) * FACTOR + self.current_level # 固定约束 min_level_constraint = res_level >= self.min_level max_level_constraint = res_level <= self.max_level volume_constraint = volume_cp >= self.target # 构建约束集 constraints = [] for i in range(N): # 绑定启停状态和运行时长:k[i]=0时running_time[i]只能为0;k[i]=1时在[MIN_RUN_TIME, 周期总时长]区间取值 constraints += [running_time[i] >= cp.multiply(k[i], mins[i])] constraints += [running_time[i] <= cp.multiply(k[i], maxs[i])] # 追加公共约束 constraints += [min_level_constraint] constraints += [max_level_constraint] constraints += [volume_constraint] # 定义目标与求解 objective = cp.Minimize(sum_of_energy) prob = cp.Problem(objective, constraints) prob.solve(solver=cp.CPLEX, verbose=False)
注意事项
- 确保设置的最小运行阈值
MIN_RUN_TIME不大于任意周期的总时长periods_minutes[i],否则会出现模型不可行的问题 - 求解完成后可以通过
k.value查看每个周期的启停状态,running_time.value读取对应周期的优化运行时长,不会出现0到阈值之间的非法非零值 - 因为你已经将
running_time设为整数变量,求解结果会自动取整到分钟,符合实际调度场景需求
内容的提问来源于stack exchange,提问作者Aidan Donnelly
相关产品推荐
相关产品推荐

