Commit a464ca47 authored by Christian Würdig's avatar Christian Würdig
Browse files

added option to choose between perfect and normal matching

[r8242]
parent 29c261eb
...@@ -34,17 +34,21 @@ ...@@ -34,17 +34,21 @@
#include "xmalloc.h" #include "xmalloc.h"
#include "debug.h" #include "debug.h"
#include "obst.h" #include "obst.h"
#include "bitset.h"
#include "hungarian.h" #include "hungarian.h"
#define INF (0x7FFFFFFF) #define INF (0x7FFFFFFF)
struct _hungarian_problem_t { struct _hungarian_problem_t {
int num_rows; int num_rows; /**< number of rows */
int num_cols; int num_cols; /**< number of columns */
int **cost; int **cost; /**< the cost matrix */
int width; int width; /**< the width for cost matrix dumper */
int max_cost; int max_cost; /**< the maximal costs in the matrix */
int match_type; /**< PERFECT or NORMAL matching */
bitset_t *missing_left; /**< left side nodes having no edge to the right side */
bitset_t *missing_right; /**< right side nodes having no edge to the left side */
struct obstack obst; struct obstack obst;
DEBUG_ONLY(firm_dbg_module_t *dbg); DEBUG_ONLY(firm_dbg_module_t *dbg);
}; };
...@@ -76,7 +80,7 @@ void hungarian_print_costmatrix(hungarian_problem_t *p) { ...@@ -76,7 +80,7 @@ void hungarian_print_costmatrix(hungarian_problem_t *p) {
/** /**
* Create the object and allocate memory for the data structures. * Create the object and allocate memory for the data structures.
*/ */
hungarian_problem_t *hungarian_new(int rows, int cols, int width) { hungarian_problem_t *hungarian_new(int rows, int cols, int width, int match_type) {
int i; int i;
int max_cost = 0; int max_cost = 0;
hungarian_problem_t *p = xmalloc(sizeof(*p)); hungarian_problem_t *p = xmalloc(sizeof(*p));
...@@ -94,12 +98,25 @@ hungarian_problem_t *hungarian_new(int rows, int cols, int width) { ...@@ -94,12 +98,25 @@ hungarian_problem_t *hungarian_new(int rows, int cols, int width) {
obstack_init(&p->obst); obstack_init(&p->obst);
p->num_rows = rows; p->num_rows = rows;
p->num_cols = cols; p->num_cols = cols;
p->width = width; p->width = width;
p->cost = (int **)get_init_mem(&p->obst, rows * sizeof(p->cost[0])); p->match_type = match_type;
/*
In case of normal matching, we have to keep
track of nodes without edges to kill them in
the assignment later.
*/
if (match_type == HUNGARIAN_MATCH_NORMAL) {
p->missing_left = bitset_obstack_alloc(&p->obst, rows);
p->missing_right = bitset_obstack_alloc(&p->obst, cols);
bitset_set_all(p->missing_left);
bitset_set_all(p->missing_right);
}
/* allocate space for cost matrix */ /* allocate space for cost matrix */
p->cost = (int **)get_init_mem(&p->obst, rows * sizeof(p->cost[0]));
for (i = 0; i < p->num_rows; i++) for (i = 0; i < p->num_rows; i++)
p->cost[i] = (int *)get_init_mem(&p->obst, cols * sizeof(p->cost[0][0])); p->cost[i] = (int *)get_init_mem(&p->obst, cols * sizeof(p->cost[0][0]));
...@@ -135,6 +152,11 @@ void hungarian_add(hungarian_problem_t *p, int left, int right, int cost) { ...@@ -135,6 +152,11 @@ void hungarian_add(hungarian_problem_t *p, int left, int right, int cost) {
p->cost[left][right] = cost; p->cost[left][right] = cost;
p->max_cost = MAX(p->max_cost, cost); p->max_cost = MAX(p->max_cost, cost);
if (p->match_type == HUNGARIAN_MATCH_NORMAL) {
bitset_clear(p->missing_left, left);
bitset_clear(p->missing_right, right);
}
} }
/** /**
...@@ -145,6 +167,11 @@ void hungarian_remv(hungarian_problem_t *p, int left, int right) { ...@@ -145,6 +167,11 @@ void hungarian_remv(hungarian_problem_t *p, int left, int right) {
assert(p->num_cols > right && "Invalid column selected."); assert(p->num_cols > right && "Invalid column selected.");
p->cost[left][right] = 0; p->cost[left][right] = 0;
if (p->match_type == HUNGARIAN_MATCH_NORMAL) {
bitset_set(p->missing_left, left);
bitset_set(p->missing_right, right);
}
} }
/** /**
...@@ -183,21 +210,6 @@ int hungarian_solve(hungarian_problem_t* p, int *assignment) { ...@@ -183,21 +210,6 @@ int hungarian_solve(hungarian_problem_t* p, int *assignment) {
col_inc = xcalloc(p->num_cols, sizeof(col_inc[0])); col_inc = xcalloc(p->num_cols, sizeof(col_inc[0]));
slack = xcalloc(p->num_cols, sizeof(slack[0])); slack = xcalloc(p->num_cols, sizeof(slack[0]));
#if 0
for (i = 0; i < p->num_rows; ++i) {
col_mate[i] = 0;
unchosen_row[i] = 0;
row_dec[i] = 0;
slack_row[i]=0;
}
for (j=0;j<p->num_cols;j++) {
row_mate[j]=0;
parent_row[j] = 0;
col_inc[j]=0;
slack[j]=0;
}
#endif
memset(assignment, -1, m * sizeof(assignment[0])); memset(assignment, -1, m * sizeof(assignment[0]));
/* Begin subtract column minima in order to start with lots of zeros 12 */ /* Begin subtract column minima in order to start with lots of zeros 12 */
...@@ -400,6 +412,14 @@ done: ...@@ -400,6 +412,14 @@ done:
assignment[i] = col_mate[i]; assignment[i] = col_mate[i];
} }
/* In case of normal matching: remove impossible ones */
if (p->match_type == HUNGARIAN_MATCH_NORMAL) {
for (i = 0; i < m; ++i) {
if (bitset_is_set(p->missing_left, i) || bitset_is_set(p->missing_right, col_mate[i]))
assignment[i] = -1;
}
}
for (k = 0; k < m; ++k) { for (k = 0; k < m; ++k) {
for (l = 0; l < n; ++l) { for (l = 0; l < n; ++l) {
p->cost[k][l] = p->cost[k][l] - row_dec[k] + col_inc[l]; p->cost[k][l] = p->cost[k][l] - row_dec[k] + col_inc[l];
...@@ -423,5 +443,5 @@ done: ...@@ -423,5 +443,5 @@ done:
xfree(unchosen_row); xfree(unchosen_row);
xfree(col_mate); xfree(col_mate);
return 0; return cost;
} }
...@@ -32,18 +32,22 @@ ...@@ -32,18 +32,22 @@
#define HUNGARIAN_MODE_MINIMIZE_COST 0 #define HUNGARIAN_MODE_MINIMIZE_COST 0
#define HUNGARIAN_MODE_MAXIMIZE_UTIL 1 #define HUNGARIAN_MODE_MAXIMIZE_UTIL 1
#define HUNGARIAN_MATCH_NORMAL 0
#define HUNGARIAN_MATCH_PERFECT 1
typedef struct _hungarian_problem_t hungarian_problem_t; typedef struct _hungarian_problem_t hungarian_problem_t;
/** /**
* This method initialize the hungarian_problem structure and init * This method initialize the hungarian_problem structure and init
* the cost matrix (missing lines or columns are filled with 0). * the cost matrix (missing lines or columns are filled with 0).
* *
* @param rows Number of rows in the given matrix * @param rows Number of rows in the given matrix
* @param cols Number of cols in the given matrix * @param cols Number of cols in the given matrix
* @param width Element width for matrix dumping * @param width Element width for matrix dumping
* @param match_type The type of matching HUNGARIAN_MATCH_NORMAL or HUNGARIAN_MATCH_PERFECT
* @return The problem object. * @return The problem object.
*/ */
hungarian_problem_t *hungarian_new(int rows, int cols, int width); hungarian_problem_t *hungarian_new(int rows, int cols, int width, int match_type);
/** /**
* Adds an edge from left to right with some costs. * Adds an edge from left to right with some costs.
...@@ -72,7 +76,7 @@ void hungarian_free(hungarian_problem_t *p); ...@@ -72,7 +76,7 @@ void hungarian_free(hungarian_problem_t *p);
* This method computes the optimal assignment. * This method computes the optimal assignment.
* @param p The hungarian object * @param p The hungarian object
* @param assignment The final assignment * @param assignment The final assignment
* @return Negative value if solution is invalid, 0 otherwise * @return The resulting cost or a negative value if matching is invalid.
*/ */
int hungarian_solve(hungarian_problem_t *p, int *assignment); int hungarian_solve(hungarian_problem_t *p, int *assignment);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment