|
Graphviz
2.29.20120524.0446
|
00001 /* $Id$ $Revision$ */ 00002 /* vim:set shiftwidth=4 ts=8: */ 00003 00004 /************************************************************************* 00005 * Copyright (c) 2011 AT&T Intellectual Property 00006 * All rights reserved. This program and the accompanying materials 00007 * are made available under the terms of the Eclipse Public License v1.0 00008 * which accompanies this distribution, and is available at 00009 * http://www.eclipse.org/legal/epl-v10.html 00010 * 00011 * Contributors: See CVS logs. Details at http://www.graphviz.org/ 00012 *************************************************************************/ 00013 00014 #include "digcola.h" 00015 #ifdef DIGCOLA 00016 #include <math.h> 00017 #include <stdlib.h> 00018 #include <time.h> 00019 #include <stdio.h> 00020 #include <float.h> 00021 #include <assert.h> 00022 #include "matrix_ops.h" 00023 #include "kkutils.h" 00024 #include "quad_prog_solver.h" 00025 00026 #define quad_prog_tol 1e-2 00027 00028 float **unpackMatrix(float *packedMat, int n) 00029 { 00030 float **mat; 00031 int i, j, k; 00032 00033 mat = N_GNEW(n, float *); 00034 mat[0] = N_GNEW(n * n, float); 00035 set_vector_valf(n * n, 0, mat[0]); 00036 for (i = 1; i < n; i++) { 00037 mat[i] = mat[0] + i * n; 00038 } 00039 00040 for (i = 0, k = 0; i < n; i++) { 00041 for (j = i; j < n; j++, k++) { 00042 mat[j][i] = mat[i][j] = packedMat[k]; 00043 } 00044 } 00045 return mat; 00046 } 00047 00048 static void ensureMonotonicOrdering(float *place, int n, int *ordering) 00049 { 00050 /* ensure that 'ordering' is monotonically increasing by 'place', */ 00051 /* this also implies that levels are separated in the initial layout */ 00052 int i, node; 00053 float lower_bound = place[ordering[0]]; 00054 for (i = 1; i < n; i++) { 00055 node = ordering[i]; 00056 if (place[node] < lower_bound) { 00057 place[node] = lower_bound; 00058 } 00059 lower_bound = place[node]; 00060 } 00061 } 00062 00063 static void 00064 ensureMonotonicOrderingWithGaps(float *place, int n, int *ordering, 00065 int *levels, int num_levels, 00066 float levels_gap) 00067 { 00068 /* ensure that levels are separated in the initial layout and that 00069 * places are monotonic increasing within layer 00070 */ 00071 00072 int i; 00073 int node, level, max_in_level; 00074 float lower_bound = (float) -1e9; 00075 00076 level = -1; 00077 max_in_level = 0; 00078 for (i = 0; i < n; i++) { 00079 if (i >= max_in_level) { 00080 /* we are entering a new level */ 00081 level++; 00082 if (level == num_levels) { 00083 /* last_level */ 00084 max_in_level = n; 00085 } else { 00086 max_in_level = levels[level]; 00087 } 00088 lower_bound = 00089 i > 0 ? place[ordering[i - 1]] + levels_gap : (float) -1e9; 00090 quicksort_placef(place, ordering, i, max_in_level - 1); 00091 } 00092 00093 node = ordering[i]; 00094 if (place[node] < lower_bound) { 00095 place[node] = lower_bound; 00096 } 00097 } 00098 } 00099 00100 static void 00101 computeHierarchyBoundaries(float *place, int n, int *ordering, int *levels, 00102 int num_levels, float *hierarchy_boundaries) 00103 { 00104 int i; 00105 for (i = 0; i < num_levels; i++) { 00106 hierarchy_boundaries[i] = place[ordering[levels[i] - 1]]; 00107 } 00108 } 00109 00110 00111 int 00112 constrained_majorization_new(CMajEnv * e, float *b, float **coords, 00113 int cur_axis, int dims, int max_iterations, 00114 float *hierarchy_boundaries, float levels_gap) 00115 { 00116 int n = e->n; 00117 float *place = coords[cur_axis]; 00118 float **lap = e->A; 00119 int *ordering = e->ordering; 00120 int *levels = e->levels; 00121 int num_levels = e->num_levels; 00122 int i, j; 00123 float new_place_i; 00124 boolean converged = FALSE; 00125 float upper_bound, lower_bound; 00126 int node; 00127 int left, right; 00128 float cur_place; 00129 float des_place_block; 00130 float block_deg; 00131 float toBlockConnectivity; 00132 float *lap_node; 00133 int block_len; 00134 int first_next_level; 00135 int level = -1, max_in_level = 0; 00136 float *desired_place; 00137 float *prefix_desired_place; 00138 float *suffix_desired_place; 00139 int *block; 00140 int *lev; 00141 int counter; 00142 00143 if (max_iterations <= 0) { 00144 return 0; 00145 } 00146 if (levels_gap != 0) { 00147 return constrained_majorization_new_with_gaps(e, b, coords, 00148 cur_axis, dims, 00149 max_iterations, 00150 hierarchy_boundaries, 00151 levels_gap); 00152 } 00153 00154 /* ensureMonotonicOrderingWithGaps(place, n, ordering, levels, num_levels); */ 00155 ensureMonotonicOrdering(place, n, ordering); 00156 /* it is important that in 'ordering' nodes are always sorted by layers, 00157 * and within a layer by 'place' 00158 */ 00159 00160 /* the desired place of each individual node in the current block */ 00161 desired_place = e->fArray1; 00162 /* the desired place of each prefix of current block */ 00163 prefix_desired_place = e->fArray2; 00164 /* the desired place of each suffix of current block */ 00165 suffix_desired_place = e->fArray3; 00166 /* current block (nodes connected by active constraints) */ 00167 block = e->iArray1; 00168 00169 lev = e->iArray2; /* level of each node */ 00170 for (i = 0; i < n; i++) { 00171 if (i >= max_in_level) { 00172 /* we are entering a new level */ 00173 level++; 00174 if (level == num_levels) { 00175 /* last_level */ 00176 max_in_level = n; 00177 } else { 00178 max_in_level = levels[level]; 00179 } 00180 } 00181 node = ordering[i]; 00182 lev[node] = level; 00183 } 00184 00185 for (counter = 0; counter < max_iterations && !converged; counter++) { 00186 converged = TRUE; 00187 lower_bound = -1e9; /* no lower bound for first level */ 00188 for (left = 0; left < n; left = right) { 00189 int best_i; 00190 double max_movement; 00191 double movement; 00192 float prefix_des_place, suffix_des_place; 00193 /* compute a block 'ordering[left]...ordering[right-1]' of 00194 * nodes with the same coordinate: 00195 */ 00196 cur_place = place[ordering[left]]; 00197 for (right = left + 1; right < n; right++) { 00198 if (place[ordering[right]] != cur_place) { 00199 break; 00200 } 00201 } 00202 00203 /* compute desired place of nodes in block: */ 00204 for (i = left; i < right; i++) { 00205 node = ordering[i]; 00206 new_place_i = -b[node]; 00207 lap_node = lap[node]; 00208 for (j = 0; j < n; j++) { 00209 if (j == node) { 00210 continue; 00211 } 00212 new_place_i += lap_node[j] * place[j]; 00213 } 00214 desired_place[node] = new_place_i / (-lap_node[node]); 00215 } 00216 00217 /* reorder block by levels, and within levels by "relaxed" desired position */ 00218 block_len = 0; 00219 first_next_level = 0; 00220 for (i = left; i < right; i = first_next_level) { 00221 level = lev[ordering[i]]; 00222 if (level == num_levels) { 00223 /* last_level */ 00224 first_next_level = right; 00225 } else { 00226 first_next_level = MIN(right, levels[level]); 00227 } 00228 00229 /* First, collect all nodes with desired places smaller than current place */ 00230 for (j = i; j < first_next_level; j++) { 00231 node = ordering[j]; 00232 if (desired_place[node] < cur_place) { 00233 block[block_len++] = node; 00234 } 00235 } 00236 /* Second, collect all nodes with desired places equal to current place */ 00237 for (j = i; j < first_next_level; j++) { 00238 node = ordering[j]; 00239 if (desired_place[node] == cur_place) { 00240 block[block_len++] = node; 00241 } 00242 } 00243 /* Third, collect all nodes with desired places greater than current place */ 00244 for (j = i; j < first_next_level; j++) { 00245 node = ordering[j]; 00246 if (desired_place[node] > cur_place) { 00247 block[block_len++] = node; 00248 } 00249 } 00250 } 00251 00252 /* loop through block and compute desired places of its prefixes */ 00253 des_place_block = 0; 00254 block_deg = 0; 00255 for (i = 0; i < block_len; i++) { 00256 node = block[i]; 00257 toBlockConnectivity = 0; 00258 lap_node = lap[node]; 00259 for (j = 0; j < i; j++) { 00260 toBlockConnectivity -= lap_node[block[j]]; 00261 } 00262 toBlockConnectivity *= 2; 00263 /* update block stats */ 00264 des_place_block = 00265 (block_deg * des_place_block + 00266 (-lap_node[node]) * desired_place[node] + 00267 toBlockConnectivity * cur_place) / (block_deg - 00268 lap_node[node] + 00269 toBlockConnectivity); 00270 prefix_desired_place[i] = des_place_block; 00271 block_deg += toBlockConnectivity - lap_node[node]; 00272 } 00273 00274 /* loop through block and compute desired places of its suffixes */ 00275 des_place_block = 0; 00276 block_deg = 0; 00277 for (i = block_len - 1; i >= 0; i--) { 00278 node = block[i]; 00279 toBlockConnectivity = 0; 00280 lap_node = lap[node]; 00281 for (j = i + 1; j < block_len; j++) { 00282 toBlockConnectivity -= lap_node[block[j]]; 00283 } 00284 toBlockConnectivity *= 2; 00285 /* update block stats */ 00286 des_place_block = 00287 (block_deg * des_place_block + 00288 (-lap_node[node]) * desired_place[node] + 00289 toBlockConnectivity * cur_place) / (block_deg - 00290 lap_node[node] + 00291 toBlockConnectivity); 00292 suffix_desired_place[i] = des_place_block; 00293 block_deg += toBlockConnectivity - lap_node[node]; 00294 } 00295 00296 00297 /* now, find best place to split block */ 00298 best_i = -1; 00299 max_movement = 0; 00300 for (i = 0; i < block_len; i++) { 00301 suffix_des_place = suffix_desired_place[i]; 00302 prefix_des_place = 00303 i > 0 ? prefix_desired_place[i - 1] : suffix_des_place; 00304 /* limit moves to ensure that the prefix is placed before the suffix */ 00305 if (suffix_des_place < prefix_des_place) { 00306 if (suffix_des_place < cur_place) { 00307 if (prefix_des_place > cur_place) { 00308 prefix_des_place = cur_place; 00309 } 00310 suffix_des_place = prefix_des_place; 00311 } else if (prefix_des_place > cur_place) { 00312 prefix_des_place = suffix_des_place; 00313 } 00314 } 00315 movement = 00316 (block_len - i) * fabs(suffix_des_place - cur_place) + 00317 i * fabs(prefix_des_place - cur_place); 00318 if (movement > max_movement) { 00319 max_movement = movement; 00320 best_i = i; 00321 } 00322 } 00323 /* Actually move prefix and suffix */ 00324 if (best_i >= 0) { 00325 suffix_des_place = suffix_desired_place[best_i]; 00326 prefix_des_place = 00327 best_i > 00328 0 ? prefix_desired_place[best_i - 00329 1] : suffix_des_place; 00330 00331 /* compute right border of feasible move */ 00332 if (right >= n) { 00333 /* no nodes after current block */ 00334 upper_bound = 1e9; 00335 } else { 00336 upper_bound = place[ordering[right]]; 00337 } 00338 suffix_des_place = MIN(suffix_des_place, upper_bound); 00339 prefix_des_place = MAX(prefix_des_place, lower_bound); 00340 00341 /* limit moves to ensure that the prefix is placed before the suffix */ 00342 if (suffix_des_place < prefix_des_place) { 00343 if (suffix_des_place < cur_place) { 00344 if (prefix_des_place > cur_place) { 00345 prefix_des_place = cur_place; 00346 } 00347 suffix_des_place = prefix_des_place; 00348 } else if (prefix_des_place > cur_place) { 00349 prefix_des_place = suffix_des_place; 00350 } 00351 } 00352 00353 /* move prefix: */ 00354 for (i = 0; i < best_i; i++) { 00355 place[block[i]] = prefix_des_place; 00356 } 00357 /* move suffix: */ 00358 for (i = best_i; i < block_len; i++) { 00359 place[block[i]] = suffix_des_place; 00360 } 00361 00362 lower_bound = suffix_des_place; /* lower bound for next block */ 00363 00364 /* reorder 'ordering' to reflect change of places 00365 * Note that it is enough to reorder the level where 00366 * the split was done 00367 */ 00368 #if 0 00369 int max_in_level, min_in_level; 00370 00371 level = lev[best_i]; 00372 if (level == num_levels) { 00373 /* last_level */ 00374 max_in_level = MIN(right, n); 00375 } else { 00376 max_in_level = MIN(right, levels[level]); 00377 } 00378 if (level == 0) { 00379 /* first level */ 00380 min_in_level = MAX(left, 0); 00381 } else { 00382 min_in_level = MAX(left, levels[level - 1]); 00383 } 00384 #endif 00385 for (i = left; i < right; i++) { 00386 ordering[i] = block[i - left]; 00387 } 00388 converged = converged 00389 && fabs(prefix_des_place - cur_place) < quad_prog_tol 00390 && fabs(suffix_des_place - cur_place) < quad_prog_tol; 00391 00392 } else { 00393 /* no movement */ 00394 lower_bound = cur_place; /* lower bound for next block */ 00395 } 00396 00397 } 00398 } 00399 00400 computeHierarchyBoundaries(place, n, ordering, levels, num_levels, 00401 hierarchy_boundaries); 00402 00403 return counter; 00404 } 00405 00406 #ifdef IPSEPCOLA 00407 static float *place; 00408 static int compare_incr(const void *a, const void *b) 00409 { 00410 if (place[*(int *) a] > place[*(int *) b]) { 00411 return 1; 00412 } else if (place[*(int *) a] < place[*(int *) b]) { 00413 return -1; 00414 } 00415 return 0; 00416 } 00417 00418 /* 00419 While not converged: move everything towards the optimum, then satisfy constraints with as little displacement as possible. 00420 Returns number of iterations before convergence. 00421 */ 00422 int constrained_majorization_gradient_projection(CMajEnv * e, 00423 float *b, float **coords, 00424 int ndims, int cur_axis, 00425 int max_iterations, 00426 float 00427 *hierarchy_boundaries, 00428 float levels_gap) 00429 { 00430 00431 int i, j, counter; 00432 int *ordering = e->ordering; 00433 int *levels = e->levels; 00434 int num_levels = e->num_levels; 00435 boolean converged = FALSE; 00436 float *g = e->fArray1; 00437 float *old_place = e->fArray2; 00438 float *d = e->fArray4; 00439 float test = 0, tmptest = 0; 00440 float beta; 00441 00442 if (max_iterations == 0) 00443 return 0; 00444 00445 place = coords[cur_axis]; 00446 #ifdef CONMAJ_LOGGING 00447 double prev_stress = 0; 00448 static int call_no = 0; 00449 for (i = 0; i < e->n; i++) { 00450 prev_stress += 2 * b[i] * place[i]; 00451 for (j = 0; j < e->n; j++) { 00452 prev_stress -= e->A[i][j] * place[j] * place[i]; 00453 } 00454 } 00455 FILE *logfile = fopen("constrained_majorization_log", "a"); 00456 00457 fprintf(logfile, "grad proj %d: stress=%f\n", call_no, prev_stress); 00458 #endif 00459 for (counter = 0; counter < max_iterations && !converged; counter++) { 00460 float alpha; 00461 float numerator = 0, denominator = 0, r; 00462 converged = TRUE; 00463 /* find steepest descent direction */ 00464 for (i = 0; i < e->n; i++) { 00465 old_place[i] = place[i]; 00466 g[i] = 2 * b[i]; 00467 for (j = 0; j < e->n; j++) { 00468 g[i] -= 2 * e->A[i][j] * place[j]; 00469 } 00470 } 00471 for (i = 0; i < e->n; i++) { 00472 numerator += g[i] * g[i]; 00473 r = 0; 00474 for (j = 0; j < e->n; j++) { 00475 r += 2 * e->A[i][j] * g[j]; 00476 } 00477 denominator -= r * g[i]; 00478 } 00479 alpha = numerator / denominator; 00480 for (i = 0; i < e->n; i++) { 00481 if (alpha > 0 && alpha < 1000) { 00482 place[i] -= alpha * g[i]; 00483 } 00484 } 00485 if (num_levels) 00486 qsort((int *) ordering, (size_t) levels[0], sizeof(int), 00487 compare_incr); 00488 /* project to constraint boundary */ 00489 for (i = 0; i < num_levels; i++) { 00490 int endOfLevel = i == num_levels - 1 ? e->n : levels[i + 1]; 00491 int ui, li, u, l; 00492 00493 /* ensure monotic increase in position within levels */ 00494 qsort((int *) ordering + levels[i], 00495 (size_t) endOfLevel - levels[i], sizeof(int), 00496 compare_incr); 00497 /* If there are overlapping levels find offending nodes and place at average position */ 00498 ui = levels[i]; li = ui - 1; 00499 l = ordering[li--]; u = ordering[ui++]; 00500 if (place[l] + levels_gap > place[u]) { 00501 float sum = 00502 place[l] + place[u] - levels_gap * (e->lev[l] + 00503 e->lev[u]), w = 2; 00504 float avgPos = sum / w; 00505 float pos; 00506 boolean finished; 00507 do { 00508 finished = TRUE; 00509 if (ui < endOfLevel) { 00510 u = ordering[ui]; 00511 pos = place[u] - levels_gap * e->lev[u]; 00512 if (pos < avgPos) { 00513 ui++; 00514 w++; 00515 sum += pos; 00516 avgPos = sum / w; 00517 finished = FALSE; 00518 } 00519 } 00520 00521 if (li >= 0) { 00522 l = ordering[li]; 00523 pos = place[l] - levels_gap * e->lev[l]; 00524 if (pos > avgPos) { 00525 li--; 00526 w++; 00527 sum += pos; 00528 avgPos = sum / w; 00529 finished = FALSE; 00530 } 00531 } 00532 } while (!finished); 00533 for (j = li + 1; j < ui; j++) { 00534 place[ordering[j]] = 00535 avgPos + levels_gap * e->lev[ordering[j]]; 00536 } 00537 } 00538 } 00539 /* set place to the intersection of old_place-g and boundary and compute d, the vector from intersection pnt to projection pnt */ 00540 for (i = 0; i < e->n; i++) { 00541 d[i] = place[i] - old_place[i]; 00542 } 00543 /* now compute beta */ 00544 numerator = 0, denominator = 0; 00545 for (i = 0; i < e->n; i++) { 00546 numerator += g[i] * d[i]; 00547 r = 0; 00548 for (j = 0; j < e->n; j++) { 00549 r += 2 * e->A[i][j] * d[j]; 00550 } 00551 denominator += r * d[i]; 00552 } 00553 beta = numerator / denominator; 00554 00555 for (i = 0; i < e->n; i++) { 00556 if (beta > 0 && beta < 1.0) { 00557 place[i] = old_place[i] + beta * d[i]; 00558 } 00559 tmptest = fabs(place[i] - old_place[i]); 00560 if (test < tmptest) 00561 test = tmptest; 00562 } 00563 computeHierarchyBoundaries(place, e->n, ordering, levels, 00564 num_levels, hierarchy_boundaries); 00565 #if 0 00566 if (num_levels) 00567 qsort((int *) ordering, (size_t) levels[0], sizeof(int), 00568 compare_incr); 00569 for (i = 0; i < num_levels; i++) { 00570 int endOfLevel = i == num_levels - 1 ? e->n : levels[i + 1]; 00571 /* ensure monotic increase in position within levels */ 00572 qsort((int *) ordering + levels[i], 00573 (size_t) endOfLevel - levels[i], sizeof(int), 00574 compare_incr); 00575 /* If there are overlapping levels find offending nodes and place at average position */ 00576 int l = ordering[levels[i] - 1], u = ordering[levels[i]]; 00577 /* assert(place[l]+levels_gap<=place[u]+0.00001); */ 00578 } 00579 #endif 00580 #ifdef CONMAJ_LOGGING 00581 double stress = 0; 00582 for (i = 0; i < e->n; i++) { 00583 stress += 2 * b[i] * place[i]; 00584 for (j = 0; j < e->n; j++) { 00585 stress -= e->A[i][j] * place[j] * place[i]; 00586 } 00587 } 00588 fprintf(logfile, "%d: stress=%f, test=%f, %s\n", call_no, stress, 00589 test, (stress >= prev_stress) ? "No Improvement" : ""); 00590 prev_stress = stress; 00591 #endif 00592 if (test > quad_prog_tol) { 00593 converged = FALSE; 00594 } 00595 } 00596 #ifdef CONMAJ_LOGGING 00597 call_no++; 00598 fclose(logfile); 00599 #endif 00600 return counter; 00601 } 00602 #endif 00603 00604 int 00605 constrained_majorization_new_with_gaps(CMajEnv * e, float *b, 00606 float **coords, int ndims, 00607 int cur_axis, int max_iterations, 00608 float *hierarchy_boundaries, 00609 float levels_gap) 00610 { 00611 float *place = coords[cur_axis]; 00612 int i, j; 00613 int n = e->n; 00614 float **lap = e->A; 00615 int *ordering = e->ordering; 00616 int *levels = e->levels; 00617 int num_levels = e->num_levels; 00618 float new_place_i; 00619 boolean converged = FALSE; 00620 float upper_bound, lower_bound; 00621 int node; 00622 int left, right; 00623 float cur_place; 00624 float des_place_block; 00625 float block_deg; 00626 float toBlockConnectivity; 00627 float *lap_node; 00628 float *desired_place; 00629 float *prefix_desired_place; 00630 float *suffix_desired_place; 00631 int *block; 00632 int block_len; 00633 int first_next_level; 00634 int *lev; 00635 int level = -1, max_in_level = 0; 00636 int counter; 00637 float *gap; 00638 float total_gap, target_place; 00639 00640 if (max_iterations <= 0) { 00641 return 0; 00642 } 00643 00644 ensureMonotonicOrderingWithGaps(place, n, ordering, levels, num_levels, 00645 levels_gap); 00646 /* it is important that in 'ordering' nodes are always sorted by layers, 00647 * and within a layer by 'place' 00648 */ 00649 00650 /* the desired place of each individual node in the current block */ 00651 desired_place = e->fArray1; 00652 /* the desired place of each prefix of current block */ 00653 prefix_desired_place = e->fArray2; 00654 /* the desired place of each suffix of current block */ 00655 suffix_desired_place = e->fArray3; 00656 /* current block (nodes connected by active constraints) */ 00657 block = e->iArray1; 00658 00659 lev = e->iArray2; /* level of each node */ 00660 for (i = 0; i < n; i++) { 00661 if (i >= max_in_level) { 00662 /* we are entering a new level */ 00663 level++; 00664 if (level == num_levels) { 00665 /* last_level */ 00666 max_in_level = n; 00667 } else { 00668 max_in_level = levels[level]; 00669 } 00670 } 00671 node = ordering[i]; 00672 lev[node] = level; 00673 } 00674 00675 /* displacement of block's nodes from block's reference point */ 00676 gap = e->fArray4; 00677 00678 for (counter = 0; counter < max_iterations && !converged; counter++) { 00679 converged = TRUE; 00680 lower_bound = -1e9; /* no lower bound for first level */ 00681 for (left = 0; left < n; left = right) { 00682 int best_i; 00683 double max_movement; 00684 double movement; 00685 float prefix_des_place, suffix_des_place; 00686 /* compute a block 'ordering[left]...ordering[right-1]' of 00687 * nodes connected with active constraints 00688 */ 00689 cur_place = place[ordering[left]]; 00690 total_gap = 0; 00691 target_place = cur_place; 00692 gap[ordering[left]] = 0; 00693 for (right = left + 1; right < n; right++) { 00694 if (lev[right] > lev[right - 1]) { 00695 /* we are entering a new level */ 00696 target_place += levels_gap; /* note that 'levels_gap' may be negative */ 00697 total_gap += levels_gap; 00698 } 00699 node = ordering[right]; 00700 #if 0 00701 if (place[node] != target_place) 00702 #endif 00703 /* not sure if this is better than 'place[node]!=target_place' */ 00704 if (fabs(place[node] - target_place) > 1e-9) { 00705 break; 00706 } 00707 gap[node] = place[node] - cur_place; 00708 } 00709 00710 /* compute desired place of block's reference point according 00711 * to each node in the block: 00712 */ 00713 for (i = left; i < right; i++) { 00714 node = ordering[i]; 00715 new_place_i = -b[node]; 00716 lap_node = lap[node]; 00717 for (j = 0; j < n; j++) { 00718 if (j == node) { 00719 continue; 00720 } 00721 new_place_i += lap_node[j] * place[j]; 00722 } 00723 desired_place[node] = 00724 new_place_i / (-lap_node[node]) - gap[node]; 00725 } 00726 00727 /* reorder block by levels, and within levels 00728 * by "relaxed" desired position 00729 */ 00730 block_len = 0; 00731 first_next_level = 0; 00732 for (i = left; i < right; i = first_next_level) { 00733 level = lev[ordering[i]]; 00734 if (level == num_levels) { 00735 /* last_level */ 00736 first_next_level = right; 00737 } else { 00738 first_next_level = MIN(right, levels[level]); 00739 } 00740 00741 /* First, collect all nodes with desired places smaller 00742 * than current place 00743 */ 00744 for (j = i; j < first_next_level; j++) { 00745 node = ordering[j]; 00746 if (desired_place[node] < cur_place) { 00747 block[block_len++] = node; 00748 } 00749 } 00750 /* Second, collect all nodes with desired places equal 00751 * to current place 00752 */ 00753 for (j = i; j < first_next_level; j++) { 00754 node = ordering[j]; 00755 if (desired_place[node] == cur_place) { 00756 block[block_len++] = node; 00757 } 00758 } 00759 /* Third, collect all nodes with desired places greater 00760 * than current place 00761 */ 00762 for (j = i; j < first_next_level; j++) { 00763 node = ordering[j]; 00764 if (desired_place[node] > cur_place) { 00765 block[block_len++] = node; 00766 } 00767 } 00768 } 00769 00770 /* loop through block and compute desired places of its prefixes */ 00771 des_place_block = 0; 00772 block_deg = 0; 00773 for (i = 0; i < block_len; i++) { 00774 node = block[i]; 00775 toBlockConnectivity = 0; 00776 lap_node = lap[node]; 00777 for (j = 0; j < i; j++) { 00778 toBlockConnectivity -= lap_node[block[j]]; 00779 } 00780 toBlockConnectivity *= 2; 00781 /* update block stats */ 00782 des_place_block = 00783 (block_deg * des_place_block + 00784 (-lap_node[node]) * desired_place[node] + 00785 toBlockConnectivity * cur_place) / (block_deg - 00786 lap_node[node] + 00787 toBlockConnectivity); 00788 prefix_desired_place[i] = des_place_block; 00789 block_deg += toBlockConnectivity - lap_node[node]; 00790 } 00791 00792 if (block_len == n) { 00793 /* fix is needed since denominator was 0 in this case */ 00794 prefix_desired_place[n - 1] = cur_place; /* a "neutral" value */ 00795 } 00796 00797 /* loop through block and compute desired places of its suffixes */ 00798 des_place_block = 0; 00799 block_deg = 0; 00800 for (i = block_len - 1; i >= 0; i--) { 00801 node = block[i]; 00802 toBlockConnectivity = 0; 00803 lap_node = lap[node]; 00804 for (j = i + 1; j < block_len; j++) { 00805 toBlockConnectivity -= lap_node[block[j]]; 00806 } 00807 toBlockConnectivity *= 2; 00808 /* update block stats */ 00809 des_place_block = 00810 (block_deg * des_place_block + 00811 (-lap_node[node]) * desired_place[node] + 00812 toBlockConnectivity * cur_place) / (block_deg - 00813 lap_node[node] + 00814 toBlockConnectivity); 00815 suffix_desired_place[i] = des_place_block; 00816 block_deg += toBlockConnectivity - lap_node[node]; 00817 } 00818 00819 if (block_len == n) { 00820 /* fix is needed since denominator was 0 in this case */ 00821 suffix_desired_place[0] = cur_place; /* a "neutral" value? */ 00822 } 00823 00824 00825 /* now, find best place to split block */ 00826 best_i = -1; 00827 max_movement = 0; 00828 for (i = 0; i < block_len; i++) { 00829 suffix_des_place = suffix_desired_place[i]; 00830 prefix_des_place = 00831 i > 0 ? prefix_desired_place[i - 1] : suffix_des_place; 00832 /* limit moves to ensure that the prefix is placed before the suffix */ 00833 if (suffix_des_place < prefix_des_place) { 00834 if (suffix_des_place < cur_place) { 00835 if (prefix_des_place > cur_place) { 00836 prefix_des_place = cur_place; 00837 } 00838 suffix_des_place = prefix_des_place; 00839 } else if (prefix_des_place > cur_place) { 00840 prefix_des_place = suffix_des_place; 00841 } 00842 } 00843 movement = 00844 (block_len - i) * fabs(suffix_des_place - cur_place) + 00845 i * fabs(prefix_des_place - cur_place); 00846 if (movement > max_movement) { 00847 max_movement = movement; 00848 best_i = i; 00849 } 00850 } 00851 /* Actually move prefix and suffix */ 00852 if (best_i >= 0) { 00853 suffix_des_place = suffix_desired_place[best_i]; 00854 prefix_des_place = 00855 best_i > 00856 0 ? prefix_desired_place[best_i - 00857 1] : suffix_des_place; 00858 00859 /* compute right border of feasible move */ 00860 if (right >= n) { 00861 /* no nodes after current block */ 00862 upper_bound = 1e9; 00863 } else { 00864 /* notice that we have to deduct 'gap[block[block_len-1]]' 00865 * since all computations should be relative to 00866 * the block's reference point 00867 */ 00868 if (lev[ordering[right]] > lev[ordering[right - 1]]) { 00869 upper_bound = 00870 place[ordering[right]] - levels_gap - 00871 gap[block[block_len - 1]]; 00872 } else { 00873 upper_bound = 00874 place[ordering[right]] - 00875 gap[block[block_len - 1]]; 00876 } 00877 } 00878 suffix_des_place = MIN(suffix_des_place, upper_bound); 00879 prefix_des_place = MAX(prefix_des_place, lower_bound); 00880 00881 /* limit moves to ensure that the prefix is placed before the suffix */ 00882 if (suffix_des_place < prefix_des_place) { 00883 if (suffix_des_place < cur_place) { 00884 if (prefix_des_place > cur_place) { 00885 prefix_des_place = cur_place; 00886 } 00887 suffix_des_place = prefix_des_place; 00888 } else if (prefix_des_place > cur_place) { 00889 prefix_des_place = suffix_des_place; 00890 } 00891 } 00892 00893 /* move prefix: */ 00894 for (i = 0; i < best_i; i++) { 00895 place[block[i]] = prefix_des_place + gap[block[i]]; 00896 } 00897 /* move suffix: */ 00898 for (i = best_i; i < block_len; i++) { 00899 place[block[i]] = suffix_des_place + gap[block[i]]; 00900 } 00901 00902 00903 /* compute lower bound for next block */ 00904 if (right < n 00905 && lev[ordering[right]] > lev[ordering[right - 1]]) { 00906 lower_bound = place[block[block_len - 1]] + levels_gap; 00907 } else { 00908 lower_bound = place[block[block_len - 1]]; 00909 } 00910 00911 00912 /* reorder 'ordering' to reflect change of places 00913 * Note that it is enough to reorder the level where 00914 * the split was done 00915 */ 00916 #if 0 00917 int max_in_level, min_in_level; 00918 00919 level = lev[best_i]; 00920 if (level == num_levels) { 00921 /* last_level */ 00922 max_in_level = MIN(right, n); 00923 } else { 00924 max_in_level = MIN(right, levels[level]); 00925 } 00926 if (level == 0) { 00927 /* first level */ 00928 min_in_level = MAX(left, 0); 00929 } else { 00930 min_in_level = MAX(left, levels[level - 1]); 00931 } 00932 #endif 00933 for (i = left; i < right; i++) { 00934 ordering[i] = block[i - left]; 00935 } 00936 converged = converged 00937 && fabs(prefix_des_place - cur_place) < quad_prog_tol 00938 && fabs(suffix_des_place - cur_place) < quad_prog_tol; 00939 00940 00941 } else { 00942 /* no movement */ 00943 /* compute lower bound for next block */ 00944 if (right < n 00945 && lev[ordering[right]] > lev[ordering[right - 1]]) { 00946 lower_bound = place[block[block_len - 1]] + levels_gap; 00947 } else { 00948 lower_bound = place[block[block_len - 1]]; 00949 } 00950 } 00951 } 00952 orthog1f(n, place); /* for numerical stability, keep ||place|| small */ 00953 computeHierarchyBoundaries(place, n, ordering, levels, num_levels, 00954 hierarchy_boundaries); 00955 } 00956 00957 return counter; 00958 } 00959 00960 void deleteCMajEnv(CMajEnv * e) 00961 { 00962 free(e->A[0]); 00963 free(e->A); 00964 free(e->lev); 00965 free(e->fArray1); 00966 free(e->fArray2); 00967 free(e->fArray3); 00968 free(e->fArray4); 00969 free(e->iArray1); 00970 free(e->iArray2); 00971 free(e->iArray3); 00972 free(e->iArray4); 00973 free(e); 00974 } 00975 00976 CMajEnv *initConstrainedMajorization(float *packedMat, int n, 00977 int *ordering, int *levels, 00978 int num_levels) 00979 { 00980 int i, level = -1, start_of_level_above = 0; 00981 CMajEnv *e = GNEW(CMajEnv); 00982 e->A = NULL; 00983 e->n = n; 00984 e->ordering = ordering; 00985 e->levels = levels; 00986 e->num_levels = num_levels; 00987 e->A = unpackMatrix(packedMat, n); 00988 e->lev = N_GNEW(n, int); 00989 for (i = 0; i < e->n; i++) { 00990 if (i >= start_of_level_above) { 00991 level++; 00992 start_of_level_above = 00993 (level == num_levels) ? e->n : levels[level]; 00994 } 00995 e->lev[ordering[i]] = level; 00996 } 00997 e->fArray1 = N_GNEW(n, float); 00998 e->fArray2 = N_GNEW(n, float); 00999 e->fArray3 = N_GNEW(n, float); 01000 e->fArray4 = N_GNEW(n, float); 01001 e->iArray1 = N_GNEW(n, int); 01002 e->iArray2 = N_GNEW(n, int); 01003 e->iArray3 = N_GNEW(n, int); 01004 e->iArray4 = N_GNEW(n, int); 01005 return e; 01006 } 01007 #endif /* DIGCOLA */
1.7.5