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

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")

关键修改点说明

  1. 约束替换:将原有的平方根约束转换为二次约束x[i]**2 + y[i]**2 <= (R - r_i)**2,Docplex完全支持二次约束的求解。
  2. 关联二进制变量:通过if_then确保只有当物品被放置(d[i]==1)时,位置约束才会被强制执行,未放置的物品不受该约束限制。
  3. 目标函数优化:将np.sum替换为Docplex原生的CDA.sum,避免numpy对模型变量的潜在兼容性问题,同时保持计算逻辑不变。
  4. 容错处理:增加了解存在性判断,避免求解失败时出现属性访问错误。

内容的提问来源于stack exchange,提问作者Rashad Moqa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 04:25:21