/******************************************************************** ******************************************************************** ** ** libhungarian by Cyrill Stachniss, 2004 ** Modified by Benjamin Auder to work on floating point number, ** and to fit into a R package (2017) ** ** Solving the Minimum Assignment Problem using the Hungarian Method. ** ** ** This file may be freely copied and distributed! ** ** ** Parts of the used code was originally provided by the ** "Stanford GraphGase", but I made changes to this code. ** As asked by the copyright node of the "Stanford GraphGase", ** I hereby proclaim that this file are *NOT* part of the ** "Stanford GraphGase" distrubition! ** ** This file is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ** PURPOSE. ** ******************************************************************** ********************************************************************/ #include #include #define HUNGARIAN_NOT_ASSIGNED 0 #define HUNGARIAN_ASSIGNED 1 #define HUNGARIAN_MODE_MINIMIZE_COST 0 #define HUNGARIAN_MODE_MAXIMIZE_UTIL 1 #define INF (1e32) #define verbose (0) typedef struct { int num_rows; int num_cols; double** cost; int** assignment; } hungarian_problem_t; int hungarian_imax(int a, int b) { return (anum_rows = rows; p->num_cols = cols; p->cost = (double**)calloc(rows,sizeof(double*)); p->assignment = (int**)calloc(rows,sizeof(int*)); for(i=0; inum_rows; i++) { p->cost[i] = (double*)calloc(cols,sizeof(double)); p->assignment[i] = (int*)calloc(cols,sizeof(int)); for(j=0; jnum_cols; j++) { p->cost[i][j] = (i < org_rows && j < org_cols) ? cost_matrix[i][j] : 0.; p->assignment[i][j] = 0; if (max_cost < p->cost[i][j]) max_cost = p->cost[i][j]; } } if (mode == HUNGARIAN_MODE_MAXIMIZE_UTIL) { for(i=0; inum_rows; i++) { for(j=0; jnum_cols; j++) p->cost[i][j] = max_cost - p->cost[i][j]; } } else if (mode == HUNGARIAN_MODE_MINIMIZE_COST) { // nothing to do } // else // fprintf(stderr,"%s: unknown mode. Mode was set to HUNGARIAN_MODE_MINIMIZE_COST !\n", __FUNCTION__); return rows; } /** Free the memory allocated by init. **/ void hungarian_free(hungarian_problem_t* p) { int i; for(i=0; inum_rows; i++) { free(p->cost[i]); free(p->assignment[i]); } free(p->cost); free(p->assignment); p->cost = NULL; p->assignment = NULL; } /** This method computes the optimal assignment. **/ void hungarian_solve(hungarian_problem_t* p) { int i, j, m, n, k, l, t, q, unmatched; double cost, s; int* col_mate; int* row_mate; int* parent_row; int* unchosen_row; double* row_dec; double* col_inc; double* slack; int* slack_row; cost = 0.; m =p->num_rows; n =p->num_cols; col_mate = (int*)calloc(p->num_rows,sizeof(int)); unchosen_row = (int*)calloc(p->num_rows,sizeof(int)); row_dec = (double*)calloc(p->num_rows,sizeof(double)); slack_row = (int*)calloc(p->num_rows,sizeof(int)); row_mate = (int*)calloc(p->num_cols,sizeof(int)); parent_row = (int*)calloc(p->num_cols,sizeof(int)); col_inc = (double*)calloc(p->num_cols,sizeof(double)); slack = (double*)calloc(p->num_cols,sizeof(double)); for (i=0; inum_rows; i++) { col_mate[i]=0; unchosen_row[i]=0; row_dec[i]=0.; slack_row[i]=0; } for (j=0; jnum_cols; j++) { row_mate[j]=0; parent_row[j] = 0; col_inc[j]=0.; slack[j]=0.; } for (i=0; inum_rows; ++i) for (j=0; jnum_cols; ++j) p->assignment[i][j]=HUNGARIAN_NOT_ASSIGNED; // Begin subtract column minima in order to start with lots of zeroes 12 for (l=0; lcost[0][l]; for (k=1; kcost[k][l]cost[k][l]; cost+=s; if (s!=0.) for (k=0; kcost[k][l]-=s; } // End subtract column minima in order to start with lots of zeroes 12 // Begin initial state 16 t=0; for (l=0; lcost[k][0]; for (l=1; lcost[k][l]cost[k][l]; row_dec[k]=s; for (l=0; lcost[k][l] && row_mate[l]<0) { col_mate[k]=l; row_mate[l]=k; goto row_done; } col_mate[k]= -1; unchosen_row[t++]=k; row_done: ; } // End initial state 16 // Begin Hungarian algorithm 18 if (t==0) goto done; unmatched=t; while (1) { q=0; while (1) { while (q 0.) { double del=p->cost[k][l]-s+col_inc[l]; if (del0. && slack[l]0.) { slack[l]-=s; if (slack[l]==0.) { // Begin look at a new zero 22 k=slack_row[l]; if (row_mate[l]<0) { for (j=l+1; jcost[k][l]cost[k][l]!=row_dec[k]-col_inc[l]) exit(0); } k=0; for (l=0; lm) exit(0); // End doublecheck the solution 23 */ // End Hungarian algorithm 18 for (i=0; iassignment[i][col_mate[i]]=HUNGARIAN_ASSIGNED; /*TRACE("%d - %d\n", i, col_mate[i]);*/ } for (k=0; kcost[k][l]-row_dec[k]+col_inc[l]);*/ p->cost[k][l]=p->cost[k][l]-row_dec[k]+col_inc[l]; } /*TRACE("\n");*/ } for (i=0; i