Docplex不支持np.sqrt求欧氏距离,求替代解决方案
解决方案:移除平方根的等价二次约束转换
核心思路
原约束要求物品圆心到容器中心的欧氏距离 + 物品半径 ≤ 容器半径,即:
( R \geq r_i + \sqrt{x_i^2 + y_i^2} )
由于( R > r_i )(否则物品无法放入容器),不等式两边均为非负数,因此可以两边平方得到等价的二次约束,完全规避平方根运算:
( x_i^2 + y_i^2 \leq (R - r_i)^2 )
同时需要结合二进制变量( d_i ),仅当物品被放置(( d_i=1 ))时,该约束才生效。
修改后的完整代码
from docplex.mp.model import Model import numpy as np def packing_cplex(CDA, R, H, items): # continuous variables x,y range from -R to +R x = [ CDA.continuous_var(name="x{}:".format(i), lb=-R, ub=R) for i in range(len(items))] y = [ CDA.continuous_var(name="y{}:".format(i), lb=-R, ub=R) for i in range(len(items))] # integer variable z range from 0 to H z = [ CDA.integer_var(name="z{}:".format(i), lb=0, ub=H) for i in range(len(items))] # indicator denotes whether an item is packed into the container # i=1, .., n, values 1/0 d = [ CDA.binary_var(name="d{}:".format(i)) for i in range(len(items))] # 修正约束1:替换平方根为等价二次约束,结合d_i控制是否生效 for i in range(len(items)): r_i = items[i][0] # 仅当物品被放置时,约束生效 CDA.add(CDA.if_then(d[i] == 1, x[i]**2 + y[i]**2 <= (R - r_i)**2)) # 2.constraint packed items and container height for i in range(len(items)): CDA.add( CDA.if_then( d[i]==1, H >= ( items[i][1] + z[i] ) ) ) # 目标函数:改用Docplex原生sum更规范(避免numpy与变量的潜在冲突) total_volume = CDA.sum(d[i] * np.pi * items[i][0]**2 * items[i][1] for i in range(len(items))) CDA.set_objective("max", total_volume) # radius and height of cylinder container R, H = 3, 2 volume = np.pi * R**2 * H # pack, [(ri,hi), ... ([rn,hn]) where ri/hi is radius/height of item items = [(1,2),(1,2),(1,2),(1,2),(1,2),(1,2),(1,2)] CDA = Model(name='CDA') packing_cplex(CDA, R, H, items) CDA.print_information() solution = CDA.solve() if solution: utilization = solution.objective_value / volume print('Utilization (%) ', utilization * 100) else: print("No solution found")
关键修改点说明
- 约束替换:将原有的平方根约束转换为二次约束
x[i]**2 + y[i]**2 <= (R - r_i)**2,Docplex完全支持二次约束的求解。 - 关联二进制变量:通过
if_then确保只有当物品被放置(d[i]==1)时,位置约束才会被强制执行,未放置的物品不受该约束限制。 - 目标函数优化:将
np.sum替换为Docplex原生的CDA.sum,避免numpy对模型变量的潜在兼容性问题,同时保持计算逻辑不变。 - 容错处理:增加了解存在性判断,避免求解失败时出现属性访问错误。
内容的提问来源于stack exchange,提问作者Rashad Moqa
相关产品推荐
相关产品推荐

