GRASS 8 Programmer's Manual 8.6.0dev(2026)-1878fdfec5
Loading...
Searching...
No Matches
centrality.c
Go to the documentation of this file.
1/*!
2 \file lib/vector/neta/centrality.c
3
4 \brief Network Analysis library - centrality
5
6 Centrality measures
7
8 SPDX-FileCopyrightText: 2009-2010 Daniel Bundala
9 SPDX-FileCopyrightText: GRASS Development Team
10 SPDX-License-Identifier: GPL-2.0-or-later
11
12 \author Daniel Bundala (Google Summer of Code 2009)
13 */
14
15#include <stdio.h>
16#include <stdlib.h>
17#include <grass/gis.h>
18#include <grass/vector.h>
19#include <grass/glocale.h>
20#include <grass/dgl/graph.h>
21#include <grass/neta.h>
22
23/*!
24 \brief Computes degree centrality measure.
25
26 Array degree has to be properly initialised to nnodes+1 elements
27
28 \param graph input graph
29 \param[out] degree array of degrees
30 */
32{
33 int i;
35
36 for (i = 1; i <= nnodes; i++)
37 degree[i] =
39 nnodes;
40}
41
42/*!
43 \brief Computes eigenvector centrality using edge costs as weights.
44
45 \param graph input graph
46 \param iterations number of iterations
47 \param error ?
48 \param[out] eigenvector eigen vector value
49
50 \return 0 on success
51 \return -1 on failure
52 */
54 double *eigenvector)
55{
56 int i, iter, nnodes;
57 double *tmp;
58
60 tmp = (double *)G_calloc(nnodes + 1, sizeof(double));
61 if (!tmp) {
62 G_fatal_error(_("Out of memory"));
63 return -1;
64 }
65
66 error *= error;
67 for (i = 1; i <= nnodes; i++)
68 eigenvector[i] = 1;
69 for (iter = 0; iter < iterations; iter++) {
70 for (i = 1; i <= nnodes; i++)
71 tmp[i] = 0;
72 dglInt32_t *node;
75
77 for (node = dglNode_T_First(&nt); node; node = dglNode_T_Next(&nt)) {
80 dglInt32_t *edge;
81
84 for (edge = dglEdgeset_T_First(&et); edge;
85 edge = dglEdgeset_T_Next(&et))
88
90 }
92 double cum_error = 0, max_value = tmp[1];
93
94 for (i = 2; i <= nnodes; i++)
95 if (tmp[i] > max_value)
96 max_value = tmp[i];
97 for (i = 1; i <= nnodes; i++) {
98 tmp[i] /= max_value;
99 cum_error += (tmp[i] - eigenvector[i]) * (tmp[i] - eigenvector[i]);
100 eigenvector[i] = tmp[i];
101 }
102 if (cum_error < error)
103 break;
104 }
105
106 G_free(tmp);
107 return 0;
108}
109
110/*!
111 \brief Computes betweenness and closeness centrality measure using Brandes
112 algorithm.
113
114 Edge costs must be nonnegative. If some edge costs are negative then
115 the behaviour of this method is undefined.
116
117 \param graph input graph
118 \param[out] betweenness betweenness values
119 \param[out] closeness cloneness values
120
121 \return 0 on success
122 \return -1 on failure
123 */
125 double *closeness)
126{
127 int i, j, nnodes, stack_size, count;
128 dglInt32_t *dst, *node, *stack, *cnt, *delta;
132 struct ilist **prev;
133
135
136 dst = (dglInt32_t *)G_calloc(nnodes + 1, sizeof(dglInt32_t));
137 prev = (struct ilist **)G_calloc(nnodes + 1, sizeof(struct ilist *));
139 cnt = (dglInt32_t *)G_calloc(nnodes + 1, sizeof(dglInt32_t));
140 delta = (dglInt32_t *)G_calloc(nnodes + 1, sizeof(dglInt32_t));
141
142 if (!dst || !prev || !stack || !cnt || !delta) {
143 G_fatal_error(_("Out of memory"));
144 return -1;
145 }
146
147 for (i = 1; i <= nnodes; i++) {
148 prev[i] = Vect_new_list();
149 if (closeness)
150 closeness[i] = 0;
151 if (betweenness)
152 betweenness[i] = 0;
153 }
154
155 count = 0;
158 for (node = dglNode_T_First(&nt); node; node = dglNode_T_Next(&nt)) {
159 G_percent(count++, nnodes, 1);
160 dglInt32_t s = dglNodeGet_Id(graph, node);
163
164 stack_size = 0;
165 for (i = 1; i <= nnodes; i++)
166 Vect_reset_list(prev[i]);
167 for (i = 1; i <= nnodes; i++) {
168 cnt[i] = 0;
169 dst[i] = -1;
170 }
171 dst[s] = 0;
172 cnt[s] = 1;
174 heap_data.ul = s;
176 while (1) {
177 dglInt32_t v, dist;
178
180 break;
181 v = heap_node.value.ul;
182 dist = heap_node.key;
183 if (dst[v] < dist)
184 continue;
185 stack[stack_size++] = v;
186
187 dglInt32_t *edge;
188
191 for (edge = dglEdgeset_T_First(&et); edge;
192 edge = dglEdgeset_T_Next(&et)) {
193 dglInt32_t *to = dglEdgeGet_Tail(graph, edge);
196
197 if (dst[to_id] == -1 || dst[to_id] > dist + d) {
198 dst[to_id] = dist + d;
199 Vect_reset_list(prev[to_id]);
200 heap_data.ul = to_id;
201 dglHeapInsertMin(&heap, dist + d, ' ', heap_data);
202 }
203 if (dst[to_id] == dist + d) {
204 cnt[to_id] += cnt[v];
205 Vect_list_append(prev[to_id], v);
206 }
207 }
208
210 }
212 for (i = 1; i <= nnodes; i++)
213 delta[i] = 0;
214 for (i = stack_size - 1; i >= 0; i--) {
215 dglInt32_t w = stack[i];
216
217 if (closeness)
218 closeness[s] += dst[w];
219
220 for (j = 0; j < prev[w]->n_values; j++) {
221 dglInt32_t v = prev[w]->value[j];
222
223 delta[v] += (cnt[v] / (double)cnt[w]) * (1.0 + delta[w]);
224 }
225 if (w != s && betweenness)
226 betweenness[w] += delta[w];
227 }
228 if (closeness)
230 }
232
233 for (i = 1; i <= nnodes; i++)
234 Vect_destroy_list(prev[i]);
235 G_free(delta);
236 G_free(cnt);
237 G_free(stack);
238 G_free(prev);
239 G_free(dst);
240
241 return 0;
242}
#define NULL
Definition ccmath.h:32
int NetA_eigenvector_centrality(dglGraph_s *graph, int iterations, double error, double *eigenvector)
Computes eigenvector centrality using edge costs as weights.
Definition centrality.c:53
void NetA_degree_centrality(dglGraph_s *graph, double *degree)
Computes degree centrality measure.
Definition centrality.c:31
int NetA_betweenness_closeness(dglGraph_s *graph, double *betweenness, double *closeness)
Computes betweenness and closeness centrality measure using Brandes algorithm.
Definition centrality.c:124
void G_percent(long, long, int)
Print percent complete messages.
Definition percent.c:59
void G_percent_reset(void)
Reset G_percent() to 0%; do not add newline.
Definition percent.c:115
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:145
#define G_calloc(m, n)
Definition defs/gis.h:137
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void Vect_destroy_list(struct ilist *)
Frees all memory associated with a struct ilist, including the struct itself.
int Vect_list_append(struct ilist *, int)
Append new item to the end of list if not yet present.
struct ilist * Vect_new_list(void)
Creates and initializes a struct ilist.
int Vect_reset_list(struct ilist *)
Reset ilist structure.
#define _(str)
Definition glocale.h:10
void dglHeapInit(dglHeap_s *pheap)
Definition heap.c:15
int dglHeapInsertMin(dglHeap_s *pheap, long key, unsigned char flags, dglHeapData_u value)
Definition heap.c:38
void dglHeapFree(dglHeap_s *pheap, dglHeapCancelItem_fn pfnCancelItem)
Definition heap.c:23
int dglHeapExtractMin(dglHeap_s *pheap, dglHeapNode_s *pnoderet)
Definition heap.c:64
int count
List of integers.
Definition gis.h:712
int n_values
Number of values in the list.
Definition gis.h:720
int * value
Array of values.
Definition gis.h:716
long dglInt32_t
Definition type.h:24
dglInt32_t * dglNode_T_Next(dglNodeTraverser_s *pT)
dglInt32_t * dglNode_T_First(dglNodeTraverser_s *pT)
dglInt32_t * dglGetNode(dglGraph_s *pGraph, dglInt32_t nNodeId)
dglInt32_t * dglNodeGet_OutEdgeset(dglGraph_s *pGraph, dglInt32_t *pnNode)
int dglEdgeset_T_Initialize(dglEdgesetTraverser_s *pT, dglGraph_s *pGraph, dglInt32_t *pnEdgeset)
int dglNode_T_Initialize(dglNodeTraverser_s *pT, dglGraph_s *pGraph)
dglInt32_t * dglEdgeset_T_First(dglEdgesetTraverser_s *pT)
int dglNodeGet_OutDegree(dglGraph_s *pGraph, dglInt32_t *pnNode)
dglInt32_t * dglEdgeset_T_Next(dglEdgesetTraverser_s *pT)
int dglGet_NodeCount(dglGraph_s *pgraph)
dglInt32_t dglEdgeGet_Cost(dglGraph_s *pGraph, dglInt32_t *pnEdge)
void dglNode_T_Release(dglNodeTraverser_s *pT)
void dglEdgeset_T_Release(dglEdgesetTraverser_s *pT)
dglInt32_t * dglEdgeGet_Tail(dglGraph_s *pGraph, dglInt32_t *pnEdge)
dglInt32_t dglNodeGet_Id(dglGraph_s *pGraph, dglInt32_t *pnNode)