CPLEX(docplex)中对决策变量用floor函数报LinearExpr错如何解决
报错根因
math.floor是Python标准库提供的数值计算函数,仅支持传入整数、浮点数这类原生数值类型,无法识别docplex定义的决策变量、线性表达式对象(即报错信息中提到的LinearExpr类型)。直接把决策变量传入该函数时,函数无法对优化模型中的符号表达式执行数值计算,就会触发该类型错误。
所有Python原生数学函数(包括math模块下的floor、sqrt、log等)都不能直接作用于docplex的决策变量,这类函数不具备优化模型表达式的解析能力。
步长离散化的正确实现
你要实现的步长为1/6小时的向下取整离散化,不需要强行调用floor函数,用整数变量+线性约束的方式等价建模即可,这也是数学规划求解器处理这类离散逻辑的标准方案,模型保持线性,求解效率极高:
- 离散步长固定为1/6小时,说明离散后的时间值一定是1/6的非负整数倍
- 为每个标签新增一个非负整数决策变量
k[a],代表对应时间点覆盖的离散步长数量 - 离散后的时间直接用
k[a] * 1/6表示,天然符合步长要求 - 补充两组线性约束,和原连续变量
x1[a]绑定:k[a]*(1/6) ≤ x1[a] < (k[a]+1)*(1/6),这组约束的效果和math.floor(x1[a]/(1/6))*(1/6)完全等价。
修正后的可运行代码如下:
from docplex.mp.model import Model m = Model(name='time_schedule') labels = ['home', 'study', 'work'] disc_step = 1/6 # 10分钟为一个离散步长 # 原连续开始时间变量 x1 = m.continuous_var_dict(labels, lb=0, name='start_time') # 新增整数变量:记录对应时间对应的离散步长计数 step_cnt = m.integer_var_dict(labels, lb=0, name='step_count') discret_start = {} for loc in labels: # 离散后的时间值,天然为1/6的整数倍 discret_start[loc] = step_cnt[loc] * disc_step # 加约束保证离散值是原时间向下取步长倍数的结果 m.add_constraint(discret_start[loc] <= x1[loc]) m.add_constraint(x1[loc] < discret_start[loc] + disc_step) # 后续正常添加业务约束、目标函数,调用m.solve()求解即可
注意:如果你的时间本身就只需要按1/6小时的粒度调度,甚至可以直接把
x1定义为整数变量,单位设为1/6小时,后续计算实际时间的时候再乘1/6即可,模型会更简洁。
内容的提问来源于stack exchange,提问作者Negar
相关产品推荐
相关产品推荐

