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