/* Header File Including ------------------------------------------------------------------------ */#include #include #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; }