mirror of
https://github.com/L-yang-yang/cugenopt.git
synced 2026-04-25 12:16:21 +02:00
98 lines
3.1 KiB
Text
98 lines
3.1 KiB
Text
|
|
/**
|
|||
|
|
* 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;
|
|||
|
|
}
|
|||
|
|
};
|