26 #define quad_prog_tol 1e-2
28 float **unpackMatrix(
float *packedMat,
int n)
34 mat[0] =
N_GNEW(n * n,
float);
36 for (i = 1; i < n; i++) {
37 mat[i] = mat[0] + i * n;
40 for (i = 0, k = 0; i < n; i++) {
41 for (j = i; j < n; j++, k++) {
42 mat[j][i] = mat[i][j] = packedMat[k];
48 static void ensureMonotonicOrdering(
float *place,
int n,
int *ordering)
53 float lower_bound = place[ordering[0]];
54 for (i = 1; i < n; i++) {
56 if (place[node] < lower_bound) {
57 place[
node] = lower_bound;
59 lower_bound = place[
node];
64 ensureMonotonicOrderingWithGaps(
float *place,
int n,
int *ordering,
65 int *levels,
int num_levels,
73 int node, level, max_in_level;
74 float lower_bound = (float) -1e9;
78 for (i = 0; i < n; i++) {
79 if (i >= max_in_level) {
82 if (level == num_levels) {
86 max_in_level = levels[level];
89 i > 0 ? place[ordering[i - 1]] + levels_gap : (float) -1e9;
94 if (place[node] < lower_bound) {
95 place[
node] = lower_bound;
101 computeHierarchyBoundaries(
float *place,
int n,
int *ordering,
int *levels,
102 int num_levels,
float *hierarchy_boundaries)
105 for (i = 0; i < num_levels; i++) {
106 hierarchy_boundaries[i] = place[ordering[levels[i] - 1]];
112 constrained_majorization_new(CMajEnv * e,
float *b,
float **coords,
113 int cur_axis,
int dims,
int max_iterations,
114 float *hierarchy_boundaries,
float levels_gap)
117 float *place = coords[cur_axis];
119 int *ordering = e->ordering;
120 int *levels = e->levels;
121 int num_levels = e->num_levels;
124 boolean converged =
FALSE;
125 float upper_bound, lower_bound;
129 float des_place_block;
131 float toBlockConnectivity;
134 int first_next_level;
135 int level = -1, max_in_level = 0;
136 float *desired_place;
137 float *prefix_desired_place;
138 float *suffix_desired_place;
143 if (max_iterations <= 0) {
146 if (levels_gap != 0) {
147 return constrained_majorization_new_with_gaps(e, b, coords,
150 hierarchy_boundaries,
155 ensureMonotonicOrdering(place, n, ordering);
161 desired_place = e->fArray1;
163 prefix_desired_place = e->fArray2;
165 suffix_desired_place = e->fArray3;
170 for (i = 0; i < n; i++) {
171 if (i >= max_in_level) {
174 if (level == num_levels) {
178 max_in_level = levels[level];
185 for (counter = 0; counter < max_iterations && !converged; counter++) {
188 for (left = 0; left < n; left =
right) {
192 float prefix_des_place, suffix_des_place;
196 cur_place = place[ordering[
left]];
197 for (right = left + 1; right < n; right++) {
198 if (place[ordering[right]] != cur_place) {
204 for (i = left; i <
right; i++) {
206 new_place_i = -b[
node];
207 lap_node = lap[
node];
208 for (j = 0; j < n; j++) {
212 new_place_i += lap_node[j] * place[j];
214 desired_place[
node] = new_place_i / (-lap_node[
node]);
219 first_next_level = 0;
220 for (i = left; i <
right; i = first_next_level) {
221 level = lev[ordering[i]];
222 if (level == num_levels) {
224 first_next_level =
right;
226 first_next_level =
MIN(right, levels[level]);
230 for (j = i; j < first_next_level; j++) {
232 if (desired_place[node] < cur_place) {
233 block[block_len++] =
node;
237 for (j = i; j < first_next_level; j++) {
239 if (desired_place[node] == cur_place) {
240 block[block_len++] =
node;
244 for (j = i; j < first_next_level; j++) {
246 if (desired_place[node] > cur_place) {
247 block[block_len++] =
node;
255 for (i = 0; i < block_len; i++) {
257 toBlockConnectivity = 0;
258 lap_node = lap[
node];
259 for (j = 0; j < i; j++) {
260 toBlockConnectivity -= lap_node[block[j]];
262 toBlockConnectivity *= 2;
265 (block_deg * des_place_block +
266 (-lap_node[
node]) * desired_place[node] +
267 toBlockConnectivity * cur_place) / (block_deg -
269 toBlockConnectivity);
270 prefix_desired_place[i] = des_place_block;
271 block_deg += toBlockConnectivity - lap_node[
node];
277 for (i = block_len - 1; i >= 0; i--) {
279 toBlockConnectivity = 0;
280 lap_node = lap[
node];
281 for (j = i + 1; j < block_len; j++) {
282 toBlockConnectivity -= lap_node[block[j]];
284 toBlockConnectivity *= 2;
287 (block_deg * des_place_block +
288 (-lap_node[
node]) * desired_place[node] +
289 toBlockConnectivity * cur_place) / (block_deg -
291 toBlockConnectivity);
292 suffix_desired_place[i] = des_place_block;
293 block_deg += toBlockConnectivity - lap_node[
node];
300 for (i = 0; i < block_len; i++) {
301 suffix_des_place = suffix_desired_place[i];
303 i > 0 ? prefix_desired_place[i - 1] : suffix_des_place;
305 if (suffix_des_place < prefix_des_place) {
306 if (suffix_des_place < cur_place) {
307 if (prefix_des_place > cur_place) {
308 prefix_des_place = cur_place;
310 suffix_des_place = prefix_des_place;
311 }
else if (prefix_des_place > cur_place) {
312 prefix_des_place = suffix_des_place;
316 (block_len - i) * fabs(suffix_des_place - cur_place) +
317 i * fabs(prefix_des_place - cur_place);
318 if (movement > max_movement) {
319 max_movement = movement;
325 suffix_des_place = suffix_desired_place[best_i];
328 0 ? prefix_desired_place[best_i -
329 1] : suffix_des_place;
336 upper_bound = place[ordering[
right]];
338 suffix_des_place =
MIN(suffix_des_place, upper_bound);
339 prefix_des_place =
MAX(prefix_des_place, lower_bound);
342 if (suffix_des_place < prefix_des_place) {
343 if (suffix_des_place < cur_place) {
344 if (prefix_des_place > cur_place) {
345 prefix_des_place = cur_place;
347 suffix_des_place = prefix_des_place;
348 }
else if (prefix_des_place > cur_place) {
349 prefix_des_place = suffix_des_place;
354 for (i = 0; i < best_i; i++) {
355 place[block[i]] = prefix_des_place;
358 for (i = best_i; i < block_len; i++) {
359 place[block[i]] = suffix_des_place;
362 lower_bound = suffix_des_place;
369 int max_in_level, min_in_level;
372 if (level == num_levels) {
374 max_in_level =
MIN(right, n);
376 max_in_level =
MIN(right, levels[level]);
380 min_in_level =
MAX(left, 0);
382 min_in_level =
MAX(left, levels[level - 1]);
385 for (i = left; i <
right; i++) {
386 ordering[i] = block[i -
left];
388 converged = converged
389 && fabs(prefix_des_place - cur_place) < quad_prog_tol
390 && fabs(suffix_des_place - cur_place) < quad_prog_tol;
394 lower_bound = cur_place;
400 computeHierarchyBoundaries(place, n, ordering, levels, num_levels,
401 hierarchy_boundaries);
408 static int compare_incr(
const void *a,
const void *b)
410 if (place[*(
int *) a] > place[*(
int *) b]) {
412 }
else if (place[*(
int *) a] < place[*(
int *) b]) {
422 int constrained_majorization_gradient_projection(CMajEnv * e,
423 float *b,
float **coords,
424 int ndims,
int cur_axis,
427 *hierarchy_boundaries,
432 int *ordering = e->ordering;
433 int *levels = e->levels;
434 int num_levels = e->num_levels;
435 boolean converged =
FALSE;
436 float *g = e->fArray1;
437 float *old_place = e->fArray2;
438 float *d = e->fArray4;
439 float test = 0, tmptest = 0;
442 if (max_iterations == 0)
445 place = coords[cur_axis];
446 #ifdef CONMAJ_LOGGING
447 double prev_stress = 0;
448 static int call_no = 0;
449 for (i = 0; i < e->n; i++) {
450 prev_stress += 2 * b[i] * place[i];
451 for (j = 0; j < e->n; j++) {
452 prev_stress -= e->A[i][j] * place[j] * place[i];
455 FILE *logfile = fopen(
"constrained_majorization_log",
"a");
457 fprintf(logfile,
"grad proj %d: stress=%f\n", call_no, prev_stress);
459 for (counter = 0; counter < max_iterations && !converged; counter++) {
461 float numerator = 0, denominator = 0, r;
464 for (i = 0; i < e->n; i++) {
465 old_place[i] = place[i];
467 for (j = 0; j < e->n; j++) {
468 g[i] -= 2 * e->A[i][j] * place[j];
471 for (i = 0; i < e->n; i++) {
472 numerator += g[i] * g[i];
474 for (j = 0; j < e->n; j++) {
475 r += 2 * e->A[i][j] * g[j];
477 denominator -= r * g[i];
479 alpha = numerator / denominator;
480 for (i = 0; i < e->n; i++) {
481 if (alpha > 0 && alpha < 1000) {
482 place[i] -= alpha * g[i];
486 qsort((
int *) ordering, (
size_t) levels[0],
sizeof(
int),
489 for (i = 0; i < num_levels; i++) {
490 int endOfLevel = i == num_levels - 1 ? e->n : levels[i + 1];
494 qsort((
int *) ordering + levels[i],
495 (
size_t) endOfLevel - levels[i],
sizeof(
int),
498 ui = levels[i]; li = ui - 1;
499 l = ordering[li--]; u = ordering[ui++];
500 if (place[l] + levels_gap > place[u]) {
502 place[l] + place[u] - levels_gap * (e->lev[l] +
504 float avgPos = sum / w;
509 if (ui < endOfLevel) {
511 pos = place[u] - levels_gap * e->lev[u];
523 pos = place[l] - levels_gap * e->lev[l];
533 for (j = li + 1; j < ui; j++) {
535 avgPos + levels_gap * e->lev[ordering[j]];
540 for (i = 0; i < e->n; i++) {
541 d[i] = place[i] - old_place[i];
544 numerator = 0, denominator = 0;
545 for (i = 0; i < e->n; i++) {
546 numerator += g[i] * d[i];
548 for (j = 0; j < e->n; j++) {
549 r += 2 * e->A[i][j] * d[j];
551 denominator += r * d[i];
553 beta = numerator / denominator;
555 for (i = 0; i < e->n; i++) {
556 if (beta > 0 && beta < 1.0) {
557 place[i] = old_place[i] + beta * d[i];
559 tmptest = fabs(place[i] - old_place[i]);
563 computeHierarchyBoundaries(place, e->n, ordering, levels,
564 num_levels, hierarchy_boundaries);
567 qsort((
int *) ordering, (
size_t) levels[0],
sizeof(
int),
569 for (i = 0; i < num_levels; i++) {
570 int endOfLevel = i == num_levels - 1 ? e->n : levels[i + 1];
572 qsort((
int *) ordering + levels[i],
573 (
size_t) endOfLevel - levels[i],
sizeof(
int),
576 int l = ordering[levels[i] - 1], u = ordering[levels[i]];
580 #ifdef CONMAJ_LOGGING
582 for (i = 0; i < e->n; i++) {
583 stress += 2 * b[i] * place[i];
584 for (j = 0; j < e->n; j++) {
585 stress -= e->A[i][j] * place[j] * place[i];
588 fprintf(logfile,
"%d: stress=%f, test=%f, %s\n", call_no, stress,
589 test, (stress >= prev_stress) ?
"No Improvement" :
"");
590 prev_stress = stress;
592 if (test > quad_prog_tol) {
596 #ifdef CONMAJ_LOGGING
605 constrained_majorization_new_with_gaps(CMajEnv * e,
float *b,
606 float **coords,
int ndims,
607 int cur_axis,
int max_iterations,
608 float *hierarchy_boundaries,
611 float *place = coords[cur_axis];
615 int *ordering = e->ordering;
616 int *levels = e->levels;
617 int num_levels = e->num_levels;
619 boolean converged =
FALSE;
620 float upper_bound, lower_bound;
624 float des_place_block;
626 float toBlockConnectivity;
628 float *desired_place;
629 float *prefix_desired_place;
630 float *suffix_desired_place;
633 int first_next_level;
635 int level = -1, max_in_level = 0;
638 float total_gap, target_place;
640 if (max_iterations <= 0) {
644 ensureMonotonicOrderingWithGaps(place, n, ordering, levels, num_levels,
651 desired_place = e->fArray1;
653 prefix_desired_place = e->fArray2;
655 suffix_desired_place = e->fArray3;
660 for (i = 0; i < n; i++) {
661 if (i >= max_in_level) {
664 if (level == num_levels) {
668 max_in_level = levels[level];
678 for (counter = 0; counter < max_iterations && !converged; counter++) {
681 for (left = 0; left < n; left =
right) {
685 float prefix_des_place, suffix_des_place;
689 cur_place = place[ordering[
left]];
691 target_place = cur_place;
692 gap[ordering[
left]] = 0;
693 for (right = left + 1; right < n; right++) {
694 if (lev[right] > lev[right - 1]) {
696 target_place += levels_gap;
697 total_gap += levels_gap;
699 node = ordering[
right];
701 if (place[node] != target_place)
704 if (fabs(place[node] - target_place) > 1e-9) {
707 gap[
node] = place[
node] - cur_place;
713 for (i = left; i <
right; i++) {
715 new_place_i = -b[
node];
716 lap_node = lap[
node];
717 for (j = 0; j < n; j++) {
721 new_place_i += lap_node[j] * place[j];
723 desired_place[
node] =
724 new_place_i / (-lap_node[
node]) - gap[node];
731 first_next_level = 0;
732 for (i = left; i <
right; i = first_next_level) {
733 level = lev[ordering[i]];
734 if (level == num_levels) {
736 first_next_level =
right;
738 first_next_level =
MIN(right, levels[level]);
744 for (j = i; j < first_next_level; j++) {
746 if (desired_place[node] < cur_place) {
747 block[block_len++] =
node;
753 for (j = i; j < first_next_level; j++) {
755 if (desired_place[node] == cur_place) {
756 block[block_len++] =
node;
762 for (j = i; j < first_next_level; j++) {
764 if (desired_place[node] > cur_place) {
765 block[block_len++] =
node;
773 for (i = 0; i < block_len; i++) {
775 toBlockConnectivity = 0;
776 lap_node = lap[
node];
777 for (j = 0; j < i; j++) {
778 toBlockConnectivity -= lap_node[block[j]];
780 toBlockConnectivity *= 2;
783 (block_deg * des_place_block +
784 (-lap_node[
node]) * desired_place[node] +
785 toBlockConnectivity * cur_place) / (block_deg -
787 toBlockConnectivity);
788 prefix_desired_place[i] = des_place_block;
789 block_deg += toBlockConnectivity - lap_node[
node];
792 if (block_len == n) {
794 prefix_desired_place[n - 1] = cur_place;
800 for (i = block_len - 1; i >= 0; i--) {
802 toBlockConnectivity = 0;
803 lap_node = lap[
node];
804 for (j = i + 1; j < block_len; j++) {
805 toBlockConnectivity -= lap_node[block[j]];
807 toBlockConnectivity *= 2;
810 (block_deg * des_place_block +
811 (-lap_node[
node]) * desired_place[node] +
812 toBlockConnectivity * cur_place) / (block_deg -
814 toBlockConnectivity);
815 suffix_desired_place[i] = des_place_block;
816 block_deg += toBlockConnectivity - lap_node[
node];
819 if (block_len == n) {
821 suffix_desired_place[0] = cur_place;
828 for (i = 0; i < block_len; i++) {
829 suffix_des_place = suffix_desired_place[i];
831 i > 0 ? prefix_desired_place[i - 1] : suffix_des_place;
833 if (suffix_des_place < prefix_des_place) {
834 if (suffix_des_place < cur_place) {
835 if (prefix_des_place > cur_place) {
836 prefix_des_place = cur_place;
838 suffix_des_place = prefix_des_place;
839 }
else if (prefix_des_place > cur_place) {
840 prefix_des_place = suffix_des_place;
844 (block_len - i) * fabs(suffix_des_place - cur_place) +
845 i * fabs(prefix_des_place - cur_place);
846 if (movement > max_movement) {
847 max_movement = movement;
853 suffix_des_place = suffix_desired_place[best_i];
856 0 ? prefix_desired_place[best_i -
857 1] : suffix_des_place;
868 if (lev[ordering[right]] > lev[ordering[right - 1]]) {
870 place[ordering[
right]] - levels_gap -
871 gap[block[block_len - 1]];
874 place[ordering[
right]] -
875 gap[block[block_len - 1]];
878 suffix_des_place =
MIN(suffix_des_place, upper_bound);
879 prefix_des_place =
MAX(prefix_des_place, lower_bound);
882 if (suffix_des_place < prefix_des_place) {
883 if (suffix_des_place < cur_place) {
884 if (prefix_des_place > cur_place) {
885 prefix_des_place = cur_place;
887 suffix_des_place = prefix_des_place;
888 }
else if (prefix_des_place > cur_place) {
889 prefix_des_place = suffix_des_place;
894 for (i = 0; i < best_i; i++) {
895 place[block[i]] = prefix_des_place + gap[block[i]];
898 for (i = best_i; i < block_len; i++) {
899 place[block[i]] = suffix_des_place + gap[block[i]];
905 && lev[ordering[right]] > lev[ordering[right - 1]]) {
906 lower_bound = place[block[block_len - 1]] + levels_gap;
908 lower_bound = place[block[block_len - 1]];
917 int max_in_level, min_in_level;
920 if (level == num_levels) {
922 max_in_level =
MIN(right, n);
924 max_in_level =
MIN(right, levels[level]);
928 min_in_level =
MAX(left, 0);
930 min_in_level =
MAX(left, levels[level - 1]);
933 for (i = left; i <
right; i++) {
934 ordering[i] = block[i -
left];
936 converged = converged
937 && fabs(prefix_des_place - cur_place) < quad_prog_tol
938 && fabs(suffix_des_place - cur_place) < quad_prog_tol;
945 && lev[ordering[right]] > lev[ordering[right - 1]]) {
946 lower_bound = place[block[block_len - 1]] + levels_gap;
948 lower_bound = place[block[block_len - 1]];
953 computeHierarchyBoundaries(place, n, ordering, levels, num_levels,
954 hierarchy_boundaries);
960 void deleteCMajEnv(CMajEnv * e)
976 CMajEnv *initConstrainedMajorization(
float *packedMat,
int n,
977 int *ordering,
int *levels,
980 int i, level = -1, start_of_level_above = 0;
981 CMajEnv *e =
GNEW(CMajEnv);
984 e->ordering = ordering;
986 e->num_levels = num_levels;
987 e->A = unpackMatrix(packedMat, n);
989 for (i = 0; i < e->n; i++) {
990 if (i >= start_of_level_above) {
992 start_of_level_above =
993 (level == num_levels) ? e->n : levels[level];
995 e->lev[ordering[i]] = level;
997 e->fArray1 =
N_GNEW(n,
float);
998 e->fArray2 =
N_GNEW(n,
float);
999 e->fArray3 =
N_GNEW(n,
float);
1000 e->fArray4 =
N_GNEW(n,
float);
1001 e->iArray1 =
N_GNEW(n,
int);
1002 e->iArray2 =
N_GNEW(n,
int);
1003 e->iArray3 =
N_GNEW(n,
int);
1004 e->iArray4 =
N_GNEW(n,
int);
void set_vector_valf(int n, float val, float *result)
Agnode_t * node(Agraph_t *g, char *name)
void orthog1f(int n, float *vec)
void quicksort_placef(float *place, int *ordering, int first, int last)