Graphviz 14.1.2~dev.20260118.2044
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 "config.h"
12
13#include <neatogen/digcola.h>
14#include <util/alloc.h>
15#ifdef DIGCOLA
16#include <neatogen/matrix_ops.h>
17#include <neatogen/conjgrad.h>
18#include <stddef.h>
19
20static void construct_b(vtx_data * graph, int n, double *b)
21{
22 /* construct a vector - b s.t. -b[i]=\sum_j -w_{ij}*\delta_{ij}
23 * (the "balance vector")
24 * Note that we build -b and not b, since our matrix is not the
25 * real laplacian L, but its negation: -L.
26 * So instead of solving Lx=b, we will solve -Lx=-b
27 */
28 int i;
29
30 double b_i = 0;
31
32 for (i = 0; i < n; i++) {
33 b_i = 0;
34 if (graph[0].edists == NULL) {
35 continue;
36 }
37 for (size_t j = 1; j < graph[i].nedges; j++) { // skip the self loop
38 b_i += graph[i].ewgts[j] * graph[i].edists[j];
39 }
40 b[i] = b_i;
41 }
42}
43
44#define hierarchy_cg_tol 1e-3
45
46int
47compute_y_coords(vtx_data * graph, int n, double *y_coords,
48 int max_iterations)
49{
50 /* Find y coords of a directed graph by solving L*x = b */
51 int i, rv = 0;
52 double *b = gv_calloc(n, sizeof(double));
53 double tol = hierarchy_cg_tol;
54 size_t nedges = 0;
55 float *old_ewgts = graph[0].ewgts;
56
57 construct_b(graph, n, b);
58
59 init_vec_orth1(n, y_coords);
60
61 for (i = 0; i < n; i++) {
62 nedges += graph[i].nedges;
63 }
64
65 /* replace original edge weights (which are lengths) with uniform weights */
66 /* for computing the optimal arrangement */
67 float *uniform_weights = gv_calloc(nedges, sizeof(float));
68 for (i = 0; i < n; i++) {
69 graph[i].ewgts = uniform_weights;
70 uniform_weights[0] = -(float)(graph[i].nedges - 1);
71 for (size_t j = 1; j < graph[i].nedges; j++) {
72 uniform_weights[j] = 1;
73 }
74 uniform_weights += graph[i].nedges;
75 }
76
77 if (conjugate_gradient(graph, y_coords, b, n, tol, max_iterations) < 0) {
78 rv = 1;
79 }
80
81 /* restore original edge weights */
82 free(graph[0].ewgts);
83 for (i = 0; i < n; i++) {
84 graph[i].ewgts = old_ewgts;
85 old_ewgts += graph[i].nedges;
86 }
87
88 free(b);
89 return rv;
90}
91
92#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:24
void free(void *)
node NULL
Definition grammar.y:181
Agraph_t * graph(char *name)
Definition gv.cpp:34
void init_vec_orth1(int n, double *vec)
Definition matrix_ops.c:250
static int nedges
total no. of edges used in routing
Definition routespl.c:32
static const double tol