1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
|
/*************************************************************************
* Copyright (c) 2011 AT&T Intellectual Property
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors: Details at https://graphviz.org
*************************************************************************/
/*
* this implements the resistor circuit current model for
* computing node distance, as an alternative to shortest-path.
* likely it could be improved by using edge weights, somehow.
* Return 1 if successful; 0 otherwise (e.g., graph is disconnected).
*/
#include <neatogen/neato.h>
int solveCircuit(int nG, double **Gm, double **Gm_inv)
{
double sum;
int i, j;
if (Verbose)
fprintf(stderr, "Calculating circuit model");
/* set diagonal entries to sum of conductances but ignore nth node */
for (i = 0; i < nG; i++) {
sum = 0.0;
for (j = 0; j < nG; j++)
if (i != j)
sum += Gm[i][j];
Gm[i][i] = -sum;
}
return matinv(Gm, Gm_inv, nG - 1);
}
int circuit_model(graph_t * g, int nG)
{
double **Gm;
double **Gm_inv;
int rv;
long i, j;
node_t *v;
edge_t *e;
Gm = new_array(nG, nG, 0.0);
Gm_inv = new_array(nG, nG, 0.0);
/* set non-diagonal entries */
for (v = agfstnode(g); v; v = agnxtnode(g, v)) {
for (e = agfstedge(g, v); e; e = agnxtedge(g, e, v)) {
i = AGSEQ(agtail(e));
j = AGSEQ(aghead(e));
if (i == j)
continue;
/* conductance is 1/resistance */
Gm[i][j] = Gm[j][i] = -1.0 / ED_dist(e); /* negate */
}
}
rv = solveCircuit(nG, Gm, Gm_inv);
if (rv)
for (i = 0; i < nG; i++) {
for (j = 0; j < nG; j++) {
GD_dist(g)[i][j] =
Gm_inv[i][i] + Gm_inv[j][j] - 2.0 * Gm_inv[i][j];
}
}
free_array(Gm);
free_array(Gm_inv);
return rv;
}
|