38 #include <csolve_VPSC.h>
43 #define quad_prog_tol 1e-4
49 constrained_majorization_vpsc(CMajEnvVPSC * e,
float *b,
float *place,
53 float *g, *old_place, *d;
57 int n = e->nv + e->nldv;
58 boolean converged =
FALSE;
60 static int call_no = 0;
63 if (max_iterations == 0)
66 old_place = e->fArray2;
70 for (i = 0; i < n; i++) {
71 setVariableDesiredPos(e->vs[i], place[i]);
75 for (i = 0; i < n; i++) {
76 place[i] = getVariablePos(e->vs[i]);
82 float prev_stress = 0;
83 for (i = 0; i < n; i++) {
84 prev_stress += 2 * b[i] * place[i];
85 for (j = 0; j < n; j++) {
86 prev_stress -= e->A[i][j] * place[j] * place[i];
89 FILE *logfile = fopen(
"constrained_majorization_log",
"a");
94 for (counter = 0; counter < max_iterations && !converged; counter++) {
97 float numerator = 0, denominator = 0, r;
101 for (i = 0; i < n; i++) {
102 old_place[i] = place[i];
104 for (j = 0; j < n; j++) {
105 g[i] -= 2 * e->A[i][j] * place[j];
108 for (i = 0; i < n; i++) {
109 numerator += g[i] * g[i];
111 for (j = 0; j < n; j++) {
112 r += 2 * e->A[i][j] * g[j];
114 denominator -= r * g[i];
116 if (denominator != 0)
117 alpha = numerator / denominator;
120 for (i = 0; i < n; i++) {
121 place[i] -= alpha * g[i];
125 for (i = 0; i < n; i++) {
126 setVariableDesiredPos(e->vs[i], place[i]);
128 satisfyVPSC(e->vpsc);
129 for (i = 0; i < n; i++) {
130 place[i] = getVariablePos(e->vs[i]);
136 for (i = 0; i < n; i++) {
137 d[i] = place[i] - old_place[i];
140 numerator = 0, denominator = 0;
141 for (i = 0; i < n; i++) {
142 numerator += g[i] * d[i];
144 for (j = 0; j < n; j++) {
145 r += 2 * e->A[i][j] * d[j];
147 denominator += r * d[i];
149 if (denominator != 0.0)
150 beta = numerator / denominator;
154 for (i = 0; i < n; i++) {
158 if (beta > 0 && beta < 1.0) {
159 place[i] = old_place[i] + beta * d[i];
161 test += fabs(place[i] - old_place[i]);
163 #ifdef CONMAJ_LOGGING
165 for (i = 0; i < n; i++) {
166 stress += 2 * b[i] * place[i];
167 for (j = 0; j < n; j++) {
168 stress -= e->A[i][j] * place[j] * place[i];
171 fprintf(logfile,
"%d: stress=%f, test=%f, %s\n", call_no, stress,
172 test, (stress >= prev_stress) ?
"No Improvement" :
"");
173 prev_stress = stress;
175 if (test > quad_prog_tol) {
179 #ifdef CONMAJ_LOGGING
194 CMajEnvVPSC *initCMajVPSC(
int n,
float *packedMat,
vtx_data *
graph,
195 ipsep_options * opt,
int diredges)
201 CMajEnvVPSC *e =
GNEW(CMajEnvVPSC);
203 e->packedMat = packedMat;
206 e->nldv = 2 * opt->clusters->nclusters;
211 e->vs =
N_GNEW(n, Variable *);
212 for (i = 0; i < n; i++) {
213 e->vs[i] = newVariable(i, 1.0, 1.0);
218 fprintf(stderr,
" generate edge constraints...\n");
219 for (i = 0; i < e->nv; i++) {
220 for (j = 1; j < graph[i].
nedges; j++) {
222 if (graph[i].edists[j] > 0.01) {
227 e->gcs = newConstraints(e->gm);
229 for (i = 0; i < e->nv; i++) {
230 for (j = 1; j < graph[i].
nedges; j++) {
231 int u = i, v = graph[i].
edges[j];
232 if (graph[i].edists[j] > 0) {
234 newConstraint(e->vs[u], e->vs[v], opt->edge_gap);
238 }
else if (diredges == 2) {
239 int *ordering =
NULL, *ls =
NULL, cvar;
241 DigColaLevel *levels;
242 Variable **vs = e->vs;
244 if (compute_hierarchy(graph, e->nv, 1e-2, 1e-1,
NULL, &ordering, &ls,
245 &e->ndv))
return NULL;
246 levels = assign_digcola_levels(ordering, e->nv, ls, e->ndv);
248 fprintf(stderr,
"Found %d DiG-CoLa boundaries\n", e->ndv);
250 get_num_digcola_constraints(levels, e->ndv + 1) + e->ndv - 1;
251 e->gcs = newConstraints(e->gm);
253 e->vs =
N_GNEW(n + e->ndv, Variable *);
254 for (i = 0; i < n; i++) {
259 for (i = 0; i < e->ndv; i++) {
262 e->vs[cvar] = newVariable(cvar, 1.0, 0.000001);
264 halfgap = opt->edge_gap;
265 for (i = 0; i < e->ndv; i++) {
268 for (j = 0; j < levels[i].num_nodes; j++) {
270 newConstraint(e->vs[levels[i].nodes[j]], e->vs[cvar],
274 for (j = 0; j < levels[i + 1].num_nodes; j++) {
276 newConstraint(e->vs[cvar],
277 e->vs[levels[i + 1].nodes[j]], halfgap);
281 for (i = 0; i < e->ndv - 1; i++) {
283 newConstraint(e->vs[n + i], e->vs[n + i + 1], 0);
287 if (opt->clusters->nclusters > 0) {
289 Constraint **ecs = e->gcs;
290 nConCs = 2 * opt->clusters->nvars;
291 e->gcs = newConstraints(e->gm + nConCs);
292 for (i = 0; i < e->gm; i++) {
296 deleteConstraints(0, ecs);
297 for (i = 0; i < opt->clusters->nclusters; i++) {
298 for (j = 0; j < opt->clusters->clustersizes[i]; j++) {
299 Variable *v = e->vs[opt->clusters->clusters[i][j]];
300 Variable *cl = e->vs[e->nv + 2 * i];
301 Variable *cr = e->vs[e->nv + 2 * i + 1];
302 e->gcs[e->gm++] = newConstraint(cl, v, 0);
303 e->gcs[e->gm++] = newConstraint(v, cr, 0);
312 e->vpsc = newIncVPSC(n + e->ndv, e->vs, e->gm, e->gcs);
316 if (packedMat !=
NULL) {
317 e->A = unpackMatrix(packedMat, n);
323 mosek_init_sep(e->packedMat, n, e->ndv, e->gcs, e->gm);
327 e->fArray1 =
N_GNEW(n,
float);
328 e->fArray2 =
N_GNEW(n,
float);
329 e->fArray3 =
N_GNEW(n,
float);
332 " initCMajVPSC done: %d global constraints generated.\n",
337 void deleteCMajEnvVPSC(CMajEnvVPSC * e)
346 if (e->cs != e->gcs && e->gcs !=
NULL)
347 deleteConstraints(0, e->gcs);
348 deleteConstraints(e->m, e->cs);
349 for (i = 0; i < e->nv + e->nldv + e->ndv; i++) {
350 deleteVariable(e->vs[i]);
359 mosek_delete(e->mosekEnv);
376 void generateNonoverlapConstraints(CMajEnvVPSC * e,
380 boolean transitiveClosure,
383 Constraint **csol, **csolptr;
385 int n = e->nv + e->nldv;
391 boolean genclusters = opt->clusters->nclusters > 0;
394 n -= 2 * opt->clusters->nclusters;
400 nsizeScale *= 1.0001;
402 for (i = 0; i < n; i++) {
404 coords[0][i] - nsizeScale * opt->nsize[i].x / 2.0 -
407 coords[0][i] + nsizeScale * opt->nsize[i].x / 2.0 +
410 coords[1][i] - nsizeScale * opt->nsize[i].y / 2.0 -
413 coords[1][i] + nsizeScale * opt->nsize[i].y / 2.0 +
418 Constraint ***cscl =
N_GNEW(opt->clusters->nclusters + 1, Constraint**);
419 int* cm =
N_GNEW(opt->clusters->nclusters + 1,
int);
421 Constraint **cscl[opt->clusters->nclusters + 1];
422 int cm[opt->clusters->nclusters + 1];
424 for (i = 0; i < opt->clusters->nclusters; i++) {
425 int cn = opt->clusters->clustersizes[i];
427 Variable** cvs =
N_GNEW(cn + 2, Variable*);
430 Variable *cvs[cn + 2];
435 container.
LL.
x = container.
LL.
y = DBL_MAX;
436 container.
UR.
x = container.
UR.
y = -DBL_MAX;
437 for (j = 0; j < cn; j++) {
438 int iv = opt->clusters->clusters[i][j];
440 B2BF(bb[iv], cbb[j]);
443 B2BF(container, opt->clusters->bb[i]);
444 cvs[cn] = e->vs[n + 2 * i];
445 cvs[cn + 1] = e->vs[n + 2 * i + 1];
446 B2BF(container, cbb[cn]);
447 B2BF(container, cbb[cn + 1]);
449 cbb[cn].
UR.
x = container.
LL.
x + 0.0001;
450 cbb[cn + 1].
LL.
x = container.
UR.
x - 0.0001;
452 genXConstraints(cn + 2, cbb, cvs, &cscl[i],
455 cbb[cn].
UR.
y = container.
LL.
y + 0.0001;
456 cbb[cn + 1].
LL.
y = container.
UR.
y - 0.0001;
457 cm[i] = genYConstraints(cn + 2, cbb, cvs, &cscl[i]);
467 int cn = opt->clusters->ntoplevel + opt->clusters->nclusters;
469 Variable** cvs =
N_GNEW(cn,Variable*);
475 for (i = 0; i < opt->clusters->ntoplevel; i++) {
476 int iv = opt->clusters->toplevel[i];
478 B2BF(bb[iv], cbb[i]);
481 for (i = opt->clusters->ntoplevel; i < cn; i++) {
482 cvs[i] = newVariable(123 + i, 1, 1);
483 j = i - opt->clusters->ntoplevel;
484 B2BF(opt->clusters->bb[j], cbb[i]);
486 i = opt->clusters->nclusters;
489 genXConstraints(cn, cbb, cvs, &cscl[i],
492 cm[i] = genYConstraints(cn, cbb, cvs, &cscl[i]);
495 for (i = opt->clusters->ntoplevel; i < cn; i++) {
497 j = i - opt->clusters->ntoplevel;
505 dgap = -(cbb[i].
UR.
x - cbb[i].
LL.
x) / 2.0;
507 dgap = -(cbb[i].
UR.
y - cbb[i].
LL.
y) / 2.0;
509 remapInConstraints(cvs[i], e->vs[n + 2 * j], dgap);
510 remapOutConstraints(cvs[i], e->vs[n + 2 * j + 1], dgap);
533 deleteVariable(cvs[i]);
535 mol += cm[opt->clusters->nclusters];
541 csolptr = csol = newConstraints(mol);
542 for (i = 0; i < opt->clusters->nclusters + 1; i++) {
544 for (j = 0; j < cm[i]; j++) {
545 *csolptr++ = cscl[i][j];
547 deleteConstraints(0, cscl[i]);
555 mol = genXConstraints(n, bb, e->vs, &csol, transitiveClosure);
557 mol = genYConstraints(n, bb, e->vs, &csol);
564 for (i = e->gm == 0 ? 0 : e->gm; i < e->m; i++) {
566 deleteConstraint(e->cs[i]);
570 deleteConstraints(0, e->cs);
582 e->cs = newConstraints(e->m);
583 for (i = 0; i < e->m; i++) {
585 e->cs[i] = e->gcs[i];
587 e->cs[i] = csol[i - e->gm];
591 deleteConstraints(0, csol);
594 fprintf(stderr,
" generated %d constraints\n", e->m);
595 e->vpsc = newIncVPSC(e->nv + e->nldv + e->ndv, e->vs, e->m, e->cs);
598 if (e->mosekEnv !=
NULL) {
599 mosek_delete(e->mosekEnv);
602 mosek_init_sep(e->packedMat, e->nv + e->nldv, e->ndv, e->cs,
615 void removeoverlaps(
int n,
float **coords, ipsep_options * opt)
618 CMajEnvVPSC *e = initCMajVPSC(n,
NULL,
NULL, opt, 0);
619 generateNonoverlapConstraints(e, 1.0, coords, 0,
TRUE, opt);
621 for (i = 0; i < n; i++) {
622 coords[0][i] = getVariablePos(e->vs[i]);
624 generateNonoverlapConstraints(e, 1.0, coords, 1,
FALSE, opt);
626 for (i = 0; i < n; i++) {
627 coords[1][i] = getVariablePos(e->vs[i]);
629 deleteCMajEnvVPSC(e);
635 DigColaLevel *assign_digcola_levels(
int *ordering,
int n,
int *level_inds,
639 DigColaLevel *l =
N_GNEW(num_divisions + 1, DigColaLevel);
641 l[0].num_nodes = level_inds[0];
642 l[0].nodes =
N_GNEW(l[0].num_nodes,
int);
643 for (i = 0; i < l[0].num_nodes; i++) {
644 l[0].nodes[i] = ordering[i];
647 for (i = 1; i < num_divisions; i++) {
648 l[i].num_nodes = level_inds[i] - level_inds[i - 1];
649 l[i].nodes =
N_GNEW(l[i].num_nodes,
int);
650 for (j = 0; j < l[i].num_nodes; j++) {
651 l[i].nodes[j] = ordering[level_inds[i - 1] + j];
655 if (num_divisions > 0) {
656 l[num_divisions].num_nodes = n - level_inds[num_divisions - 1];
657 l[num_divisions].nodes =
N_GNEW(l[num_divisions].num_nodes,
int);
658 for (i = 0; i < l[num_divisions].num_nodes; i++) {
659 l[num_divisions].nodes[i] =
660 ordering[level_inds[num_divisions - 1] + i];
665 void delete_digcola_levels(DigColaLevel * l,
int num_levels)
668 for (i = 0; i < num_levels; i++) {
673 void print_digcola_levels(FILE * logfile, DigColaLevel * levels,
677 fprintf(logfile,
"levels:\n");
678 for (i = 0; i < num_levels; i++) {
679 fprintf(logfile,
" l[%d]:", i);
680 for (j = 0; j < levels[i].num_nodes; j++) {
681 fprintf(logfile,
"%d ", levels[i].nodes[j]);
683 fprintf(logfile,
"\n");
691 int get_num_digcola_constraints(DigColaLevel * levels,
int num_levels)
694 for (i = 1; i < num_levels; i++) {
695 nc += levels[i].num_nodes + levels[i - 1].num_nodes;
697 nc += levels[0].num_nodes + levels[num_levels - 1].num_nodes;
Agraph_t * graph(char *name)
EXTERN unsigned char Verbose