cuGenOpt/python/cugenopt/include/problems/bin_packing.cuh
2026-03-20 00:33:45 +08:00

97 lines
3.1 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* bin_packing.cuh - 一维装箱问题Integer 编码 + 约束)
*
* N 个物品,每个重量 w[i],装入最多 B 个箱子,每个箱子容量 C。
* 决策变量data[0][i] ∈ [0, B-1],表示物品 i 放入的箱子编号。
* 目标:最小化使用的箱子数。
* 约束:每个箱子总重不超过 C超出部分作为 penalty。
*
* 验证实例8 物品 weights=[7,5,3,4,6,2,8,1], C=10, 最优=4 箱
* 箱0={7,3}=10, 箱1={5,4,1}=10, 箱2={6,2}=8, 箱3={8}=8
*/
#pragma once
#include "types.cuh"
#include "cuda_utils.cuh"
struct BinPackingProblem : ProblemBase<BinPackingProblem, 1, 64> {
const float* d_weights;
int n; // 物品数
int max_bins; // 最大箱子数 B
float capacity; // 箱子容量 C
__device__ float calc_bins_used(const Sol& sol) const {
bool used[32] = {};
int size = sol.dim2_sizes[0];
for (int i = 0; i < size; i++) {
int b = sol.data[0][i];
if (b >= 0 && b < max_bins) used[b] = true;
}
int count = 0;
for (int b = 0; b < max_bins; b++)
if (used[b]) count++;
return (float)count;
}
static constexpr ObjDef OBJ_DEFS[] = {
{ObjDir::Minimize, 1.0f, 0.0f},
};
__device__ float compute_obj(int idx, const Sol& sol) const {
switch (idx) {
case 0: return calc_bins_used(sol);
default: return 0.0f;
}
}
__device__ float compute_penalty(const Sol& sol) const {
float penalty = 0.0f;
float load[32] = {};
int size = sol.dim2_sizes[0];
for (int i = 0; i < size; i++) {
int b = sol.data[0][i];
if (b >= 0 && b < max_bins)
load[b] += d_weights[i];
}
for (int b = 0; b < max_bins; b++) {
float over = load[b] - capacity;
if (over > 0.0f) penalty += over * 10.0f;
}
return penalty;
}
ProblemConfig config() const {
ProblemConfig cfg;
cfg.encoding = EncodingType::Integer;
cfg.dim1 = 1; cfg.dim2_default = n;
cfg.value_lower_bound = 0;
cfg.value_upper_bound = max_bins - 1;
fill_obj_config(cfg);
return cfg;
}
size_t shared_mem_bytes() const {
return (size_t)n * sizeof(float);
}
__device__ void load_shared(char* smem, int tid, int bsz) {
float* sw = reinterpret_cast<float*>(smem);
for (int i = tid; i < n; i += bsz) sw[i] = d_weights[i];
d_weights = sw;
}
static BinPackingProblem create(const float* h_weights, int n,
int max_bins, float capacity) {
BinPackingProblem prob;
prob.n = n; prob.max_bins = max_bins; prob.capacity = capacity;
float* dw;
CUDA_CHECK(cudaMalloc(&dw, sizeof(float) * n));
CUDA_CHECK(cudaMemcpy(dw, h_weights, sizeof(float) * n, cudaMemcpyHostToDevice));
prob.d_weights = dw;
return prob;
}
void destroy() {
if (d_weights) cudaFree(const_cast<float*>(d_weights));
d_weights = nullptr;
}
};