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