eg_menger.c

Go to the documentation of this file.
00001 #include "eg_menger.h"
00002 
00003 
00004 int EGmengerUpdateResidualGraph (EGdGraph_t * G,
00005                                  EGdGraphEdge_t * e,
00006                                  size_t * os)
00007 {
00008 
00009   EGdGraphNode_t *swap;
00010   EGdijkstraCost_t cost;
00011 
00012   /* We unattach the edge from the graph.                                     */
00013   EGdGraphUnattachEdge (G, e);
00014 
00015   /* The cost changes sign.                                                   */
00016   cost =
00017     EGdijkstraCostMul (EGdijkstraToCost (-1.0), EGmengerGetEdgeCost (e, os));
00018   EGmengerSetEdgeCost (e, os, cost);
00019 
00020   /* We swap the head and tail.                                               */
00021   swap = e->head;
00022   e->head = e->tail;
00023   e->tail = swap;
00024 
00025   /* We re-attach the edge                                                    */
00026   EGdGraphAttachEdge (G, e);
00027 
00028   return 0;
00029 
00030 }
00031 
00032 int EGmengerRecoverGraphAndSolution (EGdGraph_t * G,
00033                                      size_t * os,
00034                                      EGdGraphNode_t * s,
00035                                      EGdGraphNode_t * t,
00036                                      unsigned int npath,
00037                                      EGdGraphEdge_t ** path,
00038                                      unsigned int *path_beg)
00039 {
00040 
00041   unsigned int i,
00042     pos;
00043   EGlistNode_t *n_it,
00044    *e_it;
00045   EGdGraphNode_t *n;
00046   EGdGraphEdge_t *e;
00047 
00048   path_beg[0] = pos = 0;
00049   for (i = 0; i < npath; i++)
00050   {
00051     n = s;
00052     n_it = n->cn;
00053     while (n_it != t->cn)
00054     {
00055       for (e_it = n->in_edges->begin; e_it; e_it = e_it->next)
00056       {
00057         e = (EGdGraphEdge_t *) (e_it->this);
00058         if (EGmengerGetEdgeIsInSolution (e, os))
00059         {
00060           n = e->tail;
00061           n_it = n->cn;
00062           EGmengerSetEdgeIsInSolution (e, os, 0);
00063           EGmengerUpdateResidualGraph (G, e, os);
00064           path[pos++] = e;
00065           break;
00066         }
00067       }
00068       TEST (!e_it, "edge in solution not found for path %u", i);
00069     }
00070     path_beg[i + 1] = pos;
00071   }
00072 
00073   return 0;
00074 
00075 }
00076 
00077 /* EGmengerPathsADV: This algorithm is used to compute 'npaths' edge-disjoint
00078    paths between 's' and 't' having minimum total cost. The problem is tackled
00079    by solving a min-cost flow problem from 's' to 't' on a network with 
00080    edges of capacity one. 
00081 
00082    This program runs a succesive-shortest paths algorithm on G (as in Ahuja, 
00083    Magnanti, Orlin), taking advantage of the fact that for the problem we    
00084    need only consider capacity one edges.
00085 
00086    The output of the function is not the set of paths, however, but instead  
00087    is simply the final reduced graph and the value (menger_val) of the 
00088    optimal solution.                                                          */
00089 
00090 /* This algorithm assumes that the fields 'isInSolution' of the edges are all 
00091    set to cero.                                                               */
00092 
00093 int EGmengerPathsADV (EGdGraphNode_t * s,
00094                       EGdGraphNode_t * t,
00095                       EGdijkstraCost_t ubound,
00096                       unsigned int npaths,
00097                       unsigned int *nfpaths,
00098                       EGdijkstraCost_t * menger_val,
00099                       EGheap_t * dij_heap,
00100                       size_t * os,
00101                       EGdGraph_t * G)
00102 {
00103 
00104   /* General use                                                              */
00105   int rval;
00106   unsigned int i;
00107   size_t dij_os[6];
00108 
00109   /* Algorithm-Variables                                                      */
00110 
00111   unsigned int f,
00112     path_nedges;
00113   EGdGraphNode_t *n;
00114   EGdGraphEdge_t *e;
00115 
00116   EGlistNode_t *n_it,
00117    *e_it;
00118   EGdijkstraCost_t prev_flow_val,
00119     dij_ubound,
00120     rcost,
00121     pi;
00122 
00123   /* Algorithm-Flags                                                          */
00124   *nfpaths = 0;
00125 
00126   /* Prepare the offsets which will be used by dijkstra                       */
00127   dij_os[EG_DIJ_DIST] = os[EG_MENGER_DIST];
00128   dij_os[EG_DIJ_NDIST] = os[EG_MENGER_NDIST];
00129   dij_os[EG_DIJ_FATHER] = os[EG_MENGER_FATHER];
00130   dij_os[EG_DIJ_MARKER] = os[EG_MENGER_MARK];
00131   dij_os[EG_DIJ_HCONNECTOR] = os[EG_MENGER_HEAP_CONNECTOR];
00132   dij_os[EG_DIJ_ELENGTH] = os[EG_MENGER_REDUCED_ECOST];
00133 
00134   /* Make sure that there are enough outbound edges in s.                     */
00135   if (s->out_edges->size < npaths)
00136     goto NO_SOLUTION;
00137 
00138   /* Make sure that there are enough inbound edges in t.                      */
00139   if (t->in_edges->size < npaths)
00140     goto NO_SOLUTION;
00141 
00142   /* Make sure the shortest distance from s to t isn't too large already.     */
00143   if (npaths * EGdijkstraCostToLf (EGmengerGetOrigDist (t, os)) >
00144       EGdijkstraCostToLf (ubound))
00145     goto NO_SOLUTION;
00146 
00147 #if EG_MENGER_SAFEMODE > 1
00148 
00149 /* do an initial check of negative-edges */
00150 
00151   for (n_it = G->nodes->begin; n_it; n_it = n_it->next)
00152   {
00153     n = (EGdGraphNode_t *) (n_it->this);
00154     for (e_it = n->out_edges->begin; e_it; e_it = e_it->next)
00155     {
00156       e = (EGdGraphEdge_t *) (e_it->this);
00157       TEST (EGdijkstraCostIsLess
00158             (EGmengerGetEdgeCost (e, os), EGdijkstraToCost (0.0)),
00159             "negative edge");
00160     }
00161 
00162   }
00163 
00164 #endif
00165 
00166   /*                    ***** PART 1 *****
00167    * 
00168    * SEND THE FIRST UNIT OF FLOW FROM S TO T                       */
00169 
00170   /* Set the current value of the optimal solution.                           */
00171   *menger_val = prev_flow_val = EGmengerGetOrigDist (t, os);
00172 
00173   /* Set the dual prices on the node variables.                               */
00174   for (n_it = G->nodes->begin; n_it; n_it = n_it->next)
00175     EGmengerSetPi (n_it->this, os,
00176                    EGdijkstraCostMinus (EGmengerGetOrigDist (n_it->this, os)));
00177 
00178   /* Update the residual graph and mark the edges as 'taken'.                 */
00179   n = t;
00180   path_nedges = EGmengerGetOrigNdist (n, os);
00181 
00182   for (i = 0; i < path_nedges; i++)
00183   {
00184     e = EGmengerGetOrigFather (n, os);
00185     TEST (!e, "found node s (%u) before time %u / %u", n->id, i, path_nedges);
00186     n = e->tail;
00187 
00188     EGmengerUpdateResidualGraph (G, e, os);
00189     EGmengerSetEdgeIsInSolution (e, os, 1);
00190   }
00191 
00192   /* Update the reduced costs of the edges.                                   */
00193   for (n_it = G->nodes->begin; n_it; n_it = n_it->next)
00194   {
00195     n = (EGdGraphNode_t *) (n_it->this);
00196     for (e_it = n->out_edges->begin; e_it; e_it = e_it->next)
00197     {
00198       e = (EGdGraphEdge_t *) (e_it->this);
00199       /* rcost = cost[tail,head] + pi[head] - pi[tail]                                */
00200       rcost =
00201         EGdijkstraCostAdd (EGmengerGetEdgeCost (e, os),
00202                            EGmengerGetPi (e->head, os));
00203       rcost = EGdijkstraCostSub (rcost, EGmengerGetPi (e->tail, os));
00204 
00205 #if EG_MENGER_SAFEMODE
00206       if (EGdijkstraCostToLf (rcost) < 0.0)
00207       {
00208         fprintf (stderr,
00209                  "negative edge, WARNING!   rcost = %lf  ecost = %lf  pi_h = %lf  pi_t = %lf\n",
00210                  EGdijkstraCostToLf (rcost),
00211                  EGdijkstraCostToLf (EGmengerGetEdgeCost (e, os)),
00212                  EGdijkstraCostToLf (EGmengerGetPi (e->head, os)),
00213                  EGdijkstraCostToLf (EGmengerGetPi (e->tail, os)));
00214         rcost = EGdijkstraToCost (0.0);
00215       }
00216 #endif
00217 
00218       EGmengerSetEdgeReducedCost (e, os, rcost);
00219       TEST (EGdijkstraCostToLf (rcost) < 0.0,
00220             "\nERROR: Negative edge (%u,%u)! cost=%lf  pi_h = %lf  pi_t = %lf  val = %lf | %lf",
00221             e->head->id, e->tail->id,
00222             EGdijkstraCostToLf (EGmengerGetEdgeCost (e, os)),
00223             EGdijkstraCostToLf (EGmengerGetPi (e->head, os)),
00224             EGdijkstraCostToLf (EGmengerGetPi (e->tail, os)),
00225             EGdijkstraCostToLf (EGmengerGetEdgeReducedCost (e, os)),
00226             EGdijkstraCostToLf (rcost));
00227     }
00228   }
00229 
00230   /*                    ***** PART 2 *****
00231    * 
00232    * SEND THE OTHER UNITS OF FLOW FROM S TO T                      */
00233 
00234   /* We have found a path                                                     */
00235   *nfpaths = 1;
00236   //fprintf(stderr, "*** 0 val = %lf\n", EGdijkstraCostToLf(*menger_val));
00237 
00238   for (f = 1; f < npaths; f++)
00239   {
00240 
00241     /* We compute an upper bound, and run the partial dijkstra algorithm.     */
00242 
00243     dij_ubound = EGdijkstraCostDiv (EGdijkstraCostSub (ubound, *menger_val),
00244                                     EGdijkstraToCost ((double) (npaths - f)));
00245     dij_ubound = EGdijkstraCostSub (dij_ubound, prev_flow_val);
00246 
00247 #if MENGER_USE_BELLFORD == 0
00248     rval = EGpartialDijkstra (s, t, dij_ubound, dij_os, dij_heap, G);
00249     CHECKRVAL (rval);
00250     if (EGdijkstraGetMarker (t, dij_os) == UINT_MAX)
00251       goto NO_SOLUTION;
00252 #endif
00253 
00254 #if MENGER_USE_BELLFORD
00255     rval = EGbellFord (s, dij_os, G);
00256     CHECKRVAL (rval);
00257 #endif
00258 
00259     /* Check if we have marked 't' with a relevant value                      */
00260 
00261     /* Check if we have surpassed the upper bound.                            */
00262     if (EGdijkstraCostIsLess (dij_ubound, EGmengerGetDist (t, os)))
00263       goto NO_SOLUTION;
00264 
00265     /* Update the current value of the solution and the prev_flow variable.   */
00266     prev_flow_val = EGdijkstraCostAdd (prev_flow_val, EGmengerGetDist (t, os));
00267     *menger_val = EGdijkstraCostAdd (prev_flow_val, *menger_val);
00268 
00269     /* Update the dual variables: That is, for every marked node 'i' :
00270      * 
00271      * pi[i] = pi[i] + d[t] - d[i]                                            */
00272 
00273     for (n_it = G->nodes->begin; n_it; n_it = n_it->next)
00274       if (EGmengerGetMark (n_it->this, os) < UINT_MAX - 1)
00275       {
00276         pi =
00277           EGdijkstraCostAdd (EGmengerGetPi (n_it->this, os),
00278                              EGmengerGetDist (t, os));
00279         pi = EGdijkstraCostSub (pi, EGmengerGetDist (n_it->this, os));
00280         EGmengerSetPi (n_it->this, os, pi);
00281       }
00282 
00283     /* Update the residual graph and mark the edges as 'taken' or 'untaken'   */
00284 
00285     n = t;
00286     path_nedges = EGmengerGetNdist (n, os);
00287     for (i = 0; i < path_nedges; i++)
00288     {
00289       e = EGmengerGetFather (n, os);
00290       TEST (!e, "found node s (%u) before time %u / %u", n->id, i, path_nedges);
00291       n = e->tail;
00292 
00293       EGmengerSetEdgeIsInSolution (e, os,
00294                                    1 - EGmengerGetEdgeIsInSolution (e, os));
00295       EGmengerUpdateResidualGraph (G, e, os);
00296     }
00297 
00298     /* We have found another path                                             */
00299     *nfpaths += 1;
00300 
00301     /* Update the reduced cost of the edges                                   */
00302     for (n_it = G->nodes->begin; n_it; n_it = n_it->next)
00303     {
00304       n = (EGdGraphNode_t *) (n_it->this);
00305       for (e_it = n->out_edges->begin; e_it; e_it = e_it->next)
00306       {
00307         e = (EGdGraphEdge_t *) (e_it->this);
00308         rcost =
00309           EGdijkstraCostAdd (EGmengerGetEdgeCost (e, os),
00310                              EGmengerGetPi (e->head, os));
00311         rcost = EGdijkstraCostSub (rcost, EGmengerGetPi (e->tail, os));
00312 
00313 #if EG_MENGER_SAFEMODE
00314         if (EGdijkstraCostToLf (rcost) < 0.0)
00315         {
00316           fprintf (stdout,
00317                    "WARNING! Negative reduced-cost edge (value = %lf).\n",
00318                    EGdijkstraCostToLf (rcost));
00319           rcost = EGdijkstraToCost (0.0);
00320         }
00321 #endif
00322 
00323         EGmengerSetEdgeReducedCost (e, os, rcost);
00324         TEST (EGdijkstraCostToLf (rcost) < 0.0,
00325               "ERROR: Negative edge (%u,%u)! cost=%lf  pi_h = %lf  pi_t = %lf  val = %lf | %lf",
00326               e->head->id, e->tail->id,
00327               EGdijkstraCostToLf (EGmengerGetEdgeCost (e, os)),
00328               EGdijkstraCostToLf (EGmengerGetPi (e->head, os)),
00329               EGdijkstraCostToLf (EGmengerGetPi (e->tail, os)),
00330               EGdijkstraCostToLf (EGmengerGetEdgeReducedCost (e, os)),
00331               EGdijkstraCostToLf (rcost));
00332       }
00333     }
00334 
00335     //fprintf(stderr, "*** %u val = %lf\n", f, EGdijkstraCostToLf(*menger_val));
00336 
00337   }
00338 
00339   return 0;
00340 
00341 NO_SOLUTION:
00342 
00343   *menger_val = EG_DIJKSTRA_COST_MAX;
00344 
00345   return 0;
00346 
00347 }
00348 
00349 int EGmengerEmergencyRecovery (EGdGraph_t * G,
00350                                size_t * os)
00351 {
00352 
00353   unsigned int cnt = 0;
00354 
00355   EGlistNode_t *n_it,
00356    *e_it;
00357 
00358   EGdGraphNode_t *n;
00359   EGdGraphEdge_t *e;
00360 
00361   /* first, "unflip" solution edges */
00362 
00363 FIX_GRAPH:
00364 
00365   cnt += 1;
00366 
00367   if (cnt > 2 * (G->nedges))
00368     return 1;
00369 
00370   for (n_it = G->nodes->begin; n_it; n_it = n_it->next)
00371   {
00372     n = (EGdGraphNode_t *) (n_it->this);
00373     for (e_it = n->out_edges->begin; e_it; e_it = e_it->next)
00374     {
00375       e = (EGdGraphEdge_t *) (e_it->this);
00376       if (EGmengerGetEdgeIsInSolution (e, os))
00377       {
00378         EGmengerSetEdgeIsInSolution (e, os, 0);
00379         EGmengerUpdateResidualGraph (G, e, os);
00380         goto FIX_GRAPH;
00381       }
00382     }
00383   }
00384 
00385   /* next, make sure all edges have non-negative weights */
00386 
00387   for (n_it = G->nodes->begin; n_it; n_it = n_it->next)
00388   {
00389     n = (EGdGraphNode_t *) (n_it->this);
00390     for (e_it = n->out_edges->begin; e_it; e_it = e_it->next)
00391     {
00392       e = (EGdGraphEdge_t *) (e_it->this);
00393       if (EGdijkstraCostToLf (EGmengerGetEdgeCost (e, os)) < 0.0)
00394         return 1;
00395     }
00396   }
00397 
00398   return 0;
00399 
00400 }

Generated on Thu Oct 20 14:58:41 2005 for DominoParitySeparator by  doxygen 1.4.5