【算法】拍卖算法(最优分配问题)--启发式算法_wuxiaoxiao2021的博客-CSDN博客
竞拍算法(Auction Algorithm)原理及工作过程分析_拍卖算法_一方灯火的博客-CSDN博客
一、原理
二、代码
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <stdbool.h>
#include <fstream>
#include <math.h>
#define NLINKS 65536
using namespace std;
void CreatRandomEdge(char* filePath, int n1, int n2);
typedef struct {
unsigned u;//first node
unsigned v;//second node
unsigned w;//weight of the edge
} edge;
typedef struct {
//edge list
unsigned n1;//number of nodes
unsigned n2;//number of nodes
unsigned e;//number of edges
edge *edges;//list of edges
bool b;//b=1 iff n1>n2
//graph
unsigned *cd;//cumulative degree: (start with 0) length=dim+1
unsigned *adj;//list of neighbors
unsigned *w;//weight of the edges
} bipgraph;
void freebg(bipgraph *g) {
free(g->edges);
free(g->cd);
free(g->adj);
free(g->w);
free(g);
}
//compute the maximum of two unsigned
inline unsigned max2u(unsigned a, unsigned b) {
return (a > b) ? a : b;
}
//reading the edgelist of bipartit weighted graph from file
//从文件中读取二维加权图的边表
bipgraph* readedgelist(char* edgelist) {
unsigned e1 = NLINKS;
bipgraph *g = (bipgraph*)malloc(sizeof(bipgraph));
FILE *file;
g->n1 = 0;
g->n2 = 0;
g->e = 0;
file = fopen(edgelist, "r");
g->edges = (edge*)malloc(e1 * sizeof(edge));
//e1 += NLINKS;
//g->edges = (edge*)realloc(g->edges, e1 * sizeof(edge));
while (fscanf(file, "%u %u %u\n", &(g->edges[g->e].u), &(g->edges[g->e].v), &(g->edges[g->e].w)) == 3) {
g->n1 = max2u(g->n1, g->edges[g->e].u);
g->n2 = max2u(g->n2, g->edges[g->e].v);
if (g->e++ == e1) {
e1 += NLINKS;
g->edges = (edge*)realloc(g->edges, e1 * sizeof(edge));
}
}
fclose(file);
g->n1++;
g->n2++;
g->edges = (edge*)realloc(g->edges, g->e * sizeof(edge));
return g;
}
//Building a special sparse graph structure
//构建一个特殊的稀疏图结构
void mkbg(bipgraph *g)
{
unsigned int i, u;
unsigned int *d;
if (g->n1 <= g->n2)
{
g->b = 0;
d = (unsigned int*)calloc(g->n1, sizeof(unsigned));
g->cd = (unsigned int*)malloc((g->n1 + 1) * sizeof(unsigned));
g->adj = (unsigned int*)malloc((g->e) * sizeof(unsigned));
g->w = (unsigned int*)malloc((g->e) * sizeof(unsigned));
for (i = 0; i < g->e; i++) {
d[g->edges[i].u]++;
}
g->cd[0] = 0;
for (i = 1; i < g->n1 + 1; i++) {
g->cd[i] = g->cd[i - 1] + d[i - 1];
d[i - 1] = 0;
}
for (i = 0; i < g->e; i++) {
u = g->edges[i].u;
g->adj[g->cd[u] + d[u]] = g->edges[i].v;
g->w[g->cd[u] + d[u]++] = g->edges[i].w;
}
}
else
{
g->b = 1;
d = (unsigned int*)calloc(g->n2, sizeof(unsigned));
g->cd = (unsigned int*)malloc((g->n2 + 1) * sizeof(unsigned));
g->adj = (unsigned int*)malloc((g->e) * sizeof(unsigned));
g->w = (unsigned int*)malloc((g->e) * sizeof(unsigned));
//计算n2中每个节点有多少边
for (i = 0; i < g->e; i++) {
d[g->edges[i].v]++;
}
g->cd[0] = 0;
for (i = 1; i < g->n2 + 1; i++) {
g->cd[i] = g->cd[i - 1] + d[i - 1];
d[i - 1] = 0;
}
for (i = 0; i < g->e; i++) {
u = g->edges[i].v;
g->adj[g->cd[u] + d[u]] = g->edges[i].u;
g->w[g->cd[u] + d[u]++] = g->edges[i].w;
}
i = g->n1;
g->n1 = g->n2;
g->n2 = i;
}
free(d);
free(g->edges);
}
//bidding towards convergence
unsigned bidding(bipgraph *g, double eps)
{
unsigned u, v, w, i, j, k, res;
double *p = (double*)calloc(g->n2, sizeof(double));//p[i]=price of object i
unsigned *a = (unsigned int*)malloc(g->n2 * sizeof(unsigned));//a[target]=-1 if not assigned = source if assigned
unsigned *aw = (unsigned int*)malloc(g->n2 * sizeof(unsigned));//aw[target]=? if not assigned = weigth of edge source-target if assigned
for (v = 0; v < g->n2; v++) {
a[v] = -1;
}
//set data structure
unsigned n_set = g->n1;//
unsigned *l_set = (unsigned int*)malloc(g->n1 * sizeof(unsigned));//
//bool *t_set=malloc(g->n1*sizeof(bool));//
for (u = 0; u < n_set; u++) {
l_set[u] = u;
//t_set[u]=1;
}
//double eps=0.1;//1./((double)(g->n1)+1.);///
double max, max2;
unsigned wmax;
res = 0;
while (n_set > 0)
{
u = l_set[n_set - 1];
//printf("n_set, u, w = %u, %u, %u\n",n_set,u,res);
//找权重最大的一个u(火力点)
max = 0;
for (i = g->cd[u]; i < g->cd[u + 1]; i++) {
v = g->adj[i];
w = g->w[i];
//printf("w=%u\n",w);
if ((double)w - p[v] > max) {
max = (double)w - p[v];
wmax = w;
k = v;
}
}
//printf("max=%f\n",max);
if (max == 0) {
n_set--;
continue;
}
//找次大的一个u(火力点)
max2 = 0;
for (i = g->cd[u]; i < g->cd[u + 1]; i++) {
v = g->adj[i];
if (v != k) {
w = g->w[i];
if ((double)w - p[v] > max2) {
max2 = (double)w - p[v];
}
}
}
//printf("max2=%f\n",max2);
p[k] += max - max2 + eps;
//printf("k=%u\n",k);
//printf("p[k]=%f\n",p[k]);
if (a[k] != -1) {
l_set[n_set - 1] = a[k];
res -= aw[k];
}
else {
n_set--;
}
a[k] = u;
aw[k] = wmax;
res += wmax;
}
g->edges = (edge*)malloc(g->n1 * sizeof(edge));
j = 0;
for (i = 0; i < g->n2; i++) {
if (a[i] != -1) {
g->edges[j].u = a[i];
g->edges[j].v = i;
g->edges[j++].w = aw[i];
}
}
g->edges = (edge*)realloc(g->edges, j * sizeof(edge));
g->e = j;
return res;
}
void printres(bipgraph *g, char *output) {
unsigned i;
edge ed;
FILE* file = fopen(output, "w");
if (g->b) {
for (i = 0; i < g->e; i++) {
ed = g->edges[i];
fprintf(file, "%u %u %u\n", ed.v, ed.u, ed.w);
}
}
else {
for (i = 0; i < g->e; i++) {
ed = g->edges[i];
fprintf(file, "%u %u %u\n", ed.u, ed.v, ed.w);//输出:人序号 任务序号 代价
}
}
fclose(file);
}
int main(void)
{
bipgraph* g;
unsigned w;
time_t t0, t1, t2;
char* argv[4];
argv[1] = "testEdgesList.txt";
argv[2] = "testRes.txt";
//随机生成n x n个矩阵对,保存在testEdgesList.txt中
CreatRandomEdge("testEdgesList.txt", 60, 60);//6 6
double eps = 0.01;
printf("Reading edgelist from file %s\n", argv[1]);
//将矩阵读入矩阵图结构g中
g = readedgelist(argv[1]);
printf("Number of left nodes: %u\n", g->n1);
printf("Number of right nodes: %u\n", g->n2);
printf("Number of edges: %u\n", g->e);
printf("Building datastructure\n");
mkbg(g);
printf("计算最优分配\n");
//投标
w = bidding(g, eps);
printf("最优分配值 = %u\n", w);
printf("Writting the results in file %s\n", argv[2]);
printres(g, argv[2]);
freebg(g);
return 0;
}
void CreatRandomEdge(char* filePath, int n1, int n2)
{
ofstream fout;
fout.open(filePath);
int edgesNum = n1 * n2;//36
int pI = n1 - 1;//人索引
for (int i = 0; i < n1; i++)
{
for (int j = 0; j < n2; j++)//物品索引
{
fout << pI << " " << j << " " << (rand() % edgesNum) << "\n"; //随机生成0~35的随机数
}
pI--;
}
fout.close();
}