eg_ddpconstraint.c

Go to the documentation of this file.
00001 #include "eg_ddpconstraint.h"
00002 /* this macro return the 'edge' ponter asociated to the 'b'-th arc in path 'a'
00003  * of the domino 'dom'. It takes care of different types of dominos in an easy
00004  * form */
00005 #define EGddGetEdge(DOM,a,b) ((graphNodeP)(((DOM)->DDtype == DOM_CC_ONE) ? \
00006     (DOM)->path[a][b]:((EGmengerEdgeData_t*)(((EGdGraphEdge_t*)\
00007     ((DOM)->path[a][b]))->data))->data))
00008 
00009 static inline int EGgetPrimalDPdist (EGddpConstraint_t const *const ddp,  /* dual DP constraint */
00010 
00011                                      double *const dist)  /* where to store the distance to the
00012                                                            * fractional X */
00013 {
00014 
00015   /* local variables */
00016   double alphax = -1.0;
00017   register unsigned int k;
00018 
00019 
00020   /* now we update the parity of the edges in F */
00021   for (k = ddp->nF; k--;)
00022     alphax +=
00023       EGdijkstraCostToLf (((EGmengerEdgeData_t *) (ddp->F[k]->data))->cost);
00024 
00025   /* here we compute the primal dominoes, and loop through all of them */
00026   for (k = ddp->ndom; k--;)
00027     alphax += EGdijkstraCostToLf (ddp->ddom[k]->value);
00028 
00029   alphax /= sqrt (((double) (ddp->nF + ddp->ndom)));
00030   *dist = alphax;
00031   return 0;
00032 }
00033 
00034 static int EGdominoCompare (const void *p1,
00035                             const void *p2)
00036 {
00037 
00038   if ((*((ccddomp_t) (p1)))->id < (*((ccddomp_t) (p2)))->id)
00039     return -1;
00040   else if ((*((ccddomp_t) (p1)))->id > (*((ccddomp_t) (p2)))->id)
00041     return 1;
00042   return 0;
00043 }
00044 
00045 static inline int EGgetPrimalDPangle (EGddpConstraint_t const *const ddp1,  /* dual DP constraint */
00046 
00047                                       EGddpConstraint_t const *const ddp2,  /* dual DP constraint */
00048 
00049                                       double *const angle)  /* where to store the distance to the
00050                                                              * fractional X */
00051 {
00052 
00053   /* we define the norm of a DP inequality as nF + sum ddom_slack^2 */
00054   /* local variables */
00055   register unsigned int k1 = 0,
00056     k2 = 0;
00057   double norm3 = 0;
00058 
00059   /* now we compute  */
00060   while (k1 < ddp1->nF && k2 < ddp2->nF)
00061   {
00062     switch (EGedgeCompare (ddp1->F + k1, ddp2->F + k2))
00063     {
00064     case 0:
00065       norm3 += 1;
00066       k1++;
00067       k2++;
00068       break;
00069     case 1:
00070       k1++;
00071       break;
00072     case -1:
00073       k2++;
00074       break;
00075     }
00076   }
00077   k1 = k2 = 0;
00078   while (k1 < ddp1->ndom && k2 < ddp2->ndom)
00079   {
00080     switch (EGdominoCompare (ddp1->ddom + k1, ddp2->ddom + k2))
00081     {
00082     case 0:
00083       norm3 += 1;
00084       k1++;
00085       k2++;
00086       break;
00087     case 1:
00088       k1++;
00089       break;
00090     case -1:
00091       k2++;
00092       break;
00093     }
00094   }
00095 
00096   *angle = norm3;
00097   *angle /= sqrt ((double) ((ddp1->nF + ddp1->ndom) * (ddp2->nF + ddp2->ndom)));
00098 
00099   /* ending */
00100   return 0;
00101 }
00102 
00103 static long long unsigned int global_cnt = 0;
00104 
00105 static inline double EGddpHeuristicVal (EGdijkstraCost_t dcost)
00106 {
00107 
00108   double val = EGdijkstraCostToLf (dcost);
00109 
00110   if (val < 0.01)
00111     val = 0.01;
00112 
00113   /* original values:
00114    * if (val < 0.01)
00115    * val = 0.01;
00116    */
00117 
00118   val = (1 / val);
00119 
00120   return val;
00121 
00122 }
00123 
00124 
00125 /* this data structure is used to store relevant information 
00126    for the edges in a cycle graph */
00127 
00128 static inline EGcycleData_t *EGnewCycleData (EGmemPool_t * mem,
00129                                              EGdijkstraCost_t new_weight,
00130                                              EGddomino_t * new_ddom,
00131                                              EGdGraphEdge_t * new_e)
00132 {
00133 
00134   double val;
00135   EGcycleData_t *cycle_data;
00136 
00137   if (EGdijkstraCostIsLess (new_weight, EGdijkstraToCost (-0.02)))
00138   {
00139     fprintf (stdout,
00140              "WARNING! cycle-data edge is less than -0.02 (%lf) set to 0.0\n",
00141              EGdijkstraCostToLf (new_weight));
00142     new_weight = EGdijkstraToCost (0.0);
00143   }
00144   cycle_data = EGmemPoolSMalloc (mem, EGcycleData_t, 1);
00145   cycle_data->weight = new_weight;
00146   cycle_data->e = new_e;
00147   cycle_data->ddom = new_ddom;
00148 
00149   val = round (EGddpHeuristicVal (new_weight));
00150 
00151   cycle_data->pweight = ((unsigned int) val);
00152 
00153   return cycle_data;
00154 
00155 }
00156 
00157 void EGfreeCycleDataMP (void *v,
00158                         EGmemPool_t * mem)
00159 {
00160 
00161   EGmemPoolSFree (v, EGcycleData_t, 1, mem);
00162 
00163   return;
00164 
00165 }
00166 
00167 EGdGraph_t *EGnewCycleGraph (EGmemPool_t * mem,
00168                              EGlist_t * dlist,
00169                              EGdGraph_t * bdG,
00170                              EGdijkstraCost_t max_val)
00171 {
00172 
00173   unsigned int p,
00174     ph,
00175     pt;
00176   EGdGraphNode_t *n;
00177   EGdGraphEdge_t *e;
00178   EGlistNode_t *n_it,
00179    *e_it,
00180    *dd_it;
00181   EGdGraph_t *cycleG;
00182   EGcycleData_t *edata;
00183   EGddomino_t *ddom;
00184   EGdijkstraNodeData_t *ndata;
00185   EGmengerEdgeData_t *mdata;
00186 
00187   EGdGraphNode_t **node_array;
00188 
00189   cycleG = EGnewDGraph (mem);
00190 
00191   /* add the nodes: there are two nodes in cycleG per every node in bdG       */
00192   node_array = EGmemPoolSMalloc (mem, EGdGraphNode_t *, 2 * (bdG->nodes->size));
00193 
00194   for (n_it = bdG->nodes->begin; n_it; n_it = n_it->next)
00195   {
00196     n = (EGdGraphNode_t *) (n_it->this);
00197 
00198     /* we make a 'left' copy                                                  */
00199     p = 2 * (n->id);
00200     ndata = EGnewDijkstraNodeData (mem);
00201     ndata->father = 0;
00202     node_array[p] = EGdGraphAddNode (cycleG, ndata);
00203     /* and a 'right' copy                                                     */
00204     p = 2 * (n->id) + 1;
00205     ndata = EGnewDijkstraNodeData (mem);
00206     ndata->father = 0;
00207     node_array[p] = EGdGraphAddNode (cycleG, ndata);
00208   }
00209 
00210   /* add the F edges: there are two F edges per every edge in bdG             */
00211   for (n_it = bdG->nodes->begin; n_it; n_it = n_it->next)
00212   {
00213     n = (EGdGraphNode_t *) (n_it->this);
00214     for (e_it = n->out_edges->begin; e_it; e_it = e_it->next)
00215     {
00216       e = (EGdGraphEdge_t *) (e_it->this);
00217       mdata = (EGmengerEdgeData_t *) (e->data);
00218       if (EGdijkstraCostIsLess (max_val, mdata->cost))
00219         continue;
00220 
00221       /* we make a 'left copy'                                                */
00222 
00223       ph = 2 * (e->head->id);
00224       pt = 2 * (e->tail->id);
00225       edata = EGnewCycleData (mem, mdata->cost, 0, e);
00226       EGdGraphAddEdge (cycleG, edata, node_array[ph], node_array[pt]);
00227 
00228       /* and a 'right' copy                                                   */
00229 
00230       ph = 2 * (e->head->id) + 1;
00231       pt = 2 * (e->tail->id) + 1;
00232       edata = EGnewCycleData (mem, mdata->cost, 0, e);
00233       EGdGraphAddEdge (cycleG, edata, node_array[ph], node_array[pt]);
00234 
00235     }
00236   }
00237 
00238   /* add the odd edges                                                        */
00239   for (dd_it = dlist->begin; dd_it; dd_it = dd_it->next)
00240   {
00241     ddom = (EGddomino_t *) (dd_it->this);
00242     if (EGdijkstraCostIsLess (max_val, ddom->primalValue))
00243       continue;
00244 
00245     /* we make a 'left s' to 'right t' copy                                   */
00246 
00247     ph = 2 * (ddom->s->id);
00248     pt = 2 * (ddom->t->id) + 1;
00249     edata = EGnewCycleData (mem, ddom->primalValue, ddom, 0);
00250     EGdGraphAddEdge (cycleG, edata, node_array[ph], node_array[pt]);
00251 
00252     /* we make a 'right s' to 'left t' copy                                   */
00253 
00254     ph = 2 * (ddom->s->id) + 1;
00255     pt = 2 * (ddom->t->id);
00256     edata = EGnewCycleData (mem, ddom->primalValue, ddom, 0);
00257     EGdGraphAddEdge (cycleG, edata, node_array[ph], node_array[pt]);
00258 
00259     /* we make a 'left t' to 'right s' copy                                   */
00260 
00261     ph = 2 * (ddom->t->id);
00262     pt = 2 * (ddom->s->id) + 1;
00263     edata = EGnewCycleData (mem, ddom->primalValue, ddom, 0);
00264     EGdGraphAddEdge (cycleG, edata, node_array[ph], node_array[pt]);
00265 
00266     /* we make a 'right t' to 'left s' copy                                   */
00267 
00268     ph = 2 * (ddom->t->id) + 1;
00269     pt = 2 * (ddom->s->id);
00270     edata = EGnewCycleData (mem, ddom->primalValue, ddom, 0);
00271     EGdGraphAddEdge (cycleG, edata, node_array[ph], node_array[pt]);
00272   }
00273 
00274   EGmemPoolSFree (node_array, EGdGraphNode_t *, 2 * (bdG->nodes->size), mem);
00275 
00276   return cycleG;
00277 
00278 }
00279 
00280 void EGfreeDDPconstraintMP (void *v,
00281                             EGmemPool_t * mem)
00282 {
00283   EGddpConstraint_t *ddpc;
00284 
00285   ddpc = (EGddpConstraint_t *) (v);
00286 
00287   if (ddpc->ndom)
00288     EGmemPoolSFree (ddpc->ddom, EGddomino_t *, ddpc->ndom, mem);
00289   if (ddpc->nF)
00290     EGmemPoolSFree (ddpc->F, EGdGraphEdge_t *, ddpc->nF, mem);
00291 
00292   EGmemPoolSFree (v, EGddpConstraint_t, 1, mem);
00293 
00294   return;
00295 }
00296 
00297 
00298 int EGboyerEdgeNumber (const EGdGraphEdge_t * e)
00299 {
00300   EGmengerEdgeData_t *d;
00301   graphNodeP a;
00302 
00303   d = (EGmengerEdgeData_t *) (e->data);
00304   a = (graphNodeP) (d->data);
00305 
00306   return (a->id);
00307 }
00308 
00309 int EGedgeCompare (const void *p1,
00310                    const void *p2)
00311 {
00312   const EGdGraphEdge_t *e1,
00313    *e2;
00314 
00315   e1 = (*((ccep_t) (p1)));
00316   e2 = (*((ccep_t) (p2)));
00317 
00318   if (EGboyerEdgeNumber (e1) < EGboyerEdgeNumber (e2))
00319     return -1;
00320   else if (EGboyerEdgeNumber (e1) > EGboyerEdgeNumber (e2))
00321     return 1;
00322   return 0;
00323 }
00324 
00325 /* this macro return the dijksra cost of a dual edge */
00326 #define EGddGetEdgeCost(dedge) (\
00327     ((EGmengerEdgeData_t*)(((EGdGraphEdge_t*)(dedge))->data))->cost)
00328 static unsigned int __ndisc = 0;
00329 static unsigned int __accept = 0;
00330 static inline int EGddpMuCondition (EGddpConstraint_t * ddpc)
00331 {
00332   EGdijkstraCost_t muH = EGdijkstraToCost (ddpc->ndom + 1),
00333     p_cost[2];
00334   register unsigned int i;
00335   unsigned pth,
00336     dom;
00337   /* now we substract the central path of all dominoes and F */
00338   for (i = ddpc->nF; i--;)
00339     muH = EGdijkstraCostSub (muH, EGddGetEdgeCost (ddpc->F[i]));
00340   for (dom = ddpc->ndom; dom--;)
00341   {
00342     p_cost[0] = EGdijkstraToCost (0);
00343     p_cost[1] = EGdijkstraToCost (100);
00344     /* compute cheapest path in p_cost[1] */
00345     for (pth = 3; pth--;)
00346     {
00347       for (i = ddpc->ddom[dom]->npath[pth]; i--;)
00348         p_cost[0] = EGdijkstraCostAdd (p_cost[0],
00349                                        EGddGetEdgeCost (ddpc->ddom[dom]->
00350                                                         path[pth][i]));
00351       if (EGdijkstraCostIsLess (p_cost[0], p_cost[1]))
00352         p_cost[1] = p_cost[0];
00353     }                           /* end computing cheapest path */
00354     muH = EGdijkstraCostSub (muH, p_cost[1]);
00355   }                             /* end loop through all dominoes */
00356   /* now we check that muH > 0 */
00357   if (EGdijkstraCostIsLess (EGdijkstraToCost (0), muH))
00358   {
00359     __accept++;
00360     return 1;
00361   }
00362   __ndisc++;
00363   //fprintf(stderr,"Discarded Handle %.3lf%%\r",  
00364   //        ((double)(__ndisc))/(__ndisc+__accept) );
00365   return 0;
00366 }
00367 
00368 static inline int EGddpIsMinimal (EGddpConstraint_t * ddpc,
00369                                   unsigned int *marray,
00370                                   unsigned int marray_size)
00371 {
00372 
00373   unsigned int i;
00374 
00375   for (i = 0; i < marray_size; i++)
00376     marray[i] = 0;
00377 
00378   for (i = 0; i < ddpc->nF; i++)
00379   {
00380     marray[ddpc->F[i]->head->id] += 1;
00381     marray[ddpc->F[i]->tail->id] += 1;
00382   }
00383 
00384   for (i = 0; i < ddpc->ndom; i++)
00385   {
00386     marray[ddpc->ddom[i]->s->id] += 1;
00387     marray[ddpc->ddom[i]->t->id] += 1;
00388   }
00389 
00390   for (i = 0; i < marray_size; i++)
00391   {
00392     if (marray[i] > 2)
00393       return 0;
00394   }
00395 
00396   return 1;
00397 
00398 }
00399 
00400 static inline int EGddpExtractSolution (EGdGraphEdge_t ** path,
00401                                         unsigned int *npath,
00402                                         EGdGraphNode_t * t,
00403                                         EGdijkstraCost_t * LHS_val)
00404 {
00405 
00406   EGdijkstraCost_t dcVal;
00407 
00408   EGdGraphEdge_t *e;
00409   EGdGraphNode_t *n;
00410   EGdijkstraNodeData_t *dndata;
00411   EGcycleData_t *cdata;
00412 
00413   unsigned int pos;
00414 
00415   n = t;
00416   pos = 0;
00417   dcVal = EGdijkstraToCost (0.0);
00418 
00419   while (((n->id) / 2 != (t->id) / 2) || !pos)
00420   {
00421     dndata = (EGdijkstraNodeData_t *) (n->data);
00422     e = dndata->father;
00423 
00424     cdata = (EGcycleData_t *) (e->data);
00425     dcVal = EGdijkstraCostAdd (dcVal, cdata->weight);
00426 
00427     path[pos] = e;
00428     n = e->tail;
00429 
00430     pos += 1;
00431   }
00432 
00433   *npath = pos;
00434   *LHS_val = dcVal;
00435 
00436   return 0;
00437 
00438 }
00439 
00440 static inline int EGddpAreSame (EGddpConstraint_t * c1,
00441                                 EGddpConstraint_t * c2)
00442 {
00443   unsigned int i;
00444 
00445   if ((c1->nF != c2->nF) || (c1->ndom != c2->ndom))
00446     return 0;
00447 
00448   for (i = 0; i < c1->nF; i++)
00449   {
00450     if (EGboyerEdgeNumber (c1->F[i]) != EGboyerEdgeNumber (c2->F[i]))
00451       return 0;
00452   }
00453   for (i = 0; i < c1->ndom; i++)
00454   {
00455     if ((c1->ddom[i]->s->id) != (c2->ddom[i]->s->id))
00456       return 0;
00457     if ((c1->ddom[i]->t->id) != (c2->ddom[i]->t->id))
00458       return 0;
00459     if ((c1->ddom[i]->value != c2->ddom[i]->value))
00460       return 0;
00461   }
00462 
00463   return 1;
00464 
00465 }
00466 
00467 static inline int EGddpSortData (EGddpConstraint_t * c)
00468 {
00469   if (c->ndom > 1)
00470     qsort (c->ddom, c->ndom, sizeof (EGddomino_t *), EGdominoCompare);
00471   if (c->nF > 1)
00472     qsort (c->F, c->nF, sizeof (EGdGraphEdge_t *), EGedgeCompare);
00473 
00474   return 0;
00475 }
00476 
00477 static inline EGddpConstraint_t *EGnewDDPconstraint (EGmemPool_t * mem,
00478                                                      EGdGraphEdge_t ** dij_sol,
00479                                                      unsigned int ndij_sol,
00480                                                      int k,
00481                                                      EGdijkstraCost_t val)
00482 {
00483 
00484   EGcycleData_t *cdata;
00485   EGddpConstraint_t *ddpc;
00486   unsigned int i;
00487 
00488   ddpc = EGmemPoolSMalloc (mem, EGddpConstraint_t, 1);
00489   ddpc->ndom = 0;
00490   ddpc->nF = 0;
00491 
00492   for (i = 0; i < ndij_sol; i++)
00493   {
00494     cdata = (EGcycleData_t *) (dij_sol[i]->data);
00495     if (cdata->ddom)
00496       ddpc->ndom += 1;
00497     else
00498       ddpc->nF += 1;
00499   }
00500 
00501   if (ddpc->nF)
00502     ddpc->F = EGmemPoolSMalloc (mem, EGdGraphEdge_t *, ddpc->nF);
00503   else
00504     ddpc->F = 0;
00505   if (ddpc->ndom)
00506     ddpc->ddom = EGmemPoolSMalloc (mem, EGddomino_t *, ddpc->ndom);
00507   else
00508     ddpc->ddom = 0;
00509 
00510   ddpc->ndom = 0;
00511   ddpc->nF = 0;
00512 
00513   for (i = 0; i < ndij_sol; i++)
00514   {
00515     cdata = (EGcycleData_t *) (dij_sol[i]->data);
00516     if (cdata->ddom)
00517     {
00518       ddpc->ddom[ddpc->ndom] = cdata->ddom;
00519       ddpc->ndom += 1;
00520     }
00521     else
00522     {
00523       ddpc->F[ddpc->nF] = cdata->e;
00524       ddpc->nF += 1;
00525     }
00526   }
00527 
00528   ddpc->LHS_dp = val;
00529   ddpc->slack_dp = EGdijkstraCostToLf (val) - 1.0;
00530   return ddpc;
00531 
00532 }
00533 
00534 
00535 static int EGddpAddCutIfNew (EGddpConstraint_t ** ddpc_array,
00536                              double *const ddpc_dist,
00537                              double *const ddpc_angle_norm,
00538                              double *const *const ddpc_angle,
00539                              unsigned int *const ddpc_size,
00540                              unsigned int const ddpc_max_size,
00541                              double *const ddpc_best_angle,
00542                              double *const ddpc_worst_angle,
00543                              unsigned int *const ddpc_worst_angle_id,
00544                              EGdGraphNode_t * nrigh,
00545                              EGdGraph_t * cycleG,
00546                              EGdGraphEdge_t ** dij_sol,
00547                              unsigned int *marray,
00548                              char *sarray,
00549                              size_t * os,
00550                              int k,
00551                              EGmemPool_t * mem)
00552 {
00553 
00554   int rval;
00555   unsigned int ndij_sol;
00556   unsigned register int i;
00557   unsigned int hcmax = 0,
00558     worst_dist = 0,
00559     pos = *ddpc_size;
00560   EGddpConstraint_t *ddpc;
00561   EGdijkstraCost_t lhs_val;
00562   double val,
00563     dist,
00564     maxangle,
00565     dtmp,
00566     norm = 1.0;
00567 
00568   EGddpExtractSolution (dij_sol, &ndij_sol, nrigh, &lhs_val);
00569 
00570   os = 0;
00571   /* ensure that the constraint is sufficiently violated */
00572   if (((1.0) - EGdijkstraCostToLf (lhs_val)) <= ((DDP_MIN_VIOLATION)))
00573     return 0;
00574 
00575   /* create the new ddpc constraint */
00576   ddpc = EGnewDDPconstraint (mem, dij_sol, ndij_sol, 1, lhs_val);
00577 
00578   /* if the constraint don't have an odd number of doinos, we discardit and
00579    * return (no error) */
00580   if (!(ddpc->ndom & 1))
00581   {
00582     EGfreeDDPconstraintMP (ddpc, mem);
00583     return 0;
00584   }
00585 
00586   /* ensure the constraint got at least 3 dominoes */
00587   if (ddpc->ndom < 3)
00588   {
00589     EGfreeDDPconstraintMP (ddpc, mem);
00590     return 0;
00591   }
00592 
00593   rval = EGddpIsMinimal (ddpc, marray, cycleG->nodes->size / 2);
00594   if (!rval)
00595   {
00596     sarray[(nrigh->id) / 2] = 'M';
00597     EGfreeDDPconstraintMP (ddpc, mem);
00598     return 0;
00599   }
00600 
00601   /* sort the internal data in the new constraint */
00602   rval = EGddpSortData (ddpc);
00603   CHECKRVAL (rval);
00604 
00605   /* check if the inequality is already added to the pool */
00606   for (i = *ddpc_size; i--;)
00607   {
00608     if (EGddpAreSame (ddpc, ddpc_array[i]))
00609     {
00610       sarray[(nrigh->id) / 2] = 'R';
00611       EGfreeDDPconstraintMP (ddpc, mem);
00612       return 0;
00613     }
00614   }
00615 
00616   /* compute the distance from the fractional point to the newly found
00617    * constraint */
00618   EGgetPrimalDPdist (ddpc, &dist);
00619   val = -1.0 * dist;
00620 
00621   if (pos < ddpc_max_size)
00622   {
00623     ddpc_array[pos] = ddpc;
00624     ddpc_dist[pos] = val;
00625     ddpc_angle_norm[pos] = 1.0;
00626     /* compute the angles */
00627     if (pos)
00628     {
00629       for (i = pos; i--;)
00630       {
00631         EGgetPrimalDPangle (ddpc, ddpc_array[i], &dtmp);
00632         ddpc_angle[pos][i] = dtmp;
00633         ddpc_angle[i][pos] = dtmp;
00634         ddpc_angle_norm[i] += dtmp * dtmp;
00635         ddpc_angle_norm[pos] += dtmp * dtmp;
00636       }
00637     }
00638     else
00639       *ddpc_worst_angle_id = 0;
00640     (*ddpc_size)++;
00641     pos++;
00642     MESSAGE (EG_DP_SELECT_DEBUG, "ddpc added because pool not full");
00643   }
00644   /* if the pool is full, then we have to choose who to kick out of the pool,
00645    * we do that taking into account the angle and the distance */
00646   else
00647   {
00648     maxangle = 0.0;
00649     worst_dist = ddpc_max_size - 1;
00650     /* compute  the angle from the new cut to all cuts in the pool */
00651     for (i = ddpc_max_size; i--;)
00652     {
00653       EGgetPrimalDPangle (ddpc, ddpc_array[i], &dtmp);
00654       ddpc_angle[ddpc_max_size][i] = dtmp;
00655       norm += dtmp * dtmp;
00656       if (dtmp > maxangle)
00657       {
00658         hcmax = i;
00659         maxangle = dtmp;
00660       }
00661       if (ddpc_dist[worst_dist] > ddpc_dist[i])
00662         worst_dist = i;
00663     }
00664     /* now we  have the closest angle constraint in the pool, we first check if
00665      * the current cut is near an added cut and its distancce to X is better,
00666      * if so, we replace the old cut by the newly found cut */
00667 #if DDPC_REPLACE_CLOSE
00668     if ((maxangle > DP_BIG_ANGLE) && (ddpc_dist[hcmax] < val))
00669     {
00670       MESSAGE (EG_DP_SELECT_DEBUG, "ddpc added because dominate another"
00671                "inequality, angle(%lf) new disr(%lf) old dist(%lf)", maxangle,
00672                val, ddpc_dist[hcmax]);
00673       EGfreeDDPconstraintMP (ddpc_array[hcmax], mem);
00674       ddpc_array[hcmax] = ddpc;
00675       ddpc_dist[hcmax] = val;
00676       norm -= ddpc_angle[ddpc_max_size][hcmax] *
00677         ddpc_angle[ddpc_max_size][hcmax];
00678       for (i = ddpc_max_size; i--;)
00679       {
00680         dtmp = ddpc_angle[i][hcmax];
00681         ddpc_angle_norm[i] -= dtmp * dtmp;
00682         dtmp = ddpc_angle[ddpc_max_size][i];
00683         ddpc_angle_norm[i] += dtmp * dtmp;
00684         ddpc_angle[hcmax][i] = dtmp;
00685         ddpc_angle[i][hcmax] = dtmp;
00686       }
00687       ddpc_angle_norm[hcmax] = norm;
00688     }
00689 #else
00690     if (0)
00691     {
00692     }
00693 #endif
00694     /* if the worst norm is good enough, we put in the inequality if it improves
00695      * the wordt cuality */
00696 #if DDPC_BEST_VIOLATION
00697     else if (val > ddpc_dist[worst_dist])
00698     {
00699       pos = worst_dist;
00700       MESSAGE (EG_DP_SELECT_DEBUG, "ddpc added because improve worst distance"
00701                " with norm(%lf) angle(%lf) new dist(%lf) old dist(%lf)",
00702                norm, maxangle, val, ddpc_dist[pos]);
00703       EGfreeDDPconstraintMP (ddpc_array[pos], mem);
00704       ddpc_array[pos] = ddpc;
00705       ddpc_dist[pos] = val;
00706       norm -= ddpc_angle[ddpc_max_size][pos] * ddpc_angle[ddpc_max_size][pos];
00707       for (i = ddpc_max_size; i--;)
00708       {
00709         dtmp = ddpc_angle[i][pos];
00710         ddpc_angle_norm[i] -= dtmp * dtmp;
00711         dtmp = ddpc_angle[ddpc_max_size][i];
00712         ddpc_angle_norm[i] += dtmp * dtmp;
00713         ddpc_angle[i][pos] = dtmp;
00714         ddpc_angle[pos][i] = dtmp;
00715       }
00716       ddpc_angle_norm[pos] = norm;
00717     }
00718 #endif
00719     /* if the cut don't dominate another cut, it still may improve the spread
00720      * of the set of constraints in the pool, if so, we use it */
00721 #if DDPC_IMPROVE_SPREAD
00722     else if (*ddpc_worst_angle > SELECT_MIN_NORM && *ddpc_worst_angle +
00723              (ddpc_angle[ddpc_max_size][*ddpc_worst_angle_id]) *
00724              (ddpc_angle[ddpc_max_size][*ddpc_worst_angle_id]) > norm &&
00725              val > DP_MAXDECREASE * ddpc_dist[worst_dist])
00726     {
00727       pos = *ddpc_worst_angle_id;
00728       MESSAGE (EG_DP_SELECT_DEBUG, "ddpc added because improve worst norm(%lf)"
00729                " with norm(%lf) angle(%lf) new dist(%lf) old dist(%lf)",
00730                *ddpc_worst_angle, norm, maxangle, val, ddpc_dist[pos]);
00731       EGfreeDDPconstraintMP (ddpc_array[pos], mem);
00732       ddpc_array[pos] = ddpc;
00733       ddpc_dist[pos] = val;
00734       norm -= ddpc_angle[ddpc_max_size][pos] * ddpc_angle[ddpc_max_size][pos];
00735       for (i = ddpc_max_size; i--;)
00736       {
00737         dtmp = ddpc_angle[i][pos];
00738         ddpc_angle_norm[i] -= dtmp * dtmp;
00739         dtmp = ddpc_angle[ddpc_max_size][i];
00740         ddpc_angle_norm[i] += dtmp * dtmp;
00741         ddpc_angle[i][pos] = dtmp;
00742         ddpc_angle[pos][i] = dtmp;
00743       }
00744       ddpc_angle_norm[pos] = norm;
00745     }
00746 #endif
00747     /* now we just discard */
00748     else
00749     {
00750       MESSAGE (EG_DP_SELECT_DEBUG, "ddpc discarded. worst norm(%lf) with norm"
00751                "(%lf) angle(%lf) new dist(%lf) old dist(%lf)",
00752                *ddpc_worst_angle, norm, maxangle, val, ddpc_dist[worst_dist]);
00753       EGfreeDDPconstraintMP (ddpc, mem);
00754     }
00755   }
00756   /* now we recompute ddpc_worst/best_angle/_id */
00757   *ddpc_worst_angle = 0.0;
00758   *ddpc_best_angle = ddpc_max_size;
00759   if (*ddpc_size)
00760     for (i = *ddpc_size; i--;)
00761     {
00762       dtmp = ddpc_angle_norm[i];
00763       if (dtmp > *ddpc_worst_angle)
00764       {
00765         *ddpc_worst_angle = dtmp;
00766         *ddpc_worst_angle_id = i;
00767       }
00768       if (dtmp < *ddpc_best_angle)
00769         *ddpc_best_angle = dtmp;
00770     }
00771 
00772   return 0;
00773 }
00774 
00775 static unsigned char *__edge_valid = 0;
00776 static unsigned int __edge_valid_size = 0;
00777 static inline EGdGraphEdge_t *EGddpHeuristicSample (EGdGraphNode_t * n,
00778                                                     unsigned int
00779                                                     *marked_node_array,
00780                                                     unsigned int
00781                                                     n_marked_dominoes,
00782                                                     unsigned int *odd_num,
00783                                                     int *ddom_markers,
00784                                                     int k)
00785 {
00786 
00787   int is_e_dom,
00788     head_pid,
00789     num_feasible = 0,
00790     dom_min;
00791   double rvalue;
00792   unsigned int irvalue,
00793     max_weight = 0,
00794     current_weight = 0;
00795   EGdGraphNode_t *head;
00796   EGdGraphEdge_t *e = 0,
00797    *next_e = 0,
00798    *saved_e = 0;
00799   EGcycleData_t *cd;
00800   EGlistNode_t *it;
00801   /* these two are used to store which edges are feasibles, so we don't work
00802    * twice */
00803   unsigned int edge_valid_it;
00804 
00805   /* basic set-up */
00806   if (__edge_valid_size < n->out_edges->size)
00807   {
00808     if(__edge_valid) EGfree (__edge_valid);
00809     __edge_valid_size = n->out_edges->size;
00810     __edge_valid = EGsMalloc (unsigned char,
00811                               __edge_valid_size);
00812   }
00813   memset (__edge_valid, 0, sizeof (unsigned char) * n->out_edges->size);
00814 
00815   /* iterate through the edges to compute max_weight */
00816   for (edge_valid_it = 0, it = n->out_edges->begin; it;
00817        it = it->next, edge_valid_it++)
00818   {
00819 
00820     /* compute information relevant to this edge */
00821     e = (EGdGraphEdge_t *) (it->this);
00822     cd = (EGcycleData_t *) (e->data);
00823     head = e->head;
00824     head_pid = ((head->id) / 2);
00825 
00826     /* check if the edge is forbidden */
00827     if (cd->ddom && ddom_markers && ddom_markers[cd->ddom->id])
00828       continue;
00829 
00830     /* check if the edge leads to a previously visited node, 
00831      * and if so, check if the number of dominoes visited 
00832      * since then is odd and bigger-than-or-equal to DP_HEUR_MIN_DOM  */
00833     if (marked_node_array[head_pid])
00834     {
00835       rvalue = random ();
00836       rvalue /= EGRAND_MAX;
00837       is_e_dom = (cd->ddom ? 1 : 0);
00838       if (rvalue < DP_HEUR_MORE_DOM_BIAS)
00839         dom_min = 2 + n_marked_dominoes + is_e_dom - odd_num[head_pid];
00840       else
00841         dom_min = n_marked_dominoes + is_e_dom - odd_num[head_pid];
00842       /* check if this edge would give a valid cycle, of so, with some
00843        * probability return this edge, otherwise, discard this edge */
00844       if ((dom_min >= DP_HEUR_MIN_DOM) && (dom_min & 1))
00845       {
00846         rvalue = random ();
00847         rvalue /= EGRAND_MAX;
00848         if (rvalue < DP_HEUR_CLOSE_BIAS)
00849         {
00850           next_e = e;
00851           goto FOUND_EDGE;
00852         }
00853       }
00854       else
00855         continue;
00856     }
00857 
00858     /* we have a feasible edge: update data */
00859     __edge_valid[edge_valid_it] = 1;
00860     num_feasible += 1;
00861     max_weight += cd->pweight;
00862     saved_e = e;
00863   }
00864 
00865   /* check the trivial cases */
00866   if (!num_feasible)
00867     return 0;
00868 
00869   if (num_feasible == 1)
00870   {
00871     next_e = saved_e;
00872     goto FOUND_EDGE;
00873   }
00874 
00875   /* sample a value between 0 and max_weight */
00876   rvalue = random ();
00877   rvalue /= EGRAND_MAX;
00878   rvalue *= max_weight;
00879   rvalue = round (rvalue);
00880   irvalue = (unsigned int) (rvalue);
00881 
00882   /* iterate through the edges to choose the edge */
00883   for (edge_valid_it = 0, it = n->out_edges->begin; it;
00884        it = it->next, edge_valid_it++)
00885   {
00886     /* discard non-valid edges */
00887     if (!__edge_valid[edge_valid_it])
00888       continue;
00889 
00890     /* compute information relevant to this edge */
00891     e = (EGdGraphEdge_t *) (it->this);
00892     current_weight += ((EGcycleData_t *) (e->data))->pweight;
00893     if (current_weight >= irvalue)
00894     {
00895       next_e = e;
00896       break;
00897     }
00898 
00899   }
00900 
00901 FOUND_EDGE:
00902 
00903   /* make sure we found an edge */
00904   ADVTESTL (1, !next_e, 0, "error sampling edge");
00905 
00906   return next_e;
00907 
00908 }
00909 
00910 
00911 /* EGddpAddHeuristicCuts_3
00912  marray:  used to mark which nodes have been traversed by the random walk.
00913  odd_num: used to indicate how many odd edges have been traversed in order 
00914  to get to each node */
00915 int EGddpAddHeuristicCuts_3 (EGddpConstraint_t ** ddpc_array,
00916                              double *const ddpc_dist,
00917                              double *const ddpc_angle_norm,
00918                              double *const *const ddpc_angle,
00919                              unsigned int *const ddpc_size,
00920                              unsigned int const ddpc_max_size,
00921                              double *const ddpc_best_angle,
00922                              double *const ddpc_worst_angle,
00923                              unsigned int *const ddpc_worst_angle_id,
00924                              int const nedges,
00925                              EGdGraphNode_t * start_node,
00926                              EGdGraphEdge_t * start_edge,
00927                              int k,
00928                              double ubound,
00929                              EGdGraph_t * cycleG,
00930                              EGdGraphEdge_t ** dij_sol,
00931                              unsigned int *marray,
00932                              char *sarray,
00933                              unsigned int *odd_num,
00934                              unsigned int nddom,
00935                              int *ddom_markers,
00936                              size_t * os,
00937                              double max_node_time,
00938                              EGmemPool_t * mem)
00939 {
00940 
00941   int rval;
00942   unsigned int stop = 0;
00943 
00944   EGdijkstraCost_t path_val;
00945   unsigned int current_pid,
00946     n_marked_dominoes;
00947 
00948   EGdGraphNode_t *current_node;
00949   EGdGraphEdge_t *current_edge;
00950 
00951   EGdijkstraNodeData_t *node_data;
00952   EGcycleData_t *edge_data;
00953 
00954   EGtimer_t t;
00955 
00956   /* ensure that there is a start node */
00957   if (!start_node)
00958     start_node = start_edge->tail;
00959 
00960   /* if shortest path already exceeds bound, we abort */
00961   if (sarray[(start_node)->id / 2] == 'U')
00962     return 0;
00963 
00964   EGtimerReset (&t);
00965   EGtimerStart (&t);
00966 
00967   while (!stop)
00968   {
00969 
00970     EGtimerStop (&t);
00971 
00972     if (t.time > max_node_time)
00973     {
00974       stop = 1;
00975       break;
00976     }
00977 
00978     EGtimerStart (&t);
00979 
00980     global_cnt += 1;
00981 
00982     /* reset the current path val to zero */
00983     path_val = EGdijkstraToCost (0.0);
00984 
00985     /* set all node markers to zero as we have not visited any yet */
00986     memset (marray, 0, sizeof (unsigned int) * ((cycleG->nodes->size) / 2));
00987 
00988     /* set all ddom_markers to zero */
00989     memset (ddom_markers, 0, sizeof (int) * nddom);
00990 
00991     /* set the number of dominoes traversed to zero */
00992     n_marked_dominoes = 0;
00993 
00994     /* set starting node and pid */
00995     current_node = start_node;
00996     current_pid = (start_node->id) / 2;
00997 
00998     /* mark the current pid */
00999     marray[current_pid] = 1;
01000 
01001     /* set odd-edge counter for current node */
01002     odd_num[current_pid] = n_marked_dominoes;
01003 
01004     /* choose next edge */
01005     if (!start_edge)
01006       current_edge = EGddpHeuristicSample (current_node,
01007                                            marray,
01008                                            n_marked_dominoes,
01009                                            odd_num, ddom_markers, 1);
01010     else
01011       current_edge = start_edge;
01012 
01013     do
01014     {
01015 
01016       /* if there are no edges left to choose from, we abort this path */
01017       if (!current_edge)
01018         break;
01019 
01020       /* update the current position and data structures */
01021       current_node = current_edge->head;
01022       current_pid = (current_node->id) / 2;
01023       node_data = (EGdijkstraNodeData_t *) (current_node->data);
01024       edge_data = (EGcycleData_t *) (current_edge->data);
01025 
01026       /* update dijkstra-node data */
01027       node_data->father = current_edge;
01028 
01029       /* update total path cost (from start_node) */
01030       path_val = EGdijkstraCostAdd (path_val, edge_data->weight);
01031 
01032       /* check if the current edge is a domino (odd) edge */
01033       if (edge_data->ddom)
01034         n_marked_dominoes++;
01035 
01036       /* forbid the edge is necessary */
01037       if (edge_data->ddom && ddom_markers)
01038         ddom_markers[edge_data->ddom->id] = 1;
01039 
01040       /* check if we have detected a cycle */
01041       if (marray[current_pid])
01042       {
01043         /* add the constraint if its not there already */
01044         /* note: this function checks if its violated  */
01045         rval =
01046           EGddpAddCutIfNew (ddpc_array, ddpc_dist, ddpc_angle_norm, ddpc_angle,
01047                             ddpc_size, ddpc_max_size, ddpc_best_angle,
01048                             ddpc_worst_angle, ddpc_worst_angle_id,
01049                             current_node, cycleG, dij_sol, marray, sarray, os,
01050                             1, mem);
01051         CHECKRVAL (rval);
01052         break;
01053       }
01054       /* check that we have not exceeded the bound */
01055       if ((ubound - EGdijkstraCostToLf (path_val)) < DDP_MIN_VIOLATION)
01056         break;
01057       /* mark the current pid */
01058       marray[current_pid] = 1;
01059       /* set odd-edge counter for current node */
01060       odd_num[current_pid] = n_marked_dominoes;
01061       /* choose next edge */
01062       current_edge = EGddpHeuristicSample (current_node, marray,
01063                                            n_marked_dominoes, odd_num,
01064                                            ddom_markers, 1);
01065 
01066     } while (1);
01067   }
01068   return 0;
01069 }
01070 
01071 
01072 
01073 int EGddpcComputeAll (EGmemPool_t * mem,
01074                       EGdGraph_t * bdG,
01075                       EGlist_t * dlist,
01076                       EGlist_t * ddpc_list,
01077                       int const nedges,
01078                       int k)
01079 {
01080   register unsigned int i;
01081   int rval;
01082   size_t os[6];
01083   EGlistNode_t *n_it;
01084   EGdGraph_t *cycleG;
01085   EGdGraphNode_t *nleft,
01086    *nrigh;
01087   EGheap_t *my_heap;
01088 
01089   char *sarray;
01090   EGdijkstraCost_t max_val = EGdijkstraToCost (1 - DP_MAXVIOLATED_EPSILON);
01091   unsigned int *marray,
01092    *odd_num;
01093   double *max_weight;
01094   EGdGraphEdge_t **dij_sol;
01095 
01096   EGddpConstraint_t **ddpc_array;
01097   double *ddpc_dist;
01098   double *ddpc_angle_norm;
01099   double **ddpc_angle;
01100   unsigned int ddpc_size;
01101   unsigned int ddpc_max_size;
01102   double ddpc_best_angle;
01103   double ddpc_worst_angle;
01104   unsigned int ddpc_worst_angle_id;
01105   TEST (k != 1, "k (%d) is not one", k);
01106 
01107 #if DDP_HEURISTIC
01108   EGtimer_t heur_timer;
01109   double max_ntime = 0.0;
01110 #endif
01111 
01112 #if DISPLAY_MODE
01113   fprintf (stdout, "DDPC: Computing dual DP constraints.\n");
01114 #if DDP_HEURISTIC
01115   fprintf (stdout, "DDPC: Random Walk Heuristic: ON. Time Limit = %lf.\n",
01116            DDP_HEURISTIC_MAXTIME);
01117 #endif
01118   fflush (stdout);
01119 #endif
01120 
01121   os[EG_DIJ_DIST] = offsetof (EGdijkstraNodeData_t, dist);
01122   os[EG_DIJ_NDIST] = offsetof (EGdijkstraNodeData_t, ndist);
01123   os[EG_DIJ_FATHER] = offsetof (EGdijkstraNodeData_t, father);
01124   os[EG_DIJ_MARKER] = offsetof (EGdijkstraNodeData_t, marker);
01125   os[EG_DIJ_HCONNECTOR] = offsetof (EGdijkstraNodeData_t, hc);
01126   os[EG_DIJ_ELENGTH] = offsetof (EGcycleData_t, weight);
01127 
01128   cycleG = EGnewCycleGraph (mem, dlist, bdG, max_val);
01129 
01130   fprintf (stdout, "DDPC: Cycle graph has %d nodes and %d edges.\n",
01131            cycleG->nodes->size, cycleG->nedges);
01132 
01133   my_heap = EGnewHeap (mem, 2, cycleG->nodes->size);
01134 
01135   dij_sol = EGmemPoolSMalloc (mem, EGdGraphEdge_t *, cycleG->nedges);
01136   marray = EGmemPoolSMalloc (mem, unsigned int,
01137                              bdG->nodes->size);
01138   sarray = EGmemPoolSMalloc (mem, char,
01139                              bdG->nodes->size);
01140   odd_num = EGmemPoolSMalloc (mem, unsigned int,
01141                               bdG->nodes->size);
01142   max_weight = EGmemPoolSMalloc (mem, double,
01143                                  cycleG->nodes->size);
01144 
01145 #if DDP_HEURISTIC
01146 
01147   /* set max_weight vector */
01148   rval = EGddpSetMaxWeight (cycleG, max_weight);
01149   CHECKRVAL (rval);
01150 
01151   /* set max-time per node */
01152   max_ntime = (DDP_HEURISTIC_MAXTIME / (cycleG->nodes->size / 2));
01153 
01154   /* re-set the heuristic timer */
01155   EGtimerReset (&heur_timer);
01156 
01157 #endif
01158 
01159   ddpc_max_size = DDP_HEURISTIC_MAXCUTS;
01160   ddpc_array = EGmemPoolSMalloc (mem, EGddpConstraint_t *, ddpc_max_size);
01161   ddpc_dist = EGmemPoolSMalloc (mem, double,
01162                                 ddpc_max_size);
01163   ddpc_angle_norm = EGmemPoolSMalloc (mem, double,
01164                                       ddpc_max_size);
01165   ddpc_angle = EGmemPoolSMalloc (mem, double *,
01166                                  ddpc_max_size + 1);
01167   ddpc_angle[ddpc_max_size] = EGmemPoolSMalloc (mem, double,
01168                                                 ddpc_max_size);
01169   for (i = ddpc_max_size; i--;)
01170   {
01171     ddpc_angle[i] = EGmemPoolSMalloc (mem, double,
01172                                       ddpc_max_size);
01173     ddpc_angle[i][i] = 1.0;
01174   }
01175   ddpc_size = 0;
01176 
01177 
01178   for (n_it = cycleG->nodes->begin; n_it; n_it = ((n_it->next)->next))
01179   {
01180 
01181     TEST (!(n_it->next), "cycle graph badly defined");
01182 
01183     nleft = (EGdGraphNode_t *) (n_it->this);
01184     nrigh = (EGdGraphNode_t *) (n_it->next->this);
01185 
01186     /* default: bad (exceeds the bound) */
01187     sarray[(nleft->id) / 2] = 'B';
01188 
01189     rval =
01190       EGpartialDijkstra (nleft, nrigh, EGdijkstraToCost (((double) 1.0)), os,
01191                          my_heap, cycleG);
01192     CHECKRVAL (rval);
01193 
01194     if (EGdijkstraGetMarker (nrigh, os) == UINT_MAX)
01195       continue;
01196 
01197     if ((1.0 - EGdijkstraCostToLf (EGdijkstraGetDist (nrigh, os))) <
01198         (DDP_MIN_VIOLATION))
01199       continue;
01200 
01201     rval =
01202       EGddpAddCutIfNew (ddpc_array, ddpc_dist, ddpc_angle_norm, ddpc_angle,
01203                         &ddpc_size, ddpc_max_size, &ddpc_best_angle,
01204                         &ddpc_worst_angle, &ddpc_worst_angle_id, nrigh,
01205                         cycleG, dij_sol, marray, sarray, os, 1, mem);
01206     CHECKRVAL (rval);
01207 
01208 #if DDP_HEURISTIC
01209     EGtimerStart (&heur_timer);
01210     rval = EGddpAddHeuristicCuts_3 (ddpc_array, ddpc_dist, ddpc_angle_norm,
01211                                     ddpc_angle, &ddpc_size, ddpc_max_size,
01212                                     &ddpc_best_angle, &ddpc_worst_angle,
01213                                     &ddpc_worst_angle_id, nedges, nleft, 0, 1,
01214                                     1.0, cycleG, dij_sol, marray, sarray,
01215                                     odd_num, 0, 0, os, max_ntime, mem);
01216     CHECKRVAL (rval);
01217     EGtimerStop (&heur_timer);
01218 
01219 #endif
01220 
01221   }
01222 
01223   /* pass the constraints from the heap to the list */
01224   fprintf (stderr, "***Heuristic Iterations: %llu\n", global_cnt);
01225 
01226   for (i = ddpc_size; i--;)
01227     EGlistPushBack (ddpc_list, ddpc_array[i]);
01228 
01229 #if DISPLAY_MODE
01230   {
01231     EGddpConstraint_t *ddpc;
01232     double abs_slack,
01233       thresh,
01234       thresh_n;
01235     unsigned int range[DISPLAY_RESOLUTION],
01236       error = 0,
01237       maximally_violated = 0;
01238     double avg_teeth = 0.0;
01239 
01240     for (i = 0; i < DISPLAY_RESOLUTION; i++)
01241       range[i] = 0;
01242 
01243     for (n_it = ddpc_list->begin; n_it; n_it = n_it->next)
01244     {
01245       ddpc = (EGddpConstraint_t *) (n_it->this);
01246       avg_teeth += ddpc->ndom;
01247       for (i = 0; i < DISPLAY_RESOLUTION; i++)
01248       {
01249         abs_slack = -1 * ddpc->slack_dp;
01250         thresh = 1 * (IDR) * i + 1 * (IDR);
01251         thresh_n = 1 * IDR * i;
01252         if (thresh_n <= abs_slack && abs_slack <= thresh)
01253         {
01254           range[i] += 1;
01255           break;
01256         }
01257       }
01258 
01259       if (i == DISPLAY_RESOLUTION)
01260         error += 1;
01261 
01262       if (-1 * ddpc->slack_dp > (1.0) - DDPCONSTRAINT_MAXVIOL_EPSILON)
01263         maximally_violated += 1;
01264 
01265     }
01266     avg_teeth = avg_teeth / ((double) ddpc_list->size);
01267 #if DDP_HEURISTIC
01268     fprintf (stdout, "DDPC: Total heuristic running time: %lf seconds.\n",
01269              heur_timer.time);
01270 #endif
01271     fprintf (stdout,
01272              "DDPC: Found %u dual DP-Constraints (avg number of teeth = %lf).\n",
01273              ddpc_list->size, avg_teeth);
01274     fprintf (stdout, "DDPC:    %u / %u are maximally violated.\n",
01275              maximally_violated, ddpc_list->size);
01276     fflush (stdout);
01277 
01278     fprintf (stdout, "DDPC: |slack values|\n");
01279     fflush (stdout);
01280 
01281     for (i = 0; i < DISPLAY_RESOLUTION; i++)
01282     {
01283       thresh = 1 * IDR * i + IDR * 1;
01284       thresh_n = 1 * IDR * i;
01285       if (range[i])
01286         fprintf (stdout, "[%8lf, %8lf]   %d\n", thresh_n, thresh, range[i]);
01287       fflush (stdout);
01288     }
01289     if (error)
01290       fprintf (stdout, "[%8lf,         )   %d    (out of range constraints)\n",
01291                1.0, error);
01292   }
01293 #endif
01294 
01295 #if DISPLAY_MODE
01296   fprintf (stdout, "DDPC: Finished finding dual DP cuts.\n");
01297   fflush (stdout);
01298 #endif
01299 
01300   //EGfreeHeap (ddpc_heap, cycleG->mem);
01301   EGmemPoolSFree (ddpc_array, EGddpConstraint_t *, ddpc_max_size, mem);
01302   EGmemPoolSFree (ddpc_dist, double,
01303                   ddpc_max_size,
01304                   mem);
01305   EGmemPoolSFree (ddpc_angle_norm, double,
01306                   ddpc_max_size,
01307                   mem);
01308   for (i = ddpc_max_size + 1; i--;)
01309     EGmemPoolSFree (ddpc_angle[i], double,
01310                     ddpc_max_size,
01311                     mem);
01312   EGmemPoolSFree (ddpc_angle, double *,
01313                   ddpc_max_size + 1,
01314                   mem);
01315 
01316   EGmemPoolSFree (max_weight, double,
01317                   cycleG->nodes->size,
01318                   mem);
01319   EGmemPoolSFree (odd_num, unsigned int,
01320                   bdG->nodes->size,
01321                   mem);
01322   EGmemPoolSFree (marray, unsigned int,
01323                   bdG->nodes->size,
01324                   mem);
01325   EGmemPoolSFree (sarray, char,
01326                   bdG->nodes->size,
01327                   mem);
01328   EGmemPoolSFree (dij_sol, EGdGraphEdge_t *, cycleG->nedges, mem);
01329 
01330   EGfreeHeap (my_heap, mem);
01331   EGdGraphClearMP (cycleG, EGfreeCycleDataMP, EGfreeDijkstraNodeDataMP, 0, mem,
01332                    mem, 0);
01333   EGfreeDGraph (cycleG);
01334 
01335 
01336   return 0;
01337 }
01338 
01339 /* t = end node of the path, ddom_markers is work-array size of the number of
01340  * ddom. Checks if a ddom is used twice in the path. */
01341 int EGddpIsSolutionValid (EGdGraphNode_t * t,
01342                           int *ddom_markers,
01343                           unsigned int num_ddom)
01344 {
01345 
01346   EGdGraphEdge_t *e;
01347   EGdGraphNode_t *n;
01348   EGdijkstraNodeData_t *dndata;
01349   EGcycleData_t *cdata;
01350 
01351   unsigned int pos;
01352 
01353   memset (ddom_markers, 0, sizeof (int) * (num_ddom));
01354 
01355   n = t;
01356   pos = 0;
01357 
01358   while (((n->id) / 2 != (t->id) / 2) || !pos)
01359   {
01360     dndata = (EGdijkstraNodeData_t *) (n->data);
01361     e = dndata->father;
01362     cdata = (EGcycleData_t *) (e->data);
01363 
01364     if (cdata->ddom)
01365     {
01366       if (ddom_markers[cdata->ddom->id])
01367         return 0;
01368       else
01369         ddom_markers[cdata->ddom->id] += 1;
01370     }
01371 
01372     n = e->tail;
01373 
01374     pos += 1;
01375   }
01376 
01377   return 1;
01378 
01379 }
01380 
01381 
01382 int EGddpSetMaxWeight (EGdGraph_t * cycleG,
01383                        double *max_weight)
01384 {
01385 
01386   EGdGraphEdge_t *e;
01387   EGdGraphNode_t *n;
01388   EGlistNode_t *e_it,
01389    *n_it;
01390   EGcycleData_t *cd;
01391   double val;
01392 
01393   for (n_it = cycleG->nodes->begin; n_it; n_it = n_it->next)
01394   {
01395 
01396     n = (EGdGraphNode_t *) (n_it->this);
01397     val = 0.0;
01398 
01399     for (e_it = n->out_edges->begin; e_it; e_it = e_it->next)
01400     {
01401 
01402       e = (EGdGraphEdge_t *) (e_it->this);
01403       cd = (EGcycleData_t *) (e->data);
01404 
01405       val += cd->pweight;
01406 
01407     }
01408 
01409     max_weight[(n->id)] = val;
01410 
01411   }
01412 
01413   return 0;
01414 
01415 }
01416 
01417 void EGddpcDisplay (EGddpConstraint_t * ddpc,
01418                     FILE * file)
01419 {
01420 
01421   unsigned int i;
01422 
01423   fprintf (stderr, "F     [%u]: ", ddpc->nF);
01424   for (i = 0; i < ddpc->nF; i++)
01425     EGmengerDisplayEdgeBasic (ddpc->F[i], file);
01426   fprintf (stderr, "\n");
01427 
01428   fprintf (stderr, "ddom  [%u]: ", ddpc->ndom);
01429   for (i = 0; i < ddpc->ndom; i++)
01430     fprintf (stderr, "%d (1)(%lf) ", ddpc->ddom[i]->id,
01431              EGdijkstraCostToLf (ddpc->ddom[i]->value));
01432   fprintf (stderr, "\n");
01433 
01434   return;
01435 
01436 }

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