00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "eg_min_cut.h"
00026
00027
00028
00029
00030
00031
00032 #if __MC_PROFILE_ <= DEBUG
00033 unsigned long long __MC_profile_lvl[5] = { 0, 0, 0, 0, 0 };
00034
00035 unsigned long long __MC_profile_tn = 0;
00036 unsigned long long __MC_profile_up = 0;
00037 #define UPDATE(counter) (counter)++
00038 #else
00039 #define UPDATE(counter)
00040 #endif
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 static inline int EGalgMCexpandNode (unsigned int *const cut,
00051 EGalgMCnode_t * const N)
00052 {
00053 unsigned int register i = N->node.mmb_sz;
00054 EGeList_t *const n_end = &(N->node.members);
00055 EGeList_t *n_it = n_end->next;
00056 EGalgMCnode_t *M;
00057 cut[i] = N->id;
00058 for (; n_it != n_end; n_it = n_it->next)
00059 {
00060 M = EGcontainerOf (n_it, EGalgMCnode_t, node.members);
00061 cut[--i] = M->id;
00062 }
00063 return 0;
00064 }
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 static inline int EGalgMCtestNode (EGalgMCgraph_t * const G,
00076 EGalgMCcbk_t * const cb,
00077 EGalgMCnode_t * const N)
00078 {
00079 int rval = 0;
00080 UPDATE (__MC_profile_tn);
00081 TESTL (__MC_DEBUG_, EGlpNumIsLess (N->node.weight, zeroLpNum),
00082 "node %u with " "negative weight %lf", N->id,
00083 EGlpNumToLf (N->node.weight));
00084 if (EGlpNumIsLess (N->node.weight, G->cut_val))
00085 {
00086 UPDATE (__MC_profile_up);
00087 MESSAGE (__MC_VRBLVL_, "Update cut_val from %lf to %lf, n_nodes %u"
00088 " n_edges %u", EGlpNumToLf (G->cut_val),
00089 EGlpNumToLf (N->node.weight), G->G.G.n_nodes, G->G.G.n_edges);
00090 EGlpNumCopy (G->cut_val, N->node.weight);
00091 G->cut_sz = N->node.mmb_sz + 1;
00092 rval = EGalgMCexpandNode (G->cut, N);
00093 CHECKRVALG (rval, CLEANUP);
00094 if (cb && EGlpNumIsLess (N->node.weight, cb->cutoff))
00095 {
00096 rval = cb->do_fn (G->cut_val, G->cut_sz, G->cut, cb->param);
00097 CHECKRVALG (rval, CLEANUP);
00098 }
00099 }
00100 else if (cb && EGlpNumIsLess (N->node.weight, cb->cutoff))
00101 {
00102 unsigned int *cut = EGsMalloc (unsigned int, N->node.mmb_sz + 1);
00103 rval = EGalgMCexpandNode (cut, N);
00104 CHECKRVALG (rval, CLEANUP);
00105 rval = cb->do_fn (N->node.weight, N->node.mmb_sz + 1, cut, cb->param);
00106 CHECKRVALG (rval, CLEANUP);
00107 EGfree (cut);
00108 }
00109
00110 CLEANUP:
00111 return rval;
00112 }
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 #define _EGalgMChitNeighbours(NODE) {\
00123 e_end = &((NODE)->node.node.edges);\
00124 for( e_it = e_end->next; e_it != e_end; e_it = e_it->next)\
00125 {\
00126 lep = EGcontainerOf(e_it, EGeUgraphEP_t,cn);\
00127 o_type = lep->type ? 0U : 1U;\
00128 E = EGcontainerOf(lep, EGalgMCedge_t, edge.edge.ep[lep->type]);\
00129 M = EGcontainerOf(E->edge.edge.ep[o_type].node, EGalgMCnode_t, node.node);\
00130 M->hit = &(E->edge);\
00131 }}
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 #define _EGalgMCunhitNeighbours(NODE) {\
00142 e_end = &((NODE)->node.node.edges);\
00143 for( e_it = e_end->next; e_it != e_end; e_it = e_it->next)\
00144 {\
00145 lep = EGcontainerOf(e_it, EGeUgraphEP_t,cn);\
00146 o_type = lep->type ? 0U : 1U;\
00147 E = EGcontainerOf(lep, EGalgMCedge_t, edge.edge.ep[lep->type]);\
00148 M = EGcontainerOf(E->edge.edge.ep[o_type].node, EGalgMCnode_t, node.node);\
00149 M->hit = 0;\
00150 }}
00151
00152
00153 int EGalgMCidentifyPRedges (EGalgMCgraph_t * const G,
00154 EGalgMCcbk_t * const cb,
00155 const unsigned int max_lvl)
00156 {
00157
00158 int rval = 0;
00159 EGeList_t *e_it,
00160 *e_end,
00161 *e2_it,
00162 *e3_it,
00163 *e2_end,
00164 *c_lvl;
00165 unsigned int o_type,
00166 o_type2,
00167 o_type3;
00168 EGalgMCnode_t *N,
00169 *M,
00170 *X,
00171 *Y;
00172 EGalgMCedge_t *E,
00173 *F,
00174 *H;
00175 EGeUgraphEP_t *lep,
00176 *lep2,
00177 *lep3;
00178
00179
00180
00181 EGlpNum_t N_dv2,
00182 M_dv2,
00183 N_dv,
00184 M_dv;
00185 EGlpNumInitVar (N_dv2);
00186 EGlpNumInitVar (M_dv2);
00187 EGlpNumInitVar (N_dv);
00188 EGlpNumInitVar (M_dv);
00189 REDO:
00190
00191
00192 MESSAGE (__MC_VRBLVL_, "PR shrinking level 0, nodes %u edges %u",
00193 G->G.G.n_nodes, G->G.G.n_edges);
00194 c_lvl = G->lvl_list;
00195 while (!EGeListIsEmpty (c_lvl) && EGlpNumIsLess (zeroLpNum, G->cut_val))
00196 {
00197 N = EGcontainerOf (c_lvl->next, EGalgMCnode_t, lvl_cn);
00198 rval = EGalgMCtestNode (G, cb, N);
00199 CHECKRVALG (rval, CLEANUP);
00200 N->lvl = 1;
00201 EGeListMoveAfter (&(N->lvl_cn), c_lvl + 1);
00202 }
00203
00204
00205 if (max_lvl < 1 || G->G.G.n_nodes < 3 ||
00206 EGlpNumIsEqual (zeroLpNum, G->cut_val, G->epsilon))
00207 goto CLEANUP;
00208 MESSAGE (__MC_VRBLVL_, "PR shrinking level 1, nodes %u edges %u",
00209 G->G.G.n_nodes, G->G.G.n_edges);
00210 c_lvl++;
00211 while (!EGeListIsEmpty (c_lvl) && G->G.G.n_nodes > 2)
00212 {
00213 N = EGcontainerOf (c_lvl->next, EGalgMCnode_t, lvl_cn);
00214 TESTL (__MC_DEBUG_, EGlpNumIsLess (N->node.weight, zeroLpNum),
00215 "node %u with " "negative weight %lf", N->id,
00216 EGlpNumToLf (N->node.weight));
00217 EGlpNumCopy (N_dv, N->node.weight);
00218 EGlpNumDivUiTo (N_dv, 2);
00219 EGlpNumSubTo (N_dv, G->epsilon);
00220 e_end = &(N->node.node.edges);
00221 for (e_it = e_end->next; e_it != e_end; e_it = e_it->next)
00222 {
00223 lep = EGcontainerOf (e_it, EGeUgraphEP_t, cn);
00224 o_type = lep->type ? 0U : 1U;
00225 E = EGcontainerOf (lep, EGalgMCedge_t, edge.edge.ep[lep->type]);
00226 M =
00227 EGcontainerOf (E->edge.edge.ep[o_type].node, EGalgMCnode_t, node.node);
00228
00229
00230 if (M->lvl > 1)
00231 continue;
00232
00233 TESTL (__MC_DEBUG_, EGlpNumIsLess (M->node.weight, zeroLpNum),
00234 "node %u with " "negative weight %lf", M->id,
00235 EGlpNumToLf (M->node.weight));
00236 EGlpNumCopy (M_dv, M->node.weight);
00237 EGlpNumDivUiTo (M_dv, 2);
00238 EGlpNumSubTo (M_dv, G->epsilon);
00239
00240
00241 TESTL (__MC_DEBUG_, EGlpNumIsLess (E->edge.weight, zeroLpNum),
00242 "edge %u with " "negative weight %lf", E->id,
00243 EGlpNumToLf (E->edge.weight));
00244 if (EGlpNumIsLeq (N_dv, E->edge.weight)
00245 || EGlpNumIsLeq (M_dv, E->edge.weight))
00246 {
00247 EGalgMCidentifyNodes (G, N, M);
00248 UPDATE (__MC_profile_lvl[1]);
00249 TESTL (__MC_DEBUG_, EGlpNumIsLess (N->node.weight, zeroLpNum),
00250 "node %u" " with negative weight %lf", N->id,
00251 EGlpNumToLf (N->node.weight));
00252 goto REDO;
00253 }
00254 }
00255
00256 N->lvl = 2;
00257 EGeListMoveAfter (&(N->lvl_cn), c_lvl + 1);
00258 }
00259
00260
00261 if (max_lvl < 2 || G->G.G.n_nodes < 3)
00262 goto CLEANUP;
00263 MESSAGE (__MC_VRBLVL_, "PR shrinking level 2, nodes %u edges %u",
00264 G->G.G.n_nodes, G->G.G.n_edges);
00265 c_lvl++;
00266 while (!EGeListIsEmpty (c_lvl) && G->G.G.n_nodes > 2)
00267 {
00268 N = EGcontainerOf (c_lvl->next, EGalgMCnode_t, lvl_cn);
00269 TESTL (__MC_DEBUG_, EGlpNumIsLess (N->node.weight, zeroLpNum),
00270 "node %u with " "negative weight %lf", N->id,
00271 EGlpNumToLf (N->node.weight));
00272 EGlpNumCopy (N_dv, N->node.weight);
00273 EGlpNumDivUiTo (N_dv, 2);
00274 EGlpNumSubTo (N_dv, G->epsilon);
00275 e_end = &(N->node.node.edges);
00276
00277 _EGalgMChitNeighbours (N);
00278
00279 for (e_it = e_end->next; e_it != e_end; e_it = e_it->next)
00280 {
00281 lep = EGcontainerOf (e_it, EGeUgraphEP_t, cn);
00282 o_type = lep->type ? 0U : 1U;
00283 E = EGcontainerOf (lep, EGalgMCedge_t, edge.edge.ep[lep->type]);
00284 M =
00285 EGcontainerOf (E->edge.edge.ep[o_type].node, EGalgMCnode_t, node.node);
00286 TESTL (__MC_DEBUG_, EGlpNumIsLess (M->node.weight, zeroLpNum),
00287 "node %u with " "negative weight %lf", M->id,
00288 EGlpNumToLf (M->node.weight));
00289 EGlpNumCopyDiff (N_dv2, N_dv, E->edge.weight);
00290
00291
00292 if (M->lvl > 2)
00293 continue;
00294 TESTL (__MC_DEBUG_, EGlpNumIsLess (E->edge.weight, zeroLpNum),
00295 "edge %u with " "negative weight %lf", E->id,
00296 EGlpNumToLf (E->edge.weight));
00297 EGlpNumCopy (M_dv, M->node.weight);
00298 EGlpNumDivUiTo (M_dv, 2);
00299 EGlpNumSubTo (M_dv, G->epsilon);
00300 EGlpNumSubTo (M_dv, E->edge.weight);
00301 e2_end = &(M->node.node.edges);
00302
00303 for (e2_it = e2_end->next; e2_it != e2_end; e2_it = e2_it->next)
00304 {
00305 lep2 = EGcontainerOf (e2_it, EGeUgraphEP_t, cn);
00306 o_type2 = lep2->type ? 0U : 1U;
00307 F = EGcontainerOf (lep2, EGalgMCedge_t, edge.edge.ep[lep2->type]);
00308 X =
00309 EGcontainerOf (F->edge.edge.ep[o_type2].node, EGalgMCnode_t,
00310 node.node);
00311
00312
00313
00314 if (X->hit && EGlpNumIsLeq (N_dv2, X->hit->weight) &&
00315 EGlpNumIsLeq (M_dv, F->edge.weight))
00316 {
00317 EGalgMCidentifyNodes (G, N, M);
00318 UPDATE (__MC_profile_lvl[2]);
00319 TESTL (__MC_DEBUG_, EGlpNumIsLess (N->node.weight, zeroLpNum),
00320 "node %u" " with negative weight %lf", N->id,
00321 EGlpNumToLf (N->node.weight));
00322 goto REDO;
00323 }
00324 }
00325 }
00326
00327 _EGalgMCunhitNeighbours (N);
00328
00329 N->lvl = 3;
00330 EGeListMoveAfter (&(N->lvl_cn), c_lvl + 1);
00331 }
00332
00333
00334 if (max_lvl < 3 || G->G.G.n_nodes < 3)
00335 goto CLEANUP;
00336 MESSAGE (__MC_VRBLVL_, "PR shrinking level 3, nodes %u edges %u",
00337 G->G.G.n_nodes, G->G.G.n_edges);
00338 c_lvl++;
00339 while (!EGeListIsEmpty (c_lvl) && G->G.G.n_nodes > 2)
00340 {
00341 N = EGcontainerOf (c_lvl->next, EGalgMCnode_t, lvl_cn);
00342 e_end = &(N->node.node.edges);
00343
00344 _EGalgMChitNeighbours (N);
00345
00346 for (e_it = e_end->next; e_it != e_end; e_it = e_it->next)
00347 {
00348 lep = EGcontainerOf (e_it, EGeUgraphEP_t, cn);
00349 o_type = lep->type ? 0U : 1U;
00350 E = EGcontainerOf (lep, EGalgMCedge_t, edge.edge.ep[lep->type]);
00351 M =
00352 EGcontainerOf (E->edge.edge.ep[o_type].node, EGalgMCnode_t, node.node);
00353 EGlpNumCopyDiff (N_dv, E->edge.weight, G->epsilon);
00354
00355
00356 if (M->lvl > 3)
00357 continue;
00358 e2_end = &(M->node.node.edges);
00359
00360 for (e2_it = e2_end->next; e2_it != e2_end; e2_it = e2_it->next)
00361 {
00362 lep2 = EGcontainerOf (e2_it, EGeUgraphEP_t, cn);
00363 o_type2 = lep2->type ? 0U : 1U;
00364 F = EGcontainerOf (lep2, EGalgMCedge_t, edge.edge.ep[lep2->type]);
00365 X =
00366 EGcontainerOf (F->edge.edge.ep[o_type2].node, EGalgMCnode_t,
00367 node.node);
00368
00369
00370
00371 if (X->hit)
00372 {
00373 if (EGlpNumIsLess (X->hit->weight, F->edge.weight))
00374 EGlpNumAddTo (N_dv, X->hit->weight);
00375 else
00376 EGlpNumAddTo (N_dv, F->edge.weight);
00377 }
00378 }
00379
00380 if (EGlpNumIsLeq (G->cut_val, N_dv))
00381 {
00382 EGalgMCidentifyNodes (G, N, M);
00383 UPDATE (__MC_profile_lvl[3]);
00384 TESTL (__MC_DEBUG_, EGlpNumIsLess (N->node.weight, zeroLpNum),
00385 "node %u" " with negative weight %lf", N->id,
00386 EGlpNumToLf (N->node.weight));
00387 goto REDO;
00388 }
00389 }
00390
00391 _EGalgMCunhitNeighbours (N);
00392
00393 N->lvl = 4;
00394 EGeListMoveAfter (&(N->lvl_cn), c_lvl + 1);
00395 }
00396
00397
00398 if (max_lvl < 4 || G->G.G.n_nodes < 3)
00399 goto CLEANUP;
00400 MESSAGE (__MC_VRBLVL_, "PR shrinking level 4, nodes %u edges %u",
00401 G->G.G.n_nodes, G->G.G.n_edges);
00402 c_lvl++;
00403 while (!EGeListIsEmpty (c_lvl) && G->G.G.n_nodes > 2)
00404 {
00405 N = EGcontainerOf (c_lvl->next, EGalgMCnode_t, lvl_cn);
00406 MESSAGE (__MC_VRBLVL_, "Looking at node %u, level %u", N->id, N->lvl);
00407 e_end = &(N->node.node.edges);
00408
00409 _EGalgMChitNeighbours (N);
00410 EGlpNumCopy (N_dv, N->node.weight);
00411 EGlpNumDivUiTo (N_dv, 2);
00412 EGlpNumSubTo (N_dv, G->epsilon);
00413
00414 for (e_it = e_end->next; e_it != e_end; e_it = e_it->next)
00415 {
00416 lep = EGcontainerOf (e_it, EGeUgraphEP_t, cn);
00417 o_type = lep->type ? 0U : 1U;
00418 E = EGcontainerOf (lep, EGalgMCedge_t, edge.edge.ep[lep->type]);
00419 M =
00420 EGcontainerOf (E->edge.edge.ep[o_type].node, EGalgMCnode_t, node.node);
00421 EGlpNumCopyDiff (N_dv2, N_dv, E->edge.weight);
00422 EGlpNumCopy (M_dv, M->node.weight);
00423 EGlpNumDivUiTo (M_dv, 2);
00424 EGlpNumSubTo (M_dv, G->epsilon);
00425 EGlpNumSubTo (M_dv, E->edge.weight);
00426
00427
00428 if (M->lvl > 4)
00429 continue;
00430 e2_end = &(M->node.node.edges);
00431
00432 for (e2_it = e2_end->next; e2_it != e2_end; e2_it = e2_it->next)
00433 {
00434 lep2 = EGcontainerOf (e2_it, EGeUgraphEP_t, cn);
00435 o_type2 = lep2->type ? 0U : 1U;
00436 F = EGcontainerOf (lep2, EGalgMCedge_t, edge.edge.ep[lep2->type]);
00437 X =
00438 EGcontainerOf (F->edge.edge.ep[o_type2].node, EGalgMCnode_t,
00439 node.node);
00440
00441
00442 if (X->hit)
00443 for (e3_it = e2_it->next; e3_it != e2_end; e3_it = e3_it->next)
00444 {
00445 lep3 = EGcontainerOf (e3_it, EGeUgraphEP_t, cn);
00446 o_type3 = lep3->type ? 0U : 1U;
00447 H = EGcontainerOf (lep3, EGalgMCedge_t, edge.edge.ep[lep3->type]);
00448 Y = EGcontainerOf (H->edge.edge.ep[o_type3].node, EGalgMCnode_t,
00449 node.node);
00450
00451
00452 if (Y->hit)
00453 {
00454 EGlpNumCopySum (M_dv2, X->hit->weight, Y->hit->weight);
00455 if (EGlpNumIsLess (M_dv2, N_dv2))
00456 continue;
00457 EGlpNumCopySum (M_dv2, F->edge.weight, H->edge.weight);
00458 if (EGlpNumIsLess (M_dv2, M_dv))
00459 continue;
00460 if (EGlpNumIsLess (Y->hit->weight, N_dv2) &&
00461 EGlpNumIsLess (F->edge.weight, M_dv))
00462 continue;
00463 if (EGlpNumIsLess (X->hit->weight, N_dv2) &&
00464 EGlpNumIsLess (H->edge.weight, M_dv))
00465 continue;
00466
00467 EGalgMCidentifyNodes (G, N, M);
00468 UPDATE (__MC_profile_lvl[4]);
00469 TESTL (__MC_DEBUG_, EGlpNumIsLess (N->node.weight, zeroLpNum),
00470 "node %u with negative weight %lf", N->id,
00471 EGlpNumToLf (N->node.weight));
00472 goto REDO;
00473 }
00474 }
00475 }
00476 }
00477
00478 _EGalgMCunhitNeighbours (N);
00479
00480 N->lvl = 5;
00481 MESSAGE (__MC_VRBLVL_, "Erasing at node %u, level %u", N->id, N->lvl);
00482 EGeListDel (&(N->lvl_cn));
00483 }
00484
00485 CLEANUP:
00486 MESSAGE (__MC_VRBLVL_, "PR shrinking level %u, nodes %u edges %u", max_lvl,
00487 G->G.G.n_nodes, G->G.G.n_edges);
00488 EGlpNumClearVar (N_dv2);
00489 EGlpNumClearVar (M_dv2);
00490 EGlpNumClearVar (N_dv);
00491 EGlpNumClearVar (M_dv);
00492 return rval;
00493 }
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510 static inline int EGalgMCbuildPRgraph (EGalgMCgraph_t * const mcG,
00511 EGalgPRgraph_t * const prG,
00512 EGalgMCnode_t ** const node_map,
00513 EGalgPRnode_t * const all_pr_nodes,
00514 EGalgPRedge_t * const all_pr_edges)
00515 {
00516 int rval = 0;
00517 EGeList_t *e_it,
00518 *e_end,
00519 *n_it,
00520 *n_end;
00521 #if DEBUG
00522 unsigned int const n_pr_nodes = mcG->G.G.n_nodes;
00523 unsigned int const n_pr_edges = mcG->G.G.n_edges;
00524 #endif
00525 EGalgMCnode_t *N,
00526 *M;
00527 EGalgMCedge_t *E;
00528 EGeUgraphEP_t *lep;
00529 unsigned register int i;
00530 MESSAGE (__MC_VRBLVL_,
00531 "Building push-relabel graph on %u nodes and %u edges", n_pr_nodes,
00532 n_pr_edges);
00533
00534 EGalgPRgraphReset (prG);
00535 n_end = &(mcG->G.G.nodes);
00536
00537 for (i = 0, n_it = n_end->next; n_it != n_end; n_it = n_it->next, i++)
00538 {
00539 N = EGcontainerOf (n_it, EGalgMCnode_t, node.node.node_cn);
00540 EGalgPRnodeReset (all_pr_nodes + i);
00541 EGeDgraphAddNode (&(prG->G), &(all_pr_nodes[i].v));
00542 node_map[i] = N;
00543 N->new_id = i;
00544 }
00545
00546 TESTG ((rval = (i != n_pr_nodes)), CLEANUP, "number of added nodes %u is not"
00547 "the number of nodes in the MinCut graph %u", i, n_pr_nodes);
00548
00549 for (i = 0, n_it = n_end->next; n_it != n_end; n_it = n_it->next)
00550 {
00551 N = EGcontainerOf (n_it, EGalgMCnode_t, node.node.node_cn);
00552 e_end = &(N->node.node.edges);
00553 for (e_it = e_end->next; e_it != e_end; e_it = e_it->next)
00554 {
00555 lep = EGcontainerOf (e_it, EGeUgraphEP_t, cn);
00556 if (lep->type)
00557 continue;
00558 E = EGcontainerOf (lep, EGalgMCedge_t, edge.edge.ep[0]);
00559 M = EGcontainerOf (E->edge.edge.ep[1].node, EGalgMCnode_t, node.node);
00560
00561
00562 EGalgPRedgeReset (all_pr_edges + i);
00563 EGlpNumCopy (all_pr_edges[i].fw.u, E->edge.weight);
00564 EGlpNumCopy (all_pr_edges[i].bw.u, E->edge.weight);
00565 EGeDgraphAddEdge (&(prG->G),
00566 &(all_pr_nodes[N->new_id].v),
00567 &(all_pr_nodes[M->new_id].v), &(all_pr_edges[i].fw.e));
00568 EGeDgraphAddEdge (&(prG->G),
00569 &(all_pr_nodes[M->new_id].v),
00570 &(all_pr_nodes[N->new_id].v), &(all_pr_edges[i].bw.e));
00571 i++;
00572 }
00573 }
00574
00575 TESTG ((rval =
00576 (i != n_pr_edges)), CLEANUP,
00577 "number of added edges %u is not "
00578 "the number of edges in the MinCut graph %u", i, n_pr_edges);
00579
00580
00581 #if DEBUG
00582 CLEANUP:
00583 #endif
00584 return rval;
00585 }
00586
00587
00588
00589
00590
00591
00592
00593
00594 static inline int EGalgMCcomputeT (EGalgPRgraph_t * const prG,
00595 EGalgPRnode_t * const S,
00596 EGalgPRnode_t ** const T)
00597 {
00598 EGeList_t *n_it,
00599 *n_end,
00600 *queue;
00601 EGalgPRnode_t *N = 0,
00602 *P = 0;
00603 EGalgPRse_t *E = 0;
00604 n_end = &(prG->G.nodes);
00605
00606 for (n_it = n_end->next; n_it != n_end; n_it = n_it->next)
00607 {
00608 N = EGcontainerOf (n_it, EGalgPRnode_t, v.node_cn);
00609 N->LVL_list = (EGeList_t)
00610 {
00611 0, 0};
00612 N->d = UINT_MAX;
00613 }
00614 S->d = 0;
00615 *T = P = S;
00616 queue = &(S->LVL_list);
00617 EGeListInit (queue);
00618 n_end = &(P->v.out_edge);
00619 for (n_it = n_end->next; n_it != n_end; n_it = n_it->next)
00620 {
00621 E = EGcontainerOf (n_it, EGalgPRse_t, e.tail_cn);
00622 N = EGcontainerOf (E->e.head, EGalgPRnode_t, v);
00623 if (N->LVL_list.next)
00624 continue;
00625 EGeListAddAfter (&(N->LVL_list), queue);
00626 N->d = P->d + 1;
00627 }
00628 while (!EGeListIsEmpty (queue))
00629 {
00630 P = EGcontainerOf (queue->prev, EGalgPRnode_t, LVL_list);
00631 EGeListDel (queue->prev);
00632 n_end = &(P->v.out_edge);
00633 for (n_it = n_end->next; n_it != n_end; n_it = n_it->next)
00634 {
00635 E = EGcontainerOf (n_it, EGalgPRse_t, e.tail_cn);
00636 N = EGcontainerOf (E->e.head, EGalgPRnode_t, v);
00637 if (N->LVL_list.next)
00638 continue;
00639 EGeListAddAfter (&(N->LVL_list), queue);
00640 N->d = P->d + 1;
00641 }
00642 }
00643 n_end = &(prG->G.nodes);
00644 for (n_it = n_end->next; n_it != n_end; n_it = n_it->next)
00645 {
00646 N = EGcontainerOf (n_it, EGalgPRnode_t, v.node_cn);
00647 if ((*T)->d < N->d)
00648 *T = N;
00649 }
00650 MESSAGE (__MC_VRBLVL_, "worst distance is %u", (*T)->d);
00651 return 0;
00652 }
00653
00654
00655 int EGalgMC (EGalgMCgraph_t * const G,
00656 EGalgMCcbk_t * const cb,
00657 const unsigned int max_lvl)
00658 {
00659 int rval = 0;
00660 EGalgPRgraph_t prG;
00661 EGalgPRnode_t *all_pr_nodes = 0,
00662 *pr_node,
00663 *pr_node2;
00664 EGalgPRedge_t *all_pr_edges = 0;
00665 EGalgMCnode_t **node_map = 0;
00666 EGalgMCnode_t *N;
00667 unsigned int *const cut = G->cut;
00668 EGeList_t *n_it,
00669 *n_end,
00670 *c_it,
00671 *c_end;
00672 unsigned int n_pr_nodes,
00673 n_pr_edges,
00674 cur_s = 0;
00675 unsigned register int i;
00676
00677 srandom (1);
00678
00679 rval = EGalgMCidentifyPRedges (G, cb, max_lvl);
00680 CHECKRVALG (rval, CLEANUP);
00681
00682 n_pr_nodes = G->G.G.n_nodes;
00683 n_pr_edges = G->G.G.n_edges;
00684
00685 if (n_pr_nodes < 3 || !n_pr_edges)
00686 goto CLEANUP;
00687
00688 all_pr_nodes = EGsMalloc (EGalgPRnode_t, n_pr_nodes);
00689 for (i = n_pr_nodes; i--;)
00690 EGalgPRnodeInit (all_pr_nodes + i);
00691 all_pr_edges = EGsMalloc (EGalgPRedge_t, n_pr_edges);
00692 for (i = n_pr_edges; i--;)
00693 EGalgPRedgeInit (all_pr_edges + i);
00694 node_map = EGsMalloc (EGalgMCnode_t *, n_pr_nodes);
00695 EGalgPRgraphInit (&prG);
00696
00697 while (G->G.G.n_nodes > 2 && G->G.G.n_edges &&
00698 EGlpNumIsLess (zeroLpNum, G->cut_val))
00699 {
00700
00701 rval = EGalgMCbuildPRgraph (G, &prG, node_map, all_pr_nodes, all_pr_edges);
00702 CHECKRVALG (rval, CLEANUP);
00703
00704
00705
00706
00707
00708 cur_s = random () % prG.G.n_nodes;
00709 MESSAGE (__MC_VRBLVL_, "computing t, maximum distance node from s");
00710 rval = EGalgMCcomputeT (&prG, all_pr_nodes + cur_s, &pr_node);
00711 CHECKRVALG (rval, CLEANUP);
00712 MESSAGE (__MC_VRBLVL_, "computing s-t cut");
00713 rval = EGalgPRminSTcut (&prG, all_pr_nodes + cur_s, pr_node);
00714 CHECKRVALG (rval, CLEANUP);
00715
00716 if (EGlpNumIsLess (pr_node->e, G->cut_val))
00717 {
00718
00719 UPDATE (__MC_profile_up);
00720 MESSAGE (__MC_VRBLVL_, "Update cut_val from %lf to %lf",
00721 EGlpNumToLf (G->cut_val), EGlpNumToLf (pr_node->e));
00722 EGlpNumCopy (G->cut_val, pr_node->e);
00723 c_end = &(prG.G.nodes);
00724 for (c_it = c_end->next, i = 0; c_it != c_end; c_it = c_it->next)
00725 {
00726 pr_node2 = EGcontainerOf (c_it, EGalgPRnode_t, v.node_cn);
00727 if (pr_node2->d >= prG.G.n_nodes)
00728 continue;
00729 N = node_map[pr_node2 - all_pr_nodes];
00730 cut[i++] = N->id;
00731 n_end = &(N->node.members);
00732 for (n_it = n_end->next; n_it != n_end; n_it = n_it->next)
00733 {
00734 N = EGcontainerOf (n_it, EGalgMCnode_t, node.members);
00735 cut[i++] = N->id;
00736 }
00737 }
00738 G->cut_sz = i;
00739
00740 if (cb && EGlpNumIsLess (G->cut_val, cb->cutoff))
00741 {
00742 rval = cb->do_fn (G->cut_val, G->cut_sz, G->cut, cb->param);
00743 CHECKRVALG (rval, CLEANUP);
00744 }
00745 }
00746 else if (cb && EGlpNumIsLess (pr_node->e, cb->cutoff))
00747 {
00748 unsigned int *lcut = EGsMalloc (unsigned int, G->G.n_onodes);
00749 c_end = &(prG.G.nodes);
00750 for (c_it = c_end->next, i = 0; c_it != c_end; c_it = c_it->next)
00751 {
00752 pr_node2 = EGcontainerOf (c_it, EGalgPRnode_t, v.node_cn);
00753 if (pr_node2->d >= prG.G.n_nodes)
00754 continue;
00755 N = node_map[pr_node2 - all_pr_nodes];
00756 lcut[i++] = N->id;
00757 n_end = &(N->node.members);
00758 for (n_it = n_end->next; n_it != n_end; n_it = n_it->next)
00759 {
00760 N = EGcontainerOf (n_it, EGalgMCnode_t, node.members);
00761 lcut[i++] = N->id;
00762 }
00763 }
00764 rval = cb->do_fn (pr_node->e, i, lcut, cb->param);
00765 CHECKRVALG (rval, CLEANUP);
00766 EGfree (lcut);
00767
00768 }
00769
00770 UPDATE (__MC_profile_lvl[0]);
00771 TESTL (__MC_DEBUG_,
00772 EGlpNumIsLess (node_map[cur_s]->node.weight, zeroLpNum),
00773 "node %u with negative weight %lf", node_map[cur_s]->id,
00774 EGlpNumToLf (node_map[0]->node.weight));
00775 EGalgMCidentifyNodes (G, node_map[cur_s], node_map[pr_node - all_pr_nodes]);
00776 TESTL (__MC_DEBUG_,
00777 EGlpNumIsLess (node_map[cur_s]->node.weight, zeroLpNum),
00778 "node %u with negative weight %lf", node_map[cur_s]->id,
00779 EGlpNumToLf (node_map[cur_s]->node.weight));
00780 rval = EGalgMCidentifyPRedges (G, cb, max_lvl);
00781 CHECKRVALG (rval, CLEANUP);
00782 }
00783
00784
00785 CLEANUP:
00786 if (all_pr_nodes)
00787 {
00788 for (i = n_pr_nodes; i--;)
00789 EGalgPRnodeClear (all_pr_nodes + i);
00790 EGfree (all_pr_nodes);
00791 }
00792 if (all_pr_edges)
00793 {
00794 for (i = n_pr_edges; i--;)
00795 EGalgPRedgeClear (all_pr_edges + i);
00796 EGfree (all_pr_edges);
00797 }
00798 if (node_map)
00799 EGfree (node_map);
00800 return rval;
00801 }
00802
00803
00804
00805