Graphviz 12.0.1~dev.20240716.0800
Loading...
Searching...
No Matches
opt_arrangement.c
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (c) 2011 AT&T Intellectual Property
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors: Details at https://graphviz.org
9 *************************************************************************/
10
11#include <cgraph/alloc.h>
12#include <neatogen/digcola.h>
13#ifdef DIGCOLA
14#include <neatogen/matrix_ops.h>
15#include <neatogen/conjgrad.h>
16#include <stddef.h>
17
18static void construct_b(vtx_data * graph, int n, double *b)
19{
20 /* construct a vector - b s.t. -b[i]=\sum_j -w_{ij}*\delta_{ij}
21 * (the "balance vector")
22 * Note that we build -b and not b, since our matrix is not the
23 * real laplacian L, but its negation: -L.
24 * So instead of solving Lx=b, we will solve -Lx=-b
25 */
26 int i;
27
28 double b_i = 0;
29
30 for (i = 0; i < n; i++) {
31 b_i = 0;
32 if (graph[0].edists == NULL) {
33 continue;
34 }
35 for (size_t j = 1; j < graph[i].nedges; j++) { // skip the self loop
36 b_i += graph[i].ewgts[j] * graph[i].edists[j];
37 }
38 b[i] = b_i;
39 }
40}
41
42#define hierarchy_cg_tol 1e-3
43
44int
45compute_y_coords(vtx_data * graph, int n, double *y_coords,
46 int max_iterations)
47{
48 /* Find y coords of a directed graph by solving L*x = b */
49 int i, rv = 0;
50 double *b = gv_calloc(n, sizeof(double));
51 double tol = hierarchy_cg_tol;
52 size_t nedges = 0;
53 float *old_ewgts = graph[0].ewgts;
54
55 construct_b(graph, n, b);
56
57 init_vec_orth1(n, y_coords);
58
59 for (i = 0; i < n; i++) {
60 nedges += graph[i].nedges;
61 }
62
63 /* replace original edge weights (which are lengths) with uniform weights */
64 /* for computing the optimal arrangement */
65 float *uniform_weights = gv_calloc(nedges, sizeof(float));
66 for (i = 0; i < n; i++) {
67 graph[i].ewgts = uniform_weights;
68 uniform_weights[0] = -(float)(graph[i].nedges - 1);
69 for (size_t j = 1; j < graph[i].nedges; j++) {
70 uniform_weights[j] = 1;
71 }
72 uniform_weights += graph[i].nedges;
73 }
74
75 if (conjugate_gradient(graph, y_coords, b, n, tol, max_iterations) < 0) {
76 rv = 1;
77 }
78
79 /* restore original edge weights */
80 free(graph[0].ewgts);
81 for (i = 0; i < n; i++) {
82 graph[i].ewgts = old_ewgts;
83 old_ewgts += graph[i].nedges;
84 }
85
86 free(b);
87 return rv;
88}
89
90#endif /* DIGCOLA */
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
Definition alloc.h:26
int conjugate_gradient(vtx_data *A, double *x, double *b, int n, double tol, int max_iterations)
Definition conjgrad.c:23
void free(void *)
node NULL
Definition grammar.y:149
Agraph_t * graph(char *name)
Definition gv.cpp:31
void init_vec_orth1(int n, double *vec)
Definition matrix_ops.c:254
static int nedges
total no. of edges used in routing
Definition routespl.c:31
static const double tol