如何将Pyomo中无人机充电次数变量从浮点型转为整型?
问题:Pyomo中实现任务调度的整型充电次数计算(N_d = ⌊E_d/B_d⌋)
我在处理论文《Holistic energy awareness for intelligent drones》表3的任务调度问题,需要实现公式N_d = E_d/B_d的向下取整整型转换,当前使用Pyomo 6.4.0(Abstract模型)、Python 3.7和GLPK 4.65求解器。
原始核心代码如下:
model.Drones = Set() # List of drones model.Battery_capacity = Param(model.Drones, within=NonNegativeReals) # =170 model.Energy_total = Var(model.Drones, within=NonNegativeReals, initialize=1) model.Charging_sessions = Var(model.Drones, within=NonNegativeReals, initialize=1) def battery_charging_sessions_rule(model, d): return model.Charging_sessions[d] == (model.Energy_total[d]/model.Battery_capacity[d]) model.battery_charging_sessions = Constraint(model.Drones, rule=battery_charging_sessions_rule)
此时Charging_sessions为浮点型,可能小于1。尝试过两种修改但均失败:
- 将变量改为整型:
model.Charging_sessions = Var(model.Drones, within=Integers, initialize=1, bounds=(0,None))
- 约束中用
floor(value()):
return model.Charging_sessions[d] == floor(value((model.Energy_total[d]/model.Battery_capacity[d])))
修改后Charging_sessions被强制设为0,日志显示(0.0058823530*Energy_total[d])被置为0——原因是value()会在模型构建阶段就求值,此时Energy_total还未被求解,初始值1代入后1/170≈0.00588,floor后为0,导致约束被固定为Charging_sessions[d] == 0。
可行解决方法
方法1:用线性约束实现向下取整
通过两个线性约束表达N_d = ⌊E_d/B_d⌋的逻辑,避免直接使用浮点函数:
N_d ≤ E_d/B_d→ 转换为乘法形式避免精度问题:N_d * B_d ≤ E_dN_d + 1 > E_d/B_d→ 由于求解器不支持严格不等式,转换为(N_d + 1)*B_d ≥ E_d + 1e-6(1e-6为极小偏移量)
代码示例:
model.Drones = Set() model.Battery_capacity = Param(model.Drones, within=NonNegativeReals) # =170 model.Energy_total = Var(model.Drones, within=NonNegativeReals, initialize=1) # 定义为非负整数变量 model.Charging_sessions = Var(model.Drones, within=Integers, initialize=1, bounds=(0, None)) def charging_lower_bound_rule(model, d): return model.Charging_sessions[d] * model.Battery_capacity[d] <= model.Energy_total[d] def charging_upper_bound_rule(model, d): return (model.Charging_sessions[d] + 1) * model.Battery_capacity[d] >= model.Energy_total[d] + 1e-6 model.charging_lower = Constraint(model.Drones, rule=charging_lower_bound_rule) model.charging_upper = Constraint(model.Drones, rule=charging_upper_bound_rule)
方法2:求解后对结果进行向下取整
如果Charging_sessions不需要作为决策变量参与后续约束计算,可以先求解浮点值,再在求解后处理:
代码示例:
import math # 原始浮点变量定义 model.Charging_sessions = Var(model.Drones, within=NonNegativeReals, initialize=1) model.battery_charging_sessions = Constraint(model.Drones, rule=battery_charging_sessions_rule) # 求解模型 solver = SolverFactory('glpk') result = solver.solve(model) # 求解后处理结果 integer_charging_sessions = {} for d in model.Drones: float_val = value(model.Charging_sessions[d]) integer_charging_sessions[d] = math.floor(float_val) # 输出结果 for d, n in integer_charging_sessions.items(): print(f"无人机{d}的充电次数:{n}")
方法3:使用Pyomo原生floor表达式
直接对变量表达式应用Pyomo的floor函数,避免提前求值:
代码示例:
from pyomo.environ import floor model.Charging_sessions = Var(model.Drones, within=Integers, initialize=1, bounds=(0, None)) def charging_floor_rule(model, d): return model.Charging_sessions[d] == floor(model.Energy_total[d] / model.Battery_capacity[d]) model.charging_floor_constraint = Constraint(model.Drones, rule=charging_floor_rule)
内容的提问来源于stack exchange,提问作者rrsaxena92
相关产品推荐
相关产品推荐

