eg_dpseparator.c

Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 
00004 #include "eg_list.h"
00005 #include "eg_mempool.h"
00006 #include "graph_boyer.h"
00007 #include "graphdual.h"
00008 
00009 #include "eg_util.h"
00010 #include "eg_dgraph.h"
00011 #include "eg_ddomino.h"
00012 #include "eg_pdp.h"
00013 #include "eg_util.h"
00014 #include "eg_ddpconstraint.h"
00015 #include "bc_spanning.h"
00016 #include "bc_util.h"
00017 #include "cookInterface.h"
00018 #include "eg_1pchecker.h"
00019 #include "eg_emptyhandles.h"
00020 double DDP_HEURISTIC_MAXTIME = 10.0;
00021 
00022 /* Function Definitions */
00023 int DPseparator (int nnodes,
00024                  int norig_edges,
00025                  int *const orig_edges,
00026                  double *const orig_weight,
00027                  int *const nIneq,
00028                  int **const ndominoes,
00029                  int ***const naset,
00030                  int ***const nbset,
00031                  int **const nhandle,
00032                  int ****const aset,
00033                  int ****const bset,
00034                  int ***const handle,
00035                  const char *const boss_name,
00036                  double percentage,
00037                  double ddp_heuristic_maxtime)
00038 {
00039   /* auxiliary variables */
00040   int i,
00041     rval;
00042   int is_connected;
00043   /* flags */
00044   int eliminated_edges_b = 0,
00045     is_G_planar_b = 0;
00046   int l_count = 0;
00047   unsigned int n_empty_handle = 0;
00048   /* where we will store the edges that are bigger than ZERO_X_EPSILON */
00049   int *edges = 0,
00050     nedges = 0,
00051     nelim_edges = 0;
00052   double *weight = 0;
00053   double dpViolation;
00054   double *slack = 0;
00055   /* for the primal-dual-primal conversions we need an 'applegate' graph */
00056   graphP primalG = 0;
00057   /* the bi-directed dual over which we will search for ddominoes */
00058   EGdGraph_t *biDualG = 0;
00059   /* the list of ddominoes */
00060   EGlist_t *dlist = 0;
00061   EGlist_t **dembed = 0;
00062   /* the list of dual dp constraints */
00063   EGlist_t *ddpc_list = 0;
00064   /* memory pool */
00065   EGmemPool_t *mem = 0;
00066   /* used for handling the list of ddominoes */
00067   EGddomino_t *ddom;
00068   EGlistNode_t *ddom_it,
00069    *ddp_it;
00070 #if ELIM_EDGES
00071   int *planar_edges = 0,
00072     nplanar_edges = 0,
00073    *elim_edges = 0;
00074   double *planar_weight = 0,
00075     error = 0;
00076 #endif
00077 #if DISPLAY_MODE
00078   int nfeasible = 0;
00079   int ncorrected = 0;
00080   int nnegative = 0;
00081   double dual_val,
00082     prim_val;
00083 #endif
00084   /* seting up time */
00085   DDP_HEURISTIC_MAXTIME = ddp_heuristic_maxtime;
00086   fprintf (stderr, "DP Version %s\n", DP_VERSION_STRING);
00087 #if DISPLAY_MODE
00088   if (!boss_name)
00089     fprintf (stdout, "DP Separator: NO boss.\n");
00090   else
00091     fprintf (stdout, "DP Separator: Noss name = %s.\n", boss_name);
00092   fflush (stdout);
00093 #endif
00094 
00095 #if LOG_MODE
00096   saveBgraph ("graph.b.x", nnodes, norig_edges, orig_edges, orig_weight);
00097 #endif
00098 
00099   /* initialize memory pool                                                   */
00100   mem = EGnewMemPool (512, EGmemPoolNewSize, EGmemPoolNewSize (1));
00101 
00102   /* initialize linked lists                                                  */
00103   dlist = EGnewList (mem);
00104   ddpc_list = EGnewList (mem);
00105 
00106 #if DISPLAY_MODE
00107   fprintf (stdout, "DP Separator: Graph G^* has %d nodes, and %d edges.\n",
00108            nnodes, norig_edges);
00109   fprintf (stdout,
00110            "DP Separator: Number of necessary edges for non-planarity = %d.\n",
00111            3 * nnodes - 5);
00112   fflush (stdout);
00113 #endif
00114 
00115   /* remove small edges (ie: those smaller than ZERO_X_EPSILON)               */
00116   rval = removeSmallEdges (ZERO_X_EPSILON, orig_edges, norig_edges, orig_weight,
00117                            &nedges, &edges, &weight, mem);
00118   CHECKRVAL (rval);
00119 
00120 #if DISPLAY_MODE
00121   fprintf (stdout,
00122            "DP Separator: Eliminated %d edges of value less than %lf.\n",
00123            (norig_edges - nedges), ZERO_X_EPSILON);
00124   fflush (stdout);
00125   fprintf (stdout, "DP Separator: Graph G^* now has %d nodes, and %d edges.\n",
00126            nnodes, nedges);
00127   fflush (stdout);
00128 #endif
00129 
00130   /* check if the graph is planar                                             */
00131   primalG = gp_New ();
00132   rval = cook2boyerGraph (primalG, nnodes, nedges, edges);
00133   CHECKRVAL (rval);
00134   is_G_planar_b = gp_Embed (primalG, EMBEDFLAGS_PLANAR);
00135   rval = gp_SortVertices (primalG);
00136   EXITRVAL (rval);
00137 
00138   /* if not planar, run heuristic to planarize                                */
00139   if (is_G_planar_b != OK)
00140   {
00141 #if DISPLAY_MODE
00142     fprintf (stdout, "DP Separator: Graph G^* is not planar.\n");
00143     fflush (stdout);
00144 #endif
00145     /* First: Contractions.                                                   */
00146     /* Second: Eliminate Edges using the Kruskal Heuristic.                   */
00147 #if ELIM_EDGES
00148 #if DISPLAY_MODE
00149     fprintf (stdout, "DP Separator: Running edge-elimination "
00150              "heuristic to find planar sub-graph.\n");
00151     fflush (stdout);
00152 #endif
00153 
00154     /* cuidado! */
00155     planar_edges = EGmemPoolMalloc (mem, sizeof (int) * 2 * nedges);
00156     planar_weight = EGmemPoolMalloc (mem, sizeof (double) * nedges);
00157     elim_edges = EGmemPoolMalloc (mem, sizeof (int) * nedges);
00158     /* cuidado! */
00159 
00160     rval =
00161       DPedgeEliminationHeuristic (nnodes, nedges, edges, weight, &nplanar_edges,
00162                                   planar_edges, planar_weight, &nelim_edges,
00163                                   elim_edges);
00164 
00165     /*  
00166      * rval = 
00167      * DPfastEdgeEliminationHeuristic(nnodes, nedges, edges, weight, &nplanar_edges,
00168      * planar_edges, planar_weight, &nelim_edges, elim_edges, 10);
00169      */
00170 
00171     CHECKRVAL (rval);
00172 
00173 #if DISPLAY_MODE
00174     fprintf (stdout, "DP Separator: Completed edge-elimination.");
00175     fflush (stdout);
00176 #endif
00177 
00178     eliminated_edges_b = 1;
00179     TEST (nplanar_edges == nedges, "ERROR: Graph is not planar, yet no edges "
00180           "were eliminated.");
00181 
00182     for (i = 0; i < nedges - nplanar_edges; i++)
00183       error += weight[elim_edges[i]];
00184 
00185 #if DISPLAY_MODE
00186     fprintf (stdout, "DP Separator: Found a planar sub-graph with %d edges.\n",
00187              nplanar_edges);
00188     fflush (stdout);
00189     fprintf (stdout, "DP Separator: Total weight of eliminated edges is %lf.\n",
00190              error);
00191     fflush (stdout);
00192 #endif
00193 #endif
00194   }
00195 
00196   /* if graph is planar, we use the original edge set.                        */
00197   else
00198   {
00199 #if DISPLAY_MODE
00200     fprintf (stdout, "DP Separator: Graph G^* is planar.\n");
00201     fflush (stdout);
00202 #endif
00203     eliminated_edges_b = 0;
00204     planar_edges = edges;
00205     nplanar_edges = nedges;
00206     planar_weight = weight;
00207   }
00208 
00209 #if LOG_MODE
00210   saveBgraph ("graph.planar.b.x", nnodes, nplanar_edges, planar_edges,
00211               planar_weight);
00212   saveGraph ("graph.planar.x", nnodes, nplanar_edges, planar_edges,
00213              planar_weight);
00214 #endif
00215 #if DISPLAY_MODE
00216   fprintf (stdout, "DP Separator: Computing dual of G^*.\n");
00217   fflush (stdout);
00218 #endif
00219   is_connected = EGisCookGraphConnected (nnodes, nplanar_edges, planar_edges,
00220                                          mem);
00221 
00222 #if DISPLAY_MODE
00223   if (is_connected)
00224     fprintf (stdout, "DP Separator: G^* is connected.\n");
00225   else
00226     fprintf (stdout, "DP Separator: G^* is not connected.\n");
00227 #endif
00228 
00229   if (!is_connected)
00230     goto END_DP;
00231 
00232   /* compute dual of graph                                                    */
00233   gp_Free (&primalG);
00234   primalG = gp_New ();
00235   rval = cook2boyerGraph (primalG, nnodes, nplanar_edges, planar_edges);
00236   CHECKRVAL (rval);
00237   biDualG = getDualBoyer (primalG, nnodes, nplanar_edges, planar_weight,
00238                           &dembed, mem,0);
00239   if (!biDualG)
00240     goto END_DP;
00241 
00242 #if DISPLAY_MODE
00243   fprintf (stdout, "DP Separator: Bi-directed dual graph "
00244            "has %d nodes and %d edges.\n",
00245            biDualG->nodes->size, biDualG->nedges);
00246   fprintf (stdout, "DP Separator: Looking for dual dominoes.\n");
00247   fflush (stdout);
00248 #endif
00249 
00250   /* with dual of planar graph, obtain dual dominoes                          */
00251   if (boss_name == 0)
00252     rval = EGddominoComputeAll (mem, biDualG, dlist, 1, percentage);
00253   else
00254     rval = EGddominoComputeAllRemote (mem, biDualG, dlist, 1, boss_name,
00255                                       DDP_HEURISTIC_MAXTIME);
00256   CHECKRVAL (rval);
00257 
00258 #if DISPLAY_MODE
00259   fprintf (stdout, "DP Separator: Found %d dual dominoes.\n", dlist->size);
00260   fflush (stdout);
00261 #endif
00262 
00263   /* now we untengle all the obtained dominoes */
00264   rval = EGuntangleAllDomino (dlist, biDualG, dembed, mem);
00265   CHECKRVAL (rval);
00266 
00267   if (!dlist->size)
00268     goto END_DP;
00269 
00270   /* if using an edge-elimination heuristic, we might want to fix (some? all?) domino values and store this corrected value in primalValue. If there is no edge-elimination we also need to set primalValue, however, in this case there is no need for corrections. Finally, we need to fix numerical errors. Specifically, should we encounter dominoes with slightly negative values, we will round these up to zero (slightly negative == DP_RESET_VALUE. */
00271   rval =
00272     EGfixDualDominos (dlist, nnodes, nedges, weight, edges,
00273                       elim_edges, nelim_edges, primalG, mem);
00274   CHECKRVAL (rval);
00275 
00276 
00277 #if DISPLAY_MODE
00278   if (eliminated_edges_b)
00279   {
00280 
00281     ncorrected = 0;
00282     nnegative = 0;
00283     nfeasible = 0;
00284 
00285     for (ddom_it = dlist->begin; ddom_it; ddom_it = ddom_it->next)
00286     {
00287 
00288       ddom = (EGddomino_t *) (ddom_it->this);
00289       dual_val = EGdijkstraCostToLf (ddom->value);
00290       prim_val = EGdijkstraCostToLf (ddom->primalValue);
00291 
00292       if (fabs (dual_val - prim_val) > 0.0001)
00293       {
00294         ncorrected++;
00295       }
00296       if (dual_val < 0)
00297       {
00298         nnegative++;
00299       }
00300       if (prim_val < 1.0000)
00301         nfeasible++;
00302     }
00303     fprintf (stdout,
00304              "DP Separator: Corrected %d values. %d / %d dominoes remain feasible.\n",
00305              ncorrected, nfeasible, dlist->size);
00306     fflush (stdout);
00307   }
00308 #endif
00309 
00310   /* Solve the cycle problems to compute the dual form of the dp constraints  */
00311   rval = EGddpcComputeAll (mem, biDualG, dlist, ddpc_list, nedges, 1);
00312   CHECKRVAL (rval);
00313 
00314 #if DISPLAY_MODE
00315 
00316   double thresh,
00317     thresh_n;
00318   unsigned int range[DISPLAY_RESOLUTION],
00319     max_violated = 0;
00320 
00321   for (i = 0; i < DISPLAY_RESOLUTION; i++)
00322     range[i] = 0;
00323 
00324 #endif
00325 
00326   /* reset all values to NULL */
00327   *nIneq = 0;
00328   *ndominoes = 0;
00329   *naset = 0;
00330   *nbset = 0;
00331   *aset = 0;
00332   *bset = 0;
00333   *nhandle = 0;
00334   *handle = 0;
00335 
00336   /* ask for space for the constraints */
00337   if (ddpc_list->size)
00338   {
00339     *ndominoes = EGsMalloc (int,
00340                             ddpc_list->size);
00341     *naset = EGsMalloc (int *,
00342                         ddpc_list->size);
00343     *nbset = EGsMalloc (int *,
00344                         ddpc_list->size);
00345     *nhandle = EGsMalloc (int,
00346                           ddpc_list->size);
00347     *aset = EGsMalloc (int **,
00348                        ddpc_list->size);
00349     *bset = EGsMalloc (int **,
00350                        ddpc_list->size);
00351     *handle = EGsMalloc (int *,
00352                          ddpc_list->size);
00353     (*aset)[0] = 0;
00354   }
00355 
00356   if (ddpc_list->size)
00357     slack = EGsMalloc (double,
00358                        ddpc_list->size);
00359 
00360 #if DISPLAY_MODE
00361   fprintf (stdout,
00362            "DP Separator: Primalizing constraints and computing primal slack.\n");
00363 #endif
00364 
00365   for (ddp_it = ddpc_list->begin; ddp_it; ddp_it = ddp_it->next)
00366   {
00367     rval = EGgetPrimalDP ((EGddpConstraint_t *) (ddp_it->this),
00368                           nnodes,
00369                           nedges,
00370                           edges,
00371                           elim_edges,
00372                           nelim_edges,
00373                           weight,
00374                           (*ndominoes) + (*nIneq),
00375                           (*naset) + (*nIneq),
00376                           (*nbset) + (*nIneq),
00377                           (*nhandle) + (*nIneq),
00378                           (*aset) + (*nIneq),
00379                           (*bset) + (*nIneq),
00380                           (*handle) + (*nIneq), &dpViolation, primalG, mem);
00381     CHECKRVAL (rval);
00382     if (!((*nhandle)[*nIneq]))
00383       n_empty_handle++;
00384     //fprintf(stderr,"%p %d::%d::%u no\n",(void*)((*aset)[0]), *nIneq,l_count,ddpc_list->size);
00385     l_count++;
00386     if (dpViolation < 0)
00387     {
00388       slack[*nIneq] = dpViolation;
00389       (*nIneq)++;
00390 #if DISPLAY_MODE
00391       for (i = 0; i < DISPLAY_RESOLUTION; i++)
00392       {
00393         thresh = IDR * i + IDR;
00394         thresh_n = IDR * i;
00395         if (thresh_n <= -1 * dpViolation && -1 * dpViolation <= thresh)
00396         {
00397           range[i] += 1;
00398           break;
00399         }
00400       }
00401 
00402       if (-1 * dpViolation > 1.0 - DP_MAXVIOLATED_EPSILON)
00403         max_violated += 1;
00404 
00405 #endif
00406 
00407     }                           /* end case we have found a violated constraint */
00408     else
00409     {
00410       for (i = (*ndominoes)[*nIneq]; i--;)
00411       {
00412         EGfree ((*aset)[*nIneq][i]);
00413         EGfree ((*bset)[*nIneq][i]);
00414       }
00415       EGfree ((*naset)[*nIneq]);
00416       EGfree ((*nbset)[*nIneq]);
00417       EGfree ((*aset)[*nIneq]);
00418       EGfree ((*bset)[*nIneq]);
00419       if ((*nhandle)[*nIneq])
00420         EGfree ((*handle)[*nIneq]);
00421     }                           /* end freing the non violated primal constraint */
00422   }                             /* end for ddp_it */
00423 
00424 #if DISPLAY_MODE
00425   fprintf (stdout, "DP Separator: Found %d primal DP-Constraints.\n", *nIneq);
00426   fprintf (stdout, "DP Separator: Found %u empty handles.\n", n_empty_handle);
00427   fflush (stdout);
00428 
00429   if (nelim_edges || 1)
00430   {
00431 
00432     fprintf (stdout, "DP Separator: Final |slack values|\n");
00433     fflush (stdout);
00434 
00435     for (i = 0; i < DISPLAY_RESOLUTION; i++)
00436     {
00437       thresh = IDR * i + IDR;
00438       thresh_n = IDR * i;
00439       if (range[i])
00440         fprintf (stdout, "[%8lf, %8lf]   %d\n", thresh_n, thresh, range[i]);
00441       fflush (stdout);
00442     }
00443 
00444     fprintf (stdout, "Max-Violations        %d\n", max_violated);
00445     fflush (stdout);
00446 
00447   }
00448 #endif
00449 
00450   if (*nIneq)
00451   {
00452     double *violation;
00453     int **e_coeff;
00454     violation = EGsMalloc (double,
00455                            *nIneq);
00456     e_coeff = EGsMalloc (int *,
00457                          *nIneq);
00458     for (i = *nIneq; i--;)
00459       e_coeff[i] = EGsMalloc (int,
00460                               norig_edges);
00461     rval = EG1pChecker (nnodes, norig_edges, orig_edges, orig_weight, *nIneq,
00462                         *ndominoes, *naset, *nbset, *nhandle,
00463                         *aset, *bset, *handle, violation, e_coeff);
00464     CHECKRVAL (rval);
00465     for (i = *nIneq; i--;)
00466     {
00467       WARNING (fabs (violation[i] - slack[i]) > 1e-2,
00468                "Violation don't agree for ineq "
00469                "%i\n(computed)%7.5lf (alg)%7.5lf (diff)%7.5lf\n", i,
00470                violation[i], slack[i], fabs (violation[i] - slack[i]));
00471       EGfree (e_coeff[i]);
00472     }
00473     EGfree (violation);
00474     EGfree (e_coeff);
00475   }
00476   if (slack)
00477     EGfree (slack);
00478 
00479 #if DP_REMOVE_EMPTY_HANDLES
00480   if (n_empty_handle)
00481   {
00482 
00483 #if DISPLAY_MODE
00484     fprintf (stdout, "DP Separator: Removing empty-handle constraints.\n");
00485     fflush (stdout);
00486 #endif
00487 
00488     rval =
00489       DPremoveEmptyHandles (nIneq, ndominoes, naset, nbset, nhandle, aset, bset,
00490                             handle);
00491     CHECKRVAL (rval);
00492 
00493 #if DISPLAY_MODE
00494     fprintf (stdout,
00495              "DP Separator: Final number of non-empty-handle constraints: %d.\n",
00496              *nIneq);
00497     fflush (stdout);
00498 #endif
00499 
00500   }
00501 #endif
00502 
00503   /* EGfree up used memory */
00504 
00505 END_DP:
00506 
00507 #if DISPLAY_MODE
00508   fprintf (stdout, "DP Separator: Bye.\n");
00509   fflush (stdout);
00510 #endif
00511 
00512   /* EGfree dlist, ddplist, and pdplist */
00513   if (dlist)
00514   {
00515     if (dlist->size)
00516       EGlistClearMP (dlist, EGfreeDdomino, mem);
00517     EGfreeList (dlist);
00518   }
00519 
00520   if (ddpc_list)
00521   {
00522     if (ddpc_list->size)
00523       EGlistClearMP (ddpc_list, EGfreeDDPconstraintMP, mem);
00524     EGfreeList (ddpc_list);
00525   }
00526 
00527   /* EGfree 'graphdual' objects */
00528   if (weight)
00529     EGmemPoolFree (weight, sizeof (double) * nedges, mem);
00530   if (edges)
00531     EGmemPoolFree (edges, sizeof (int) * 2 * nedges, mem);
00532 
00533 #if ELIM_EDGES
00534   /* EGfree planar-graph heuristic data structures */
00535   if (eliminated_edges_b)
00536   {
00537     EGmemPoolSFree (planar_edges, int,
00538                     2 * nedges,
00539                     mem);
00540     EGmemPoolSFree (elim_edges, int,
00541                     nedges,
00542                     mem);
00543     EGmemPoolSFree (planar_weight, double,
00544                     nedges,
00545                     mem);
00546   }
00547 #endif
00548 
00549   /* EGfree biDualG: weight, edges, and graph structure. */
00550   if (biDualG)
00551   {
00552     EGdGraphClearMP (biDualG, EGfreeMengerEdgeDataMP, EGfreeMengerNodeDataMP, 0,
00553                      mem, mem, 0);
00554     EGfreeDGraph (biDualG);
00555   }
00556 
00557   if (dembed)
00558   {
00559     for (i = nplanar_edges - nnodes + 2; i--;)
00560       EGfreeList (dembed[i]);
00561     EGmemPoolSFree (dembed, EGlist_t *, nplanar_edges - nnodes + 2, mem);
00562   }
00563   /* EGfree memory pool */
00564   EGfreeMemPool (mem);
00565   gp_Free (&primalG);
00566 
00567   /* return */
00568   return 0;
00569 
00570 }

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