Graphviz  2.29.20120523.0446
lib/neatogen/circuit.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 /*
00015  * this implements the resistor circuit current model for
00016  * computing node distance, as an alternative to shortest-path.
00017  * likely it could be improved by using edge weights, somehow.
00018  * Return 1 if successful; 0 otherwise (e.g., graph is disconnected).
00019  */
00020 #include        "neato.h"
00021 
00022 int solveCircuit(int nG, double **Gm, double **Gm_inv)
00023 {
00024     double sum;
00025     int i, j;
00026 
00027     if (Verbose)
00028         fprintf(stderr, "Calculating circuit model");
00029 
00030     /* set diagonal entries to sum of conductances but ignore nth node */
00031     for (i = 0; i < nG; i++) {
00032         sum = 0.0;
00033         for (j = 0; j < nG; j++)
00034             if (i != j)
00035                 sum += Gm[i][j];
00036         Gm[i][i] = -sum;
00037     }
00038     return matinv(Gm, Gm_inv, nG - 1);
00039 }
00040 
00041 int circuit_model(graph_t * g, int nG)
00042 {
00043     double **Gm;
00044     double **Gm_inv;
00045     int rv;
00046     long i, j;
00047     node_t *v;
00048     edge_t *e;
00049 
00050     Gm = new_array(nG, nG, 0.0);
00051     Gm_inv = new_array(nG, nG, 0.0);
00052 
00053     /* set non-diagonal entries */
00054     for (v = agfstnode(g); v; v = agnxtnode(g, v)) {
00055         for (e = agfstedge(g, v); e; e = agnxtedge(g, e, v)) {
00056             i = AGSEQ(agtail(e));
00057             j = AGSEQ(aghead(e));
00058             if (i == j)
00059                 continue;
00060             /* conductance is 1/resistance */
00061             Gm[i][j] = Gm[j][i] = -1.0 / ED_dist(e);    /* negate */
00062         }
00063     }
00064 
00065     rv = solveCircuit(nG, Gm, Gm_inv);
00066 
00067     if (rv)
00068         for (i = 0; i < nG; i++) {
00069             for (j = 0; j < nG; j++) {
00070                 GD_dist(g)[i][j] =
00071                     Gm_inv[i][i] + Gm_inv[j][j] - 2.0 * Gm_inv[i][j];
00072             }
00073         }
00074     free_array(Gm);
00075     free_array(Gm_inv);
00076     return rv;
00077 }