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

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

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