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

Go to the documentation of this file.
00001 /* $Id: compute_hierarchy.c,v 1.3 2006/04/28 20:33:44 ellson Exp $ $Revision: 1.3 $ */
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 "kkutils.h"
00020 
00021 static int* given_levels = NULL;
00022 /*
00023  * This function partitions the graph nodes into levels
00024  * according to the minimizer of the hierarchy energy.
00025  * 
00026  * To allow more flexibility we define a new level only 
00027  * when the hierarchy energy shows a significant jump
00028  * (to compensate for noise).
00029  * This is controlled by two parameters: 'abs_tol' and 
00030  * 'relative_tol'. The smaller these two are, the more 
00031  * levels we'll get. 
00032  * More speciffically:
00033  * We never consider gaps smaller than 'abs_tol'
00034  * Additionally, we never consider gaps smaller than 'abs_tol'*<avg_gap>
00035  * 
00036  * The output is an ordering of the nodes according to 
00037  * their levels, as follows:
00038  *   First level: 
00039  *     ordering[0],ordering[1],...ordering[levels[0]-1]
00040  *   Second level: 
00041  *     ordering[levels[0]],ordering[levels[0]+1],...ordering[levels[1]-1]
00042  *   ...
00043  *   Last level: 
00044  *     ordering[levels[num_levels-1]],ordering[levels[num_levels-1]+1],...ordering[n-1]
00045  * 
00046  * Hence, the nodes were partitioned into 'num_levels'+1
00047  * levels.
00048  * 
00049  * Please note that 'ordering[levels[i]]' contains the first node at level i+1,
00050  *  and not the last node of level i.
00051  */
00052 double 
00053 compute_hierarchy(vtx_data* graph, int n, double abs_tol, double relative_tol, 
00054       double* given_coords, int** orderingp, int** levelsp, int* num_levelsp) 
00055 {
00056         double* y;
00057         int i;
00058         double spread;
00059         int use_given_levels=FALSE;
00060     int* ordering;
00061     int* levels;
00062         double tol; /* node 'i' precedes 'j' in hierachy iff y[i]-y[j]>tol */
00063         double hierarchy_span;
00064     int num_levels;
00065 
00066         /* compute optimizer of hierarchy energy: 'y' */
00067         if (given_coords) {
00068                 y = given_coords;
00069         }
00070         else {
00071                 y = N_GNEW(n,double);
00072                 compute_y_coords(graph, n, y, n);
00073         }
00074 
00075         /* sort nodes accoridng to their y-ordering */
00076         *orderingp = ordering = N_NEW(n, int);
00077         for (i=0; i<n; i++) {
00078                 ordering[i] = i;
00079         }
00080         quicksort_place(y, ordering, 0,n-1);    
00081         
00082         spread = y[ordering[n-1]]-y[ordering[0]];
00083 
00084         /* after spread is computed, we may take the y-coords as the given levels */
00085         if (given_levels) {
00086                 use_given_levels=TRUE;
00087                 for (i=0; i<n; i++) {
00088                         use_given_levels = use_given_levels && given_levels[i]>=0;
00089                 }
00090         }
00091         if (use_given_levels) {
00092                 for (i=0; i<n; i++) {
00093                         y[i] = given_levels[i];
00094                         ordering[i] = i;
00095                 }
00096                 quicksort_place(y,  ordering, 0,n-1);
00097         }
00098         
00099         /* compute tolerance
00100          * take the maximum between 'abs_tol' and a fraction of the average gap
00101          * controlled by 'relative_tol'
00102      */
00103         hierarchy_span = y[ordering[n-1]]-y[ordering[0]];
00104         tol = MAX(abs_tol, relative_tol*hierarchy_span/(n-1)); 
00105         /* 'hierarchy_span/(n-1)' - average gap between consecutive nodes */
00106 
00107         
00108         /* count how many levels the hierarchy contains (a SINGLE_LINK clustering */
00109     /* alternatively we could use COMPLETE_LINK clustering) */
00110         num_levels = 0;
00111         for (i=1; i<n; i++) {
00112                 if (y[ordering[i]] - y[ordering[i-1]] > tol) {
00113                         num_levels++;
00114                 }
00115         }
00116         *num_levelsp = num_levels;
00117         if (num_levels==0) {
00118                 *levelsp = levels = N_GNEW(1, int);
00119                 levels[0] = n;
00120         }
00121         else {
00122                 int count=0;
00123                 *levelsp = levels = N_GNEW(num_levels, int);
00124                 for (i=1; i<n; i++) {
00125                         if (y[ordering[i]] - y[ordering[i-1]] > tol) {
00126                                 levels[count++] = i;
00127                         }
00128                 }
00129         }
00130         if (!given_coords) {
00131                 free(y);
00132         }
00133 
00134         return spread;
00135 }
00136 
00137 #endif /* DIGCOLA */
00138 

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