cuGenOpt/benchmark/experiments/e13_multiobjective/bi_objective_knapsack.cuh
2026-03-20 00:33:45 +08:00

161 lines
5.3 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.

#pragma once
#include "types.cuh"
#include "cuda_utils.cuh"
#include "operators.cuh"
/**
* 双目标 Knapsack: 最大化价值 + 最小化重量
*
* 目标1: 总价值(最大化)
* 目标2: 总重量(最小化,在满足容量约束下尽量少用重量)
*
* 测试场景:
* - Weighted 模式:权重配置 [0.8, 0.2]80% 关注价值)
* - Lexicographic 模式:优先级 [价值, 重量]
*/
struct BiObjectiveKnapsack : ProblemBase<BiObjectiveKnapsack, 1, 128> {
const int* d_values;
const int* d_weights;
int n;
int capacity;
// 双目标定义
static constexpr ObjDef OBJ_DEFS[] = {
{ObjDir::Maximize, 1.0f, 0.0f}, // 目标0: 最大化总价值
{ObjDir::Minimize, 1.0f, 0.0f}, // 目标1: 最小化总重量
};
__device__ float compute_obj(int obj_idx, const Sol& s) const {
if (obj_idx == 0) {
// 目标1: 总价值(最大化)
int total_value = 0;
for (int i = 0; i < s.dim2_sizes[0]; i++) {
if (s.data[0][i] == 1) {
total_value += d_values[i];
}
}
return (float)total_value;
} else {
// 目标2: 总重量(最小化)
int total_weight = 0;
for (int i = 0; i < s.dim2_sizes[0]; i++) {
if (s.data[0][i] == 1) {
total_weight += d_weights[i];
}
}
return (float)total_weight;
}
}
__device__ float compute_penalty(const Sol& s) const {
int total_weight = 0;
for (int i = 0; i < s.dim2_sizes[0]; i++) {
if (s.data[0][i] == 1) {
total_weight += d_weights[i];
}
}
if (total_weight > capacity) {
return (float)(total_weight - capacity) * 10.0f;
}
return 0.0f;
}
// 运行时配置覆盖
CompareMode override_mode = CompareMode::Weighted;
float override_weights[2] = {0.8f, 0.2f};
int override_priority[2] = {0, 1};
float override_tolerance[2] = {0.0f, 0.0f};
ProblemConfig config() const {
ProblemConfig cfg;
cfg.encoding = EncodingType::Binary;
cfg.dim1 = 1;
cfg.dim2_default = n;
fill_obj_config(cfg);
// 应用运行时覆盖
cfg.compare_mode = override_mode;
for (int i = 0; i < 2; i++) {
cfg.obj_weights[i] = override_weights[i];
cfg.obj_priority[i] = override_priority[i];
cfg.obj_tolerance[i] = override_tolerance[i];
}
return cfg;
}
size_t working_set_bytes() const {
return (size_t)n * (sizeof(int) + sizeof(int));
}
static BiObjectiveKnapsack create(const int* h_values, const int* h_weights,
int num_items, int knapsack_capacity) {
BiObjectiveKnapsack prob;
prob.n = num_items;
prob.capacity = knapsack_capacity;
size_t size = num_items * sizeof(int);
CUDA_CHECK(cudaMalloc(&prob.d_values, size));
CUDA_CHECK(cudaMalloc(&prob.d_weights, size));
CUDA_CHECK(cudaMemcpy((void*)prob.d_values, h_values, size, cudaMemcpyHostToDevice));
CUDA_CHECK(cudaMemcpy((void*)prob.d_weights, h_weights, size, cudaMemcpyHostToDevice));
return prob;
}
void destroy() {
if (d_values) CUDA_CHECK(cudaFree((void*)d_values));
if (d_weights) CUDA_CHECK(cudaFree((void*)d_weights));
}
BiObjectiveKnapsack* clone_to_device(int gpu_id) const override {
int orig_device;
CUDA_CHECK(cudaGetDevice(&orig_device));
CUDA_CHECK(cudaSetDevice(gpu_id));
// 在目标 GPU 上分配设备内存
int* dv;
int* dw;
size_t size = n * sizeof(int);
CUDA_CHECK(cudaMalloc(&dv, size));
CUDA_CHECK(cudaMalloc(&dw, size));
// 从原设备读取数据到 host
int* h_values = new int[n];
int* h_weights = new int[n];
CUDA_CHECK(cudaSetDevice(orig_device));
CUDA_CHECK(cudaMemcpy(h_values, d_values, size, cudaMemcpyDeviceToHost));
CUDA_CHECK(cudaMemcpy(h_weights, d_weights, size, cudaMemcpyDeviceToHost));
// 写入目标设备
CUDA_CHECK(cudaSetDevice(gpu_id));
CUDA_CHECK(cudaMemcpy(dv, h_values, size, cudaMemcpyHostToDevice));
CUDA_CHECK(cudaMemcpy(dw, h_weights, size, cudaMemcpyHostToDevice));
// 恢复原设备
CUDA_CHECK(cudaSetDevice(orig_device));
// 创建新的 host 端 Problem 实例
BiObjectiveKnapsack* new_prob = new BiObjectiveKnapsack();
new_prob->n = n;
new_prob->capacity = capacity;
new_prob->d_values = dv;
new_prob->d_weights = dw;
new_prob->override_mode = override_mode;
for (int i = 0; i < 2; i++) {
new_prob->override_weights[i] = override_weights[i];
new_prob->override_priority[i] = override_priority[i];
new_prob->override_tolerance[i] = override_tolerance[i];
}
delete[] h_values;
delete[] h_weights;
return new_prob;
}
};
// 类外定义静态成员
constexpr ObjDef BiObjectiveKnapsack::OBJ_DEFS[];