mirror of
https://github.com/L-yang-yang/cugenopt.git
synced 2026-04-25 12:16:21 +02:00
88 lines
2.8 KiB
Text
88 lines
2.8 KiB
Text
/**
|
||
* knapsack.cuh - 0-1 背包问题
|
||
*
|
||
* 继承 ProblemBase,使用 ObjDef 目标注册机制
|
||
*/
|
||
|
||
#pragma once
|
||
#include "types.cuh"
|
||
#include "cuda_utils.cuh"
|
||
#include "operators.cuh"
|
||
|
||
struct KnapsackProblem : ProblemBase<KnapsackProblem, 1, 32> {
|
||
// 问题数据(d_weights 是物品重量,非目标权重)
|
||
const float* d_weights;
|
||
const float* d_values;
|
||
float capacity;
|
||
int n;
|
||
|
||
// ---- 目标计算 ----
|
||
__device__ float calc_total_value(const Sol& sol) const {
|
||
float tv = 0.0f;
|
||
const int* sel = sol.data[0];
|
||
int size = sol.dim2_sizes[0];
|
||
for (int i = 0; i < size; i++)
|
||
if (sel[i]) tv += d_values[i];
|
||
return tv;
|
||
}
|
||
|
||
// ---- 目标定义(OBJ_DEFS 与 compute_obj 必须一一对应)----
|
||
static constexpr ObjDef OBJ_DEFS[] = {
|
||
{ObjDir::Maximize, 1.0f, 0.0f}, // case 0: calc_total_value
|
||
};
|
||
__device__ float compute_obj(int idx, const Sol& sol) const {
|
||
switch (idx) {
|
||
case 0: return calc_total_value(sol); // OBJ_DEFS[0]
|
||
default: return 0.0f;
|
||
}
|
||
}
|
||
|
||
__device__ float compute_penalty(const Sol& sol) const {
|
||
float tw = 0.0f;
|
||
const int* sel = sol.data[0];
|
||
int size = sol.dim2_sizes[0];
|
||
for (int i = 0; i < size; i++)
|
||
if (sel[i]) tw += d_weights[i];
|
||
float over = tw - capacity;
|
||
return (over > 0.0f) ? over : 0.0f;
|
||
}
|
||
|
||
ProblemConfig config() const {
|
||
ProblemConfig cfg;
|
||
cfg.encoding = EncodingType::Binary;
|
||
cfg.dim1 = 1; cfg.dim2_default = n;
|
||
fill_obj_config(cfg);
|
||
return cfg;
|
||
}
|
||
|
||
// ---- shared memory 接口 ----
|
||
size_t shared_mem_bytes() const {
|
||
return 2 * (size_t)n * sizeof(float);
|
||
}
|
||
|
||
__device__ void load_shared(char* smem, int tid, int bsz) {
|
||
float* sw = reinterpret_cast<float*>(smem);
|
||
float* sv = sw + n;
|
||
for (int i = tid; i < n; i += bsz) { sw[i] = d_weights[i]; sv[i] = d_values[i]; }
|
||
d_weights = sw;
|
||
d_values = sv;
|
||
}
|
||
|
||
static KnapsackProblem create(const float* hw, const float* hv, int n, float cap) {
|
||
KnapsackProblem prob;
|
||
prob.n = n; prob.capacity = cap;
|
||
float *dw, *dv;
|
||
CUDA_CHECK(cudaMalloc(&dw, sizeof(float)*n));
|
||
CUDA_CHECK(cudaMalloc(&dv, sizeof(float)*n));
|
||
CUDA_CHECK(cudaMemcpy(dw, hw, sizeof(float)*n, cudaMemcpyHostToDevice));
|
||
CUDA_CHECK(cudaMemcpy(dv, hv, sizeof(float)*n, cudaMemcpyHostToDevice));
|
||
prob.d_weights = dw; prob.d_values = dv;
|
||
return prob;
|
||
}
|
||
|
||
void destroy() {
|
||
if (d_weights) cudaFree(const_cast<float*>(d_weights));
|
||
if (d_values) cudaFree(const_cast<float*>(d_values));
|
||
d_weights = nullptr; d_values = nullptr;
|
||
}
|
||
};
|