PDR/1.Software/PDR 1.0/src/m_munkres.c

344 lines
9.2 KiB
C
Raw Normal View History

2022-09-15 16:35:25 +08:00
/* Header File Including ------------------------------------------------------------------------ */#include <stdint.h>
#include <string.h>
#include "m_munkres.h"
//#include "loc_vivo_pdr.h"
/* Macro Definition ----------------------------------------------------------------------------- */
#define COST(i, j) cost[(i) + (j) * m]
#define MARK(i, j) mark[(i) + (j) * m]
#define PATH(i, j) path[(i) + (j) * 64]
#define CLR_ALL(flag) (*flag##_cover = 0)
#define SET_FLG(flag, index) (*flag##_cover |= (1 << (index)))
#define CLR_FLG(flag, index) (*flag##_cover &= ~(1 << (index)))
#define TST_FLG(flag, index) (*flag##_cover & (1 << (index)))
/* Global Variable Definition ------------------------------------------------------------------- */
static float g_cost[64];
static int g_mark[64];
static uint8_t g_row_cover;
static uint8_t g_col_cover;
/* Function Declaration ------------------------------------------------------------------------- */
static int step_one(float *cost, int m, int n);
static int step_two(float *cost, int *mark, int m, int n, uint8_t *col_cover);
static int step_three(int *mark, int m, int n, uint8_t *col_cover);
static int step_four(float *cost, int *mark, int m, int n, uint8_t *row_cover, uint8_t *col_cover, int *path_start_i, int *path_start_j);
static int step_five(int *mark, int m, int n, uint8_t *row_cover, uint8_t *col_cover, int path_start_i, int path_start_j);
static int step_six(float *cost, int m, int n, uint8_t *row_cover, uint8_t *col_cover);
#ifdef __MATLAB_DBG
void display_cost_matrix_and_cover(float *cost, int m, int n, uint8_t row_cover, uint8_t col_cover);
void display_mark_matrix_and_cover(int *mark, int m, int n, uint8_t row_cover, uint8_t col_cover);
#endif
/* Function Definition -------------------------------------------------------------------------- */
int MUNKRES_get_assignment(int *assignment, float *cost, int m, int n) {
int i = 0;
int j = 0;
int step;
#if PRINT_ALGO_RUN_TIME
uint64 time_algo_1 = 0l;
uint64 time_algo_2 = 0l;
uint64 time_algo_3 = 0l;
uint64 time_algo_4 = 0l;
#endif
if (m > 8 || n > 8) {
return MUNKRES_EXCESSIVE_MATRIX;
}
memcpy(g_cost, cost, m * n * sizeof(*g_cost));
memset(g_mark, 0, m * n * sizeof(*g_mark));
g_row_cover = 0;
g_col_cover = 0;
step = 0;
#if PRINT_ALGO_RUN_TIME
time_algo_1 = uTimetick_Get();
#endif
while (7 != step) {
#ifdef __MATLAB_DBG
mexPrintf("step %d:\n", step);
#endif
switch (step) {
case 0:
case 1:
step = step_one(g_cost, m, n);
break;
case 2:
step = step_two(g_cost, g_mark, m, n, &g_col_cover);
break;
case 3:
step = step_three(g_mark, m, n, &g_col_cover);
break;
case 4:
step = step_four(g_cost, g_mark, m, n, &g_row_cover, &g_col_cover, &i, &j);
#if PRINT_ALGO_RUN_TIME
time_algo_3 = uTimetick_Get();
time_algo_3 = (time_algo_3-time_algo_1);
#if defined(LOCATION_PLATFORM_QCOM_MODEM)
Geek_PDR_LOGH_NMEA("step_4 run time ms %d",(int)time_algo_3,0,0,0);
#endif
#endif
break;
case 5:
step = step_five(g_mark, m, n, &g_row_cover, &g_col_cover, i, j);
#if PRINT_ALGO_RUN_TIME
time_algo_4 = uTimetick_Get();
time_algo_4 = (time_algo_4-time_algo_1);
#if defined(LOCATION_PLATFORM_QCOM_MODEM)
Geek_PDR_LOGH_NMEA("step_5 run time ms %d",(int)time_algo_4,0,0,0);
#endif
#endif
break;
case 6:
step = step_six(g_cost, m, n, &g_row_cover, &g_col_cover);
break;
default:
step = 7;
break;
}
#ifdef __MATLAB_DBG
mexPrintf(" cost:\n", step);
display_cost_matrix_and_cover(g_cost, m, n, g_row_cover, g_col_cover);
mexPrintf(" mark:\n", step);
display_mark_matrix_and_cover(g_mark, m, n, g_row_cover, g_col_cover);
#endif
}
#if PRINT_ALGO_RUN_TIME
time_algo_2 = uTimetick_Get();
#endif
#if PRINT_ALGO_RUN_TIME
time_algo_2 = (time_algo_2-time_algo_1);
// time_algo_3 = (time_algo_3-time_algo_2);
#if defined(LOCATION_PLATFORM_QCOM_MODEM)
Geek_PDR_LOGH_NMEA("munkres run time ms %d",(int)time_algo_2,0,0,0);
#endif
// Geek_PDR_LOGH_NMEA("pdr2 run time ms %d %d",(int)time_algo_5,time_algo_6,0,0);
#endif
for (i = 0; i < m; ++i) {
for (j = 0; j < n; ++j) {
if (0 != g_mark[(i) + (j) * m]) {
assignment[i] = j;
break;
}
}
}
return MUNKRES_NO_ERROR;
}
static int step_one(float *cost, int m, int n) {
int i;
int j;
float min;
for (i = 0; i < m; ++i) {
min = COST(i, 0);
for (j = 1; j < n; ++j) {
if (min > COST(i, j)) {
min = COST(i, j);
}
}
for (j = 0; j < n; ++j) {
COST(i, j) -= min;
}
}
return 2;
}
static int step_two(float *cost, int *mark, int m, int n, uint8_t *col_cover) {
int i;
int j;
for (i = 0; i < m; ++i) {
for (j = 0; j < n; ++j) {
if (0 == COST(i, j) && 0 == TST_FLG(col, j)) {
MARK(i, j) = 1;
SET_FLG(col, j);
break;
}
}
}
CLR_ALL(col);
return 3;
}
static int step_three(int *mark, int m, int n, uint8_t *col_cover) {
int i;
int j;
int count;
CLR_ALL(col);
for (i = 0; i < m; ++i) {
for (j = 0; j < n; ++j) {
if (1 == MARK(i, j)) {
SET_FLG(col, j);
}
}
}
count = 0;
for (j = 0; j < n; ++j) {
count += (0 != TST_FLG(col, j) ? 1 : 0);
}
return (count >= m || count >= n) ? 7 : 4;
}
static void find_a_noncovered_zero(int *i, int *j, float *cost, int m, int n, uint8_t *row_cover, uint8_t *col_cover) {
for (*i = 0; *i < m; ++*i) {
if (0 != TST_FLG(row, *i)) {
continue;
}
for (*j = 0; *j < n; ++*j) {
if (0 == COST(*i, *j) && 0 == TST_FLG(col, *j)) {
break;
}
}
if (n != *j) {
break;
}
}
}
static void find_a_star_zero_in_row(int *j, int i, int *mark, int m, int n) {
for (*j = 0; *j < n; ++*j) {
if (1 == MARK(i, *j)) {
break;
}
}
}
static int step_four(float *cost, int *mark, int m, int n, uint8_t *row_cover, uint8_t *col_cover, int *path_start_i, int *path_start_j) {
int i;
int j;
int jj;
while (1) {
find_a_noncovered_zero(&i, &j, cost, m, n, row_cover, col_cover);
if (m == i) {
return 6;
}
else {
MARK(i, j) = 2;
find_a_star_zero_in_row(&jj, i, mark, m, n);
if (m != jj) {
SET_FLG(row, i);
CLR_FLG(col, jj);
j = jj;
}
else {
*path_start_i = i;
*path_start_j = j;
return 5;
}
}
}
}
static void find_a_star_zero_in_col(int *i, int j, int *mark, int m) {
for (*i = 0; *i < m; ++*i) {
if (1 == MARK(*i, j)) {
break;
}
}
}
static void find_a_prime_zero_in_row(int *j, int i, int *mark, int m, int n) {
for (*j = 0; *j < n; ++*j) {
if (2 == MARK(i, *j)) {
break;
}
}
}
static int step_five(int *mark, int m, int n, uint8_t *row_cover, uint8_t *col_cover, int path_start_i, int path_start_j) {
static int path[64 * 2];
int i;
int j;
int k;
k = 0;
PATH(k, 0) = path_start_i;
PATH(k, 1) = path_start_j;
while (1) {
find_a_star_zero_in_col(&i, PATH(k, 1), mark, m);
if (m == i) {
goto STEP_FIVE_EXIT;
}
else {
PATH(k + 1, 0) = i;
PATH(k + 1, 1) = PATH(k, 1);
++k;
find_a_prime_zero_in_row(&j, PATH(k, 0), mark, m, n);
PATH(k + 1, 0) = PATH(k, 0);
PATH(k + 1, 1) = j;
++k;
}
}
STEP_FIVE_EXIT:
/* augment path */
for(; k >= 0; --k) {
MARK(PATH(k, 0), PATH(k, 1)) = (1 == MARK(PATH(k, 0), PATH(k, 1)) ? 0 : 1);
}
/* clear covers */
CLR_ALL(row);
CLR_ALL(col);
/* erease primes */
for (i = 0; i < m; ++i) {
for (j = 0; j < n; ++j) {
if (2 == MARK(i, j)) {
MARK(i, j) = 0;
break;
}
}
}
return 3;
}
static int step_six(float *cost, int m, int n, uint8_t *row_cover, uint8_t *col_cover) {
float min;
int i;
int j;
min = 1e6;
for (i = 0; i < m; ++i) {
for (j = 0; j < n; ++j) {
if (0 == TST_FLG(row, i) && 0 == TST_FLG(col, j)) {
if (min > COST(i, j)) {
min = COST(i, j);
}
}
}
}
for (i = 0; i < m; ++i) {
for (j = 0; j < n; ++j) {
if (0 != TST_FLG(row, i)) {
COST(i, j) += min;
}
if (0 == TST_FLG(col, j)) {
COST(i, j) -= min;
}
}
}
return 4;
}