mirror of
https://github.com/L-yang-yang/cugenopt.git
synced 2026-04-25 12:16:21 +02:00
84 lines
2.6 KiB
Text
84 lines
2.6 KiB
Text
/**
|
||
* qap.cuh - 二次分配问题 (Quadratic Assignment Problem)
|
||
*
|
||
* N 个设施分配到 N 个位置(排列编码)。
|
||
* 决策变量:data[0][i] = 设施 i 分配到的位置。
|
||
* 目标:Minimize sum(flow[i][j] * dist[perm[i]][perm[j]])
|
||
*
|
||
* 验证实例:自定义 5x5
|
||
* flow: 设施间的物流量
|
||
* dist: 位置间的距离
|
||
* 已知最优 = 58
|
||
*/
|
||
|
||
#pragma once
|
||
#include "types.cuh"
|
||
#include "cuda_utils.cuh"
|
||
|
||
struct QAPProblem : ProblemBase<QAPProblem, 1, 32> {
|
||
const float* d_flow; // 物流量矩阵 [N*N]
|
||
const float* d_dist; // 距离矩阵 [N*N]
|
||
int n;
|
||
|
||
__device__ float calc_cost(const Sol& sol) const {
|
||
float cost = 0.0f;
|
||
int size = sol.dim2_sizes[0];
|
||
for (int i = 0; i < size; i++)
|
||
for (int j = 0; j < size; j++)
|
||
cost += d_flow[i * n + j] * d_dist[sol.data[0][i] * n + sol.data[0][j]];
|
||
return cost;
|
||
}
|
||
|
||
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_cost(sol);
|
||
default: return 0.0f;
|
||
}
|
||
}
|
||
|
||
__device__ float compute_penalty(const Sol& sol) const {
|
||
return 0.0f;
|
||
}
|
||
|
||
ProblemConfig config() const {
|
||
ProblemConfig cfg;
|
||
cfg.encoding = EncodingType::Permutation;
|
||
cfg.dim1 = 1; cfg.dim2_default = n;
|
||
fill_obj_config(cfg);
|
||
return cfg;
|
||
}
|
||
|
||
size_t shared_mem_bytes() const {
|
||
return 2 * (size_t)n * n * sizeof(float);
|
||
}
|
||
|
||
__device__ void load_shared(char* smem, int tid, int bsz) {
|
||
float* sf = reinterpret_cast<float*>(smem);
|
||
float* sd = sf + n * n;
|
||
int total = n * n;
|
||
for (int i = tid; i < total; i += bsz) { sf[i] = d_flow[i]; sd[i] = d_dist[i]; }
|
||
d_flow = sf;
|
||
d_dist = sd;
|
||
}
|
||
|
||
static QAPProblem create(const float* h_flow, const float* h_dist, int n) {
|
||
QAPProblem prob;
|
||
prob.n = n;
|
||
float *df, *dd;
|
||
CUDA_CHECK(cudaMalloc(&df, sizeof(float) * n * n));
|
||
CUDA_CHECK(cudaMalloc(&dd, sizeof(float) * n * n));
|
||
CUDA_CHECK(cudaMemcpy(df, h_flow, sizeof(float) * n * n, cudaMemcpyHostToDevice));
|
||
CUDA_CHECK(cudaMemcpy(dd, h_dist, sizeof(float) * n * n, cudaMemcpyHostToDevice));
|
||
prob.d_flow = df; prob.d_dist = dd;
|
||
return prob;
|
||
}
|
||
|
||
void destroy() {
|
||
if (d_flow) cudaFree(const_cast<float*>(d_flow));
|
||
if (d_dist) cudaFree(const_cast<float*>(d_dist));
|
||
d_flow = nullptr; d_dist = nullptr;
|
||
}
|
||
};
|