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

如何将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。尝试过两种修改但均失败:

  1. 将变量改为整型:
model.Charging_sessions = Var(model.Drones, within=Integers, initialize=1, bounds=(0,None))
  1. 约束中用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_d
  • N_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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 15:25:22