/misc/src/release/graphviz-2.18-1/src/graphviz-2.18/lib/neatogen/quad_prog_vpsc.c

Go to the documentation of this file.
00001 /* $Id: quad_prog_vpsc.c,v 1.5 2007/08/16 18:10:13 erg Exp $ $Revision: 1.5 $ */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00020 /**********************************************************
00021  *
00022  * Solve a quadratic function f(X) = X' e->A X + b X
00023  * subject to a set of separation constraints e->cs
00024  *
00025  * Tim Dwyer, 2006
00026  **********************************************************/
00027 
00028 #include "digcola.h"
00029 #ifdef IPSEPCOLA
00030 #include <math.h>
00031 #include <stdlib.h>
00032 #include <time.h>
00033 #include <stdio.h>
00034 #include <float.h>
00035 #include <assert.h>
00036 #include "matrix_ops.h"
00037 #include "kkutils.h"
00038 #include <csolve_VPSC.h>
00039 #include "quad_prog_vpsc.h"
00040 #include "quad_prog_solver.h"
00041 
00042 /* #define CONMAJ_LOGGING 1 */
00043 #define quad_prog_tol 1e-4
00044 
00045 /*
00046  * Use gradient-projection to solve Variable Placement with Separation Constraints problem.
00047  */
00048 int
00049 constrained_majorization_vpsc(CMajEnvVPSC * e, float *b, float *place,
00050                               int max_iterations)
00051 {
00052     int i, j, counter;
00053     float *g, *old_place, *d;
00054     /* for laplacian computation need number of real vars and those
00055      * dummy vars included in lap
00056      */
00057     int n = e->nv + e->nldv;
00058     boolean converged = FALSE;
00059 #ifdef CONMAJ_LOGGING
00060     static int call_no = 0;
00061 #endif                          /* CONMAJ_LOGGING */
00062 
00063     if (max_iterations == 0)
00064         return 0;
00065     g = e->fArray1;
00066     old_place = e->fArray2;
00067     d = e->fArray3;
00068     /* fprintf(stderr,"Entered: constrained_majorization_vpsc, #constraints=%d\n",e->m); */
00069     if (e->m > 0) {
00070         for (i = 0; i < n; i++) {
00071             setVariableDesiredPos(e->vs[i], place[i]);
00072         }
00073         /* fprintf(stderr,"  calling satisfyVPSC...\n"); */
00074         satisfyVPSC(e->vpsc);
00075         for (i = 0; i < n; i++) {
00076             place[i] = getVariablePos(e->vs[i]);
00077             /* fprintf(stderr,"vs[%d]=%f\n",i,place[i]); */
00078         }
00079         /* fprintf(stderr,"    done.\n"); */
00080     }
00081 #ifdef CONMAJ_LOGGING
00082     float prev_stress = 0;
00083     for (i = 0; i < n; i++) {
00084         prev_stress += 2 * b[i] * place[i];
00085         for (j = 0; j < n; j++) {
00086             prev_stress -= e->A[i][j] * place[j] * place[i];
00087         }
00088     }
00089     FILE *logfile = fopen("constrained_majorization_log", "a");
00090 
00091     /* fprintf(logfile,"grad proj %d: stress=%f\n",call_no,prev_stress); */
00092 #endif
00093 
00094     for (counter = 0; counter < max_iterations && !converged; counter++) {
00095         float test = 0;
00096         float alpha, beta;
00097         float numerator = 0, denominator = 0, r;
00098         /* fprintf(stderr,"."); */
00099         converged = TRUE;
00100         /* find steepest descent direction */
00101         for (i = 0; i < n; i++) {
00102             old_place[i] = place[i];
00103             g[i] = 2 * b[i];
00104             for (j = 0; j < n; j++) {
00105                 g[i] -= 2 * e->A[i][j] * place[j];
00106             }
00107         }
00108         for (i = 0; i < n; i++) {
00109             numerator += g[i] * g[i];
00110             r = 0;
00111             for (j = 0; j < n; j++) {
00112                 r += 2 * e->A[i][j] * g[j];
00113             }
00114             denominator -= r * g[i];
00115         }
00116         alpha = numerator / denominator;
00117         for (i = 0; i < n; i++) {
00118             place[i] -= alpha * g[i];
00119         }
00120         if (e->m > 0) {
00121             /* project to constraint boundary */
00122             for (i = 0; i < n; i++) {
00123                 setVariableDesiredPos(e->vs[i], place[i]);
00124             }
00125             satisfyVPSC(e->vpsc);
00126             for (i = 0; i < n; i++) {
00127                 place[i] = getVariablePos(e->vs[i]);
00128             }
00129         }
00130         /* set place to the intersection of old_place-g and boundary and 
00131          * compute d, the vector from intersection pnt to projection pnt
00132          */
00133         for (i = 0; i < n; i++) {
00134             d[i] = place[i] - old_place[i];
00135         }
00136         /* now compute beta */
00137         numerator = 0, denominator = 0;
00138         for (i = 0; i < n; i++) {
00139             numerator += g[i] * d[i];
00140             r = 0;
00141             for (j = 0; j < n; j++) {
00142                 r += 2 * e->A[i][j] * d[j];
00143             }
00144             denominator += r * d[i];
00145         }
00146         beta = numerator / denominator;
00147 
00148         for (i = 0; i < n; i++) {
00149             /* beta > 1.0 takes us back outside the feasible region
00150              * beta < 0 clearly not useful and may happen due to numerical imp.
00151              */
00152             if (beta > 0 && beta < 1.0) {
00153                 place[i] = old_place[i] + beta * d[i];
00154             }
00155             test += fabs(place[i] - old_place[i]);
00156         }
00157 #ifdef CONMAJ_LOGGING
00158         float stress = 0;
00159         for (i = 0; i < n; i++) {
00160             stress += 2 * b[i] * place[i];
00161             for (j = 0; j < n; j++) {
00162                 stress -= e->A[i][j] * place[j] * place[i];
00163             }
00164         }
00165         fprintf(logfile, "%d: stress=%f, test=%f, %s\n", call_no, stress,
00166                 test, (stress >= prev_stress) ? "No Improvement" : "");
00167         prev_stress = stress;
00168 #endif
00169         if (test > quad_prog_tol) {
00170             converged = FALSE;
00171         }
00172     }
00173 #ifdef CONMAJ_LOGGING
00174     call_no++;
00175     fclose(logfile);
00176 #endif
00177     return counter;
00178 }
00179 
00180 /*
00181  * Set up environment and global constraints (dir-edge constraints, containment constraints
00182  * etc).
00183  *
00184  * diredges: 0=no dir edge constraints
00185  *           1=one separation constraint for each edge (in acyclic subgraph)
00186  *           2=DiG-CoLa level constraints
00187  */
00188 CMajEnvVPSC *initCMajVPSC(int n, float *packedMat, vtx_data * graph,
00189                           ipsep_options * opt, int diredges)
00190 {
00191     int i, j;
00192     /* nv is the number of real nodes */
00193     int nConCs;
00194     /* fprintf(stderr,"Entered initCMajVPSC\n"); */
00195     CMajEnvVPSC *e = GNEW(CMajEnvVPSC);
00196     e->A = NULL;
00197     e->packedMat = packedMat;
00198     /* if we have clusters then we'll need two constraints for each var in
00199      * a cluster */
00200     e->nldv = 2 * opt->clusters->nclusters;
00201     e->nv = n - e->nldv;
00202     e->ndv = 0;
00203 
00204     e->gcs = NULL;
00205     e->vs = N_GNEW(n, Variable *);
00206     for (i = 0; i < n; i++) {
00207         e->vs[i] = newVariable(i, 1.0, 1.0);
00208     }
00209     e->gm = 0;
00210     if (diredges == 1) {
00211         if (Verbose)
00212             fprintf(stderr, "  generate edge constraints...\n");
00213         for (i = 0; i < e->nv; i++) {
00214             for (j = 1; j < graph[i].nedges; j++) {
00215                 /* fprintf(stderr,"edist=%f\n",graph[i].edists[j]); */
00216                 if (graph[i].edists[j] > 0.01) {
00217                     e->gm++;
00218                 }
00219             }
00220         }
00221         e->gcs = newConstraints(e->gm);
00222         e->gm = 0;
00223         for (i = 0; i < e->nv; i++) {
00224             for (j = 1; j < graph[i].nedges; j++) {
00225                 int u = i, v = graph[i].edges[j];
00226                 if (graph[i].edists[j] > 0) {
00227                     e->gcs[e->gm++] =
00228                         newConstraint(e->vs[u], e->vs[v], opt->edge_gap);
00229                 }
00230             }
00231         }
00232     } else if (diredges == 2) {
00233         int *ordering = NULL, *ls = NULL, cvar;
00234         double halfgap;
00235         DigColaLevel *levels;
00236         Variable **vs = e->vs;
00237         /* e->ndv is the number of dummy variables required, one for each boundary */
00238         compute_hierarchy(graph, n, 1e-2, 1e-1, NULL, &ordering, &ls,
00239                           &e->ndv);
00240         levels = assign_digcola_levels(ordering, n, ls, e->ndv);
00241         if (Verbose)
00242             fprintf(stderr, "Found %d DiG-CoLa boundaries\n", e->ndv);
00243         e->gm =
00244             get_num_digcola_constraints(levels, e->ndv + 1) + e->ndv - 1;
00245         e->gcs = newConstraints(e->gm);
00246         e->gm = 0;
00247         e->vs = N_GNEW(n + e->ndv, Variable *);
00248         for (i = 0; i < n; i++) {
00249             e->vs[i] = vs[i];
00250         }
00251         free(vs);
00252         /* create dummy vars */
00253         for (i = 0; i < e->ndv; i++) {
00254             /* dummy vars should have 0 weight */
00255             cvar = n + i;
00256             e->vs[cvar] = newVariable(cvar, 1.0, 0.000001);
00257         }
00258         halfgap = opt->edge_gap;
00259         for (i = 0; i < e->ndv; i++) {
00260             cvar = n + i;
00261             /* outgoing constraints for each var in level below boundary */
00262             for (j = 0; j < levels[i].num_nodes; j++) {
00263                 e->gcs[e->gm++] =
00264                     newConstraint(e->vs[levels[i].nodes[j]], e->vs[cvar],
00265                                   halfgap);
00266             }
00267             /* incoming constraints for each var in level above boundary */
00268             for (j = 0; j < levels[i + 1].num_nodes; j++) {
00269                 e->gcs[e->gm++] =
00270                     newConstraint(e->vs[cvar],
00271                                   e->vs[levels[i + 1].nodes[j]], halfgap);
00272             }
00273         }
00274         /* constraints between adjacent boundary dummy vars */
00275         for (i = 0; i < e->ndv - 1; i++) {
00276             e->gcs[e->gm++] =
00277                 newConstraint(e->vs[n + i], e->vs[n + i + 1], 0);
00278         }
00279     }
00280     /* fprintf(stderr,"  generate edge constraints... done: n=%d,m=%d\n",e->n,e->gm); */
00281     if (opt->clusters->nclusters > 0) {
00282         /* fprintf(stderr,"  generate cluster containment constraints...\n"); */
00283         Constraint **ecs = e->gcs;
00284         nConCs = 2 * opt->clusters->nvars;
00285         e->gcs = newConstraints(e->gm + nConCs);
00286         for (i = 0; i < e->gm; i++) {
00287             e->gcs[i] = ecs[i];
00288         }
00289         if (ecs != NULL)
00290             deleteConstraints(0, ecs);
00291         for (i = 0; i < opt->clusters->nclusters; i++) {
00292             for (j = 0; j < opt->clusters->clustersizes[i]; j++) {
00293                 Variable *v = e->vs[opt->clusters->clusters[i][j]];
00294                 Variable *cl = e->vs[e->nv + 2 * i];
00295                 Variable *cr = e->vs[e->nv + 2 * i + 1];
00296                 e->gcs[e->gm++] = newConstraint(cl, v, 0);
00297                 e->gcs[e->gm++] = newConstraint(v, cr, 0);
00298             }
00299         }
00300         /* fprintf(stderr,"  containment constraints... done: \n"); */
00301     }
00302 
00303     e->m = 0;
00304     e->cs = NULL;
00305     if (e->gm > 0) {
00306         e->vpsc = newIncVPSC(n + e->ndv, e->vs, e->gm, e->gcs);
00307         e->m = e->gm;
00308         e->cs = e->gcs;
00309     }
00310     if (packedMat != NULL) {
00311         e->A = unpackMatrix(packedMat, n);
00312     }
00313 #ifdef MOSEK
00314     e->mosekEnv = NULL;
00315     if (opt->mosek) {
00316         e->mosekEnv =
00317             mosek_init_sep(e->packedMat, n, e->ndv, e->gcs, e->gm);
00318     }
00319 #endif
00320 
00321     e->fArray1 = N_GNEW(n, float);
00322     e->fArray2 = N_GNEW(n, float);
00323     e->fArray3 = N_GNEW(n, float);
00324     if (Verbose)
00325         fprintf(stderr,
00326                 "  initCMajVPSC done: %d global constraints generated.\n",
00327                 e->m);
00328     return e;
00329 }
00330 
00331 void deleteCMajEnvVPSC(CMajEnvVPSC * e)
00332 {
00333     int i;
00334     if (e->A != NULL) {
00335         free(e->A[0]);
00336         free(e->A);
00337     }
00338     if (e->m > 0) {
00339         deleteVPSC(e->vpsc);
00340         if (e->cs != e->gcs && e->gcs != NULL)
00341             deleteConstraints(0, e->gcs);
00342         deleteConstraints(e->m, e->cs);
00343         for (i = 0; i < e->nv + e->nldv + e->ndv; i++) {
00344             deleteVariable(e->vs[i]);
00345         }
00346         free(e->vs);
00347     }
00348     free(e->fArray1);
00349     free(e->fArray2);
00350     free(e->fArray3);
00351 #ifdef MOSEK
00352     if (e->mosekEnv) {
00353         mosek_delete(e->mosekEnv);
00354     }
00355 #endif                          /* MOSEK */
00356     free(e);
00357 }
00358 
00359 /* generate non-overlap constraints inside each cluster, including dummy
00360  * nodes at bounds of cluster
00361  * generate constraints again for top level nodes and clusters treating
00362  * clusters as rectangles of dim (l,r,b,t)
00363  * for each cluster map in-constraints to l out-constraints to r 
00364  *
00365  * For now, we'll keep the global containment constraints already
00366  * generated for each cluster, and simply generate non-overlap constraints
00367  * for all nodes and then an additional set of non-overlap constraints for
00368  * clusters that we'll map back to the dummy vars as above.
00369  */
00370 void generateNonoverlapConstraints(CMajEnvVPSC * e,
00371                                    float nsizeScale,
00372                                    float **coords,
00373                                    int k,
00374                                    boolean transitiveClosure,
00375                                    ipsep_options * opt)
00376 {
00377     Constraint **csol, **csolptr;
00378     int i, j, mol = 0;
00379     int n = e->nv + e->nldv;
00380 #ifdef WIN32
00381     boxf* bb = N_GNEW (n, boxf);
00382 #else
00383     boxf bb[n];
00384 #endif
00385     boolean genclusters = opt->clusters->nclusters > 0;
00386     if (genclusters) {
00387         /* n is the number of real variables, not dummy cluster vars */
00388         n -= 2 * opt->clusters->nclusters;
00389     }
00390     if (k == 0) {
00391         /* grow a bit in the x dimension, so that if overlap is resolved
00392          * horizontally then it won't be considered overlapping vertically
00393          */
00394         nsizeScale *= 1.0001;
00395     }
00396     for (i = 0; i < n; i++) {
00397         bb[i].LL.x =
00398             coords[0][i] - nsizeScale * opt->nsize[i].x / 2.0 -
00399             opt->gap.x / 2.0;
00400         bb[i].UR.x =
00401             coords[0][i] + nsizeScale * opt->nsize[i].x / 2.0 +
00402             opt->gap.x / 2.0;
00403         bb[i].LL.y =
00404             coords[1][i] - nsizeScale * opt->nsize[i].y / 2.0 -
00405             opt->gap.y / 2.0;
00406         bb[i].UR.y =
00407             coords[1][i] + nsizeScale * opt->nsize[i].y / 2.0 +
00408             opt->gap.y / 2.0;
00409     }
00410     if (genclusters) {
00411 #ifdef WIN32
00412         Constraint ***cscl = N_GNEW(opt->clusters->nclusters + 1, Constraint**);
00413         int* cm = N_GNEW(opt->clusters->nclusters + 1, int);
00414 #else
00415         Constraint **cscl[opt->clusters->nclusters + 1];
00416         int cm[opt->clusters->nclusters + 1];
00417 #endif
00418         for (i = 0; i < opt->clusters->nclusters; i++) {
00419             int cn = opt->clusters->clustersizes[i];
00420 #ifdef WIN32
00421             Variable** cvs = N_GNEW(cn + 2, Variable*);
00422             boxf* cbb = N_GNEW(cn + 2, boxf);
00423 #else
00424             Variable *cvs[cn + 2];
00425             boxf cbb[cn + 2];
00426 #endif
00427             /* compute cluster bounding bb */
00428             boxf container;
00429             container.LL.x = container.LL.y = DBL_MAX;
00430             container.UR.x = container.UR.y = -DBL_MAX;
00431             for (j = 0; j < cn; j++) {
00432                 int iv = opt->clusters->clusters[i][j];
00433                 cvs[j] = e->vs[iv];
00434                 B2BF(bb[iv], cbb[j]);
00435                 EXPANDBB(container, bb[iv]);
00436             }
00437             B2BF(container, opt->clusters->bb[i]);
00438             cvs[cn] = e->vs[n + 2 * i];
00439             cvs[cn + 1] = e->vs[n + 2 * i + 1];
00440             B2BF(container, cbb[cn]);
00441             B2BF(container, cbb[cn + 1]);
00442             if (k == 0) {
00443                 cbb[cn].UR.x = container.LL.x + 0.0001;
00444                 cbb[cn + 1].LL.x = container.UR.x - 0.0001;
00445                 cm[i] =
00446                     genXConstraints(cn + 2, cbb, cvs, &cscl[i],
00447                                     transitiveClosure);
00448             } else {
00449                 cbb[cn].UR.y = container.LL.y + 0.0001;
00450                 cbb[cn + 1].LL.y = container.UR.y - 0.0001;
00451                 cm[i] = genYConstraints(cn + 2, cbb, cvs, &cscl[i]);
00452             }
00453             mol += cm[i];
00454 #ifdef WIN32
00455             free (cvs);
00456             free (cbb);
00457 #endif
00458         }
00459         /* generate top level constraints */
00460         {
00461             int cn = opt->clusters->ntoplevel + opt->clusters->nclusters;
00462 #ifdef WIN32
00463             Variable** cvs = N_GNEW(cn,Variable*);
00464             boxf* cbb = N_GNEW(cn, boxf);
00465 #else
00466             Variable *cvs[cn];
00467             boxf cbb[cn];
00468 #endif
00469             for (i = 0; i < opt->clusters->ntoplevel; i++) {
00470                 int iv = opt->clusters->toplevel[i];
00471                 cvs[i] = e->vs[iv];
00472                 B2BF(bb[iv], cbb[i]);
00473             }
00474             /* make dummy variables for clusters */
00475             for (i = opt->clusters->ntoplevel; i < cn; i++) {
00476                 cvs[i] = newVariable(123 + i, 1, 1);
00477                 j = i - opt->clusters->ntoplevel;
00478                 B2BF(opt->clusters->bb[j], cbb[i]);
00479             }
00480             i = opt->clusters->nclusters;
00481             if (k == 0) {
00482                 cm[i] =
00483                     genXConstraints(cn, cbb, cvs, &cscl[i],
00484                                     transitiveClosure);
00485             } else {
00486                 cm[i] = genYConstraints(cn, cbb, cvs, &cscl[i]);
00487             }
00488             /* remap constraints from tmp dummy vars to cluster l and r vars */
00489             for (i = opt->clusters->ntoplevel; i < cn; i++) {
00490                 double dgap;
00491                 j = i - opt->clusters->ntoplevel;
00492                 /* dgap is the change in required constraint gap.
00493                  * since we are going from a source rectangle the size
00494                  * of the cluster bounding box to a zero width (in x dim,
00495                  * zero height in y dim) rectangle, the change will be
00496                  * half the bb width.
00497                  */
00498                 if (k == 0) {
00499                     dgap = -(cbb[i].UR.x - cbb[i].LL.x) / 2.0;
00500                 } else {
00501                     dgap = -(cbb[i].UR.y - cbb[i].LL.y) / 2.0;
00502                 }
00503                 remapInConstraints(cvs[i], e->vs[n + 2 * j], dgap);
00504                 remapOutConstraints(cvs[i], e->vs[n + 2 * j + 1], dgap);
00505                 /* there may be problems with cycles between
00506                  * cluster non-overlap and diredge constraints,
00507                  * to resolve:
00508                  * 
00509                  * for each constraint c:v->cvs[i]:
00510                  *   if exists diredge constraint u->v where u in c:
00511                  *     remap v->cl to cr->v (gap = height(v)/2)
00512                  *
00513                  * in = getInConstraints(cvs[i])
00514                  * for(c : in) {
00515                  *   assert(c.right==cvs[i]);
00516                  *   vin = getOutConstraints(v=c.left)
00517                  *   for(d : vin) {
00518                  *     if(d.left.cluster==i):
00519                  *       tmp = d.left
00520                  *       d.left = d.right
00521                  *       d.right = tmp
00522                  *       d.gap = height(d.right)/2
00523                  *   }
00524                  * }
00525                  *       
00526                  */
00527                 deleteVariable(cvs[i]);
00528             }
00529             mol += cm[opt->clusters->nclusters];
00530 #ifdef WIN32
00531             free (cvs);
00532             free (cbb);
00533 #endif
00534         }
00535         csolptr = csol = newConstraints(mol);
00536         for (i = 0; i < opt->clusters->nclusters + 1; i++) {
00537             /* copy constraints into csol */
00538             for (j = 0; j < cm[i]; j++) {
00539                 *csolptr++ = cscl[i][j];
00540             }
00541             deleteConstraints(0, cscl[i]);
00542         }
00543 #ifdef WIN32
00544         free (cscl);
00545         free (cm);
00546 #endif
00547     } else {
00548         if (k == 0) {
00549             mol = genXConstraints(n, bb, e->vs, &csol, transitiveClosure);
00550         } else {
00551             mol = genYConstraints(n, bb, e->vs, &csol);
00552         }
00553     }
00554     /* remove constraints from previous iteration */
00555     if (e->m > 0) {
00556         /* can't reuse instance of VPSC when constraints change! */
00557         deleteVPSC(e->vpsc);
00558         for (i = e->gm == 0 ? 0 : e->gm; i < e->m; i++) {
00559             /* delete previous overlap constraints */
00560             deleteConstraint(e->cs[i]);
00561         }
00562         /* just delete the array, not the elements */
00563         if (e->cs != e->gcs)
00564             deleteConstraints(0, e->cs);
00565     }
00566     /* if we have no global constraints then the overlap constraints
00567      * are all we have to worry about.
00568      * Otherwise, we have to copy the global and overlap constraints 
00569      * into the one array
00570      */
00571     if (e->gm == 0) {
00572         e->m = mol;
00573         e->cs = csol;
00574     } else {
00575         e->m = mol + e->gm;
00576         e->cs = newConstraints(e->m);
00577         for (i = 0; i < e->m; i++) {
00578             if (i < e->gm) {
00579                 e->cs[i] = e->gcs[i];
00580             } else {
00581                 e->cs[i] = csol[i - e->gm];
00582             }
00583         }
00584         /* just delete the array, not the elements */
00585         deleteConstraints(0, csol);
00586     }
00587     if (Verbose)
00588         fprintf(stderr, "  generated %d constraints\n", e->m);
00589     e->vpsc = newIncVPSC(e->nv + e->nldv + e->ndv, e->vs, e->m, e->cs);
00590 #ifdef MOSEK
00591     if (opt->mosek) {
00592         if (e->mosekEnv != NULL) {
00593             mosek_delete(e->mosekEnv);
00594         }
00595         e->mosekEnv =
00596             mosek_init_sep(e->packedMat, e->nv + e->nldv, e->ndv, e->cs,
00597                            e->m);
00598     }
00599 #endif
00600 #ifdef WIN32
00601     free (bb);
00602 #endif
00603 }
00604 
00605 /*
00606  * Statically remove overlaps, that is remove all overlaps by moving each node as
00607  * little as possible.
00608  */
00609 void removeoverlaps(int n, float **coords, ipsep_options * opt)
00610 {
00611     int i;
00612     CMajEnvVPSC *e = initCMajVPSC(n, NULL, NULL, opt, 0);
00613     generateNonoverlapConstraints(e, 1.0, coords, 0, TRUE, opt);
00614     solveVPSC(e->vpsc);
00615     for (i = 0; i < n; i++) {
00616         coords[0][i] = getVariablePos(e->vs[i]);
00617     }
00618     generateNonoverlapConstraints(e, 1.0, coords, 1, FALSE, opt);
00619     solveVPSC(e->vpsc);
00620     for (i = 0; i < n; i++) {
00621         coords[1][i] = getVariablePos(e->vs[i]);
00622     }
00623     deleteCMajEnvVPSC(e);
00624 }
00625 
00626 /*
00627  unpack the "ordering" array into an array of DigColaLevel
00628 */
00629 DigColaLevel *assign_digcola_levels(int *ordering, int n, int *level_inds,
00630                                     int num_divisions)
00631 {
00632     int i, j;
00633     DigColaLevel *l = N_GNEW(num_divisions + 1, DigColaLevel);
00634     /* first level */
00635     l[0].num_nodes = level_inds[0];
00636     l[0].nodes = N_GNEW(l[0].num_nodes, int);
00637     for (i = 0; i < l[0].num_nodes; i++) {
00638         l[0].nodes[i] = ordering[i];
00639     }
00640     /* second through second last level */
00641     for (i = 1; i < num_divisions; i++) {
00642         l[i].num_nodes = level_inds[i] - level_inds[i - 1];
00643         l[i].nodes = N_GNEW(l[i].num_nodes, int);
00644         for (j = 0; j < l[i].num_nodes; j++) {
00645             l[i].nodes[j] = ordering[level_inds[i - 1] + j];
00646         }
00647     }
00648     /* last level */
00649     if (num_divisions > 0) {
00650         l[num_divisions].num_nodes = n - level_inds[num_divisions - 1];
00651         l[num_divisions].nodes = N_GNEW(l[num_divisions].num_nodes, int);
00652         for (i = 0; i < l[num_divisions].num_nodes; i++) {
00653             l[num_divisions].nodes[i] =
00654                 ordering[level_inds[num_divisions - 1] + i];
00655         }
00656     }
00657     return l;
00658 }
00659 void delete_digcola_levels(DigColaLevel * l, int num_levels)
00660 {
00661     int i;
00662     for (i = 0; i < num_levels; i++) {
00663         free(l[i].nodes);
00664     }
00665     free(l);
00666 }
00667 void print_digcola_levels(FILE * logfile, DigColaLevel * levels,
00668                           int num_levels)
00669 {
00670     int i, j;
00671     fprintf(logfile, "levels:\n");
00672     for (i = 0; i < num_levels; i++) {
00673         fprintf(logfile, "  l[%d]:", i);
00674         for (j = 0; j < levels[i].num_nodes; j++) {
00675             fprintf(logfile, "%d ", levels[i].nodes[j]);
00676         }
00677         fprintf(logfile, "\n");
00678     }
00679 }
00680 
00681 /*********************
00682 get number of separation constraints based on the number of nodes in each level
00683 ie, num_sep_constraints = sum_i^{num_levels-1} (|L[i]|+|L[i+1]|)
00684 **********************/
00685 int get_num_digcola_constraints(DigColaLevel * levels, int num_levels)
00686 {
00687     int i, nc = 0;
00688     for (i = 1; i < num_levels; i++) {
00689         nc += levels[i].num_nodes + levels[i - 1].num_nodes;
00690     }
00691     nc += levels[0].num_nodes + levels[num_levels - 1].num_nodes;
00692     return nc;
00693 }
00694 
00695 #endif                          /* IPSEPCOLA */

Generated on Mon Mar 31 19:03:27 2008 for Graphviz by  doxygen 1.5.1