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

如何在or-solver中添加非线性目标函数实现装箱剩余容量均匀分配

目标逻辑纠正

首先明确一个基础逻辑:所有箱子的总剩余容量 = 所有箱子初始总容量 - 所有包裹总体积,是固定常数。要让剩余容量尽可能均匀,等价于最小化各剩余容量的平方和(和固定的前提下,平方和越小代表各数值的差异越小,分布越均匀),你当前写的Maximize(score)会得到剩余容量尽可能不均匀的结果,注意根据你的需求调整目标方向。

OR-Tools 实现方案

分两种常用求解器场景给出实现方式:

1. 使用支持二次规划的MIP求解器(如SCIP、Gurobi、CPLEX)

可以直接调用二次项接口添加目标:

from ortools.linear_solver import pywraplp

# 初始化求解器,选择支持MIQP的后端
solver = pywraplp.Solver.CreateSolver('SCIP')

# 入参示例
box_num = 3 # 箱子总数
parcel_num = 4 # 包裹总数
box_capacity = [10, 8, 5] # 各箱子初始容量
parcel_size = [2, 3, 1, 2] # 各包裹体积

# 定义0-1决策变量x[i][j]:1代表第j个包裹分配给第i个箱子
x = []
for i in range(box_num):
    x_i = []
    for j in range(parcel_num):
        x_i.append(solver.IntVar(0, 1, f'x_{i}_{j}'))
    x.append(x_i)

# 约束1:每个包裹必须分配给恰好一个箱子
for j in range(parcel_num):
    solver.Add(sum(x[i][j] for i in range(box_num)) == 1)

# 约束2:每个箱子装的包裹总体积不能超过自身容量
for i in range(box_num):
    solver.Add(sum(parcel_size[j] * x[i][j] for j in range(parcel_num)) <= box_capacity[i])

# 定义目标函数
objective = solver.Objective()
for i in range(box_num):
    # 计算第i个箱子的剩余容量
    cap_left = box_capacity[i] - sum(parcel_size[j] * x[i][j] for j in range(parcel_num))
    # 添加平方项,系数为1
    objective.AddQuadraticTerm(cap_left, cap_left, 1)
# 要均匀就设最小化,要不均匀就设最大化
objective.SetMinimization()

# 执行求解
status = solver.Solve()

# 输出结果(和你给出的result矩阵格式一致)
result = []
for i in range(box_num):
    row = []
    for j in range(parcel_num):
        row.append(int(solver.Value(x[i][j])))
    result.append(row)
print(result)

2. 使用CP-SAT求解器

CP-SAT不支持直接写入二次目标,需要先定义辅助变量绑定平方值,再添加目标:

from ortools.sat.python import cp_model

model = cp_model.CpModel()

# 入参和上面一致
box_num = 3
parcel_num = 4
box_capacity = [10, 8, 5]
parcel_size = [2, 3, 1, 2]

# 定义0-1决策变量x[i][j]
x = [[model.NewIntVar(0, 1, f'x_{i}_{j}') for j in range(parcel_num)] for i in range(box_num)]
# 定义各箱子剩余容量变量,上下界设为0到对应箱子初始容量即可
cap_left = [model.NewIntVar(0, box_capacity[i], f'cap_left_{i}') for i in range(box_num)]

# 约束1:每个包裹恰好分配一个箱子
for j in range(parcel_num):
    model.Add(sum(x[i][j] for i in range(box_num)) == 1)

# 约束2:箱子容量不超限,同时绑定cap_left变量
for i in range(box_num):
    model.Add(cap_left[i] == box_capacity[i] - sum(parcel_size[j] * x[i][j] for j in range(parcel_num)))

# 定义平方值辅助变量
cap_left_sq = [model.NewIntVar(0, box_capacity[i] ** 2, f'cap_left_sq_{i}') for i in range(box_num)]
# 用乘法约束绑定平方关系
for i in range(box_num):
    model.AddMultiplicationEquality(cap_left_sq[i], cap_left[i], cap_left[i])

# 目标:最小化平方和实现均匀分配
model.Minimize(sum(cap_left_sq))

# 求解
solver = cp_model.CpSolver()
status = solver.Solve(model)

# 输出结果
result = []
for i in range(box_num):
    row = []
    for j in range(parcel_num):
        row.append(int(solver.Value(x[i][j])))
    result.append(row)
print(result)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 16:06:03