Graphviz  2.31.20130618.0446
lib/neatogen/opt_arrangement.c
Go to the documentation of this file.
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 "matrix_ops.h"
00017 #include "conjgrad.h"
00018 
00019 static void construct_b(vtx_data * graph, int n, double *b)
00020 {
00021     /* construct a vector - b s.t. -b[i]=\sum_j -w_{ij}*\delta_{ij}
00022      * (the "balance vector")
00023      * Note that we build -b and not b, since our matrix is not the 
00024      * real laplacian L, but its negation: -L. 
00025      * So instead of solving Lx=b, we will solve -Lx=-b
00026      */
00027     int i, j;
00028 
00029     double b_i = 0;
00030 
00031     for (i = 0; i < n; i++) {
00032         b_i = 0;
00033         if (graph[0].edists == NULL) {
00034             continue;
00035         }
00036         for (j = 1; j < graph[i].nedges; j++) { /* skip the self loop */
00037             b_i += graph[i].ewgts[j] * graph[i].edists[j];
00038         }
00039         b[i] = b_i;
00040     }
00041 }
00042 
00043 #define hierarchy_cg_tol 1e-3
00044 
00045 int
00046 compute_y_coords(vtx_data * graph, int n, double *y_coords,
00047                  int max_iterations)
00048 {
00049     /* Find y coords of a directed graph by solving L*x = b */
00050     int i, j, rv = 0;
00051     double *b = N_NEW(n, double);
00052     double tol = hierarchy_cg_tol;
00053     int nedges = 0;
00054     float *uniform_weights;
00055     float *old_ewgts = graph[0].ewgts;
00056 
00057     construct_b(graph, n, b);
00058 
00059     init_vec_orth1(n, y_coords);
00060 
00061     for (i = 0; i < n; i++) {
00062         nedges += graph[i].nedges;
00063     }
00064 
00065     /* replace original edge weights (which are lengths) with uniform weights */
00066     /* for computing the optimal arrangement */
00067     uniform_weights = N_GNEW(nedges, float);
00068     for (i = 0; i < n; i++) {
00069         graph[i].ewgts = uniform_weights;
00070         uniform_weights[0] = (float) -(graph[i].nedges - 1);
00071         for (j = 1; j < graph[i].nedges; j++) {
00072             uniform_weights[j] = 1;
00073         }
00074         uniform_weights += graph[i].nedges;
00075     }
00076 
00077     if (conjugate_gradient(graph, y_coords, b, n, tol, max_iterations) < 0) {
00078         rv = 1;
00079     }
00080 
00081     /* restore original edge weights */
00082     free(graph[0].ewgts);
00083     for (i = 0; i < n; i++) {
00084         graph[i].ewgts = old_ewgts;
00085         old_ewgts += graph[i].nedges;
00086     }
00087 
00088     free(b);
00089     return rv;
00090 }
00091 
00092 #endif                          /* DIGCOLA */