Meta Byte Track
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

lapjv.cpp 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "lapjv.h"
  5. /** Column-reduction and reduction transfer for a dense cost matrix.
  6. */
  7. int_t _ccrrt_dense(const uint_t n, cost_t *cost[],
  8. int_t *free_rows, int_t *x, int_t *y, cost_t *v)
  9. {
  10. int_t n_free_rows;
  11. boolean *unique;
  12. for (uint_t i = 0; i < n; i++) {
  13. x[i] = -1;
  14. v[i] = LARGE;
  15. y[i] = 0;
  16. }
  17. for (uint_t i = 0; i < n; i++) {
  18. for (uint_t j = 0; j < n; j++) {
  19. const cost_t c = cost[i][j];
  20. if (c < v[j]) {
  21. v[j] = c;
  22. y[j] = i;
  23. }
  24. PRINTF("i=%d, j=%d, c[i,j]=%f, v[j]=%f y[j]=%d\n", i, j, c, v[j], y[j]);
  25. }
  26. }
  27. PRINT_COST_ARRAY(v, n);
  28. PRINT_INDEX_ARRAY(y, n);
  29. NEW(unique, boolean, n);
  30. memset(unique, TRUE, n);
  31. {
  32. int_t j = n;
  33. do {
  34. j--;
  35. const int_t i = y[j];
  36. if (x[i] < 0) {
  37. x[i] = j;
  38. }
  39. else {
  40. unique[i] = FALSE;
  41. y[j] = -1;
  42. }
  43. } while (j > 0);
  44. }
  45. n_free_rows = 0;
  46. for (uint_t i = 0; i < n; i++) {
  47. if (x[i] < 0) {
  48. free_rows[n_free_rows++] = i;
  49. }
  50. else if (unique[i]) {
  51. const int_t j = x[i];
  52. cost_t min = LARGE;
  53. for (uint_t j2 = 0; j2 < n; j2++) {
  54. if (j2 == (uint_t)j) {
  55. continue;
  56. }
  57. const cost_t c = cost[i][j2] - v[j2];
  58. if (c < min) {
  59. min = c;
  60. }
  61. }
  62. PRINTF("v[%d] = %f - %f\n", j, v[j], min);
  63. v[j] -= min;
  64. }
  65. }
  66. FREE(unique);
  67. return n_free_rows;
  68. }
  69. /** Augmenting row reduction for a dense cost matrix.
  70. */
  71. int_t _carr_dense(
  72. const uint_t n, cost_t *cost[],
  73. const uint_t n_free_rows,
  74. int_t *free_rows, int_t *x, int_t *y, cost_t *v)
  75. {
  76. uint_t current = 0;
  77. int_t new_free_rows = 0;
  78. uint_t rr_cnt = 0;
  79. PRINT_INDEX_ARRAY(x, n);
  80. PRINT_INDEX_ARRAY(y, n);
  81. PRINT_COST_ARRAY(v, n);
  82. PRINT_INDEX_ARRAY(free_rows, n_free_rows);
  83. while (current < n_free_rows) {
  84. int_t i0;
  85. int_t j1, j2;
  86. cost_t v1, v2, v1_new;
  87. boolean v1_lowers;
  88. rr_cnt++;
  89. PRINTF("current = %d rr_cnt = %d\n", current, rr_cnt);
  90. const int_t free_i = free_rows[current++];
  91. j1 = 0;
  92. v1 = cost[free_i][0] - v[0];
  93. j2 = -1;
  94. v2 = LARGE;
  95. for (uint_t j = 1; j < n; j++) {
  96. PRINTF("%d = %f %d = %f\n", j1, v1, j2, v2);
  97. const cost_t c = cost[free_i][j] - v[j];
  98. if (c < v2) {
  99. if (c >= v1) {
  100. v2 = c;
  101. j2 = j;
  102. }
  103. else {
  104. v2 = v1;
  105. v1 = c;
  106. j2 = j1;
  107. j1 = j;
  108. }
  109. }
  110. }
  111. i0 = y[j1];
  112. v1_new = v[j1] - (v2 - v1);
  113. v1_lowers = v1_new < v[j1];
  114. PRINTF("%d %d 1=%d,%f 2=%d,%f v1'=%f(%d,%g) \n", free_i, i0, j1, v1, j2, v2, v1_new, v1_lowers, v[j1] - v1_new);
  115. if (rr_cnt < current * n) {
  116. if (v1_lowers) {
  117. v[j1] = v1_new;
  118. }
  119. else if (i0 >= 0 && j2 >= 0) {
  120. j1 = j2;
  121. i0 = y[j2];
  122. }
  123. if (i0 >= 0) {
  124. if (v1_lowers) {
  125. free_rows[--current] = i0;
  126. }
  127. else {
  128. free_rows[new_free_rows++] = i0;
  129. }
  130. }
  131. }
  132. else {
  133. PRINTF("rr_cnt=%d >= %d (current=%d * n=%d)\n", rr_cnt, current * n, current, n);
  134. if (i0 >= 0) {
  135. free_rows[new_free_rows++] = i0;
  136. }
  137. }
  138. x[free_i] = j1;
  139. y[j1] = free_i;
  140. }
  141. return new_free_rows;
  142. }
  143. /** Find columns with minimum d[j] and put them on the SCAN list.
  144. */
  145. uint_t _find_dense(const uint_t n, uint_t lo, cost_t *d, int_t *cols, int_t *y)
  146. {
  147. uint_t hi = lo + 1;
  148. cost_t mind = d[cols[lo]];
  149. for (uint_t k = hi; k < n; k++) {
  150. int_t j = cols[k];
  151. if (d[j] <= mind) {
  152. if (d[j] < mind) {
  153. hi = lo;
  154. mind = d[j];
  155. }
  156. cols[k] = cols[hi];
  157. cols[hi++] = j;
  158. }
  159. }
  160. return hi;
  161. }
  162. // Scan all columns in TODO starting from arbitrary column in SCAN
  163. // and try to decrease d of the TODO columns using the SCAN column.
  164. int_t _scan_dense(const uint_t n, cost_t *cost[],
  165. uint_t *plo, uint_t*phi,
  166. cost_t *d, int_t *cols, int_t *pred,
  167. int_t *y, cost_t *v)
  168. {
  169. uint_t lo = *plo;
  170. uint_t hi = *phi;
  171. cost_t h, cred_ij;
  172. while (lo != hi) {
  173. int_t j = cols[lo++];
  174. const int_t i = y[j];
  175. const cost_t mind = d[j];
  176. h = cost[i][j] - v[j] - mind;
  177. PRINTF("i=%d j=%d h=%f\n", i, j, h);
  178. // For all columns in TODO
  179. for (uint_t k = hi; k < n; k++) {
  180. j = cols[k];
  181. cred_ij = cost[i][j] - v[j] - h;
  182. if (cred_ij < d[j]) {
  183. d[j] = cred_ij;
  184. pred[j] = i;
  185. if (cred_ij == mind) {
  186. if (y[j] < 0) {
  187. return j;
  188. }
  189. cols[k] = cols[hi];
  190. cols[hi++] = j;
  191. }
  192. }
  193. }
  194. }
  195. *plo = lo;
  196. *phi = hi;
  197. return -1;
  198. }
  199. /** Single iteration of modified Dijkstra shortest path algorithm as explained in the JV paper.
  200. *
  201. * This is a dense matrix version.
  202. *
  203. * \return The closest free column index.
  204. */
  205. int_t find_path_dense(
  206. const uint_t n, cost_t *cost[],
  207. const int_t start_i,
  208. int_t *y, cost_t *v,
  209. int_t *pred)
  210. {
  211. uint_t lo = 0, hi = 0;
  212. int_t final_j = -1;
  213. uint_t n_ready = 0;
  214. int_t *cols;
  215. cost_t *d;
  216. NEW(cols, int_t, n);
  217. NEW(d, cost_t, n);
  218. for (uint_t i = 0; i < n; i++) {
  219. cols[i] = i;
  220. pred[i] = start_i;
  221. d[i] = cost[start_i][i] - v[i];
  222. }
  223. PRINT_COST_ARRAY(d, n);
  224. while (final_j == -1) {
  225. // No columns left on the SCAN list.
  226. if (lo == hi) {
  227. PRINTF("%d..%d -> find\n", lo, hi);
  228. n_ready = lo;
  229. hi = _find_dense(n, lo, d, cols, y);
  230. PRINTF("check %d..%d\n", lo, hi);
  231. PRINT_INDEX_ARRAY(cols, n);
  232. for (uint_t k = lo; k < hi; k++) {
  233. const int_t j = cols[k];
  234. if (y[j] < 0) {
  235. final_j = j;
  236. }
  237. }
  238. }
  239. if (final_j == -1) {
  240. PRINTF("%d..%d -> scan\n", lo, hi);
  241. final_j = _scan_dense(
  242. n, cost, &lo, &hi, d, cols, pred, y, v);
  243. PRINT_COST_ARRAY(d, n);
  244. PRINT_INDEX_ARRAY(cols, n);
  245. PRINT_INDEX_ARRAY(pred, n);
  246. }
  247. }
  248. PRINTF("found final_j=%d\n", final_j);
  249. PRINT_INDEX_ARRAY(cols, n);
  250. {
  251. const cost_t mind = d[cols[lo]];
  252. for (uint_t k = 0; k < n_ready; k++) {
  253. const int_t j = cols[k];
  254. v[j] += d[j] - mind;
  255. }
  256. }
  257. FREE(cols);
  258. FREE(d);
  259. return final_j;
  260. }
  261. /** Augment for a dense cost matrix.
  262. */
  263. int_t _ca_dense(
  264. const uint_t n, cost_t *cost[],
  265. const uint_t n_free_rows,
  266. int_t *free_rows, int_t *x, int_t *y, cost_t *v)
  267. {
  268. int_t *pred;
  269. NEW(pred, int_t, n);
  270. for (int_t *pfree_i = free_rows; pfree_i < free_rows + n_free_rows; pfree_i++) {
  271. int_t i = -1, j;
  272. uint_t k = 0;
  273. PRINTF("looking at free_i=%d\n", *pfree_i);
  274. j = find_path_dense(n, cost, *pfree_i, y, v, pred);
  275. ASSERT(j >= 0);
  276. ASSERT(j < n);
  277. while (i != *pfree_i) {
  278. PRINTF("augment %d\n", j);
  279. PRINT_INDEX_ARRAY(pred, n);
  280. i = pred[j];
  281. PRINTF("y[%d]=%d -> %d\n", j, y[j], i);
  282. y[j] = i;
  283. PRINT_INDEX_ARRAY(x, n);
  284. SWAP_INDICES(j, x[i]);
  285. k++;
  286. if (k >= n) {
  287. ASSERT(FALSE);
  288. }
  289. }
  290. }
  291. FREE(pred);
  292. return 0;
  293. }
  294. /** Solve dense sparse LAP.
  295. */
  296. int lapjv_internal(
  297. const uint_t n, cost_t *cost[],
  298. int_t *x, int_t *y)
  299. {
  300. int ret;
  301. int_t *free_rows;
  302. cost_t *v;
  303. NEW(free_rows, int_t, n);
  304. NEW(v, cost_t, n);
  305. ret = _ccrrt_dense(n, cost, free_rows, x, y, v);
  306. int i = 0;
  307. while (ret > 0 && i < 2) {
  308. ret = _carr_dense(n, cost, ret, free_rows, x, y, v);
  309. i++;
  310. }
  311. if (ret > 0) {
  312. ret = _ca_dense(n, cost, ret, free_rows, x, y, v);
  313. }
  314. FREE(v);
  315. FREE(free_rows);
  316. return ret;
  317. }