Docplex中Model.if_then()触发DOcplexException的问题排查与修复
Docplex
if_then约束异常:原因及修复 原代码
from docplex.mp.model import Model car=[1, 2, 3] myorder=[391, 392, 393, 448, 449, 450] mdl = Model(name='planning') Assignment = mdl.binary_var_matrix(myorder, car, name='Assignment') CarLoaded = mdl.integer_var_dict(car, name='CarLoaded') for f in car: CarLoaded[f] = mdl.sum(Assignment[o, f] * 20 for o in myorder) CarUtilized = mdl.binary_var_dict(car, name='CarUtilized') for f in car: mdl.add_constraint( mdl.if_then(CarLoaded[f] / 123 >= 0.8, CarUtilized[f] == 1)) LoadSum = mdl.sum(CarUtilized[f] * CarLoaded[f] / 30 for f in car) mdl.maximize(LoadSum)
运行异常
Traceback (most recent call last): File "D:\Dev\my_test.py", line 17, in <module> mdl.if_then(CarLoaded[f] / 123 >= 0.8, CarUtilized[f] == 1)) File "C:\ProgramData\Anaconda3\lib\site-packages\docplex\mp\model.py", line 3971, in if_then StaticTypeChecker.typecheck_discrete_constraint(logger=self, ct=if_ct, msg='Model.if_then()') File "C:\ProgramData\Anaconda3\lib\site-packages\docplex\mp\sttck.py", line 66, in typecheck_discrete_constraint logger.fatal('{0}, {1!s} is not discrete', msg, ct) File "C:\ProgramData\Anaconda3\lib\site-packages\docplex\mp\model.py", line 1078, in fatal self._error_handler.fatal(msg, args) File "C:\ProgramData\Anaconda3\lib\site-packages\docplex\mp\error_handler.py", line 210, in fatal raise DOcplexException(resolved_message) docplex.mp.utils.DOcplexException: Model.if_then(), 0.163Assignment_391_1+0.163Assignment_392_1+0.163Assignment_393_1+0.163Assignment_448_1+0.163Assignment_449_1+0.163Assignment_450_1 >= 0.8 is not discrete
异常原因
Docplex的if_then约束要求条件部分必须是离散约束——即约束中的所有系数、常数项都需为整数,避免浮点运算引发的精度问题和类型不兼容。原代码中CarLoaded[f] / 123 >= 0.8是浮点运算,导致条件约束变为非离散类型,触发了类型检查错误。
修复方案
将浮点条件转换为等价的整数约束:
计算0.8 * 123 = 98.4,由于CarLoaded[f]是整数变量,要满足CarLoaded[f]/123 >=0.8,等价于CarLoaded[f] >= 99(因为整数98<98.4,不满足条件;99≥98.4,满足条件)。
修复后的代码:
from docplex.mp.model import Model car=[1, 2, 3] myorder=[391, 392, 393, 448, 449, 450] mdl = Model(name='planning') Assignment = mdl.binary_var_matrix(myorder, car, name='Assignment') CarLoaded = mdl.integer_var_dict(car, name='CarLoaded') for f in car: CarLoaded[f] = mdl.sum(Assignment[o, f] * 20 for o in myorder) CarUtilized = mdl.binary_var_dict(car, name='CarUtilized') for f in car: # 替换浮点约束为等价整数约束 mdl.add_constraint( mdl.if_then(CarLoaded[f] >= 99, CarUtilized[f] == 1)) LoadSum = mdl.sum(CarUtilized[f] * CarLoaded[f] / 30 for f in car) mdl.maximize(LoadSum)
也可以通过两边同乘10的方式保留原逻辑形式:CarLoaded[f] * 10 >= 123 * 8,计算后同样得到CarLoaded[f] >= 99,效果一致。
内容的提问来源于stack exchange,提问作者william007
相关产品推荐
相关产品推荐

